From 15c3ad6ea3968753606727e2ed6812ca708817ee9ff3f81034888d874996753e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Schr=C3=B6ter?= Date: Fri, 3 May 2024 17:31:54 +0200 Subject: [PATCH] Sync from SUSE:SLFO:Main openssh revision f793e41158efbf91a9de8e2e7a9a07fd --- .gitattributes | 23 + README.FIPS | 64 + README.SUSE | 16 + README.kerberos | 18 + _multibuild | 3 + cavs_driver-ssh.pl | 184 + fix-missing-lz.patch | 25 + logind_set_tty.patch | 197 + openssh-6.6.1p1-selinux-contexts.patch | 119 + openssh-6.6p1-keycat.patch | 491 ++ openssh-6.6p1-privsep-selinux.patch | 125 + openssh-7.6p1-cleanup-selinux.patch | 291 + openssh-7.7p1-IPv6_X_forwarding.patch | 38 + openssh-7.7p1-X11_trusted_forwarding.patch | 47 + ...h-7.7p1-X_forward_with_disabled_ipv6.patch | 23 + openssh-7.7p1-cavstest-ctr.patch | 304 + openssh-7.7p1-cavstest-kdf.patch | 450 ++ openssh-7.7p1-disable_openssl_abi_check.patch | 48 + openssh-7.7p1-eal3.patch | 18 + openssh-7.7p1-enable_PAM_by_default.patch | 19 + openssh-7.7p1-fips.patch | 810 +++ openssh-7.7p1-fips_checks.patch | 471 ++ openssh-7.7p1-host_ident.patch | 20 + ...1-hostname_changes_when_forwarding_X.patch | 83 + openssh-7.7p1-ldap.patch | 2719 ++++++++ openssh-7.7p1-no_fork-no_pid_file.patch | 17 + openssh-7.7p1-pam_check_locks.patch | 134 + openssh-7.7p1-pts_names_formatting.patch | 30 + ...h-7.7p1-remove_xauth_cookies_on_exit.patch | 46 + openssh-7.7p1-seccomp_ipc_flock.patch | 41 + openssh-7.7p1-seccomp_stat.patch | 21 + openssh-7.7p1-send_locale.patch | 37 + openssh-7.7p1-sftp_force_permissions.patch | 125 + ...7.7p1-sftp_print_diagnostic_messages.patch | 60 + openssh-7.7p1-systemd-notify.patch | 87 + openssh-7.8p1-role-mls.patch | 885 +++ openssh-7.9p1-keygen-preserve-perms.patch | 39 + openssh-7.9p1-revert-new-qos-defaults.patch | 76 + openssh-8.0p1-gssapi-keyex.patch | 3966 +++++++++++ openssh-8.1p1-audit.patch | 2476 +++++++ openssh-8.1p1-ed25519-use-openssl-rng.patch | 74 + openssh-8.1p1-seccomp-clock_gettime64.patch | 25 + openssh-8.1p1-seccomp-clock_nanosleep.patch | 14 + ...8.1p1-seccomp-clock_nanosleep_time64.patch | 24 + openssh-8.1p1-use-openssl-kdf.patch | 158 + openssh-8.4p1-pam_motd.patch | 13 + openssh-8.4p1-ssh_config_d.patch | 40 + openssh-8.4p1-vendordir.patch | 208 + openssh-9.6p1.tar.gz | 3 + openssh-9.6p1.tar.gz.asc | 16 + openssh-askpass-gnome.changes | 334 + openssh-askpass-gnome.spec | 66 + openssh-do-not-send-empty-message.patch | 19 + openssh-fips-ensure-approved-moduli.patch | 78 + openssh-link-with-sk.patch | 15 + openssh-openssl-3.patch | 125 + ...ssh-reenable-dh-group14-sha1-default.patch | 41 + openssh-whitelist-syscalls.patch | 34 + openssh.changes | 6027 +++++++++++++++++ openssh.keyring | 353 + openssh.spec | 571 ++ ssh-askpass | 26 + ssh.reg | 18 + sshd-gen-keys-start | 9 + sshd-sle.pamd | 11 + sshd.fw | 5 + sshd.pamd | 14 + sshd.service | 18 + sysconfig.ssh | 14 + sysusers-sshd.conf | 2 + wtmpdb.patch | 185 + 71 files changed, 23186 insertions(+) create mode 100644 .gitattributes create mode 100644 README.FIPS create mode 100644 README.SUSE create mode 100644 README.kerberos create mode 100644 _multibuild create mode 100644 cavs_driver-ssh.pl create mode 100644 fix-missing-lz.patch create mode 100644 logind_set_tty.patch create mode 100644 openssh-6.6.1p1-selinux-contexts.patch create mode 100644 openssh-6.6p1-keycat.patch create mode 100644 openssh-6.6p1-privsep-selinux.patch create mode 100644 openssh-7.6p1-cleanup-selinux.patch create mode 100644 openssh-7.7p1-IPv6_X_forwarding.patch create mode 100644 openssh-7.7p1-X11_trusted_forwarding.patch create mode 100644 openssh-7.7p1-X_forward_with_disabled_ipv6.patch create mode 100644 openssh-7.7p1-cavstest-ctr.patch create mode 100644 openssh-7.7p1-cavstest-kdf.patch create mode 100644 openssh-7.7p1-disable_openssl_abi_check.patch create mode 100644 openssh-7.7p1-eal3.patch create mode 100644 openssh-7.7p1-enable_PAM_by_default.patch create mode 100644 openssh-7.7p1-fips.patch create mode 100644 openssh-7.7p1-fips_checks.patch create mode 100644 openssh-7.7p1-host_ident.patch create mode 100644 openssh-7.7p1-hostname_changes_when_forwarding_X.patch create mode 100644 openssh-7.7p1-ldap.patch create mode 100644 openssh-7.7p1-no_fork-no_pid_file.patch create mode 100644 openssh-7.7p1-pam_check_locks.patch create mode 100644 openssh-7.7p1-pts_names_formatting.patch create mode 100644 openssh-7.7p1-remove_xauth_cookies_on_exit.patch create mode 100644 openssh-7.7p1-seccomp_ipc_flock.patch create mode 100644 openssh-7.7p1-seccomp_stat.patch create mode 100644 openssh-7.7p1-send_locale.patch create mode 100644 openssh-7.7p1-sftp_force_permissions.patch create mode 100644 openssh-7.7p1-sftp_print_diagnostic_messages.patch create mode 100644 openssh-7.7p1-systemd-notify.patch create mode 100644 openssh-7.8p1-role-mls.patch create mode 100644 openssh-7.9p1-keygen-preserve-perms.patch create mode 100644 openssh-7.9p1-revert-new-qos-defaults.patch create mode 100644 openssh-8.0p1-gssapi-keyex.patch create mode 100644 openssh-8.1p1-audit.patch create mode 100644 openssh-8.1p1-ed25519-use-openssl-rng.patch create mode 100644 openssh-8.1p1-seccomp-clock_gettime64.patch create mode 100644 openssh-8.1p1-seccomp-clock_nanosleep.patch create mode 100644 openssh-8.1p1-seccomp-clock_nanosleep_time64.patch create mode 100644 openssh-8.1p1-use-openssl-kdf.patch create mode 100644 openssh-8.4p1-pam_motd.patch create mode 100644 openssh-8.4p1-ssh_config_d.patch create mode 100644 openssh-8.4p1-vendordir.patch create mode 100644 openssh-9.6p1.tar.gz create mode 100644 openssh-9.6p1.tar.gz.asc create mode 100644 openssh-askpass-gnome.changes create mode 100644 openssh-askpass-gnome.spec create mode 100644 openssh-do-not-send-empty-message.patch create mode 100644 openssh-fips-ensure-approved-moduli.patch create mode 100644 openssh-link-with-sk.patch create mode 100644 openssh-openssl-3.patch create mode 100644 openssh-reenable-dh-group14-sha1-default.patch create mode 100644 openssh-whitelist-syscalls.patch create mode 100644 openssh.changes create mode 100644 openssh.keyring create mode 100644 openssh.spec create mode 100644 ssh-askpass create mode 100644 ssh.reg create mode 100644 sshd-gen-keys-start create mode 100644 sshd-sle.pamd create mode 100644 sshd.fw create mode 100644 sshd.pamd create mode 100644 sshd.service create mode 100644 sysconfig.ssh create mode 100644 sysusers-sshd.conf create mode 100644 wtmpdb.patch diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9b03811 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,23 @@ +## Default LFS +*.7z filter=lfs diff=lfs merge=lfs -text +*.bsp filter=lfs diff=lfs merge=lfs -text +*.bz2 filter=lfs diff=lfs merge=lfs -text +*.gem filter=lfs diff=lfs merge=lfs -text +*.gz filter=lfs diff=lfs merge=lfs -text +*.jar filter=lfs diff=lfs merge=lfs -text +*.lz filter=lfs diff=lfs merge=lfs -text +*.lzma filter=lfs diff=lfs merge=lfs -text +*.obscpio filter=lfs diff=lfs merge=lfs -text +*.oxt filter=lfs diff=lfs merge=lfs -text +*.pdf filter=lfs diff=lfs merge=lfs -text +*.png filter=lfs diff=lfs merge=lfs -text +*.rpm filter=lfs diff=lfs merge=lfs -text +*.tbz filter=lfs diff=lfs merge=lfs -text +*.tbz2 filter=lfs diff=lfs merge=lfs -text +*.tgz filter=lfs diff=lfs merge=lfs -text +*.ttf filter=lfs diff=lfs merge=lfs -text +*.txz filter=lfs diff=lfs merge=lfs -text +*.whl filter=lfs diff=lfs merge=lfs -text +*.xz filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text +*.zst filter=lfs diff=lfs merge=lfs -text diff --git a/README.FIPS b/README.FIPS new file mode 100644 index 0000000..0f21716 --- /dev/null +++ b/README.FIPS @@ -0,0 +1,64 @@ +Notes on FIPS mode and OpenSSH + +--- + +SUSE OpenSSH comes with FIPS 140-2 support, and certain versions have been +certified as FIPS compliant by NIST. Apart from other things, this standard +puts restrictions on cryptographic algorithms that may be used. + +Important notice: FIPS is not only a matter of functionality. If you want to +claim having a FIPS certified service, you *must* use the certified binaries. +Even binaries built from the same sources in the same environment and running +on a certified system, yet from a package lacking the certification, are +formally not considered to be fulfilling the requirements. + +The certified binaries (ssh, sshd, sftp-server) perform mandatory selfcheck at +startup and proceed only when the checks succeed (non-certified binaries may +skip the check). These checks require the cryptographic hashes contained in the +openssh-fips subpackage. + +The FIPS mode for OpenSSH is enabled in two ways - either: + +1) /proc/sys/crypto/fips_enabled contains a single character '1' - this is a +system-wide setting controlled bu the fips kernel parameter; or + +2) the environment variable SSH_FORCE_FIPS - if set (to any value), the +binaries behave as if they were running on a system in FIPS mode. + +Since FIPS 140-2 only allows use of certain cryptographic algorithms, both the +client and server will fail if they are requested to use non-approved +algorithms while in FIPS mode. This means that working configurations for FIPS +mode form a proper subset of all working (generic) configurations. Some +configurations may even prevent the binaries from starting at all. + +This however should be viewed in the context of FIPS being a security policy +tool - it is not of much use to run the same system both in FIPS mode and +outside of it, since that would defeat the main purpose of FIPS having +guaranteeing standardised minimum restrictions on cryptographic algorithms +(and thus on the overall security of the system). + +Unless you specify what cryptographic algorithms you wish to use, both the +client and server should work out of the box in FIPS mode. + +For sshd, you can use the `-t` option to check whether the configuration file +is working. Setting the above mentioned environment variable allows testing of +behaviour in FIPS mode (checksum files for both OpenSSH and OpenSSL must be +installed). + +In addition to cryptographic algorithms restrictions, sshd performs periodic +PRNG re-seeding. The seed is read from entropy source either /dev/urandom or +/dev/random. By default, the former is used, unless the environment variable +SSH_USE_STRONG_RNG is set to a non-zero value or the binary is running in FIPS +mode. This has two important implications: + +1) the selected entropy source must be available, i.e. when running in a +changeroot the device files need to be present there. + +2) /dev/random is a blocking interface - unless enough randomness is available, +the process stops until the entropy pool is replenished. Thus on systems where +a long running processes are expected, one should make sure there is always +enough entropy for sshd. Sporadically this may also cause sshd to aborted, +since some versions of OpenSSL (the underlying cryptographic engine) don't +handle gracefully being interrupted while trying to read entropy from the +system source. + diff --git a/README.SUSE b/README.SUSE new file mode 100644 index 0000000..cb1f82b --- /dev/null +++ b/README.SUSE @@ -0,0 +1,16 @@ +There are following changes in default settings of ssh client and server: + +* Accepting and sending of locale environment variables in protocol 2 is + enabled. + +* PAM authentication is enabled and mostly even required, do not turn it off. + +* DSA authentication is enabled by default for maximum compatibility. + NOTE: do not use DSA authentication since it is being phased out for a reason + - the size of DSA keys is limited by the standard to 1024 bits which cannot + be considered safe any more. + +* Accepting all RFC4419 specified DH group parameters. See KexDHMin in + ssh_config and sshd_config manual pages. + +For more information on differences in SUSE OpenSSH package see README.FIPS diff --git a/README.kerberos b/README.kerberos new file mode 100644 index 0000000..284a9fe --- /dev/null +++ b/README.kerberos @@ -0,0 +1,18 @@ +This version of the Kerbros/GSSAPI support avoids DNS lookups +for Kerberos-related names. These DNS lookups were problematic +for dialup users because they would lead to excessive delays +if DNS was not reachable. + +If you do use Kerberos, please make sure you edit the server and +client configuration files as follows: + +/etc/ssh/sshd_config: + + GSSAPIAuthentication yes + GSSAPICleanupCredentials yes + +/etc/ssh/ssh_config: + Host * + ... lots of other options ... + GSSAPIAuthentication yes + GSSAPIDelegateCredentials yes diff --git a/_multibuild b/_multibuild new file mode 100644 index 0000000..2c8d823 --- /dev/null +++ b/_multibuild @@ -0,0 +1,3 @@ + + openssh-askpass-gnome + diff --git a/cavs_driver-ssh.pl b/cavs_driver-ssh.pl new file mode 100644 index 0000000..df1411e --- /dev/null +++ b/cavs_driver-ssh.pl @@ -0,0 +1,184 @@ +#!/usr/bin/perl +# +# CAVS test driver for OpenSSH +# +# Copyright (C) 2015, Stephan Mueller +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# NO WARRANTY +# +# BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +# FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +# OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +# PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +# OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +# TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +# PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +# REPAIR OR CORRECTION. +# +# IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +# WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +# REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +# INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +# OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +# TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +# YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +# PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGES. +# +use strict; +use warnings; +use IPC::Open2; + +# Executing a program by feeding STDIN and retrieving +# STDOUT +# $1: data string to be piped to the app on STDIN +# rest: program and args +# returns: STDOUT of program as string +sub pipe_through_program($@) { + my $in = shift; + my @args = @_; + + my ($CO, $CI); + my $pid = open2($CO, $CI, @args); + + my $out = ""; + my $len = length($in); + my $first = 1; + while (1) { + my $rin = ""; + my $win = ""; + # Output of prog is FD that we read + vec($rin,fileno($CO),1) = 1; + # Input of prog is FD that we write + # check for $first is needed because we can have NULL input + # that is to be written to the app + if ( $len > 0 || $first) { + (vec($win,fileno($CI),1) = 1); + $first=0; + } + # Let us wait for 100ms + my $nfound = select(my $rout=$rin, my $wout=$win, undef, 0.1); + if ( $wout ) { + my $written = syswrite($CI, $in, $len); + die "broken pipe" if !defined $written; + $len -= $written; + substr($in, 0, $written) = ""; + if ($len <= 0) { + close $CI or die "broken pipe: $!"; + } + } + if ( $rout ) { + my $tmp_out = ""; + my $bytes_read = sysread($CO, $tmp_out, 4096); + $out .= $tmp_out; + last if ($bytes_read == 0); + } + } + close $CO or die "broken pipe: $!"; + waitpid $pid, 0; + + return $out; +} + +# Parser of CAVS test vector file +# $1: Test vector file +# $2: Output file for test results +# return: nothing +sub parse($$) { + my $infile = shift; + my $outfile = shift; + + my $out = ""; + + my $K = ""; + my $H = ""; + my $session_id = ""; + my $ivlen = 0; + my $eklen = ""; + my $iklen = ""; + + open(IN, "<$infile"); + while() { + + my $line = $_; + chomp($line); + $line =~ s/\r//; + + if ($line =~ /\[SHA-1\]/) { + $iklen = 20; + } elsif ($line =~ /\[SHA-256\]/) { + $iklen = 32; + } elsif ($line =~ /\[SHA-384\]/) { + $iklen = 48; + } elsif ($line =~ /\[SHA-512\]/) { + $iklen = 64; + } elsif ($line =~ /^\[IV length\s*=\s*(.*)\]/) { + $ivlen = $1; + $ivlen = $ivlen / 8; + } elsif ($line =~ /^\[encryption key length\s*=\s*(.*)\]/) { + $eklen = $1; + $eklen = $eklen / 8; + } elsif ($line =~ /^K\s*=\s*(.*)/) { + $K = $1; + $K = substr($K, 8); + $K = "00" . $K; + } elsif ($line =~ /^H\s*=\s*(.*)/) { + $H = $1; + } elsif ($line =~ /^session_id\s*=\s*(.*)/) { + $session_id = $1; + } + $out .= $line . "\n"; + + if ($K ne "" && $H ne "" && $session_id ne "" && + $ivlen ne "" && $eklen ne "" && $iklen > 0) { + $out .= pipe_through_program("", "@LIBEXECDIR@/ssh/cavstest-kdf -H $H -K $K -s $session_id -i $ivlen -e $eklen -m $iklen"); + + $K = ""; + $H = ""; + $session_id = ""; + } + } + close IN; + $out =~ s/\n/\r\n/g; # make it a dos file + open(OUT, ">$outfile") or die "Cannot create output file $outfile: $?"; + print OUT $out; + close OUT; +} + +############################################################ +# +# let us pretend to be C :-) +sub main() { + + my $infile=$ARGV[0]; + die "Error: Test vector file $infile not found" if (! -f $infile); + + my $outfile = $infile; + # let us add .rsp regardless whether we could strip .req + $outfile =~ s/\.req$//; + $outfile .= ".rsp"; + if (-f $outfile) { + die "Output file $outfile could not be removed: $?" + unless unlink($outfile); + } + print STDERR "Performing tests from source file $infile with results stored in destination file $outfile\n"; + + # Do the job + parse($infile, $outfile); +} + +########################################### +# Call it +main(); +1; diff --git a/fix-missing-lz.patch b/fix-missing-lz.patch new file mode 100644 index 0000000..bc82afa --- /dev/null +++ b/fix-missing-lz.patch @@ -0,0 +1,25 @@ +Index: openssh-9.3p1/Makefile.in +=================================================================== +--- openssh-9.3p1.orig/Makefile.in ++++ openssh-9.3p1/Makefile.in +@@ -250,17 +250,17 @@ ssh-ldap-helper$(EXEEXT): $(LIBCOMPAT) l + $(LD) -o $@ ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) + + sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-sk.o sk-usbhid.o $(SFTPSERVER_OBJS) +- $(LD) -o $@ $(SFTPSERVER_OBJS) ssh-sk.o sk-usbhid.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) $(LIBFIDO2) ++ $(LD) -o $@ $(SFTPSERVER_OBJS) ssh-sk.o sk-usbhid.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) $(LIBFIDO2) -lz + + sftp$(EXEEXT): $(LIBCOMPAT) libssh.a $(SFTP_OBJS) + $(LD) -o $@ $(SFTP_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(LIBEDIT) + + # FIPS tests + cavstest-ctr$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-sk.o sk-usbhid.o cavstest-ctr.o +- $(LD) -o $@ cavstest-ctr.o ssh-sk.o sk-usbhid.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) $(LIBFIDO2) ++ $(LD) -o $@ cavstest-ctr.o ssh-sk.o sk-usbhid.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) $(LIBFIDO2) -lz + + cavstest-kdf$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-sk.o sk-usbhid.o cavstest-kdf.o +- $(LD) -o $@ cavstest-kdf.o ssh-sk.o sk-usbhid.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) $(LIBFIDO2) ++ $(LD) -o $@ cavstest-kdf.o ssh-sk.o sk-usbhid.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) $(LIBFIDO2) -lz + + # test driver for the loginrec code - not built by default + logintest: logintest.o $(LIBCOMPAT) libssh.a loginrec.o diff --git a/logind_set_tty.patch b/logind_set_tty.patch new file mode 100644 index 0000000..5d3e37c --- /dev/null +++ b/logind_set_tty.patch @@ -0,0 +1,197 @@ +diff --git a/Makefile.in b/Makefile.in +index f0ea07e7b..35dcf45f1 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -56,6 +56,7 @@ SSHDLIBS=@SSHDLIBS@ + LIBEDIT=@LIBEDIT@ + LIBFIDO2=@LIBFIDO2@ + LIBWTMPDB=@LIBWTMPDB@ ++LIBSYSTEMD=@LIBSYSTEMD@ + AR=@AR@ + AWK=@AWK@ + RANLIB=@RANLIB@ +@@ -208,7 +209,7 @@ ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS) + $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(GSSLIBS) $(CHANNELLIBS) + + sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS) +- $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS) $(CHANNELLIBS) $(LIBWTMPDB) ++ $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS) $(CHANNELLIBS) $(LIBWTMPDB) $(LIBSYSTEMD) + + scp$(EXEEXT): $(LIBCOMPAT) libssh.a $(SCP_OBJS) + $(LD) -o $@ $(SCP_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) +diff --git a/configure.ac b/configure.ac +index a12c6f7ad..860df3379 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1789,6 +1789,47 @@ AC_ARG_WITH([wtmpdb], + ) + + ++# Check whether user wants logind/set tty support ++AC_ARG_WITH([logind], ++ [ --with-logind[[=PATH]] Enable logind support for sshd], ++ [ if test "x$withval" != "xno" ; then ++ if test "x$withval" = "xyes" ; then ++ AC_PATH_TOOL([PKGCONFIG], [pkg-config], [no]) ++ if test "x$PKGCONFIG" != "xno"; then ++ AC_MSG_CHECKING([if $PKGCONFIG knows about libsystemd]) ++ if "$PKGCONFIG" libsystemd; then ++ AC_MSG_RESULT([yes]) ++ use_pkgconfig_for_libsystemd=yes ++ else ++ AC_MSG_RESULT([no]) ++ fi ++ fi ++ else ++ CPPFLAGS="$CPPFLAGS -I${withval}/include" ++ if test -n "${rpath_opt}"; then ++ LDFLAGS="-L${withval}/lib ${rpath_opt}${withval}/lib ${LDFLAGS}" ++ else ++ LDFLAGS="-L${withval}/lib ${LDFLAGS}" ++ fi ++ fi ++ if test "x$use_pkgconfig_for_libsystemd" = "xyes"; then ++ LIBSYSTEMD=`$PKGCONFIG --libs libsystemd` ++ CPPFLAGS="$CPPFLAGS `$PKGCONFIG --cflags libsystemd`" ++ else ++ LIBSYSTEMD="-lsystemd" ++ fi ++ OTHERLIBS=`echo $LIBSYSTEMD | sed 's/-lsystemd//'` ++ AC_CHECK_LIB([systemd], [sd_bus_open_system], ++ [ AC_DEFINE([USE_LOGIND], [1], [Use systemd-logind]) ++ AC_SUBST([LIBSYSTEMD]) ++ ], ++ [ AC_MSG_ERROR([libsystemd not found]) ], ++ [ $OTHERLIBS ] ++ ) ++ fi ] ++) ++ ++ + AUDIT_MODULE=none + AC_ARG_WITH([audit], + [ --with-audit=module Enable audit support (modules=debug,bsm,linux)], +diff --git a/loginrec.c b/loginrec.c +index 86caf83b2..8b413190b 100644 +--- a/loginrec.c ++++ b/loginrec.c +@@ -191,6 +191,10 @@ + # include + #endif + ++#ifdef USE_LOGIND ++# include ++#endif ++ + /** + ** prototypes for helper functions in this file + **/ +@@ -214,6 +218,9 @@ int syslogin_write_entry(struct logininfo *li); + #ifdef USE_WTMPDB + int wtmpdb_write_entry(struct logininfo *li); + #endif ++#ifdef USE_LOGIND ++int logind_set_tty(struct logininfo *li); ++#endif + + int getlast_entry(struct logininfo *li); + int lastlog_get_entry(struct logininfo *li); +@@ -477,6 +484,9 @@ login_write(struct logininfo *li) + #ifdef USE_WTMPDB + wtmpdb_write_entry(li); + #endif ++#ifdef USE_LOGIND ++ logind_set_tty(li); ++#endif + #ifdef CUSTOM_SYS_AUTH_RECORD_LOGIN + if (li->type == LTYPE_LOGIN && + !sys_auth_record_login(li->username,li->hostname,li->line, +@@ -1476,6 +1486,88 @@ wtmpdb_write_entry(struct logininfo *li) + } + #endif + ++#ifdef USE_LOGIND ++#define DBUS_DESTINATION "org.freedesktop.login1" ++#define DBUS_PATH_ID "/org/freedesktop/login1/session/auto" ++#define DBUS_INTERFACE "org.freedesktop.login1.Session" ++#define DBUS_PATH "/org/freedesktop/login1/session/%s" ++ ++static int ++logind_perform_login(struct logininfo *li) ++{ ++ sd_bus *bus = NULL; ++ sd_bus_error error = SD_BUS_ERROR_NULL; ++ char *session_id = NULL; ++ char *dbus_path; ++ const char *tty; ++ char buf[PATH_MAX]; ++ int r; ++ int fd; ++ ++ if (sd_bus_open_system(&bus) < 0) ++ { ++ logit("logind: canot open dbus"); ++ return (0); ++ } ++ ++ if (sd_bus_get_property_string(bus, DBUS_DESTINATION, ++ DBUS_PATH_ID, DBUS_INTERFACE, ++ "Id", &error, &session_id) < 0) ++ { ++ logit("logind: cannot get session ID"); ++ return (0); ++ } ++ ++ if (strncmp(li->line, "/dev/", 5) != 0) ++ snprintf (buf, sizeof(buf), "/dev/%s", li->line); ++ else ++ tty = li->line; ++ ++ fd = open(tty, O_RDWR|O_CLOEXEC|O_NOCTTY); ++ ++ if (asprintf (&dbus_path, DBUS_PATH, session_id) < 0) ++ return (0); ++ ++ if (sd_bus_call_method(bus, DBUS_DESTINATION, dbus_path, ++ DBUS_INTERFACE, "TakeControl", &error, NULL, ++ "b", 1) < 0) { ++ logit("logind: cannot take control"); ++ free(dbus_path); ++ return (0); ++ } ++ ++ if ((r = sd_bus_call_method(bus, DBUS_DESTINATION, dbus_path, ++ DBUS_INTERFACE, "SetTTY", &error, NULL, ++ "h", fd)) < 0) { ++ if (r != -EBADR) /* logind does not support "SetTTY" */ ++ logit("logind: cannot set TTY(%s, %s): %s", session_id, tty, strerror(-r)); ++ free(dbus_path); ++ return (0); ++ } ++ ++ free(dbus_path); ++ ++ if (sd_bus_flush(bus) < 0) ++ return (0); ++ ++ return (1); ++} ++ ++int ++logind_set_tty(struct logininfo *li) ++{ ++ switch(li->type) { ++ case LTYPE_LOGIN: ++ return (logind_perform_login(li)); ++ case LTYPE_LOGOUT: ++ return (1); ++ default: ++ logit("%s: invalid type field", __func__); ++ return (0); ++ } ++} ++#endif ++ + + /** + ** Low-level libutil login() functions diff --git a/openssh-6.6.1p1-selinux-contexts.patch b/openssh-6.6.1p1-selinux-contexts.patch new file mode 100644 index 0000000..42e43d1 --- /dev/null +++ b/openssh-6.6.1p1-selinux-contexts.patch @@ -0,0 +1,119 @@ +Index: openssh-9.6p1/openbsd-compat/port-linux-sshd.c +=================================================================== +--- openssh-9.6p1.orig/openbsd-compat/port-linux-sshd.c ++++ openssh-9.6p1/openbsd-compat/port-linux-sshd.c +@@ -33,6 +33,7 @@ + #include "misc.h" /* servconf.h needs misc.h for struct ForwardOptions */ + #include "servconf.h" + #include "port-linux.h" ++#include "misc.h" + #include "sshkey.h" + #include "hostfile.h" + #include "auth.h" +@@ -451,7 +452,7 @@ sshd_selinux_setup_exec_context(char *pw + void + sshd_selinux_copy_context(void) + { +- security_context_t *ctx; ++ char *ctx; + + if (!sshd_selinux_enabled()) + return; +@@ -470,6 +471,72 @@ sshd_selinux_copy_context(void) + } + } + ++void ++sshd_selinux_change_privsep_preauth_context(void) ++{ ++ int len; ++ 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) { ++ debug3_f("Failed to get the path to SELinux context"); ++ return; ++ } ++ ++ if ((contexts_file = fopen(contexts_path, "r")) == NULL) { ++ debug_f("Failed to open SELinux context file"); ++ return; ++ } ++ ++ if (fstat(fileno(contexts_file), &sb) != 0 || ++ sb.st_uid != 0 || (sb.st_mode & 022) != 0) { ++ logit_f("SELinux context file needs to be owned by root" ++ " and not writable by anyone else"); ++ 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_f("privsep_preauth is empty"); ++ fclose(contexts_file); ++ return; ++ } ++ preauth_context = xstrdup(arg); ++ } ++ } ++ fclose(contexts_file); ++ ++ if (preauth_context == NULL) { ++ debug_f("Unable to find 'privsep_preauth' option in" ++ " SELinux context file"); ++ return; ++ } ++ ++ ssh_selinux_change_context(preauth_context); ++ free(preauth_context); ++} ++ + #endif + #endif + +Index: openssh-9.6p1/openbsd-compat/port-linux.h +=================================================================== +--- openssh-9.6p1.orig/openbsd-compat/port-linux.h ++++ openssh-9.6p1/openbsd-compat/port-linux.h +@@ -27,6 +27,7 @@ int sshd_selinux_enabled(void); + void sshd_selinux_copy_context(void); + void sshd_selinux_setup_exec_context(char *); + int sshd_selinux_setup_env_variables(void); ++void sshd_selinux_change_privsep_preauth_context(void); + #endif + + #ifdef LINUX_OOM_ADJUST +Index: openssh-9.6p1/sshd.c +=================================================================== +--- openssh-9.6p1.orig/sshd.c ++++ openssh-9.6p1/sshd.c +@@ -511,7 +511,7 @@ privsep_preauth_child(struct ssh *ssh) + demote_sensitive_data(ssh); + + #ifdef WITH_SELINUX +- ssh_selinux_change_context("sshd_net_t"); ++ sshd_selinux_change_privsep_preauth_context(); + #endif + + /* Demote the child */ diff --git a/openssh-6.6p1-keycat.patch b/openssh-6.6p1-keycat.patch new file mode 100644 index 0000000..f61bb4c --- /dev/null +++ b/openssh-6.6p1-keycat.patch @@ -0,0 +1,491 @@ +Index: openssh-9.3p2/misc.c +=================================================================== +--- openssh-9.3p2.orig/misc.c ++++ openssh-9.3p2/misc.c +@@ -2770,6 +2770,13 @@ subprocess(const char *tag, const char * + error("%s: dup2: %s", tag, strerror(errno)); + _exit(1); + } ++#ifdef WITH_SELINUX ++ if (sshd_selinux_setup_env_variables() < 0) { ++ error ("failed to copy environment: %s", ++ strerror(errno)); ++ _exit(127); ++ } ++#endif + if (env != NULL) + execve(av[0], av, env); + else +Index: openssh-9.3p2/HOWTO.ssh-keycat +=================================================================== +--- /dev/null ++++ openssh-9.3p2/HOWTO.ssh-keycat +@@ -0,0 +1,12 @@ ++The ssh-keycat retrieves the content of the ~/.ssh/authorized_keys ++of an user in any environment. This includes environments with ++polyinstantiation of home directories and SELinux MLS policy enabled. ++ ++To use ssh-keycat, set these options in /etc/ssh/sshd_config file: ++ AuthorizedKeysCommand /usr/libexec/openssh/ssh-keycat ++ AuthorizedKeysCommandUser root ++ ++Do not forget to enable public key authentication: ++ PubkeyAuthentication yes ++ ++ +Index: openssh-9.3p2/Makefile.in +=================================================================== +--- openssh-9.3p2.orig/Makefile.in ++++ openssh-9.3p2/Makefile.in +@@ -24,6 +24,7 @@ SSH_PROGRAM=@bindir@/ssh + ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass + SFTP_SERVER=$(libexecdir)/sftp-server + SSH_KEYSIGN=$(libexecdir)/ssh-keysign ++SSH_KEYCAT=$(libexecdir)/ssh-keycat + SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper + SSH_SK_HELPER=$(libexecdir)/ssh-sk-helper + SSH_LDAP_HELPER=$(libexecdir)/ssh-ldap-helper +@@ -57,6 +58,7 @@ CHANNELLIBS=@CHANNELLIBS@ + K5LIBS=@K5LIBS@ + GSSLIBS=@GSSLIBS@ + SSHDLIBS=@SSHDLIBS@ ++KEYCATLIBS=@KEYCATLIBS@ + LIBEDIT=@LIBEDIT@ + LIBFIDO2=@LIBFIDO2@ + LIBWTMPDB=@LIBWTMPDB@ +@@ -75,7 +77,7 @@ MKDIR_P=@MKDIR_P@ + + .SUFFIXES: .lo + +-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT) ++TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT) ssh-keycat$(EXEEXT) + + TARGETS += cavstest-ctr$(EXEEXT) cavstest-kdf$(EXEEXT) + +@@ -245,6 +247,9 @@ ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) + ssh-sk-helper$(EXEEXT): $(LIBCOMPAT) libssh.a $(SKHELPER_OBJS) + $(LD) -o $@ $(SKHELPER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) $(LIBFIDO2) $(CHANNELLIBS) + ++ssh-keycat$(EXEEXT): $(LIBCOMPAT) $(SSHDOBJS) libssh.a ssh-keycat.o uidswap.o ++ $(LD) -o $@ ssh-keycat.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat $(KEYCATLIBS) $(LIBS) ++ + ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYSCAN_OBJS) + $(LD) -o $@ $(SSHKEYSCAN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) $(CHANNELLIBS) + +@@ -431,6 +436,7 @@ install-files: + $(INSTALL) -m 0755 ssh-ldap-wrapper $(DESTDIR)$(SSH_LDAP_WRAPPER) ; \ + fi + $(INSTALL) -m 0755 $(STRIP_OPT) ssh-sk-helper$(EXEEXT) $(DESTDIR)$(SSH_SK_HELPER)$(EXEEXT) ++ $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keycat$(EXEEXT) $(DESTDIR)$(libexecdir)/ssh-keycat$(EXEEXT) + $(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT) + $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) + $(INSTALL) -m 0755 $(STRIP_OPT) cavstest-ctr$(EXEEXT) $(DESTDIR)$(libexecdir)/cavstest-ctr$(EXEEXT) +Index: openssh-9.3p2/openbsd-compat/port-linux.h +=================================================================== +--- openssh-9.3p2.orig/openbsd-compat/port-linux.h ++++ openssh-9.3p2/openbsd-compat/port-linux.h +@@ -23,8 +23,10 @@ void ssh_selinux_setup_pty(char *, const + void ssh_selinux_change_context(const char *); + void ssh_selinux_setfscreatecon(const char *); + ++int sshd_selinux_enabled(void); + void sshd_selinux_copy_context(void); + void sshd_selinux_setup_exec_context(char *); ++int sshd_selinux_setup_env_variables(void); + #endif + + #ifdef LINUX_OOM_ADJUST +Index: openssh-9.3p2/openbsd-compat/port-linux-sshd.c +=================================================================== +--- openssh-9.3p2.orig/openbsd-compat/port-linux-sshd.c ++++ openssh-9.3p2/openbsd-compat/port-linux-sshd.c +@@ -53,6 +53,20 @@ extern Authctxt *the_authctxt; + extern int inetd_flag; + extern int rexeced_flag; + ++/* Wrapper around is_selinux_enabled() to log its return value once only */ ++int ++sshd_selinux_enabled(void) ++{ ++ static int enabled = -1; ++ ++ if (enabled == -1) { ++ enabled = (is_selinux_enabled() == 1); ++ debug("SELinux support %s", enabled ? "enabled" : "disabled"); ++ } ++ ++ return (enabled); ++} ++ + /* Send audit message */ + static int + sshd_selinux_send_audit_message(int success, security_context_t default_context, +@@ -318,7 +332,7 @@ sshd_selinux_getctxbyname(char *pwname, + + /* Setup environment variables for pam_selinux */ + static int +-sshd_selinux_setup_pam_variables(void) ++sshd_selinux_setup_variables(int(*set_it)(char *, const char *)) + { + const char *reqlvl; + char *role; +@@ -329,16 +343,16 @@ sshd_selinux_setup_pam_variables(void) + + ssh_selinux_get_role_level(&role, &reqlvl); + +- rv = do_pam_putenv("SELINUX_ROLE_REQUESTED", role ? role : ""); ++ rv = set_it("SELINUX_ROLE_REQUESTED", role ? role : ""); + + if (inetd_flag && !rexeced_flag) { + use_current = "1"; + } else { + use_current = ""; +- rv = rv || do_pam_putenv("SELINUX_LEVEL_REQUESTED", reqlvl ? reqlvl: ""); ++ rv = rv || set_it("SELINUX_LEVEL_REQUESTED", reqlvl ? reqlvl: ""); + } + +- rv = rv || do_pam_putenv("SELINUX_USE_CURRENT_RANGE", use_current); ++ rv = rv || set_it("SELINUX_USE_CURRENT_RANGE", use_current); + + if (role != NULL) + free(role); +@@ -346,6 +360,24 @@ sshd_selinux_setup_pam_variables(void) + return rv; + } + ++static int ++sshd_selinux_setup_pam_variables(void) ++{ ++ return sshd_selinux_setup_variables(do_pam_putenv); ++} ++ ++static int ++do_setenv(char *name, const char *value) ++{ ++ return setenv(name, value, 1); ++} ++ ++int ++sshd_selinux_setup_env_variables(void) ++{ ++ return sshd_selinux_setup_variables(do_setenv); ++} ++ + /* Set the execution context to the default for the specified user */ + void + sshd_selinux_setup_exec_context(char *pwname) +@@ -354,7 +386,7 @@ sshd_selinux_setup_exec_context(char *pw + int r = 0; + security_context_t default_ctx = NULL; + +- if (!ssh_selinux_enabled()) ++ if (!sshd_selinux_enabled()) + return; + + if (options.use_pam) { +@@ -421,7 +453,7 @@ sshd_selinux_copy_context(void) + { + security_context_t *ctx; + +- if (!ssh_selinux_enabled()) ++ if (!sshd_selinux_enabled()) + return; + + if (getexeccon((security_context_t *)&ctx) != 0) { +Index: openssh-9.3p2/platform.c +=================================================================== +--- openssh-9.3p2.orig/platform.c ++++ openssh-9.3p2/platform.c +@@ -100,7 +100,7 @@ platform_setusercontext(struct passwd *p + { + #ifdef WITH_SELINUX + /* Cache selinux status for later use */ +- (void)ssh_selinux_enabled(); ++ (void)sshd_selinux_enabled(); + #endif + + #ifdef USE_SOLARIS_PROJECTS +Index: openssh-9.3p2/ssh-keycat.c +=================================================================== +--- /dev/null ++++ openssh-9.3p2/ssh-keycat.c +@@ -0,0 +1,241 @@ ++/* ++ * 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, and the entire permission notice in its entirety, ++ * including the disclaimer of warranties. ++ * 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 name of the author may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * ALTERNATIVELY, this product may be distributed under the terms of ++ * the GNU Public License, in which case the provisions of the GPL are ++ * required INSTEAD OF the above restrictions. (This clause is ++ * necessary due to a potential bad interaction between the GPL and ++ * the restrictions contained in a BSD-style copyright.) ++ * ++ * THIS SOFTWARE IS PROVIDED ``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 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. ++ */ ++ ++/* ++ * Copyright (c) 2011 Red Hat, Inc. ++ * Written by Tomas Mraz ++*/ ++ ++#define _GNU_SOURCE ++ ++#include "config.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef HAVE_STDINT_H ++#include ++#endif ++ ++#include ++ ++#include "uidswap.h" ++#include "misc.h" ++ ++#define ERR_USAGE 1 ++#define ERR_PAM_START 2 ++#define ERR_OPEN_SESSION 3 ++#define ERR_CLOSE_SESSION 4 ++#define ERR_PAM_END 5 ++#define ERR_GETPWNAM 6 ++#define ERR_MEMORY 7 ++#define ERR_OPEN 8 ++#define ERR_FILE_MODE 9 ++#define ERR_FDOPEN 10 ++#define ERR_STAT 11 ++#define ERR_WRITE 12 ++#define ERR_PAM_PUTENV 13 ++#define BUFLEN 4096 ++ ++/* Just ignore the messages in the conversation function */ ++static int ++dummy_conv(int num_msg, const struct pam_message **msgm, ++ struct pam_response **response, void *appdata_ptr) ++{ ++ struct pam_response *rsp; ++ ++ (void)msgm; ++ (void)appdata_ptr; ++ ++ if (num_msg <= 0) ++ return PAM_CONV_ERR; ++ ++ /* Just allocate the array as empty responses */ ++ rsp = calloc (num_msg, sizeof (struct pam_response)); ++ if (rsp == NULL) ++ return PAM_CONV_ERR; ++ ++ *response = rsp; ++ return PAM_SUCCESS; ++} ++ ++static struct pam_conv conv = { ++ dummy_conv, ++ NULL ++}; ++ ++char * ++make_auth_keys_name(const struct passwd *pwd) ++{ ++ char *fname; ++ ++ if (asprintf(&fname, "%s/.ssh/authorized_keys", pwd->pw_dir) < 0) ++ return NULL; ++ ++ return fname; ++} ++ ++int ++dump_keys(const char *user) ++{ ++ struct passwd *pwd; ++ int fd = -1; ++ FILE *f = NULL; ++ char *fname = NULL; ++ int rv = 0; ++ char buf[BUFLEN]; ++ size_t len; ++ struct stat st; ++ ++ if ((pwd = getpwnam(user)) == NULL) { ++ return ERR_GETPWNAM; ++ } ++ ++ if ((fname = make_auth_keys_name(pwd)) == NULL) { ++ return ERR_MEMORY; ++ } ++ ++ temporarily_use_uid(pwd); ++ ++ if ((fd = open(fname, O_RDONLY|O_NONBLOCK|O_NOFOLLOW, 0)) < 0) { ++ rv = ERR_OPEN; ++ goto fail; ++ } ++ ++ if (fstat(fd, &st) < 0) { ++ rv = ERR_STAT; ++ goto fail; ++ } ++ ++ if (!S_ISREG(st.st_mode) || ++ (st.st_uid != pwd->pw_uid && st.st_uid != 0)) { ++ rv = ERR_FILE_MODE; ++ goto fail; ++ } ++ ++ unset_nonblock(fd); ++ ++ if ((f = fdopen(fd, "r")) == NULL) { ++ rv = ERR_FDOPEN; ++ goto fail; ++ } ++ ++ fd = -1; ++ ++ while ((len = fread(buf, 1, sizeof(buf), f)) > 0) { ++ rv = fwrite(buf, 1, len, stdout) != len ? ERR_WRITE : 0; ++ } ++ ++fail: ++ if (fd != -1) ++ close(fd); ++ if (f != NULL) ++ fclose(f); ++ free(fname); ++ restore_uid(); ++ return rv; ++} ++ ++static const char *env_names[] = { "SELINUX_ROLE_REQUESTED", ++ "SELINUX_LEVEL_REQUESTED", ++ "SELINUX_USE_CURRENT_RANGE" ++}; ++ ++extern char **environ; ++ ++int ++set_pam_environment(pam_handle_t *pamh) ++{ ++ int i; ++ size_t j; ++ ++ for (j = 0; j < sizeof(env_names)/sizeof(env_names[0]); ++j) { ++ int len = strlen(env_names[j]); ++ ++ for (i = 0; environ[i] != NULL; ++i) { ++ if (strncmp(env_names[j], environ[i], len) == 0 && ++ environ[i][len] == '=') { ++ if (pam_putenv(pamh, environ[i]) != PAM_SUCCESS) ++ return ERR_PAM_PUTENV; ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++int ++main(int argc, char *argv[]) ++{ ++ pam_handle_t *pamh = NULL; ++ int retval; ++ int ev = 0; ++ ++ if (argc != 2) { ++ fprintf(stderr, "Usage: %s \n", argv[0]); ++ return ERR_USAGE; ++ } ++ ++ retval = pam_start("ssh-keycat", argv[1], &conv, &pamh); ++ if (retval != PAM_SUCCESS) { ++ return ERR_PAM_START; ++ } ++ ++ ev = set_pam_environment(pamh); ++ if (ev != 0) ++ goto finish; ++ ++ retval = pam_open_session(pamh, PAM_SILENT); ++ if (retval != PAM_SUCCESS) { ++ ev = ERR_OPEN_SESSION; ++ goto finish; ++ } ++ ++ ev = dump_keys(argv[1]); ++ ++ retval = pam_close_session(pamh, PAM_SILENT); ++ if (retval != PAM_SUCCESS) { ++ ev = ERR_CLOSE_SESSION; ++ } ++ ++finish: ++ retval = pam_end (pamh,retval); ++ if (retval != PAM_SUCCESS) { ++ ev = ERR_PAM_END; ++ } ++ return ev; ++} +Index: openssh-9.3p2/configure.ac +=================================================================== +--- openssh-9.3p2.orig/configure.ac ++++ openssh-9.3p2/configure.ac +@@ -3632,6 +3632,7 @@ AC_ARG_WITH([pam], + PAM_MSG="yes" + + SSHDLIBS="$SSHDLIBS -lpam" ++ KEYCATLIBS="$KEYCATLIBS -lpam" + AC_DEFINE([USE_PAM], [1], + [Define if you want to enable PAM support]) + +@@ -3642,6 +3643,7 @@ AC_ARG_WITH([pam], + ;; + *) + SSHDLIBS="$SSHDLIBS -ldl" ++ KEYCATLIBS="$KEYCATLIBS -ldl" + ;; + esac + fi +@@ -4875,6 +4877,7 @@ AC_ARG_WITH([selinux], + fi ] + ) + AC_SUBST([SSHDLIBS]) ++AC_SUBST([KEYCATLIBS]) + + # Check whether user wants Kerberos 5 support + KRB5_MSG="no" +@@ -5905,6 +5908,9 @@ fi + if test ! -z "${SSHDLIBS}"; then + echo " +for sshd: ${SSHDLIBS}" + fi ++if test ! -z "${KEYCATLIBS}"; then ++echo " +for ssh-keycat: ${KEYCATLIBS}" ++fi + + echo "" + diff --git a/openssh-6.6p1-privsep-selinux.patch b/openssh-6.6p1-privsep-selinux.patch new file mode 100644 index 0000000..c3b6268 --- /dev/null +++ b/openssh-6.6p1-privsep-selinux.patch @@ -0,0 +1,125 @@ +Index: openssh-9.3p2/openbsd-compat/port-linux.h +=================================================================== +--- openssh-9.3p2.orig/openbsd-compat/port-linux.h ++++ openssh-9.3p2/openbsd-compat/port-linux.h +@@ -23,6 +23,7 @@ void ssh_selinux_setup_pty(char *, const + void ssh_selinux_change_context(const char *); + void ssh_selinux_setfscreatecon(const char *); + ++void sshd_selinux_copy_context(void); + void sshd_selinux_setup_exec_context(char *); + #endif + +Index: openssh-9.3p2/openbsd-compat/port-linux-sshd.c +=================================================================== +--- openssh-9.3p2.orig/openbsd-compat/port-linux-sshd.c ++++ openssh-9.3p2/openbsd-compat/port-linux-sshd.c +@@ -416,6 +416,28 @@ sshd_selinux_setup_exec_context(char *pw + debug3_f("done"); + } + ++void ++sshd_selinux_copy_context(void) ++{ ++ security_context_t *ctx; ++ ++ if (!ssh_selinux_enabled()) ++ return; ++ ++ if (getexeccon((security_context_t *)&ctx) != 0) { ++ logit_f("getexeccon failed with %s", strerror(errno)); ++ return; ++ } ++ if (ctx != NULL) { ++ /* unset exec context before we will lose this capabililty */ ++ if (setexeccon(NULL) != 0) ++ fatal_f("setexeccon failed with %s", strerror(errno)); ++ if (setcon(ctx) != 0) ++ fatal_f("setcon failed with %s", strerror(errno)); ++ freecon(ctx); ++ } ++} ++ + #endif + #endif + +Index: openssh-9.3p2/session.c +=================================================================== +--- openssh-9.3p2.orig/session.c ++++ openssh-9.3p2/session.c +@@ -1403,7 +1403,7 @@ do_setusercontext(struct passwd *pw) + + platform_setusercontext(pw); + +- if (platform_privileged_uidswap()) { ++ if (platform_privileged_uidswap() && (!is_child || !use_privsep)) { + #ifdef HAVE_LOGIN_CAP + if (setusercontext(lc, pw, pw->pw_uid, + (LOGIN_SETALL & ~(LOGIN_SETPATH|LOGIN_SETUSER))) < 0) { +@@ -1435,6 +1435,9 @@ do_setusercontext(struct passwd *pw) + (unsigned long long)pw->pw_uid); + chroot_path = percent_expand(tmp, "h", pw->pw_dir, + "u", pw->pw_name, "U", uidstr, (char *)NULL); ++#ifdef WITH_SELINUX ++ sshd_selinux_copy_context(); ++#endif + safely_chroot(chroot_path, pw->pw_uid); + free(tmp); + free(chroot_path); +@@ -1470,6 +1473,11 @@ do_setusercontext(struct passwd *pw) + /* Permanently switch to the desired uid. */ + permanently_set_uid(pw); + #endif ++ ++#ifdef WITH_SELINUX ++ if (in_chroot == 0) ++ sshd_selinux_copy_context(); ++#endif + } else if (options.chroot_directory != NULL && + strcasecmp(options.chroot_directory, "none") != 0) { + fatal("server lacks privileges to chroot to ChrootDirectory"); +@@ -1487,9 +1495,6 @@ do_pwchange(Session *s) + if (s->ttyfd != -1) { + fprintf(stderr, + "You must change your password now and login again!\n"); +-#ifdef WITH_SELINUX +- setexeccon(NULL); +-#endif + #ifdef PASSWD_NEEDS_USERNAME + execl(_PATH_PASSWD_PROG, "passwd", s->pw->pw_name, + (char *)NULL); +@@ -1723,9 +1728,6 @@ do_child(struct ssh *ssh, Session *s, co + argv[i] = NULL; + optind = optreset = 1; + __progname = argv[0]; +-#ifdef WITH_SELINUX +- ssh_selinux_change_context("sftpd_t"); +-#endif + exit(sftp_server_main(i, argv, s->pw)); + } + +Index: openssh-9.3p2/sshd.c +=================================================================== +--- openssh-9.3p2.orig/sshd.c ++++ openssh-9.3p2/sshd.c +@@ -510,6 +510,10 @@ privsep_preauth_child(struct ssh *ssh) + /* Demote the private keys to public keys. */ + demote_sensitive_data(ssh); + ++#ifdef WITH_SELINUX ++ ssh_selinux_change_context("sshd_net_t"); ++#endif ++ + /* Demote the child */ + if (privsep_chroot) { + /* Change our root directory */ +@@ -602,6 +606,9 @@ privsep_postauth(struct ssh *ssh, Authct + { + #ifdef DISABLE_FD_PASSING + if (1) { ++#elif defined(WITH_SELINUX) ++ if (0) { ++ /* even root user can be confined by SELinux */ + #else + if (authctxt->pw->pw_uid == 0) { + #endif diff --git a/openssh-7.6p1-cleanup-selinux.patch b/openssh-7.6p1-cleanup-selinux.patch new file mode 100644 index 0000000..5cf0e8f --- /dev/null +++ b/openssh-7.6p1-cleanup-selinux.patch @@ -0,0 +1,291 @@ +Index: openssh-9.3p2/auth2-pubkey.c +=================================================================== +--- openssh-9.3p2.orig/auth2-pubkey.c ++++ openssh-9.3p2/auth2-pubkey.c +@@ -72,6 +72,9 @@ + + /* import */ + extern ServerOptions options; ++extern int inetd_flag; ++extern int rexeced_flag; ++extern Authctxt *the_authctxt; + + static char * + format_key(const struct sshkey *key) +@@ -459,7 +462,8 @@ match_principals_command(struct passwd * + if ((pid = subprocess("AuthorizedPrincipalsCommand", command, + ac, av, &f, + SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD, +- runas_pw, temporarily_use_uid, restore_uid)) == 0) ++ runas_pw, temporarily_use_uid, restore_uid, ++ (inetd_flag && !rexeced_flag), the_authctxt)) == 0) + goto out; + + uid_swapped = 1; +@@ -727,7 +731,8 @@ user_key_command_allowed2(struct passwd + if ((pid = subprocess("AuthorizedKeysCommand", command, + ac, av, &f, + SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD, +- runas_pw, temporarily_use_uid, restore_uid)) == 0) ++ runas_pw, temporarily_use_uid, restore_uid, ++ (inetd_flag && !rexeced_flag), the_authctxt)) == 0) + goto out; + + uid_swapped = 1; +Index: openssh-9.3p2/misc.c +=================================================================== +--- openssh-9.3p2.orig/misc.c ++++ openssh-9.3p2/misc.c +@@ -2637,7 +2637,8 @@ stdfd_devnull(int do_stdin, int do_stdou + pid_t + subprocess(const char *tag, const char *command, + int ac, char **av, FILE **child, u_int flags, +- struct passwd *pw, privdrop_fn *drop_privs, privrestore_fn *restore_privs) ++ struct passwd *pw, privdrop_fn *drop_privs, ++ privrestore_fn *restore_privs, int inetd, void *the_authctxt) + { + FILE *f = NULL; + struct stat st; +@@ -2771,7 +2772,7 @@ subprocess(const char *tag, const char * + _exit(1); + } + #ifdef WITH_SELINUX +- if (sshd_selinux_setup_env_variables() < 0) { ++ if (sshd_selinux_setup_env_variables(inetd, the_authctxt) < 0) { + error ("failed to copy environment: %s", + strerror(errno)); + _exit(127); +Index: openssh-9.3p2/misc.h +=================================================================== +--- openssh-9.3p2.orig/misc.h ++++ openssh-9.3p2/misc.h +@@ -110,7 +110,7 @@ typedef void privrestore_fn(void); + #define SSH_SUBPROCESS_UNSAFE_PATH (1<<3) /* Don't check for safe cmd */ + #define SSH_SUBPROCESS_PRESERVE_ENV (1<<4) /* Keep parent environment */ + pid_t subprocess(const char *, const char *, int, char **, FILE **, u_int, +- struct passwd *, privdrop_fn *, privrestore_fn *); ++ struct passwd *, privdrop_fn *, privrestore_fn *, int, void *); + + typedef struct arglist arglist; + struct arglist { +Index: openssh-9.3p2/openbsd-compat/port-linux.h +=================================================================== +--- openssh-9.3p2.orig/openbsd-compat/port-linux.h ++++ openssh-9.3p2/openbsd-compat/port-linux.h +@@ -25,8 +25,8 @@ void ssh_selinux_setfscreatecon(const ch + + int sshd_selinux_enabled(void); + void sshd_selinux_copy_context(void); +-void sshd_selinux_setup_exec_context(char *); +-int sshd_selinux_setup_env_variables(void); ++void sshd_selinux_setup_exec_context(char *, int, int(char *, const char *), void *, int); ++int sshd_selinux_setup_env_variables(int inetd, void *); + void sshd_selinux_change_privsep_preauth_context(void); + #endif + +Index: openssh-9.3p2/openbsd-compat/port-linux-sshd.c +=================================================================== +--- openssh-9.3p2.orig/openbsd-compat/port-linux-sshd.c ++++ openssh-9.3p2/openbsd-compat/port-linux-sshd.c +@@ -49,11 +49,6 @@ + #include + #endif + +-extern ServerOptions options; +-extern Authctxt *the_authctxt; +-extern int inetd_flag; +-extern int rexeced_flag; +- + /* Wrapper around is_selinux_enabled() to log its return value once only */ + int + sshd_selinux_enabled(void) +@@ -223,7 +218,8 @@ get_user_context(const char *sename, con + } + + static void +-ssh_selinux_get_role_level(char **role, const char **level) ++ssh_selinux_get_role_level(char **role, const char **level, ++ Authctxt *the_authctxt) + { + *role = NULL; + *level = NULL; +@@ -241,8 +237,8 @@ ssh_selinux_get_role_level(char **role, + + /* Return the default security context for the given username */ + static int +-sshd_selinux_getctxbyname(char *pwname, +- security_context_t *default_sc, security_context_t *user_sc) ++sshd_selinux_getctxbyname(char *pwname, security_context_t *default_sc, ++ security_context_t *user_sc, int inetd, Authctxt *the_authctxt) + { + char *sename, *lvl; + char *role; +@@ -250,7 +246,7 @@ sshd_selinux_getctxbyname(char *pwname, + int r = 0; + context_t con = NULL; + +- ssh_selinux_get_role_level(&role, &reqlvl); ++ ssh_selinux_get_role_level(&role, &reqlvl, the_authctxt); + + #ifdef HAVE_GETSEUSERBYNAME + if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) { +@@ -272,7 +268,7 @@ sshd_selinux_getctxbyname(char *pwname, + + if (r == 0) { + /* If launched from xinetd, we must use current level */ +- if (inetd_flag && !rexeced_flag) { ++ if (inetd) { + security_context_t sshdsc=NULL; + + if (getcon_raw(&sshdsc) < 0) +@@ -333,7 +329,8 @@ sshd_selinux_getctxbyname(char *pwname, + + /* Setup environment variables for pam_selinux */ + static int +-sshd_selinux_setup_variables(int(*set_it)(char *, const char *)) ++sshd_selinux_setup_variables(int(*set_it)(char *, const char *), int inetd, ++ Authctxt *the_authctxt) + { + const char *reqlvl; + char *role; +@@ -342,11 +339,11 @@ sshd_selinux_setup_variables(int(*set_it + + debug3_f("setting execution context"); + +- ssh_selinux_get_role_level(&role, &reqlvl); ++ ssh_selinux_get_role_level(&role, &reqlvl, the_authctxt); + + rv = set_it("SELINUX_ROLE_REQUESTED", role ? role : ""); + +- if (inetd_flag && !rexeced_flag) { ++ if (inetd) { + use_current = "1"; + } else { + use_current = ""; +@@ -362,9 +359,10 @@ sshd_selinux_setup_variables(int(*set_it + } + + static int +-sshd_selinux_setup_pam_variables(void) ++sshd_selinux_setup_pam_variables(int inetd, ++ int(pam_setenv)(char *, const char *), Authctxt *the_authctxt) + { +- return sshd_selinux_setup_variables(do_pam_putenv); ++ return sshd_selinux_setup_variables(pam_setenv, inetd, the_authctxt); + } + + static int +@@ -374,25 +372,28 @@ do_setenv(char *name, const char *value) + } + + int +-sshd_selinux_setup_env_variables(void) ++sshd_selinux_setup_env_variables(int inetd, void *the_authctxt) + { +- return sshd_selinux_setup_variables(do_setenv); ++ Authctxt *authctxt = (Authctxt *) the_authctxt; ++ return sshd_selinux_setup_variables(do_setenv, inetd, authctxt); + } + + /* Set the execution context to the default for the specified user */ + void +-sshd_selinux_setup_exec_context(char *pwname) ++sshd_selinux_setup_exec_context(char *pwname, int inetd, ++ int(pam_setenv)(char *, const char *), void *the_authctxt, int use_pam) + { + security_context_t user_ctx = NULL; + int r = 0; + security_context_t default_ctx = NULL; ++ Authctxt *authctxt = (Authctxt *) the_authctxt; + + if (!sshd_selinux_enabled()) + return; + +- if (options.use_pam) { ++ if (use_pam) { + /* do not compute context, just setup environment for pam_selinux */ +- if (sshd_selinux_setup_pam_variables()) { ++ if (sshd_selinux_setup_pam_variables(inetd, pam_setenv, authctxt)) { + switch (security_getenforce()) { + case -1: + fatal_f("security_getenforce() failed"); +@@ -408,7 +409,7 @@ sshd_selinux_setup_exec_context(char *pw + + debug3_f("setting execution context"); + +- r = sshd_selinux_getctxbyname(pwname, &default_ctx, &user_ctx); ++ r = sshd_selinux_getctxbyname(pwname, &default_ctx, &user_ctx, inetd, authctxt); + if (r >= 0) { + r = setexeccon(user_ctx); + if (r < 0) { +Index: openssh-9.3p2/platform.c +=================================================================== +--- openssh-9.3p2.orig/platform.c ++++ openssh-9.3p2/platform.c +@@ -34,6 +34,9 @@ + + extern int use_privsep; + extern ServerOptions options; ++extern int inetd_flag; ++extern int rexeced_flag; ++extern Authctxt *the_authctxt; + + void + platform_pre_listen(void) +@@ -185,7 +188,9 @@ platform_setusercontext_post_groups(stru + } + #endif /* HAVE_SETPCRED */ + #ifdef WITH_SELINUX +- sshd_selinux_setup_exec_context(pw->pw_name); ++ sshd_selinux_setup_exec_context(pw->pw_name, ++ (inetd_flag && !rexeced_flag), do_pam_putenv, the_authctxt, ++ options.use_pam); + #endif + } + +Index: openssh-9.3p2/sshd.c +=================================================================== +--- openssh-9.3p2.orig/sshd.c ++++ openssh-9.3p2/sshd.c +@@ -166,7 +166,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; +@@ -179,7 +179,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; +@@ -2396,7 +2396,9 @@ main(int ac, char **av) + } + #endif + #ifdef WITH_SELINUX +- sshd_selinux_setup_exec_context(authctxt->pw->pw_name); ++ sshd_selinux_setup_exec_context(authctxt->pw->pw_name, ++ (inetd_flag && !rexeced_flag), do_pam_putenv, the_authctxt, ++ options.use_pam); + #endif + #ifdef USE_PAM + if (options.use_pam) { +Index: openssh-9.3p2/sshconnect.c +=================================================================== +--- openssh-9.3p2.orig/sshconnect.c ++++ openssh-9.3p2/sshconnect.c +@@ -893,7 +893,7 @@ load_hostkeys_command(struct hostkeys *h + + if ((pid = subprocess(tag, command, ac, av, &f, + SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_UNSAFE_PATH| +- SSH_SUBPROCESS_PRESERVE_ENV, NULL, NULL, NULL)) == 0) ++ SSH_SUBPROCESS_PRESERVE_ENV, NULL, NULL, NULL, 0, NULL)) == 0) + goto out; + + load_hostkeys_file(hostkeys, hostfile_hostname, tag, f, 1); diff --git a/openssh-7.7p1-IPv6_X_forwarding.patch b/openssh-7.7p1-IPv6_X_forwarding.patch new file mode 100644 index 0000000..a036a86 --- /dev/null +++ b/openssh-7.7p1-IPv6_X_forwarding.patch @@ -0,0 +1,38 @@ +# HG changeset patch +# Parent 8df645ca39d64de025d8838c5713812e72308c92 +Correctly parse DISPLAY variable for cases where it contains an IPv6 address +(which should - but not always is - in (square) brackets). + +bnc#847710 - https://bugzilla.novell.com/show_bug.cgi?id=847710 + +Index: openssh-8.8p1/channels.c +=================================================================== +--- openssh-8.8p1.orig/channels.c ++++ openssh-8.8p1/channels.c +@@ -4776,9 +4776,10 @@ x11_connect_display(struct ssh *ssh) + /* + * Connect to an inet socket. The DISPLAY value is supposedly + * hostname:d[.s], where hostname may also be numeric IP address. ++ * Note that IPv6 numeric addresses contain colons (e.g. ::1:0) + */ + strlcpy(buf, display, sizeof(buf)); +- cp = strchr(buf, ':'); ++ cp = strrchr(buf, ':'); + if (!cp) { + error("Could not find ':' in DISPLAY: %.100s", display); + return -1; +@@ -4793,6 +4794,14 @@ x11_connect_display(struct ssh *ssh) + display); + return -1; + } ++ ++ /* Remove brackets surrounding IPv6 addresses if there are any. */ ++ if (buf[0] == '[' && (cp = strchr(buf, ']'))) { ++ *cp = 0; ++ cp = buf + 1; ++ } else { ++ cp = buf; ++ } + + /* Look up the host address */ + memset(&hints, 0, sizeof(hints)); diff --git a/openssh-7.7p1-X11_trusted_forwarding.patch b/openssh-7.7p1-X11_trusted_forwarding.patch new file mode 100644 index 0000000..020a92a --- /dev/null +++ b/openssh-7.7p1-X11_trusted_forwarding.patch @@ -0,0 +1,47 @@ +# HG changeset patch +# Parent d25c96855fd67e997e25ec1198d953af33eb289c +# enable trusted X11 forwarding by default in both sshd and sshsystem-wide +# configuration +# bnc#50836 (was suse #35836) +Enable Trusted X11 forwarding by default, since the security benefits of +having it disabled are negligible these days with XI2 being widely used. + +Index: openssh-8.8p1/ssh_config +=================================================================== +--- openssh-8.8p1.orig/ssh_config ++++ openssh-8.8p1/ssh_config +@@ -17,9 +17,20 @@ + # list of available options, their meanings and defaults, please see the + # ssh_config(5) man page. + +-# Host * ++Host * + # ForwardAgent no + # ForwardX11 no ++ ++# If you do not trust your remote host (or its administrator), you ++# should not forward X11 connections to your local X11-display for ++# security reasons: Someone stealing the authentification data on the ++# remote side (the "spoofed" X-server by the remote sshd) can read your ++# keystrokes as you type, just like any other X11 client could do. ++# Set this to "no" here for global effect or in your own ~/.ssh/config ++# file if you want to have the remote X11 authentification data to ++# expire after twenty minutes after remote login. ++ ForwardX11Trusted yes ++ + # PasswordAuthentication yes + # HostbasedAuthentication no + # GSSAPIAuthentication no +Index: openssh-8.8p1/sshd_config +=================================================================== +--- openssh-8.8p1.orig/sshd_config ++++ openssh-8.8p1/sshd_config +@@ -84,7 +84,7 @@ AuthorizedKeysFile .ssh/authorized_keys + #AllowAgentForwarding yes + #AllowTcpForwarding yes + #GatewayPorts no +-#X11Forwarding no ++X11Forwarding yes + #X11DisplayOffset 10 + #X11UseLocalhost yes + #PermitTTY yes diff --git a/openssh-7.7p1-X_forward_with_disabled_ipv6.patch b/openssh-7.7p1-X_forward_with_disabled_ipv6.patch new file mode 100644 index 0000000..3e7118b --- /dev/null +++ b/openssh-7.7p1-X_forward_with_disabled_ipv6.patch @@ -0,0 +1,23 @@ +# HG changeset patch +# Parent 44592f09f090e74432f608084069d30d808fda69 +Do not throw away already open sockets for X11 forwarding if another socket +family is not available for bind() + +Index: openssh-8.8p1/channels.c +=================================================================== +--- openssh-8.8p1.orig/channels.c ++++ openssh-8.8p1/channels.c +@@ -4607,6 +4607,13 @@ x11_create_display_inet(struct ssh *ssh, + debug2_f("bind port %d: %.100s", 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; diff --git a/openssh-7.7p1-cavstest-ctr.patch b/openssh-7.7p1-cavstest-ctr.patch new file mode 100644 index 0000000..17b6672 --- /dev/null +++ b/openssh-7.7p1-cavstest-ctr.patch @@ -0,0 +1,304 @@ +# HG changeset patch +# Parent cc1022edba2c5eeb0facba08468f65afc2466b63 +CAVS test for OpenSSH's own CTR encryption mode implementation + +Index: openssh-8.8p1/Makefile.in +=================================================================== +--- openssh-8.8p1.orig/Makefile.in ++++ openssh-8.8p1/Makefile.in +@@ -26,6 +26,7 @@ SFTP_SERVER=$(libexecdir)/sftp-server + SSH_KEYSIGN=$(libexecdir)/ssh-keysign + SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper + SSH_SK_HELPER=$(libexecdir)/ssh-sk-helper ++CAVSTEST_CTR=$(libexecdir)/cavstest-ctr + PRIVSEP_PATH=@PRIVSEP_PATH@ + SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ + STRIP_OPT=@STRIP_OPT@ +@@ -69,6 +70,8 @@ MKDIR_P=@MKDIR_P@ + + TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT) + ++TARGETS += cavstest-ctr$(EXEEXT) ++ + XMSS_OBJS=\ + ssh-xmss.o \ + sshkey-xmss.o \ +@@ -245,6 +248,10 @@ sftp-server$(EXEEXT): $(LIBCOMPAT) libss + sftp$(EXEEXT): $(LIBCOMPAT) libssh.a $(SFTP_OBJS) + $(LD) -o $@ $(SFTP_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(LIBEDIT) + ++# FIPS tests ++cavstest-ctr$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-sk.o sk-usbhid.o cavstest-ctr.o ++ $(LD) -o $@ cavstest-ctr.o ssh-sk.o sk-usbhid.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) $(LIBFIDO2) ++ + # test driver for the loginrec code - not built by default + logintest: logintest.o $(LIBCOMPAT) libssh.a loginrec.o + $(LD) -o $@ logintest.o $(LDFLAGS) loginrec.o -lopenbsd-compat -lssh $(LIBS) +@@ -407,6 +414,7 @@ install-files: + $(INSTALL) -m 0755 $(STRIP_OPT) ssh-sk-helper$(EXEEXT) $(DESTDIR)$(SSH_SK_HELPER)$(EXEEXT) + $(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT) + $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) ++ $(INSTALL) -m 0755 $(STRIP_OPT) cavstest-ctr$(EXEEXT) $(DESTDIR)$(libexecdir)/cavstest-ctr$(EXEEXT) + $(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 + $(INSTALL) -m 644 scp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1 + $(INSTALL) -m 644 ssh-add.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1 +Index: openssh-8.8p1/cavstest-ctr.c +=================================================================== +--- /dev/null ++++ openssh-8.8p1/cavstest-ctr.c +@@ -0,0 +1,214 @@ ++/* ++ * ++ * invocation (all of the following are equal): ++ * ./ctr-cavstest --algo aes128-ctr --key 987212980144b6a632e864031f52dacc --mode encrypt --data a6deca405eef2e8e4609abf3c3ccf4a6 ++ * ./ctr-cavstest --algo aes128-ctr --key 987212980144b6a632e864031f52dacc --mode encrypt --data a6deca405eef2e8e4609abf3c3ccf4a6 --iv 00000000000000000000000000000000 ++ * echo -n a6deca405eef2e8e4609abf3c3ccf4a6 | ./ctr-cavstest --algo aes128-ctr --key 987212980144b6a632e864031f52dacc --mode encrypt ++ */ ++ ++#include "includes.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "xmalloc.h" ++#include "log.h" ++#include "cipher.h" ++ ++/* compatibility with old or broken OpenSSL versions */ ++#include "openbsd-compat/openssl-compat.h" ++ ++void ++usage(void) ++{ ++ fprintf(stderr, "Usage: ctr-cavstest --algo \n" ++ " --key --mode \n" ++ " [--iv ] --data \n\n" ++ "Hexadecimal output is printed to stdout.\n" ++ "Hexadecimal input data can be alternatively read from stdin.\n"); ++ exit(1); ++} ++ ++void * ++fromhex(char *hex, size_t * len) ++{ ++ unsigned char *bin; ++ char *p; ++ size_t n = 0; ++ int shift = 4; ++ unsigned char out = 0; ++ unsigned char *optr; ++ ++ bin = xmalloc(strlen(hex) / 2); ++ optr = bin; ++ ++ for (p = hex; *p != '\0'; ++p) { ++ unsigned char c; ++ ++ c = *p; ++ if (isspace(c)) ++ continue; ++ ++ if (c >= '0' && c <= '9') { ++ c = c - '0'; ++ } else if (c >= 'A' && c <= 'F') { ++ c = c - 'A' + 10; ++ } else if (c >= 'a' && c <= 'f') { ++ c = c - 'a' + 10; ++ } else { ++ /* truncate on nonhex cipher */ ++ break; ++ } ++ ++ out |= c << shift; ++ shift = (shift + 4) % 8; ++ ++ if (shift) { ++ *(optr++) = out; ++ out = 0; ++ ++n; ++ } ++ } ++ ++ *len = n; ++ return bin; ++} ++ ++#define READ_CHUNK 4096 ++#define MAX_READ_SIZE 1024*1024*100 ++char * ++read_stdin(void) ++{ ++ char *buf; ++ size_t n, total = 0; ++ ++ buf = xmalloc(READ_CHUNK); ++ ++ do { ++ n = fread(buf + total, 1, READ_CHUNK, stdin); ++ if (n < READ_CHUNK) /* terminate on short read */ ++ break; ++ ++ total += n; ++ buf = xreallocarray(buf, total + READ_CHUNK, 1); ++ } while (total < MAX_READ_SIZE); ++ return buf; ++} ++ ++int ++main(int argc, char *argv[]) ++{ ++ ++ struct sshcipher *c; ++ struct sshcipher_ctx cc; ++ struct sshcipher_ctx *ccp; ++ char *algo = "aes128-ctr"; ++ char *hexkey = NULL; ++ char *hexiv = "00000000000000000000000000000000"; ++ char *hexdata = NULL; ++ char *p; ++ int i; ++ int encrypt = 1; ++ void *key; ++ size_t keylen; ++ void *iv; ++ size_t ivlen; ++ void *data; ++ size_t datalen; ++ void *outdata; ++ ++ for (i = 1; i < argc; ++i) { ++ if (strcmp(argv[i], "--algo") == 0) { ++ algo = argv[++i]; ++ } else if (strcmp(argv[i], "--key") == 0) { ++ hexkey = argv[++i]; ++ } else if (strcmp(argv[i], "--mode") == 0) { ++ ++i; ++ if (argv[i] == NULL) { ++ usage(); ++ } ++ if (strncmp(argv[i], "enc", 3) == 0) { ++ encrypt = 1; ++ } else if (strncmp(argv[i], "dec", 3) == 0) { ++ encrypt = 0; ++ } else { ++ usage(); ++ } ++ } else if (strcmp(argv[i], "--iv") == 0) { ++ hexiv = argv[++i]; ++ } else if (strcmp(argv[i], "--data") == 0) { ++ hexdata = argv[++i]; ++ } ++ } ++ ++ if (hexkey == NULL || algo == NULL) { ++ usage(); ++ } ++ ++ OpenSSL_add_all_algorithms(); ++ ++ c = cipher_by_name(algo); ++ if (c == NULL) { ++ fprintf(stderr, "Error: unknown algorithm\n"); ++ return 2; ++ } ++ ++ if (hexdata == NULL) { ++ hexdata = read_stdin(); ++ } else { ++ hexdata = xstrdup(hexdata); ++ } ++ ++ key = fromhex(hexkey, &keylen); ++ ++ if (keylen != 16 && keylen != 24 && keylen == 32) { ++ fprintf(stderr, "Error: unsupported key length\n"); ++ return 2; ++ } ++ ++ iv = fromhex(hexiv, &ivlen); ++ ++ if (ivlen != 16) { ++ fprintf(stderr, "Error: unsupported iv length\n"); ++ return 2; ++ } ++ ++ data = fromhex(hexdata, &datalen); ++ ++ if (data == NULL || datalen == 0) { ++ fprintf(stderr, "Error: no data to encrypt/decrypt\n"); ++ return 2; ++ } ++ ++ ccp = &cc; ++ cipher_init(&ccp, c, key, keylen, iv, ivlen, encrypt); ++ ++ free(key); ++ free(iv); ++ ++ outdata = malloc(datalen); ++ if (outdata == NULL) { ++ fprintf(stderr, "Error: memory allocation failure\n"); ++ return 2; ++ } ++ ++ cipher_crypt(&cc, 0, outdata, data, datalen, 0, 0); ++ ++ free(data); ++ ++ cipher_free(&cc); ++ ++ for (p = outdata; datalen > 0; ++p, --datalen) { ++ printf("%02X", (unsigned char) *p); ++ } ++ ++ free(outdata); ++ ++ printf("\n"); ++ return 0; ++} +Index: openssh-8.8p1/cipher.c +=================================================================== +--- openssh-8.8p1.orig/cipher.c ++++ openssh-8.8p1/cipher.c +@@ -58,15 +58,6 @@ + #define EVP_CIPHER_CTX void + #endif + +-struct sshcipher_ctx { +- int plaintext; +- int encrypt; +- EVP_CIPHER_CTX *evp; +- struct chachapoly_ctx *cp_ctx; +- struct aesctr_ctx ac_ctx; /* XXX union with evp? */ +- const struct sshcipher *cipher; +-}; +- + struct sshcipher { + char *name; + u_int block_size; +Index: openssh-8.8p1/cipher.h +=================================================================== +--- openssh-8.8p1.orig/cipher.h ++++ openssh-8.8p1/cipher.h +@@ -48,7 +48,15 @@ + #define CIPHER_DECRYPT 0 + + struct sshcipher; +-struct sshcipher_ctx; ++struct sshcipher_ctx { ++ int plaintext; ++ int encrypt; ++ EVP_CIPHER_CTX *evp; ++ struct chachapoly_ctx *cp_ctx; /* XXX union with evp? */ ++ struct aesctr_ctx ac_ctx; /* XXX union with evp? */ ++ const struct sshcipher *cipher; ++}; ++ + + const struct sshcipher *cipher_by_name(const char *); + const char *cipher_warning_message(const struct sshcipher_ctx *); diff --git a/openssh-7.7p1-cavstest-kdf.patch b/openssh-7.7p1-cavstest-kdf.patch new file mode 100644 index 0000000..bc5763e --- /dev/null +++ b/openssh-7.7p1-cavstest-kdf.patch @@ -0,0 +1,450 @@ +# HG changeset patch +# Parent 1e1d5a2ab8bddfc800f570755f9ea1addcc878c1 +CAVS test for KDF implementation in OpenSSH + +Index: openssh-8.8p1/Makefile.in +=================================================================== +--- openssh-8.8p1.orig/Makefile.in ++++ openssh-8.8p1/Makefile.in +@@ -27,6 +27,7 @@ SSH_KEYSIGN=$(libexecdir)/ssh-keysign + SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper + SSH_SK_HELPER=$(libexecdir)/ssh-sk-helper + CAVSTEST_CTR=$(libexecdir)/cavstest-ctr ++CAVSTEST_KDF=$(libexecdir)/cavstest-kdf + PRIVSEP_PATH=@PRIVSEP_PATH@ + SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ + STRIP_OPT=@STRIP_OPT@ +@@ -70,7 +71,7 @@ MKDIR_P=@MKDIR_P@ + + TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT) + +-TARGETS += cavstest-ctr$(EXEEXT) ++TARGETS += cavstest-ctr$(EXEEXT) cavstest-kdf$(EXEEXT) + + XMSS_OBJS=\ + ssh-xmss.o \ +@@ -252,6 +253,9 @@ sftp$(EXEEXT): $(LIBCOMPAT) libssh.a $(S + cavstest-ctr$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-sk.o sk-usbhid.o cavstest-ctr.o + $(LD) -o $@ cavstest-ctr.o ssh-sk.o sk-usbhid.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) $(LIBFIDO2) + ++cavstest-kdf$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-sk.o sk-usbhid.o cavstest-kdf.o ++ $(LD) -o $@ cavstest-kdf.o ssh-sk.o sk-usbhid.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) $(LIBFIDO2) ++ + # test driver for the loginrec code - not built by default + logintest: logintest.o $(LIBCOMPAT) libssh.a loginrec.o + $(LD) -o $@ logintest.o $(LDFLAGS) loginrec.o -lopenbsd-compat -lssh $(LIBS) +@@ -415,6 +419,7 @@ install-files: + $(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT) + $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) + $(INSTALL) -m 0755 $(STRIP_OPT) cavstest-ctr$(EXEEXT) $(DESTDIR)$(libexecdir)/cavstest-ctr$(EXEEXT) ++ $(INSTALL) -m 0755 $(STRIP_OPT) cavstest-kdf$(EXEEXT) $(DESTDIR)$(libexecdir)/cavstest-kdf$(EXEEXT) + $(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 + $(INSTALL) -m 644 scp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1 + $(INSTALL) -m 644 ssh-add.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1 +Index: openssh-8.8p1/cavstest-kdf.c +=================================================================== +--- /dev/null ++++ openssh-8.8p1/cavstest-kdf.c +@@ -0,0 +1,402 @@ ++/* ++ * Copyright (C) 2015, Stephan Mueller ++ * ++ * 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, and the entire permission notice in its entirety, ++ * including the disclaimer of warranties. ++ * 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 name of the author may not be used to endorse or promote ++ * products derived from this software without specific prior ++ * written permission. ++ * ++ * ALTERNATIVELY, this product may be distributed under the terms of ++ * the GNU General Public License, in which case the provisions of the GPL2 ++ * are required INSTEAD OF the above restrictions. (This clause is ++ * necessary due to a potential bad interaction between the GPL and ++ * the restrictions contained in a BSD-style copyright.) ++ * ++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED ++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF ++ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 NOT ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ */ ++ ++#include "includes.h" ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "xmalloc.h" ++#include "ssherr.h" ++#include "sshbuf.h" ++#include "sshkey.h" ++#include "cipher.h" ++#include "kex.h" ++#include "packet.h" ++ ++static int bin_char(unsigned char hex) ++{ ++ if (48 <= hex && 57 >= hex) ++ return (hex - 48); ++ if (65 <= hex && 70 >= hex) ++ return (hex - 55); ++ if (97 <= hex && 102 >= hex) ++ return (hex - 87); ++ return 0; ++} ++ ++/* ++ * Convert hex representation into binary string ++ * @hex input buffer with hex representation ++ * @hexlen length of hex ++ * @bin output buffer with binary data ++ * @binlen length of already allocated bin buffer (should be at least ++ * half of hexlen -- if not, only a fraction of hexlen is converted) ++ */ ++static void hex2bin(const char *hex, size_t hexlen, ++ unsigned char *bin, size_t binlen) ++{ ++ size_t i = 0; ++ size_t chars = (binlen > (hexlen / 2)) ? (hexlen / 2) : binlen; ++ ++ for (i = 0; i < chars; i++) { ++ bin[i] = bin_char(hex[(i*2)]) << 4; ++ bin[i] |= bin_char(hex[((i*2)+1)]); ++ } ++} ++ ++/* ++ * Allocate sufficient space for binary representation of hex ++ * and convert hex into bin ++ * ++ * Caller must free bin ++ * @hex input buffer with hex representation ++ * @hexlen length of hex ++ * @bin return value holding the pointer to the newly allocated buffer ++ * @binlen return value holding the allocated size of bin ++ * ++ * return: 0 on success, !0 otherwise ++ */ ++static int hex2bin_alloc(const char *hex, size_t hexlen, ++ unsigned char **bin, size_t *binlen) ++{ ++ unsigned char *out = NULL; ++ size_t outlen = 0; ++ ++ if (!hexlen) ++ return -EINVAL; ++ ++ outlen = (hexlen + 1) / 2; ++ ++ out = calloc(1, outlen); ++ if (!out) ++ return -errno; ++ ++ hex2bin(hex, hexlen, out, outlen); ++ *bin = out; ++ *binlen = outlen; ++ return 0; ++} ++ ++static char hex_char_map_l[] = { '0', '1', '2', '3', '4', '5', '6', '7', ++ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; ++static char hex_char_map_u[] = { '0', '1', '2', '3', '4', '5', '6', '7', ++ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; ++static char hex_char(unsigned int bin, int u) ++{ ++ if (bin < sizeof(hex_char_map_l)) ++ return (u) ? hex_char_map_u[bin] : hex_char_map_l[bin]; ++ return 'X'; ++} ++ ++/* ++ * Convert binary string into hex representation ++ * @bin input buffer with binary data ++ * @binlen length of bin ++ * @hex output buffer to store hex data ++ * @hexlen length of already allocated hex buffer (should be at least ++ * twice binlen -- if not, only a fraction of binlen is converted) ++ * @u case of hex characters (0=>lower case, 1=>upper case) ++ */ ++static void bin2hex(const unsigned char *bin, size_t binlen, ++ char *hex, size_t hexlen, int u) ++{ ++ size_t i = 0; ++ size_t chars = (binlen > (hexlen / 2)) ? (hexlen / 2) : binlen; ++ ++ for (i = 0; i < chars; i++) { ++ hex[(i*2)] = hex_char((bin[i] >> 4), u); ++ hex[((i*2)+1)] = hex_char((bin[i] & 0x0f), u); ++ } ++} ++ ++struct kdf_cavs { ++ unsigned char *K; ++ size_t Klen; ++ unsigned char *H; ++ size_t Hlen; ++ unsigned char *session_id; ++ size_t session_id_len; ++ ++ unsigned int iv_len; ++ unsigned int ek_len; ++ unsigned int ik_len; ++}; ++ ++#ifdef WITH_OPENSSL ++static int ++kex_derive_keys_bn(struct ssh *ssh, u_char *hash, u_int hashlen, ++ const BIGNUM *secret) ++{ ++ struct sshbuf *shared_secret; ++ int r; ++ ++ if ((shared_secret = sshbuf_new()) == NULL) ++ return SSH_ERR_ALLOC_FAIL; ++ if ((r = sshbuf_put_bignum2(shared_secret, secret)) == 0) ++ r = kex_derive_keys(ssh, hash, hashlen, shared_secret); ++ sshbuf_free(shared_secret); ++ return r; ++} ++#endif ++ ++static int sshkdf_cavs(struct kdf_cavs *test) ++{ ++ int ret = 0; ++ struct kex kex; ++ BIGNUM *Kbn = NULL; ++ int mode = 0; ++ struct newkeys *keys_client; ++ struct newkeys *keys_server; ++ struct ssh *ssh = NULL; ++ ++#define HEXOUTLEN 500 ++ char hex[HEXOUTLEN]; ++ ++ memset(&kex, 0, sizeof(struct kex)); ++ ++ Kbn = BN_new(); ++ BN_bin2bn(test->K, test->Klen, Kbn); ++ if (!Kbn) { ++ printf("cannot convert K into BIGNUM\n"); ++ ret = 1; ++ goto out; ++ } ++ ++ kex.session_id = sshbuf_new(); ++ sshbuf_put(kex.session_id, test->session_id, test->session_id_len); ++ ++ /* setup kex */ ++ ++ /* select the right hash based on struct ssh_digest digests */ ++ switch (test->ik_len) { ++ case 20: ++ kex.hash_alg = 2; ++ break; ++ case 32: ++ kex.hash_alg = 3; ++ break; ++ case 48: ++ kex.hash_alg = 4; ++ break; ++ case 64: ++ kex.hash_alg = 5; ++ break; ++ default: ++ printf("Wrong hash type %u\n", test->ik_len); ++ ret = 1; ++ goto out; ++ } ++ ++ /* implement choose_enc */ ++ for (mode = 0; mode < 2; mode++) { ++ kex.newkeys[mode] = calloc(1, sizeof(struct newkeys)); ++ if (!kex.newkeys[mode]) { ++ printf("allocation of newkeys failed\n"); ++ ret = 1; ++ goto out; ++ } ++ kex.newkeys[mode]->enc.iv_len = test->iv_len; ++ kex.newkeys[mode]->enc.key_len = test->ek_len; ++ kex.newkeys[mode]->enc.block_size = (test->iv_len == 64) ? 8 : 16; ++ kex.newkeys[mode]->mac.key_len = test->ik_len; ++ } ++ ++ /* implement kex_choose_conf */ ++ kex.we_need = kex.newkeys[0]->enc.key_len; ++ if (kex.we_need < kex.newkeys[0]->enc.block_size) ++ kex.we_need = kex.newkeys[0]->enc.block_size; ++ if (kex.we_need < kex.newkeys[0]->enc.iv_len) ++ kex.we_need = kex.newkeys[0]->enc.iv_len; ++ if (kex.we_need < kex.newkeys[0]->mac.key_len) ++ kex.we_need = kex.newkeys[0]->mac.key_len; ++ ++ /* MODE_OUT (1) -> server to client ++ * MODE_IN (0) -> client to server */ ++ kex.server = 1; ++ ++ /* do it */ ++ if ((ssh = ssh_packet_set_connection(NULL, -1, -1)) == NULL){ ++ printf("Allocation error\n"); ++ goto out; ++ } ++ ssh->kex = &kex; ++ kex_derive_keys_bn(ssh, test->H, test->Hlen, Kbn); ++ ++ keys_client = kex.newkeys[0]; ++ keys_server = kex.newkeys[1]; ++ ++ /* get data */ ++ memset(hex, 0, HEXOUTLEN); ++ bin2hex(keys_client->enc.iv, (size_t)keys_client->enc.iv_len, ++ hex, HEXOUTLEN, 0); ++ printf("Initial IV (client to server) = %s\n", hex); ++ ++ memset(hex, 0, HEXOUTLEN); ++ bin2hex(keys_server->enc.iv, (size_t)keys_server->enc.iv_len, ++ hex, HEXOUTLEN, 0); ++ printf("Initial IV (server to client) = %s\n", hex); ++ ++ memset(hex, 0, HEXOUTLEN); ++ bin2hex(keys_client->enc.key, (size_t)keys_client->enc.key_len, ++ hex, HEXOUTLEN, 0); ++ printf("Encryption key (client to server) = %s\n", hex); ++ ++ memset(hex, 0, HEXOUTLEN); ++ bin2hex(keys_server->enc.key, (size_t)keys_server->enc.key_len, ++ hex, HEXOUTLEN, 0); ++ printf("Encryption key (server to client) = %s\n", hex); ++ ++ memset(hex, 0, HEXOUTLEN); ++ bin2hex(keys_client->mac.key, (size_t)keys_client->mac.key_len, ++ hex, HEXOUTLEN, 0); ++ printf("Integrity key (client to server) = %s\n", hex); ++ ++ memset(hex, 0, HEXOUTLEN); ++ bin2hex(keys_server->mac.key, (size_t)keys_server->mac.key_len, ++ hex, HEXOUTLEN, 0); ++ printf("Integrity key (server to client) = %s\n", hex); ++ ++out: ++ if (Kbn) ++ BN_free(Kbn); ++ if (ssh) ++ ssh_packet_close(ssh); ++ if (kex.newkeys[0]) ++ free(kex.newkeys[0]); ++ if (kex.newkeys[1]) ++ free(kex.newkeys[1]); ++ return ret; ++} ++ ++static void usage(void) ++{ ++ fprintf(stderr, "\nOpenSSH KDF CAVS Test\n\n"); ++ fprintf(stderr, "Usage:\n"); ++ fprintf(stderr, "\t-K\tShared secret string\n"); ++ fprintf(stderr, "\t-H\tHash string\n"); ++ fprintf(stderr, "\t-s\tSession ID string\n"); ++ fprintf(stderr, "\t-i\tIV length to be generated\n"); ++ fprintf(stderr, "\t-e\tEncryption key length to be generated\n"); ++ fprintf(stderr, "\t-m\tMAC key length to be generated\n"); ++} ++ ++/* ++ * Test command example: ++ * ./ssh-cavs -K 0055d50f2d163cc07cd8a93cc7c3430c30ce786b572c01ad29fec7597000cf8618d664e2ec3dcbc8bb7a1a7eb7ef67f61cdaf291625da879186ac0a5cb27af571b59612d6a6e0627344d846271959fda61c78354aa498773d59762f8ca2d0215ec590d8633de921f920d41e47b3de6ab9a3d0869e1c826d0e4adebf8e3fb646a15dea20a410b44e969f4b791ed6a67f13f1b74234004d5fa5e87eff7abc32d49bbdf44d7b0107e8f10609233b7e2b7eff74a4daf25641de7553975dac6ac1e5117df6f6dbaa1c263d23a6c3e5a3d7d49ae8a828c1e333ac3f85fbbf57b5c1a45be45e43a7be1a4707eac779b8285522d1f531fe23f890fd38a004339932b93eda4 -H d3ab91a850febb417a25d892ec48ed5952c7a5de -s d3ab91a850febb417a25d892ec48ed5952c7a5de -i 8 -e 24 -m 20 ++ * ++ * Expected result for example: ++ * Initial IV (client to server) = 4bb320d1679dfd3a ++ * Encryption key (client to server) = 13048cc600b9d3cf9095aa6cf8e2ff9cf1c54ca0520c89ed ++ * Integrity key (client to server) = ecef63a092b0dcc585bdc757e01b2740af57d640 ++ * Initial IV (server to client) = 43dea6fdf263a308 ++ * Encryption key (server to client) = 1e483c5134e901aa11fc4e0a524e7ec7b75556148a222bb0 ++ * Integrity key (server to client) = 7424b05f3c44a72b4ebd281fb71f9cbe7b64d479 ++ */ ++int main(int argc, char *argv[]) ++{ ++ struct kdf_cavs test; ++ int ret = 1; ++ int opt = 0; ++ ++ memset(&test, 0, sizeof(struct kdf_cavs)); ++ while((opt = getopt(argc, argv, "K:H:s:i:e:m:")) != -1) ++ { ++ size_t len = 0; ++ switch(opt) ++ { ++ /* ++ * CAVS K is MPINT ++ * we want a hex (i.e. the caller must ensure the ++ * following transformations already happened): ++ * 1. cut off first four bytes ++ * 2. if most significant bit of value is ++ * 1, prepend 0 byte ++ */ ++ case 'K': ++ len = strlen(optarg); ++ ret = hex2bin_alloc(optarg, len, ++ &test.K, &test.Klen); ++ if (ret) ++ goto out; ++ break; ++ case 'H': ++ len = strlen(optarg); ++ ret = hex2bin_alloc(optarg, len, ++ &test.H, &test.Hlen); ++ if (ret) ++ goto out; ++ break; ++ case 's': ++ len = strlen(optarg); ++ ret = hex2bin_alloc(optarg, len, ++ &test.session_id, ++ &test.session_id_len); ++ if (ret) ++ goto out; ++ break; ++ case 'i': ++ test.iv_len = strtoul(optarg, NULL, 10); ++ break; ++ case 'e': ++ test.ek_len = strtoul(optarg, NULL, 10); ++ break; ++ case 'm': ++ test.ik_len = strtoul(optarg, NULL, 10); ++ break; ++ default: ++ usage(); ++ goto out; ++ } ++ } ++ ++ ret = sshkdf_cavs(&test); ++ ++out: ++ if (test.session_id) ++ free(test.session_id); ++ if (test.K) ++ free(test.K); ++ if (test.H) ++ free(test.H); ++ return ret; ++ ++} diff --git a/openssh-7.7p1-disable_openssl_abi_check.patch b/openssh-7.7p1-disable_openssl_abi_check.patch new file mode 100644 index 0000000..11723a7 --- /dev/null +++ b/openssh-7.7p1-disable_openssl_abi_check.patch @@ -0,0 +1,48 @@ +# HG changeset patch +# Parent b13da8c3e99081cb92ab226d2c512241a82cd0d5 +disable run-time check for OpenSSL ABI by version number as that is not a +reliable indicator of ABI changes and doesn't make much sense in a +distribution package + +Index: openssh-8.8p1/configure.ac +=================================================================== +--- openssh-8.8p1.orig/configure.ac ++++ openssh-8.8p1/configure.ac +@@ -5236,6 +5236,19 @@ AC_ARG_WITH([bsd-auth], + ] + ) + ++# Whether we are using distribution (Open)SSL, so no runtime checks are necessary ++DISTRO_SSL=no ++AC_ARG_WITH([distro-ssl], ++ [ --with-distro-ssl Disable runtime OpenSSL version checks (good for distributions)], ++ [ ++ if test "x$withval" != "xno" ; then ++ AC_DEFINE([DISTRO_SSL], [1], ++ [Define if you are using distribution SSL library and don;t expect its API/ABI to change]) ++ DISTRO_SSL=yes ++ fi ++ ] ++) ++ + # Where to place sshd.pid + piddir=/var/run + # make sure the directory exists +Index: openssh-8.8p1/entropy.c +=================================================================== +--- openssh-8.8p1.orig/entropy.c ++++ openssh-8.8p1/entropy.c +@@ -100,11 +100,13 @@ seed_rng(void) + /* Initialise libcrypto */ + ssh_libcrypto_init(); + ++#ifndef DISTRO_SSL + if (!ssh_compatible_openssl(OPENSSL_VERSION_NUMBER, + OpenSSL_version_num())) + fatal("OpenSSL version mismatch. Built against %lx, you " + "have %lx", (u_long)OPENSSL_VERSION_NUMBER, + OpenSSL_version_num()); ++#endif + + #ifndef OPENSSL_PRNG_ONLY + if (RAND_status() == 1) diff --git a/openssh-7.7p1-eal3.patch b/openssh-7.7p1-eal3.patch new file mode 100644 index 0000000..7a52a4e --- /dev/null +++ b/openssh-7.7p1-eal3.patch @@ -0,0 +1,18 @@ +# HG changeset patch +# Parent 8fd4e445c3a5c823568661a4f71b064cbcb217a9 +fix paths and references in sshd man pages + +Index: openssh-8.8p1/Makefile.in +=================================================================== +--- openssh-8.8p1.orig/Makefile.in ++++ openssh-8.8p1/Makefile.in +@@ -165,7 +165,8 @@ PATHSUBS = \ + -e 's|/etc/ssh/ssh_known_hosts|$(sysconfdir)/ssh_known_hosts|g' \ + -e 's|/etc/ssh/sshd_config|$(sysconfdir)/sshd_config|g' \ + -e 's|/usr/libexec|$(libexecdir)|g' \ +- -e 's|/etc/shosts.equiv|$(sysconfdir)/shosts.equiv|g' \ ++ -e 's|login\.conf|login.defs|g' \ ++ -e 's|/etc/shosts.equiv|$(sysconfdir)/ssh/shosts.equiv|g' \ + -e 's|/etc/ssh/ssh_host_key|$(sysconfdir)/ssh_host_key|g' \ + -e 's|/etc/ssh/ssh_host_ecdsa_key|$(sysconfdir)/ssh_host_ecdsa_key|g' \ + -e 's|/etc/ssh/ssh_host_dsa_key|$(sysconfdir)/ssh_host_dsa_key|g' \ diff --git a/openssh-7.7p1-enable_PAM_by_default.patch b/openssh-7.7p1-enable_PAM_by_default.patch new file mode 100644 index 0000000..c47e04b --- /dev/null +++ b/openssh-7.7p1-enable_PAM_by_default.patch @@ -0,0 +1,19 @@ +# HG changeset patch +# Parent 5c1e122e31b601de64d81085294216af33f31aed +# force PAM in defaullt install (this was removed from upstream in 3.8p1) +# bnc#46749 +# --used to be called '-pam-fix2' + +Index: openssh-8.8p1/sshd_config +=================================================================== +--- openssh-8.8p1.orig/sshd_config ++++ openssh-8.8p1/sshd_config +@@ -79,7 +79,7 @@ AuthorizedKeysFile .ssh/authorized_keys + # If you just want the PAM account and session checks to run without + # PAM authentication, then enable this but set PasswordAuthentication + # and KbdInteractiveAuthentication to 'no'. +-#UsePAM no ++UsePAM yes + + #AllowAgentForwarding yes + #AllowTcpForwarding yes diff --git a/openssh-7.7p1-fips.patch b/openssh-7.7p1-fips.patch new file mode 100644 index 0000000..31207b8 --- /dev/null +++ b/openssh-7.7p1-fips.patch @@ -0,0 +1,810 @@ +# HG changeset patch +# Parent 92d953171b34f6fba18d24085eeeaa24b1d2d5b5 +FIPS 140-2 compliance. Perform selftests on start and use only FIPS approved +algorithms. + +Index: openssh-9.6p1/Makefile.in +=================================================================== +--- openssh-9.6p1.orig/Makefile.in ++++ openssh-9.6p1/Makefile.in +@@ -115,6 +115,8 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ + + SKOBJS= ssh-sk-client.o + ++LIBSSH_OBJS += fips.o ++ + SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ + sshconnect.o sshconnect2.o mux.o $(SKOBJS) + +Index: openssh-9.6p1/cipher.c +=================================================================== +--- openssh-9.6p1.orig/cipher.c ++++ openssh-9.6p1/cipher.c +@@ -51,6 +51,9 @@ + + #include "openbsd-compat/openssl-compat.h" + ++#include "fips.h" ++#include "log.h" ++ + #ifndef WITH_OPENSSL + #define EVP_CIPHER_CTX void + #endif +@@ -83,7 +86,7 @@ struct sshcipher { + #endif + }; + +-static const struct sshcipher ciphers[] = { ++static const struct sshcipher ciphers_all[] = { + #ifdef WITH_OPENSSL + #ifndef OPENSSL_NO_DES + { "3des-cbc", 8, 24, 0, 0, CFLAG_CBC, EVP_des_ede3_cbc }, +@@ -110,8 +113,52 @@ static const struct sshcipher ciphers[] + { NULL, 0, 0, 0, 0, 0, NULL } + }; + ++static const struct sshcipher ciphers_fips140_2[] = { ++#ifdef WITH_OPENSSL ++ { "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 array of ciphers available depending on selected FIPS mode */ ++static const struct sshcipher * ++fips_select_ciphers(void) ++{ ++ int fips = fips_mode(); ++ switch (fips) { ++ case 0: ++ return ciphers_all; ++ case 1: ++ return ciphers_fips140_2; ++ default: ++ /* should not be reached */ ++ fatal("Fatal error: incorrect FIPS mode '%i' at %s:%u", ++ fips, __FILE__, __LINE__); ++ return NULL; ++ } ++} ++ + /* Returns a comma-separated list of supported ciphers. */ + char * + cipher_alg_list(char sep, int auth_only) +@@ -120,7 +167,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_select_ciphers(); c->name != NULL; c++) { + if ((c->flags & CFLAG_INTERNAL) != 0) + continue; + if (auth_only && c->auth_len == 0) +@@ -203,7 +250,7 @@ const struct sshcipher * + cipher_by_name(const char *name) + { + const struct sshcipher *c; +- for (c = ciphers; c->name != NULL; c++) ++ for (c = fips_select_ciphers(); c->name != NULL; c++) + if (strcmp(c->name, name) == 0) + return c; + return NULL; +Index: openssh-9.6p1/fips.c +=================================================================== +--- /dev/null ++++ openssh-9.6p1/fips.c +@@ -0,0 +1,212 @@ ++/* ++ * Copyright (c) 2012 Petr Cerny. All rights reserved. ++ * ++ * 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. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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 "fips.h" ++ ++#include "cipher.h" ++#include "dh.h" ++#include "digest.h" ++#include "kex.h" ++#include "sshkey.h" ++#include "mac.h" ++#include "log.h" ++#include "xmalloc.h" ++ ++#include ++#include ++ ++static int fips_state = -1; ++ ++static int ++fips_check_required_env(void) ++{ ++ int fips_required = 0; ++ char *env = getenv(SSH_FORCE_FIPS_ENV); ++ ++ if (env) { ++ errno = 0; ++ fips_required = strtol(env, NULL, 10); ++ if (errno) { ++ debug("bogus value in the %s environment variable, ignoring\n" ++ , SSH_FORCE_FIPS_ENV); ++ fips_required = 0; ++ } else ++ fips_required = 1; ++ } ++ return fips_required; ++} ++ ++int ++fips_mode(void) ++{ ++ if (-1 == fips_state) { ++ fips_state = FIPS_mode(); ++ if (fips_state) ++ debug("FIPS mode initialized"); ++ else { ++ if (fips_check_required_env()) { ++ debug("FIPS mode requested through the environment variable '%s'" ++ , SSH_FORCE_FIPS_ENV); ++ if (!FIPS_mode_set(1)) ++ fatal("Unable to enter FIPS mode as requested through the environment variable '%s'" ++ , SSH_FORCE_FIPS_ENV); ++ fips_state = 1; ++ } ++ } ++ } ++ return fips_state; ++} ++ ++int ++fips_correct_dgst(int digest) ++{ ++ int fips; ++ int rv = -1; ++ ++ fips = fips_mode(); ++ switch (fips) { ++ case 0: ++ rv = digest; ++ break; ++ case 1: ++ switch (digest) { ++ case SSH_DIGEST_MD5: ++ case SSH_DIGEST_SHA1: ++ debug("MD5/RIPEMD160 digests not allowed in FIPS 140-2 mode" ++ "using SHA-256 instead."); ++ rv = SSH_DIGEST_SHA256; ++ break; ++ default: ++ rv = digest; ++ break; ++ } ++ break; ++ default: ++ /* should not be reached */ ++ fatal("Fatal error: incorrect FIPS mode '%i' at %s:%u", ++ fips, __FILE__, __LINE__); ++ } ++ ++ return rv; ++} ++ ++/* ++ * filter out FIPS disallowed algorithms ++ * *crypto MUST be free()-able - it is assigned newly allocated memory and ++ * the previous one is freed ++ * ++ * returns zero if all algorithms were rejected, non-zero otherwise ++ */ ++int ++fips_filter_crypto(char **crypto, fips_filters filter) ++{ ++ char *token, *tmp, *tmp_sav, *new; ++ int plus = 0; ++ int valid; ++ int comma = 0; ++ int empty = 1; ++ size_t len; ++ ++ tmp = tmp_sav = xstrdup(*crypto); ++ ++ len = strlen(tmp) + 1; ++ new = xcalloc(1, len); ++ ++ if ('+' == *tmp) { ++ plus = 1; ++ tmp++; ++ } ++ ++ while ((token = strsep(&tmp, ",")) != NULL) { ++ switch(filter) { ++ case FIPS_FILTER_CIPHERS: ++ valid = ciphers_valid(token); ++ if (!valid) ++ debug("Cipher '%s' is not allowed in FIPS mode", ++ token); ++ break; ++ case FIPS_FILTER_MACS: ++ valid = mac_valid(token); ++ if (!valid) ++ debug("MAC '%s' is not allowed in FIPS mode", ++ token); ++ break; ++ case FIPS_FILTER_KEX_ALGS: ++ valid = kex_names_valid(token); ++ if (!valid) ++ debug("KEX '%s' is not allowed in FIPS mode", ++ token); ++ break; ++ default: ++ /* should not be reached */ ++ fatal("Fatal error: incorrect FIPS filter '%i' requested at %s:%u", ++ filter, __FILE__, __LINE__); ++ } ++ ++ if (valid) { ++ empty = 0; ++ if (plus) { ++ strlcat(new, "+", len); ++ plus = 0; ++ } ++ if (comma) ++ strlcat(new, ",", len); ++ else ++ comma = 1; ++ strlcat(new, token, len); ++ } ++ } ++ ++ /* free tmp and re-allocate shorter buffer for result if necessary */ ++ free(tmp_sav); ++ free(*crypto); ++ *crypto = new; ++ ++ return (!empty); ++} ++ ++int ++fips_dgst_min(void) ++{ ++ int fips; ++ int dgst; ++ ++ fips = fips_mode(); ++ switch (fips) { ++ case 0: ++ dgst = SSH_DIGEST_MD5; ++ break; ++ case 1: ++ dgst = SSH_DIGEST_SHA256; ++ break; ++ default: ++ /* should not be reached */ ++ fatal("Fatal error: incorrect FIPS mode '%i' at %s:%u", ++ fips, __FILE__, __LINE__); ++ } ++ return dgst; ++} ++ +Index: openssh-9.6p1/fips.h +=================================================================== +--- /dev/null ++++ openssh-9.6p1/fips.h +@@ -0,0 +1,44 @@ ++/* ++ * Copyright (c) 2012 Petr Cerny. All rights reserved. ++ * ++ * 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. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. ++ */ ++#ifndef FIPS_H ++#define FIPS_H ++ ++#include "sshkey.h" ++ ++#define SSH_FORCE_FIPS_ENV "SSH_FORCE_FIPS" ++ ++typedef enum { ++ FIPS_FILTER_CIPHERS, ++ FIPS_FILTER_MACS, ++ FIPS_FILTER_KEX_ALGS ++} fips_filters; ++ ++int fips_mode(void); ++int fips_correct_dgst(int); ++int fips_dgst_min(void); ++enum fp_type fips_correct_fp_type(enum fp_type); ++int fips_filter_crypto(char **, fips_filters); ++ ++#endif ++ +Index: openssh-9.6p1/hmac.c +=================================================================== +--- openssh-9.6p1.orig/hmac.c ++++ openssh-9.6p1/hmac.c +@@ -145,7 +145,7 @@ hmac_test(void *key, size_t klen, void * + size_t i; + u_char digest[16]; + +- if ((ctx = ssh_hmac_start(SSH_DIGEST_MD5)) == NULL) ++ if ((ctx = ssh_hmac_start(fips_correct_dgst(SSH_DIGEST_MD5))) == NULL) + printf("ssh_hmac_start failed"); + if (ssh_hmac_init(ctx, key, klen) < 0 || + ssh_hmac_update(ctx, m, mlen) < 0 || +Index: openssh-9.6p1/kex.c +=================================================================== +--- openssh-9.6p1.orig/kex.c ++++ openssh-9.6p1/kex.c +@@ -64,6 +64,8 @@ + #include "digest.h" + #include "xmalloc.h" + ++#include "fips.h" ++ + /* prototype */ + static int kex_choose_conf(struct ssh *, uint32_t seq); + static int kex_input_newkeys(int, u_int32_t, struct ssh *); +@@ -87,7 +89,7 @@ struct kexalg { + int ec_nid; + int hash_alg; + }; +-static const struct kexalg kexalgs[] = { ++static const struct kexalg kexalgs_all[] = { + #ifdef WITH_OPENSSL + { KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, + { KEX_DH14_SHA1, KEX_DH_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, +@@ -120,6 +122,47 @@ static const struct kexalg kexalgs[] = { + { NULL, 0, -1, -1}, + }; + ++static const struct kexalg kexalgs_fips140_2[] = { ++#ifdef WITH_OPENSSL ++ { KEX_DH14_SHA1, KEX_DH_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, ++ { 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 }, ++ { KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, ++#ifdef HAVE_EVP_SHA256 ++ { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, SSH_DIGEST_SHA256 }, ++#endif /* HAVE_EVP_SHA256 */ ++#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 /* OPENSSL_HAS_NISTP521 */ ++#endif /* OPENSSL_HAS_ECC */ ++#endif /* WITH_OPENSSL */ ++ { NULL, -1, -1, -1}, ++}; ++ ++/* Returns array of macs available depending on selected FIPS mode */ ++static const struct kexalg * ++fips_select_kexalgs(void) ++{ ++ int fips = fips_mode(); ++ switch (fips) { ++ case 0: ++ return kexalgs_all; ++ case 1: ++ return kexalgs_fips140_2; ++ default: ++ /* should not be reached */ ++ fatal("Fatal error: incorrect FIPS mode '%i' at %s:%u", ++ fips, __FILE__, __LINE__); ++ } ++} ++ + char * + kex_alg_list(char sep) + { +@@ -127,7 +170,7 @@ kex_alg_list(char sep) + size_t nlen, rlen = 0; + const struct kexalg *k; + +- for (k = kexalgs; k->name != NULL; k++) { ++ for (k = fips_select_kexalgs(); k->name != NULL; k++) { + if (ret != NULL) + ret[rlen++] = sep; + nlen = strlen(k->name); +@@ -147,7 +190,7 @@ kex_alg_by_name(const char *name) + { + const struct kexalg *k; + +- for (k = kexalgs; k->name != NULL; k++) { ++ for (k = fips_select_kexalgs(); k->name != NULL; k++) { + if (strcmp(k->name, name) == 0) + return k; + } +@@ -167,7 +210,10 @@ kex_names_valid(const char *names) + for ((p = strsep(&cp, ",")); p && *p != '\0'; + (p = strsep(&cp, ","))) { + if (kex_alg_by_name(p) == NULL) { ++ /* do not complain here - MACs and ciphers checks ++ * are silent here + error("Unsupported KEX algorithm \"%.100s\"", p); ++ */ + free(s); + return 0; + } +Index: openssh-9.6p1/mac.c +=================================================================== +--- openssh-9.6p1.orig/mac.c ++++ openssh-9.6p1/mac.c +@@ -41,6 +41,9 @@ + + #include "openbsd-compat/openssl-compat.h" + ++#include "fips.h" ++#include "log.h" ++ + #define SSH_DIGEST 1 /* SSH_DIGEST_XXX */ + #define SSH_UMAC 2 /* UMAC (not integrated with OpenSSL) */ + #define SSH_UMAC128 3 +@@ -55,7 +58,7 @@ struct macalg { + int etm; /* Encrypt-then-MAC */ + }; + +-static const struct macalg macs[] = { ++static const struct macalg macs_all[] = { + /* 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 }, +@@ -79,6 +82,41 @@ static const struct macalg macs[] = { + { NULL, 0, 0, 0, 0, 0, 0 } + }; + ++static const struct macalg macs_fips140_2[] = { ++ /* 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 array of macs available depending on selected FIPS mode */ ++static const struct macalg * ++fips_select_macs(void) ++{ ++ int fips = fips_mode(); ++ switch (fips) { ++ case 0: ++ return macs_all; ++ case 1: ++ return macs_fips140_2; ++ default: ++ /* should not be reached */ ++ fatal("Fatal error: incorrect FIPS mode '%i' at %s:%u", ++ fips, __FILE__, __LINE__); ++ } ++} ++ + /* Returns a list of supported MACs separated by the specified char. */ + char * + mac_alg_list(char sep) +@@ -87,7 +125,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_select_macs(); m->name != NULL; m++) { + if (ret != NULL) + ret[rlen++] = sep; + nlen = strlen(m->name); +@@ -126,7 +164,7 @@ mac_setup(struct sshmac *mac, char *name + { + const struct macalg *m; + +- for (m = macs; m->name != NULL; m++) { ++ for (m = fips_select_macs(); m->name != NULL; m++) { + if (strcmp(name, m->name) != 0) + continue; + if (mac != NULL) +Index: openssh-9.6p1/readconf.c +=================================================================== +--- openssh-9.6p1.orig/readconf.c ++++ openssh-9.6p1/readconf.c +@@ -71,6 +71,8 @@ + #include "myproposal.h" + #include "digest.h" + ++#include "fips.h" ++ + /* Format of the configuration file: + + # Configuration data is parsed as follows: +@@ -2478,6 +2480,23 @@ config_has_permitted_cnames(Options *opt + return options->num_permitted_cnames > 0; + } + ++/* remove algorithms not approved for use in FIPS mode, when running in FIPS ++ * mode ++ */ ++void ++filter_fips_algorithms(Options *o) ++{ ++ if (fips_mode()) { ++ if (!fips_filter_crypto(&o->ciphers, FIPS_FILTER_CIPHERS)) ++ fatal("None of selected ciphers can be used in FIPS mode"); ++ if (!fips_filter_crypto(&o->macs, FIPS_FILTER_MACS)) ++ fatal("None of selected MAC algorithms can be used in FIPS mode"); ++ if (!fips_filter_crypto(&o->kex_algorithms, FIPS_FILTER_KEX_ALGS)) ++ fatal("None of selected KEX algorithms can be used in FIPS mode"); ++ } ++ return; ++} ++ + /* + * Initializes options to special values that indicate that they have not yet + * been set. Read_config_file will only set options with this value. Options +@@ -2796,6 +2815,9 @@ fill_default_options(Options * options) + options->canonicalize_hostname = SSH_CANONICALISE_NO; + if (options->fingerprint_hash == -1) + options->fingerprint_hash = SSH_FP_HASH_DEFAULT; ++ options->fingerprint_hash = ++ fips_correct_dgst(options->fingerprint_hash); ++ + #ifdef ENABLE_SK_INTERNAL + if (options->sk_provider == NULL) + options->sk_provider = xstrdup("internal"); +@@ -2840,6 +2862,8 @@ fill_default_options(Options * options) + ASSEMBLE(ca_sign_algorithms, def_sig, all_sig); + #undef ASSEMBLE + ++ filter_fips_algorithms(options); ++ + #define CLEAR_ON_NONE(v) \ + do { \ + if (option_clear_or_none(v)) { \ +Index: openssh-9.6p1/readconf.h +=================================================================== +--- openssh-9.6p1.orig/readconf.h ++++ openssh-9.6p1/readconf.h +@@ -231,6 +231,7 @@ typedef struct { + #define SSH_KEYSTROKE_CHAFF_MIN_MS 1024 + #define SSH_KEYSTROKE_CHAFF_RNG_MS 2048 + ++void filter_fips_algorithms(Options *o); + const char *kex_default_pk_alg(void); + char *ssh_connection_hash(const char *thishost, const char *host, + const char *portstr, const char *user, const char *jump_host); +Index: openssh-9.6p1/servconf.c +=================================================================== +--- openssh-9.6p1.orig/servconf.c ++++ openssh-9.6p1/servconf.c +@@ -68,6 +68,7 @@ + #include "auth.h" + #include "myproposal.h" + #include "digest.h" ++#include "fips.h" + + static void add_listen_addr(ServerOptions *, const char *, + const char *, int); +@@ -207,6 +208,23 @@ option_clear_or_none(const char *o) + return o == NULL || strcasecmp(o, "none") == 0; + } + ++/* remove algorithms not approved for use in FIPS mode, when running in FIPS ++ * mode ++ */ ++static void ++filter_fips_algorithms_s(ServerOptions *o) ++{ ++ if (fips_mode()) { ++ if (!fips_filter_crypto(&o->ciphers, FIPS_FILTER_CIPHERS)) ++ fatal("None of selected ciphers can be used in FIPS mode"); ++ if (!fips_filter_crypto(&o->macs, FIPS_FILTER_MACS)) ++ fatal("None of selected MAC algorithms can be used in FIPS mode"); ++ if (!fips_filter_crypto(&o->kex_algorithms, FIPS_FILTER_KEX_ALGS)) ++ fatal("None of selected KEX algorithms can be used in FIPS mode"); ++ } ++ return; ++} ++ + static void + assemble_algorithms(ServerOptions *o) + { +@@ -248,6 +266,8 @@ assemble_algorithms(ServerOptions *o) + free(def_kex); + free(def_key); + free(def_sig); ++ ++ filter_fips_algorithms_s(o); + } + + void +@@ -440,6 +460,8 @@ fill_default_server_options(ServerOption + options->fwd_opts.streamlocal_bind_unlink = 0; + if (options->fingerprint_hash == -1) + options->fingerprint_hash = SSH_FP_HASH_DEFAULT; ++ options->fingerprint_hash = ++ fips_correct_dgst(options->fingerprint_hash); + if (options->disable_forwarding == -1) + options->disable_forwarding = 0; + if (options->expose_userauth_info == -1) +Index: openssh-9.6p1/ssh-keygen.c +=================================================================== +--- openssh-9.6p1.orig/ssh-keygen.c ++++ openssh-9.6p1/ssh-keygen.c +@@ -18,6 +18,8 @@ + #include + #include + ++#include "fips.h" ++ + #ifdef WITH_OPENSSL + #include + #include +@@ -1040,11 +1042,13 @@ do_fingerprint(struct passwd *pw) + static void + do_gen_all_hostkeys(struct passwd *pw) + { +- struct { ++ struct Key_types { + char *key_type; + char *key_type_display; + char *path; +- } key_types[] = { ++ }; ++ ++ struct Key_types key_types_all[] = { + #ifdef WITH_OPENSSL + { "rsa", "RSA" ,_PATH_HOST_RSA_KEY_FILE }, + #ifdef OPENSSL_HAS_ECC +@@ -1058,6 +1062,17 @@ do_gen_all_hostkeys(struct passwd *pw) + { NULL, NULL, NULL } + }; + ++ struct Key_types key_types_fips140_2[] = { ++#ifdef WITH_OPENSSL ++ { "rsa", "RSA" ,_PATH_HOST_RSA_KEY_FILE }, ++#ifdef OPENSSL_HAS_ECC ++ { "ecdsa", "ECDSA",_PATH_HOST_ECDSA_KEY_FILE }, ++#endif /* OPENSSL_HAS_ECC */ ++#endif /* WITH_OPENSSL */ ++ { NULL, NULL, NULL } ++ }; ++ ++ struct Key_types *key_types; + u_int32_t bits = 0; + int first = 0; + struct stat st; +@@ -1065,6 +1080,12 @@ do_gen_all_hostkeys(struct passwd *pw) + char comment[1024], *prv_tmp, *pub_tmp, *prv_file, *pub_file; + int i, type, fd, r; + ++ if (fips_mode()) { ++ key_types = key_types_fips140_2; ++ } else { ++ key_types = key_types_all; ++ } ++ + for (i = 0; key_types[i].key_type; i++) { + public = private = NULL; + prv_tmp = pub_tmp = prv_file = pub_file = NULL; +@@ -3794,6 +3815,15 @@ main(int argc, char **argv) + key_type_name = DEFAULT_KEY_TYPE_NAME; + + type = sshkey_type_from_name(key_type_name); ++ ++ /* protocol v1 is not allowed in FIPS mode, DSA is not acceptable because ++ * it has to be 1024 bit due to RFC 4253 using SHA-1 which implies 1024 bit ++ * keys due to FIPS-186 specification for DSS */ ++ if (fips_mode() && ++ (type == KEY_DSA || type == KEY_ED25519 || ++ type == KEY_DSA_CERT || type == KEY_ED25519_CERT)) ++ fatal("Key type %s not alowed in FIPS mode", key_type_name); ++ + type_bits_valid(type, key_type_name, &bits); + + if (!quiet) +Index: openssh-9.6p1/ssh_config.5 +=================================================================== +--- openssh-9.6p1.orig/ssh_config.5 ++++ openssh-9.6p1/ssh_config.5 +@@ -831,6 +831,8 @@ The argument to this keyword must be + option) or + .Cm no + (the default). ++.Pp ++In the FIPS mode the minimum of SHA-1 is enforced (which means sha256). + .It Cm ForwardAgent + Specifies whether the connection to the authentication agent (if any) + will be forwarded to the remote machine. +Index: openssh-9.6p1/sshd.c +=================================================================== +--- openssh-9.6p1.orig/sshd.c ++++ openssh-9.6p1/sshd.c +@@ -128,6 +128,8 @@ + #include "srclimit.h" + #include "dh.h" + ++#include "fips.h" ++ + /* Re-exec fds */ + #define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1) + #define REEXEC_STARTUP_PIPE_FD (STDERR_FILENO + 2) +Index: openssh-9.6p1/sshd_config.5 +=================================================================== +--- openssh-9.6p1.orig/sshd_config.5 ++++ openssh-9.6p1/sshd_config.5 +@@ -681,6 +681,8 @@ and + .Cm sha256 . + The default is + .Cm sha256 . ++.Pp ++In the FIPS mode the minimum of SHA-1 is enforced (which means sha256). + .It Cm ForceCommand + Forces the execution of the command specified by + .Cm ForceCommand , diff --git a/openssh-7.7p1-fips_checks.patch b/openssh-7.7p1-fips_checks.patch new file mode 100644 index 0000000..ebbf1ab --- /dev/null +++ b/openssh-7.7p1-fips_checks.patch @@ -0,0 +1,471 @@ +# HG changeset patch +# Parent e9b69da9a0f8dca923f8fc2836b38fe6590c791a +# +# Simple implementation of FIPS 140-2 selfchecks. Use OpenSSL to generate and +# verify checksums of binaries. Any hash iused in OpenSSH can be used (MD5 would +# obviously be a poor choice, since OpenSSL would barf and abort immediately in +# FIPS mode). SHA-2 seems to be a reasonable choice. +# +# The logic of the checks is as follows: decide whether FIPS mode is mandated +# (either by checking /proc/sys/crypto/fips_enabled or environment variable +# SSH_FORCE_FIPS. In FIPS mode, checksums are required to match (inability to +# retrieve pre-calculated hash is a fatal error). In non-FIPS mode the checks +# still must be performed, unless the hashes are not installed. Thus if the hash +# file is not found (or the hash matches), proceed in non-FIPS mode and abort +# otherwise. + +Index: openssh-8.8p1/fips-check.c +=================================================================== +--- /dev/null ++++ openssh-8.8p1/fips-check.c +@@ -0,0 +1,34 @@ ++#include "includes.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "digest.h" ++#include "fips.h" ++ ++#include ++ ++#define PROC_NAME_LEN 64 ++ ++static const char *argv0; ++ ++void ++print_help_exit(int ev) ++{ ++ fprintf(stderr, "%s <-c|-w> \n", argv0); ++ fprintf(stderr, " -c verify hash of 'file' against hash in 'checksum_file'\n"); ++ fprintf(stderr, " -w write hash of 'file' into 'checksum_file'\n"); ++ exit(ev); ++} ++ ++int ++main(int argc, char **argv) ++{ ++ fips_ssh_init(); ++ return 0; ++} +Index: openssh-8.8p1/fips.c +=================================================================== +--- openssh-8.8p1.orig/fips.c ++++ openssh-8.8p1/fips.c +@@ -35,30 +35,293 @@ + #include "log.h" + #include "xmalloc.h" + ++#include ++#include + #include ++#include ++#include ++#include ++#include + #include ++#include ++#include + + static int fips_state = -1; + ++/* calculates HMAC of contents of a file given by filename using the hash ++ * algorithm specified by FIPS_HMAC_EVP in fips.h and placing the result into ++ * newly allacated memory - remember to free it when not needed anymore */ + static int +-fips_check_required_env(void) ++hmac_file(const char *filename, u_char **hmac_out) ++{ ++ int check = -1; ++ int fd; ++ struct stat fs; ++ void *hmap; ++ unsigned char *hmac; ++ unsigned char *hmac_rv = NULL; ++ ++ hmac = xmalloc(FIPS_HMAC_LEN); ++ ++ fd = open(filename, O_RDONLY); ++ if (-1 == fd) ++ goto bail_out; ++ ++ if (-1 == fstat(fd, &fs)) ++ goto bail_out; ++ ++ hmap = mmap(NULL, fs.st_size, PROT_READ, MAP_SHARED, fd, 0); ++ ++ if ((void *)(-1) != hmap) { ++ hmac_rv = HMAC(FIPS_HMAC_EVP(), FIPS_HMAC_KEY ++ , strlen(FIPS_HMAC_KEY), hmap, fs.st_size, hmac, NULL); ++ check = CHECK_OK; ++ munmap(hmap, fs.st_size); ++ } ++ close(fd); ++ ++bail_out: ++ if (hmac_rv) { ++ check = CHECK_OK; ++ *hmac_out = hmac; ++ } else { ++ check = CHECK_FAIL; ++ *hmac_out = NULL; ++ free(hmac); ++ } ++ return check; ++} ++ ++/* find pathname of binary of process with PID pid. exe is buffer expected to ++ * be capable of holding at least max_pathlen characters ++ */ ++static int ++get_executable_path(pid_t pid, char *exe, int max_pathlen) ++{ ++ char exe_sl[PROC_EXE_PATH_LEN]; ++ int n; ++ int rv = -1; ++ ++ n = snprintf(exe_sl, sizeof(exe_sl), "/proc/%u/exe", pid); ++ if ((n <= 10) || (n >= max_pathlen)) { ++ fatal("error compiling filename of link to executable"); ++ } ++ ++ exe[0] = 0; ++ n = readlink(exe_sl, exe, max_pathlen); ++ /* the file doesn't need to exist - procfs might not be mounted in ++ * chroot */ ++ if (n == -1) { ++ rv = CHECK_MISSING; ++ } else { ++ if (n < max_pathlen) { ++ exe[n] = 0; ++ rv = CHECK_OK; ++ } else { ++ rv = CHECK_FAIL; ++ } ++ } ++ return rv; ++} ++ ++/* Read HMAC from file chk, allocating enough memory to hold the HMAC and ++ * return it in *hmac. ++ * Remember to free() it when it's not needed anymore. ++ */ ++static int ++read_hmac(const char *chk, u_char **hmac) ++{ ++ int check = -1; ++ int fdh, n; ++ u_char *hmac_in; ++ ++ *hmac = NULL; ++ ++ fdh = open(chk, O_RDONLY); ++ if (-1 == fdh) { ++ switch (errno) { ++ case ENOENT: ++ check = CHECK_MISSING; ++ debug("fips: checksum file %s is missing\n", chk); ++ break; ++ default: ++ check = CHECK_FAIL; ++ debug("fips: ckecksum file %s not accessible\n", chk); ++ break; ++ ++ } ++ goto bail_out; ++ } ++ ++ hmac_in = xmalloc(FIPS_HMAC_LEN); ++ ++ n = read(fdh, (void *)hmac_in, FIPS_HMAC_LEN); ++ if (FIPS_HMAC_LEN != n) { ++ debug("fips: unable to read whole checksum from checksum file\n"); ++ free (hmac_in); ++ check = CHECK_FAIL; ++ } else { ++ check = CHECK_OK; ++ *hmac = hmac_in; ++ } ++bail_out: ++ return check; ++} ++ ++static int ++fips_hmac_self(void) ++{ ++ int check = -1; ++ u_char *hmac = NULL, *hmac_chk = NULL; ++ char *exe, *chk; ++ ++ exe = xmalloc(PATH_MAX); ++ chk = xmalloc(PATH_MAX); ++ ++ /* we will need to add the suffix and the null terminator */ ++ check = get_executable_path(getpid(), exe ++ , PATH_MAX - strlen(CHECKSUM_SUFFIX) - 1); ++ if (CHECK_OK != check) ++ goto cleanup; ++ ++ strncpy(chk, exe, PATH_MAX); ++ strlcat(chk, CHECKSUM_SUFFIX, PATH_MAX); ++ ++ check = read_hmac(chk, &hmac_chk); ++ if (CHECK_OK != check) ++ goto cleanup; ++ ++ check = hmac_file(exe, &hmac); ++ if (CHECK_OK != check) ++ goto cleanup; ++ ++ check = memcmp(hmac, hmac_chk, FIPS_HMAC_LEN); ++ if (0 == check) { ++ check = CHECK_OK; ++ debug("fips: checksum matches\n"); ++ } else { ++ check = CHECK_FAIL; ++ debug("fips: checksum mismatch!\n"); ++ } ++ ++cleanup: ++ free(hmac); ++ free(hmac_chk); ++ free(chk); ++ free(exe); ++ ++ return check; ++} ++ ++static int ++fips_check_required_proc(void) + { + int fips_required = 0; +- char *env = getenv(SSH_FORCE_FIPS_ENV); ++ int fips_fd; ++ char fips_sys = 0; + +- if (env) { +- errno = 0; +- fips_required = strtol(env, NULL, 10); +- if (errno) { +- debug("bogus value in the %s environment variable, ignoring\n" +- , SSH_FORCE_FIPS_ENV); +- fips_required = 0; +- } else +- fips_required = 1; ++ struct stat dummy; ++ if (-1 == stat(FIPS_PROC_PATH, &dummy)) { ++ switch (errno) { ++ case ENOENT: ++ case ENOTDIR: ++ break; ++ default: ++ fatal("Check for system-wide FIPS mode is required and %s cannot" ++ " be accessed for reason other than non-existence - aborting" ++ , FIPS_PROC_PATH); ++ break; ++ } ++ } else { ++ if (-1 == (fips_fd = open(FIPS_PROC_PATH, O_RDONLY))) ++ fatal("Check for system-wide FIPS mode is required and %s cannot" ++ " be opened for reading - aborting" ++ , FIPS_PROC_PATH); ++ if (1 > read(fips_fd, &fips_sys, 1)) ++ fatal("Check for system-wide FIPS mode is required and %s doesn't" ++ " return at least one character - aborting" ++ , FIPS_PROC_PATH); ++ close(fips_sys); ++ switch (fips_sys) { ++ case '0': ++ case '1': ++ fips_required = fips_sys - '0'; ++ break; ++ default: ++ fatal("Bogus character %c found in %s - aborting" ++ , fips_sys, FIPS_PROC_PATH); ++ } + } + return fips_required; + } + ++static int ++fips_check_required_env(void) ++{ ++ return (NULL != getenv(SSH_FORCE_FIPS_ENV)); ++} ++ ++static int ++fips_required(void) ++{ ++ int fips_requests = 0; ++ fips_requests += fips_check_required_proc(); ++ fips_requests += fips_check_required_env(); ++ return fips_requests; ++} ++ ++/* check whether FIPS mode is required and perform selfchecksum/selftest */ ++void ++fips_ssh_init(void) ++{ ++ int checksum; ++ ++ checksum = fips_hmac_self(); ++ ++ if (fips_required()) { ++ switch (checksum) { ++ case CHECK_OK: ++ debug("fips: mandatory checksum ok"); ++ break; ++ case CHECK_FAIL: ++ fatal("fips: mandatory checksum failed - aborting"); ++ break; ++ case CHECK_MISSING: ++ fatal("fips: mandatory checksum data missing - aborting"); ++ break; ++ default: ++ fatal("Fatal error: internal error at %s:%u" ++ , __FILE__, __LINE__); ++ break; ++ } ++ fips_state = FIPS_mode_set(1); ++ if (1 != fips_state) { ++ ERR_load_crypto_strings(); ++ u_long err = ERR_get_error(); ++ error("fips: OpenSSL error %lx: %s" ++ , err, ERR_error_string(err, NULL)); ++ fatal("fips: unable to set OpenSSL into FIPS mode - aborting"); ++ } ++ } else { ++ switch (checksum) { ++ case CHECK_OK: ++ debug("fips: checksum ok"); ++ break; ++ case CHECK_FAIL: ++ fatal("fips: checksum failed - aborting"); ++ break; ++ case CHECK_MISSING: ++ debug("fips: checksum data missing, but not required - continuing non-FIPS"); ++ break; ++ default: ++ fatal("Fatal error: internal error at %s:%u", ++ __FILE__, __LINE__); ++ break; ++ } ++ } ++ return; ++} ++ + int + fips_mode(void) + { +Index: openssh-8.8p1/fips.h +=================================================================== +--- openssh-8.8p1.orig/fips.h ++++ openssh-8.8p1/fips.h +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2012 Petr Cerny. All rights reserved. ++ * Copyright (c) 2012-2014 Petr Cerny. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -27,6 +27,15 @@ + #include "sshkey.h" + + #define SSH_FORCE_FIPS_ENV "SSH_FORCE_FIPS" ++#define FIPS_PROC_PATH "/proc/sys/crypto/fips_enabled" ++ ++#define PROC_EXE_PATH_LEN 64 ++#define CHECKSUM_SUFFIX ".hmac" ++#define FIPS_HMAC_KEY "HMAC_KEY:OpenSSH-FIPS@SLE" ++#define FIPS_HMAC_EVP EVP_sha256 ++#define FIPS_HMAC_LEN 32 ++ ++void fips_ssh_init(void); + + typedef enum { + FIPS_FILTER_CIPHERS, +@@ -34,6 +43,12 @@ typedef enum { + FIPS_FILTER_KEX_ALGS + } fips_filters; + ++typedef enum { ++ CHECK_OK = 0, ++ CHECK_FAIL, ++ CHECK_MISSING ++} fips_checksum_status; ++ + int fips_mode(void); + int fips_correct_dgst(int); + int fips_dgst_min(void); +@@ -41,4 +56,3 @@ enum fp_type fips_correct_fp_type(enum + int fips_filter_crypto(char **, fips_filters); + + #endif +- +Index: openssh-8.8p1/sftp-server.c +=================================================================== +--- openssh-8.8p1.orig/sftp-server.c ++++ openssh-8.8p1/sftp-server.c +@@ -57,6 +57,8 @@ char *sftp_realpath(const char *, char * + /* Maximum data read that we are willing to accept */ + #define SFTP_MAX_READ_LENGTH (SFTP_MAX_MSG_LENGTH - 1024) + ++#include "fips.h" ++ + /* Our verbosity */ + static LogLevel log_level = SYSLOG_LEVEL_ERROR; + +@@ -1717,6 +1719,9 @@ sftp_server_main(int argc, char **argv, + extern char *optarg; + extern char *__progname; + ++ /* initialize fips */ ++ fips_ssh_init(); ++ + __progname = ssh_get_progname(argv[0]); + log_init(__progname, log_level, log_facility, log_stderr); + +Index: openssh-8.8p1/ssh.c +=================================================================== +--- openssh-8.8p1.orig/ssh.c ++++ openssh-8.8p1/ssh.c +@@ -113,6 +113,8 @@ + #include "ssh-pkcs11.h" + #endif + ++#include "fips.h" ++ + extern char *__progname; + + /* Saves a copy of argv for setproctitle emulation */ +@@ -632,6 +634,10 @@ main(int ac, char **av) + u_int j; + struct ssh_conn_info *cinfo = NULL; + ++ /* initialize fips - can go before ssh_malloc_init(), since that is a ++ * OpenBSD-only thing (as of OpenSSH 7.6p1) */ ++ fips_ssh_init(); ++ + /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ + sanitise_stdfd(); + +Index: openssh-8.8p1/sshd.c +=================================================================== +--- openssh-8.8p1.orig/sshd.c ++++ openssh-8.8p1/sshd.c +@@ -1547,6 +1547,10 @@ main(int ac, char **av) + struct connection_info *connection_info = NULL; + sigset_t sigmask; + ++ /* initialize fips - can go before ssh_malloc_init(), since that is a ++ * OpenBSD-only thing (as of OpenSSH 7.6p1) */ ++ fips_ssh_init(); ++ + #ifdef HAVE_SECUREWARE + (void)set_auth_parameters(ac, av); + #endif diff --git a/openssh-7.7p1-host_ident.patch b/openssh-7.7p1-host_ident.patch new file mode 100644 index 0000000..9e08375 --- /dev/null +++ b/openssh-7.7p1-host_ident.patch @@ -0,0 +1,20 @@ +# HG changeset patch +# Parent 0f731d0b541b8a919d24ac91098f560a49712822 +Suggest command line for removal of offending keys from known_hosts file + +Index: openssh-8.8p1/sshconnect.c +=================================================================== +--- openssh-8.8p1.orig/sshconnect.c ++++ openssh-8.8p1/sshconnect.c +@@ -1270,6 +1270,11 @@ check_host_key(char *hostname, const str + error("Offending %s key in %s:%lu", + sshkey_type(host_found->key), + host_found->file, host_found->line); ++ error("You can use following command to remove the offending key:"); ++ if (host_found->file) ++ error("ssh-keygen -R %s -f %s", host, host_found->file); ++ else ++ error("ssh-keygen -R %s", host); + + /* + * If strict host key checking is in use, the user will have diff --git a/openssh-7.7p1-hostname_changes_when_forwarding_X.patch b/openssh-7.7p1-hostname_changes_when_forwarding_X.patch new file mode 100644 index 0000000..33fd46c --- /dev/null +++ b/openssh-7.7p1-hostname_changes_when_forwarding_X.patch @@ -0,0 +1,83 @@ +# HG changeset patch +# Parent 5e19a205fa03584bb0d829ecbba7495ce1899b65 +# -- uset do be called '-xauthlocalhostname' +handle hostname changes when forwarding X + +Index: openssh-8.8p1/session.c +=================================================================== +--- openssh-8.8p1.orig/session.c ++++ openssh-8.8p1/session.c +@@ -981,7 +981,7 @@ copy_environment(char **source, char *** + #endif + + static char ** +-do_setup_env(struct ssh *ssh, Session *s, const char *shell) ++do_setup_env(struct ssh *ssh, Session *s, const char *shell, int *env_size) + { + char buf[256]; + size_t n; +@@ -1191,6 +1191,8 @@ do_setup_env(struct ssh *ssh, Session *s + for (i = 0; env[i]; i++) + fprintf(stderr, " %.200s\n", env[i]); + } ++ ++ *env_size = envsize; + return env; + } + +@@ -1199,7 +1201,7 @@ do_setup_env(struct ssh *ssh, Session *s + * first in this order). + */ + static void +-do_rc_files(struct ssh *ssh, Session *s, const char *shell) ++do_rc_files(struct ssh *ssh, Session *s, const char *shell, char **env, int *env_size) + { + FILE *f = NULL; + char *cmd = NULL, *user_rc = NULL; +@@ -1256,12 +1258,20 @@ do_rc_files(struct ssh *ssh, Session *s, + fatal_f("xasprintf: %s", strerror(errno)); + f = popen(cmd, "w"); + if (f) { ++ char hostname[MAXHOSTNAMELEN]; ++ + fprintf(f, "remove %s\n", + s->auth_display); + fprintf(f, "add %s %s %s\n", + s->auth_display, s->auth_proto, + s->auth_data); + pclose(f); ++ if (gethostname(hostname,sizeof(hostname)) >= 0) ++ child_set_env(&env,env_size,"XAUTHLOCALHOSTNAME", ++ hostname); ++ else ++ debug("Cannot set up XAUTHLOCALHOSTNAME %s\n", ++ strerror(errno)); + } else { + fprintf(stderr, "Could not run %s\n", + cmd); +@@ -1518,6 +1528,7 @@ do_child(struct ssh *ssh, Session *s, co + char **env, *argv[ARGV_MAX], remote_id[512]; + const char *shell, *shell0; + struct passwd *pw = s->pw; ++ int env_size; + int r = 0; + + sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id)); +@@ -1574,7 +1585,7 @@ do_child(struct ssh *ssh, Session *s, co + * Make sure $SHELL points to the shell from the password file, + * even if shell is overridden from login.conf + */ +- env = do_setup_env(ssh, s, shell); ++ env = do_setup_env(ssh, s, shell, &env_size); + + #ifdef HAVE_LOGIN_CAP + shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell); +@@ -1638,7 +1649,7 @@ do_child(struct ssh *ssh, Session *s, co + + closefrom(STDERR_FILENO + 1); + +- do_rc_files(ssh, s, shell); ++ do_rc_files(ssh, s, shell, env, &env_size); + + /* restore SIGPIPE for child */ + ssh_signal(SIGPIPE, SIG_DFL); diff --git a/openssh-7.7p1-ldap.patch b/openssh-7.7p1-ldap.patch new file mode 100644 index 0000000..9f11f91 --- /dev/null +++ b/openssh-7.7p1-ldap.patch @@ -0,0 +1,2719 @@ +# HG changeset patch +# Parent 860ce7cab52a11c12df044de6ffdcffa58c13f23 +# Helper app for retrieving keys from a LDAP server +# by Jan F. Chadima +# +# patch for openbsd-compat/base64.* introduces preprocessor macro +# USE_INTERNAL_B64 intended to enforce using ssh supplied functions. +# (The additional -lldap/-llber introduced in the patch cause configure to +# discover the base64 functions in glibc (libresolv) and not to build the +# internal versions. ssh-keyconverter consequently fails to link as it lacks +# the proper flags, and libopenbsd-compat doesn't contain the b64_* functions) + +Index: openssh-8.9p1/HOWTO.ldap-keys +=================================================================== +--- /dev/null ++++ openssh-8.9p1/HOWTO.ldap-keys +@@ -0,0 +1,108 @@ ++ ++HOW TO START ++ ++1) configure LDAP server ++ * Use LDAP server documentation ++2) add appropriate LDAP schema ++ * For OpenLDAP or SunONE Use attached schema, otherwise you have to create ++ it. ++ * LDAP user entry ++ User entry: ++ - attached to the 'ldapPublicKey' objectclass ++ - attached to the 'posixAccount' objectclass ++ - with a filled 'sshPublicKey' attribute ++3) insert users into LDAP ++ * Use LDAP Tree management tool as useful ++ * Entry in the LDAP server must respect 'posixAccount' and 'ldapPublicKey' ++ which are defined in core.schema and the additionnal lpk.schema. ++ * Example: ++ dn: uid=captain,ou=commanders,dc=enterprise,dc=universe ++ objectclass: top ++ objectclass: person ++ objectclass: organizationalPerson ++ objectclass: posixAccount ++ objectclass: ldapPublicKey ++ description: Jonathan Archer ++ userPassword: Porthos ++ cn: onathan Archer ++ sn: onathan Archer ++ uid: captain ++ uidNumber: 1001 ++ gidNumber: 1001 ++ homeDirectory: /home/captain ++ sshPublicKey: ssh-rss AAAAB3.... =captain@universe ++ sshPublicKey: command="kill -9 1" ssh-rss AAAAM5... ++4) on the ssh side set in sshd_config ++ * Set up the backend ++ AuthorizedKeysCommand "@LIBEXECDIR@/ssh-ldap-wrapper" ++ AuthorizedKeysCommandRunAs ++ * Do not forget to set ++ PubkeyAuthentication yes ++ * Swith off unnecessary auth methods ++5) confugure ldap.conf ++ * Default ldap.conf is placed in /etc/ssh ++ * The configuration style is the same as other ldap based aplications ++6) if necessary edit ssh-ldap-wrapper ++ * There is a possibility to change ldap.conf location ++ * There are some debug options ++ * Example ++ @LIBEXECDIR@/ssh-ldap-wrapper -s -f /etc/ldap.conf -w -d >> /tmp/ldapdebuglog.txt ++ ++HOW TO MIGRATE FROM LPK ++ ++1) goto HOW TO START 4) .... the ldap schema is the same ++ ++2) convert the group requests to the appropriate LDAP requests ++ ++HOW TO SOLVE PROBLEMS ++ ++1) use debug in sshd ++ * /usr/sbin/sshd -d -d -d -d ++2) use debug in ssh-ldap-helper ++ * ssh-ldap-helper -d -d -d -d -s ++3) use tcpdump ... other ldap client etc. ++ ++ADVANTAGES ++ ++1) Blocking an user account can be done directly from LDAP (if sshd is using ++ PubkeyAuthentication + AuthorizedKeysCommand with ldap only). ++ ++DISADVANTAGES ++ ++1) LDAP must be well configured, getting the public key of some user is not ++ a problem, but if anonymous LDAP allows write to users dn, somebody could ++ replace some user's public key by his own and impersonate some of your users ++ in all your server farm -- be VERY CAREFUL. ++2) With incomplete PKI the MITM attack when sshd is requesting the public key, ++ could lead to a compromise of your servers allowing login as the ++ impersonated user. ++3) If LDAP server is down there may be no fallback on passwd auth. ++ ++MISC. ++ ++1) todo ++ * Possibility to reuse the ssh-ldap-helper. ++ * Tune the LDAP part to accept all possible LDAP configurations. ++ ++2) differences from original lpk ++ * No LDAP code in sshd. ++ * Support for various LDAP platforms and configurations. ++ * LDAP is configured in separate ldap.conf file. ++ ++3) docs/link ++ * http://pacsec.jp/core05/psj05-barisani-en.pdf ++ * http://fritz.potsdam.edu/projects/openssh-lpk/ ++ * http://fritz.potsdam.edu/projects/sshgate/ ++ * http://dev.inversepath.com/trac/openssh-lpk ++ * http://lam.sf.net/ ++ ( http://lam.sourceforge.net/documentation/supportedSchemas.htm ) ++ ++4) contributors/ideas/greets ++ - Eric AUGE ++ - Andrea Barisani ++ - Falk Siemonsmeier. ++ - Jacob Rief. ++ - Michael Durchgraf. ++ - frederic peters. ++ - Finlay dobbie. ++ - Stefan Fisher. +Index: openssh-8.9p1/Makefile.in +=================================================================== +--- openssh-8.9p1.orig/Makefile.in ++++ openssh-8.9p1/Makefile.in +@@ -27,6 +27,8 @@ SFTP_SERVER=$(libexecdir)/sftp-server + SSH_KEYSIGN=$(libexecdir)/ssh-keysign + SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper + SSH_SK_HELPER=$(libexecdir)/ssh-sk-helper ++SSH_LDAP_HELPER=$(libexecdir)/ssh-ldap-helper ++SSH_LDAP_WRAPPER=$(libexecdir)/ssh-ldap-wrapper + CAVSTEST_CTR=$(libexecdir)/cavstest-ctr + CAVSTEST_KDF=$(libexecdir)/cavstest-kdf + PRIVSEP_PATH=@PRIVSEP_PATH@ +@@ -75,6 +77,9 @@ TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-a + + TARGETS += cavstest-ctr$(EXEEXT) cavstest-kdf$(EXEEXT) + ++INSTALL_SSH_LDAP_HELPER=@INSTALL_SSH_LDAP_HELPER@ ++TARGETS += ssh-ldap-helper$(EXEEXT) ++ + XMSS_OBJS=\ + ssh-xmss.o \ + sshkey-xmss.o \ +@@ -162,8 +167,8 @@ SFTPSERVER_OBJS=sftp-common.o sftp-serve + + SFTP_OBJS= sftp.o sftp-usergroup.o progressmeter.o $(SFTP_CLIENT_OBJS) + +-MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out ssh-sk-helper.8.out sshd_config.5.out ssh_config.5.out +-MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 ssh-sk-helper.8 sshd_config.5 ssh_config.5 ++MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out ssh-sk-helper.8.out sshd_config.5.out ssh_config.5.out ssh-ldap-helper.8.out ssh-ldap.conf.5.out ++MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 ssh-sk-helper.8 sshd_config.5 ssh_config.5 ssh-ldap-helper.8 ssh-ldap.conf.5 + MANTYPE = @MANTYPE@ + + CONFIGFILES=sshd_config.out ssh_config.out moduli.out +@@ -246,6 +251,9 @@ ssh-sk-helper$(EXEEXT): $(LIBCOMPAT) lib + ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYSCAN_OBJS) + $(LD) -o $@ $(SSHKEYSCAN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) $(CHANNELLIBS) + ++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 $(LIBS) ++ + sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a $(SFTPSERVER_OBJS) + $(LD) -o $@ $(SFTPSERVER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) + +@@ -421,6 +429,10 @@ install-files: + $(INSTALL) -m 0755 $(STRIP_OPT) sshd$(EXEEXT) $(DESTDIR)$(sbindir)/sshd$(EXEEXT) + $(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT) + $(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT) ++ if test ! -z "$(INSTALL_SSH_LDAP_HELPER)" ; then \ ++ $(INSTALL) -m 0755 $(STRIP_OPT) ssh-ldap-helper $(DESTDIR)$(SSH_LDAP_HELPER) ; \ ++ $(INSTALL) -m 0755 ssh-ldap-wrapper $(DESTDIR)$(SSH_LDAP_WRAPPER) ; \ ++ fi + $(INSTALL) -m 0755 $(STRIP_OPT) ssh-sk-helper$(EXEEXT) $(DESTDIR)$(SSH_SK_HELPER)$(EXEEXT) + $(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT) + $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) +@@ -440,6 +452,10 @@ install-files: + $(INSTALL) -m 644 sftp-server.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8 + $(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8 + $(INSTALL) -m 644 ssh-pkcs11-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8 ++ if test ! -z "$(INSTALL_SSH_LDAP_HELPER)" ; then \ ++ $(INSTALL) -m 644 ssh-ldap-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-ldap-helper.8 ; \ ++ $(INSTALL) -m 644 ssh-ldap.conf.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/ssh-ldap.conf.5 ; \ ++ fi + $(INSTALL) -m 644 ssh-sk-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-sk-helper.8 + + install-sysconf: +@@ -464,6 +480,13 @@ install-sysconf: + else \ + echo "$(DESTDIR)$(sysconfdir)/moduli already exists, install will not overwrite"; \ + fi ++ if test ! -z "$(INSTALL_SSH_LDAP_HELPER)" ; then \ ++ if [ ! -f $(DESTDIR)$(sysconfdir)/ldap.conf ]; then \ ++ $(INSTALL) -m 644 ldap.conf $(DESTDIR)$(sysconfdir)/ldap.conf; \ ++ else \ ++ echo "$(DESTDIR)$(sysconfdir)/ldap.conf already exists, install will not overwrite"; \ ++ fi ; \ ++ fi + + host-key: ssh-keygen$(EXEEXT) + @if [ -z "$(DESTDIR)" ] ; then \ +@@ -502,6 +525,8 @@ uninstall: + -rm -f $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT) + -rm -f $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT) + -rm -f $(DESTDIR)$(SSH_SK_HELPER)$(EXEEXT) ++ -rm -f $(DESTDIR)$(SSH_LDAP_HELPER)$(EXEEXT) ++ -rm -f $(DESTDIR)$(SSH_LDAP_WRAPPER)$(EXEEXT) + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1 +@@ -514,6 +539,7 @@ uninstall: + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-sk-helper.8 ++ -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-ldap-helper.8 + + regress-prep: + $(MKDIR_P) `pwd`/regress/unittests/test_helper +Index: openssh-8.9p1/configure.ac +=================================================================== +--- openssh-8.9p1.orig/configure.ac ++++ openssh-8.9p1/configure.ac +@@ -1780,6 +1780,106 @@ AC_ARG_WITH([audit], + esac ] + ) + ++# Check whether user wants LDAP support ++LDAP_MSG="no" ++INSTALL_SSH_LDAP_HELPER="" ++AC_ARG_WITH(ldap, ++ [ --with-ldap[[=PATH]] Enable LDAP pubkey support (optionally in PATH)], ++ [ ++ if test "x$withval" != "xno" ; then ++ ++ INSTALL_SSH_LDAP_HELPER="yes" ++ CPPFLAGS="$CPPFLAGS -DLDAP_DEPRECATED" ++ ++ if test "x$withval" != "xyes" ; then ++ CPPFLAGS="$CPPFLAGS -I${withval}/include" ++ LDFLAGS="$LDFLAGS -L${withval}/lib" ++ fi ++ ++ AC_DEFINE([WITH_LDAP_PUBKEY], 1, [Enable LDAP pubkey support]) ++ LDAP_MSG="yes" ++ ++ AC_CHECK_HEADERS(lber.h) ++ AC_CHECK_HEADERS(ldap.h, , AC_MSG_ERROR(could not locate )) ++ AC_CHECK_HEADERS(ldap_ssl.h) ++ ++ AC_ARG_WITH(ldap-lib, ++ [ --with-ldap-lib=type select ldap library [auto|netscape5|netscape4|netscape3|umich|openldap]]) ++ ++ if test -z "$with_ldap_lib"; then ++ with_ldap_lib=auto ++ fi ++ ++ if test -z "$found_ldap_lib" -a \( $with_ldap_lib = auto -o $with_ldap_lib = umich -o $with_ldap_lib = openldap \); then ++ AC_CHECK_LIB(lber, main, LIBS="-llber $LIBS" found_ldap_lib=yes) ++ AC_CHECK_LIB(ldap, main, LIBS="-lldap $LIBS" found_ldap_lib=yes) ++ fi ++ ++ if test -z "$found_ldap_lib" -a \( $with_ldap_lib = auto -o $with_ldap_lib = netscape5 \); then ++ AC_CHECK_LIB(ldap50, main, LIBS="-lldap50 -lssldap50 -lssl3 -lnss3 -lnspr4 -lprldap50 -lplc4 -lplds4 $LIBS" found_ldap_lib=yes) ++ fi ++ ++ if test -z "$found_ldap_lib" -a \( $with_ldap_lib = auto -o $with_ldap_lib = netscape4 \); then ++ AC_CHECK_LIB(ldapssl41, main, LIBS="-lldapssl41 -lplc3 -lplds3 -lnspr3 $LIBS" found_ldap_lib=yes) ++ if test -z "$found_ldap_lib"; then ++ AC_CHECK_LIB(ldapssl40, main, LIBS="-lldapssl40 $LIBS" found_ldap_lib=yes) ++ fi ++ if test -z "$found_ldap_lib"; then ++ AC_CHECK_LIB(ldap41, main, LIBS="-lldap41 $LIBS" found_ldap_lib=yes) ++ fi ++ if test -z "$found_ldap_lib"; then ++ AC_CHECK_LIB(ldap40, main, LIBS="-lldap40 $LIBS" found_ldap_lib=yes) ++ fi ++ fi ++ ++ if test -z "$found_ldap_lib" -a \( $with_ldap_lib = auto -o $with_ldap_lib = netscape3 \); then ++ AC_CHECK_LIB(ldapssl30, main, LIBS="-lldapssl30 $LIBS" found_ldap_lib=yes) ++ fi ++ ++ if test -z "$found_ldap_lib"; then ++ AC_MSG_ERROR(could not locate a valid LDAP library) ++ fi ++ ++ AC_MSG_CHECKING([for working LDAP support]) ++ AC_TRY_COMPILE( ++ [#include ++ #include ], ++ [(void)ldap_init(0, 0);], ++ [AC_MSG_RESULT(yes)], ++ [ ++ AC_MSG_RESULT(no) ++ AC_MSG_ERROR([** Incomplete or missing ldap libraries **]) ++ ]) ++ AC_CHECK_FUNCS( \ ++ ldap_init \ ++ ldap_get_lderrno \ ++ ldap_set_lderrno \ ++ ldap_parse_result \ ++ ldap_memfree \ ++ ldap_controls_free \ ++ ldap_set_option \ ++ ldap_get_option \ ++ ldapssl_init \ ++ ldap_start_tls_s \ ++ ldap_pvt_tls_set_option \ ++ ldap_initialize \ ++ ) ++ AC_CHECK_FUNCS(ldap_set_rebind_proc, ++ AC_MSG_CHECKING([number arguments of ldap_set_rebind_proc]) ++ AC_TRY_COMPILE( ++ [#include ++ #include ], ++ [ldap_set_rebind_proc(0, 0, 0);], ++ [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]) ++ ) ++ fi ++ ] ++) ++AC_SUBST(INSTALL_SSH_LDAP_HELPER) ++ + AC_ARG_WITH([pie], + [ --with-pie Build Position Independent Executables if possible], [ + if test "x$withval" = "xno"; then +Index: openssh-8.9p1/ldap-helper.c +=================================================================== +--- /dev/null ++++ openssh-8.9p1/ldap-helper.c +@@ -0,0 +1,155 @@ ++/* $OpenBSD: ssh-pka-ldap.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ ++/* ++ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. ++ * ++ * 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. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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 "ldapincludes.h" ++#include "log.h" ++#include "misc.h" ++#include "xmalloc.h" ++#include "ldapconf.h" ++#include "ldapbody.h" ++#include ++#include ++ ++static int config_debug = 0; ++int config_exclusive_config_file = 0; ++static char *config_file_name = "/etc/ssh/ldap.conf"; ++static char *config_single_user = NULL; ++static int config_verbose = SYSLOG_LEVEL_VERBOSE; ++int config_warning_config_file = 0; ++extern char *__progname; ++ ++static void ++usage(void) ++{ ++ fprintf(stderr, "usage: %s [options]\n", ++ __progname); ++ fprintf(stderr, "Options:\n"); ++ fprintf(stderr, " -d Output the log messages to stderr.\n"); ++ fprintf(stderr, " -e Check the config file for unknown commands.\n"); ++ fprintf(stderr, " -f file Use alternate config file (default is /etc/ssh/ldap.conf).\n"); ++ fprintf(stderr, " -s user Do not demonize, send the user's key to stdout.\n"); ++ fprintf(stderr, " -v Increase verbosity of the debug output (implies -d).\n"); ++ fprintf(stderr, " -w Warn on unknown commands in the config file.\n"); ++ exit(1); ++} ++ ++/* ++ * Main program for the ssh pka ldap agent. ++ */ ++ ++int ++main(int ac, char **av) ++{ ++ int opt; ++ FILE *outfile = NULL; ++ ++ __progname = ssh_get_progname(av[0]); ++ ++ log_init(__progname, SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 0); ++ ++ /* ++ * Initialize option structure to indicate that no values have been ++ * set. ++ */ ++ initialize_options(); ++ ++ /* Parse command-line arguments. */ ++ while ((opt = getopt(ac, av, "def:s:vw")) != -1) { ++ switch (opt) { ++ case 'd': ++ config_debug = 1; ++ break; ++ ++ case 'e': ++ config_exclusive_config_file = 1; ++ config_warning_config_file = 1; ++ break; ++ ++ case 'f': ++ config_file_name = optarg; ++ break; ++ ++ case 's': ++ config_single_user = optarg; ++ outfile = fdopen (dup (fileno (stdout)), "w"); ++ break; ++ ++ case 'v': ++ config_debug = 1; ++ if (config_verbose < SYSLOG_LEVEL_DEBUG3) ++ config_verbose++; ++ break; ++ ++ case 'w': ++ config_warning_config_file = 1; ++ break; ++ ++ case '?': ++ default: ++ usage(); ++ break; ++ } ++ } ++ ++ /* Initialize loging */ ++ log_init(__progname, config_verbose, SYSLOG_FACILITY_AUTH, config_debug); ++ ++ if (ac != optind) ++ fatal ("illegal extra parameter %s", av[1]); ++ ++ /* Ensure that fds 0 and 2 are open or directed to /dev/null */ ++ if (config_debug == 0) ++ sanitise_stdfd(); ++ ++ /* Read config file */ ++ read_config_file(config_file_name); ++ fill_default_options(); ++ if (config_verbose == SYSLOG_LEVEL_DEBUG3) { ++ debug3 ("=== Configuration ==="); ++ dump_config(); ++ debug3 ("=== *** ==="); ++ } ++ ++ ldap_checkconfig(); ++ ldap_do_connect(); ++ ++ if (config_single_user) { ++ process_user (config_single_user, outfile); ++ } else { ++ usage(); ++ fatal ("Not yet implemented"); ++/* TODO ++ * open unix socket a run the loop on it ++ */ ++ } ++ ++ ldap_do_close(); ++ return 0; ++} ++ ++/* Ugly hack */ ++void *buffer_get_string(struct sshbuf *b, u_int *l) { return NULL; } ++void buffer_put_string(struct sshbuf *b, const void *f, u_int l) {} ++ +Index: openssh-8.9p1/ldap-helper.h +=================================================================== +--- /dev/null ++++ openssh-8.9p1/ldap-helper.h +@@ -0,0 +1,32 @@ ++/* $OpenBSD: ldap-helper.h,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ ++/* ++ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. ++ * ++ * 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. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. ++ */ ++ ++#ifndef LDAP_HELPER_H ++#define LDAP_HELPER_H ++ ++extern int config_exclusive_config_file; ++extern int config_warning_config_file; ++ ++#endif /* LDAP_HELPER_H */ +Index: openssh-8.9p1/ldap.conf +=================================================================== +--- /dev/null ++++ openssh-8.9p1/ldap.conf +@@ -0,0 +1,88 @@ ++# $Id: openssh-5.5p1-ldap.patch,v 1.3 2010/07/07 13:48:36 jfch2222 Exp $ ++# ++# This is the example configuration file for the OpenSSH ++# LDAP backend ++# ++# see ssh-ldap.conf(5) ++# ++ ++# URI with your LDAP server name. This allows to use ++# Unix Domain Sockets to connect to a local LDAP Server. ++#uri ldap://127.0.0.1/ ++#uri ldaps://127.0.0.1/ ++#uri ldapi://%2fvar%2frun%2fldapi_sock/ ++# Note: %2f encodes the '/' used as directory separator ++ ++# Another way to specify your LDAP server is to provide an ++# host name and the port of our LDAP server. Host name ++# must be resolvable without using LDAP. ++# Multiple hosts may be specified, each separated by a ++# space. How long nss_ldap takes to failover depends on ++# whether your LDAP client library supports configurable ++# network or connect timeouts (see bind_timelimit). ++#host 127.0.0.1 ++ ++# The port. ++# Optional: default is 389. ++#port 389 ++ ++# The distinguished name to bind to the server with. ++# Optional: default is to bind anonymously. ++#binddn cn=openssh_keys,dc=example,dc=org ++ ++# The credentials to bind with. ++# Optional: default is no credential. ++#bindpw TopSecret ++ ++# The distinguished name of the search base. ++#base dc=example,dc=org ++ ++# The LDAP version to use (defaults to 3 ++# if supported by client library) ++#ldap_version 3 ++ ++# The search scope. ++#scope sub ++#scope one ++#scope base ++ ++# Search timelimit ++#timelimit 30 ++ ++# Bind/connect timelimit ++#bind_timelimit 30 ++ ++# Reconnect policy: hard (default) will retry connecting to ++# the software with exponential backoff, soft will fail ++# immediately. ++#bind_policy hard ++ ++# SSL setup, may be implied by URI also. ++#ssl no ++#ssl on ++#ssl start_tls ++ ++# OpenLDAP SSL options ++# Require and verify server certificate (yes/no) ++# Default is to use libldap's default behavior, which can be configured in ++# /etc/openldap/ldap.conf using the TLS_REQCERT setting. The default for ++# OpenLDAP 2.0 and earlier is "no", for 2.1 and later is "yes". ++#tls_checkpeer hard ++ ++# CA certificates for server certificate verification ++# At least one of these are required if tls_checkpeer is "yes" ++#tls_cacertfile /etc/ssl/ca.cert ++#tls_cacertdir /etc/pki/tls/certs ++ ++# Seed the PRNG if /dev/urandom is not provided ++#tls_randfile /var/run/egd-pool ++ ++# SSL cipher suite ++# See man ciphers for syntax ++#tls_ciphers TLSv1 ++ ++# Client certificate and key ++# Use these, if your server requires client authentication. ++#tls_cert ++#tls_key ++ +Index: openssh-8.9p1/ldapbody.c +=================================================================== +--- /dev/null ++++ openssh-8.9p1/ldapbody.c +@@ -0,0 +1,503 @@ ++/* $OpenBSD: ldapbody.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ ++/* ++ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. ++ * ++ * 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. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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 "ldapincludes.h" ++#include "log.h" ++#include "xmalloc.h" ++#include "ldapconf.h" ++#include "ldapmisc.h" ++#include "ldapbody.h" ++#include ++#include ++#include ++ ++#ifndef FALSE ++# define FALSE 0 ++#endif ++ ++#ifndef TRUE ++# define TRUE 1 ++#endif ++ ++#define LDAPSEARCH_FORMAT "(&(objectclass=posixAccount)(objectclass=ldapPublicKey)(uid=%s)%s)" ++#define PUBKEYATTR "sshPublicKey" ++#define LDAP_LOGFILE "%s/ldap.%d" ++ ++static FILE *logfile = NULL; ++static LDAP *ld; ++ ++static char *attrs[] = { ++ PUBKEYATTR, ++ NULL ++}; ++ ++void ++ldap_checkconfig (void) ++{ ++#ifdef HAVE_LDAP_INITIALIZE ++ if (options.host == NULL && options.uri == NULL) ++#else ++ if (options.host == NULL) ++#endif ++ fatal ("missing \"host\" in config file"); ++} ++ ++#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) ++static int ++_rebind_proc (LDAP * ld, LDAP_CONST char *url, int request, ber_int_t msgid) ++{ ++ struct timeval timeout; ++ int rc; ++#if defined(HAVE_LDAP_PARSE_RESULT) && defined(HAVE_LDAP_CONTROLS_FREE) ++ LDAPMessage *result; ++#endif /* HAVE_LDAP_PARSE_RESULT && HAVE_LDAP_CONTROLS_FREE */ ++ ++ debug2 ("Doing LDAP rebind to %s", options.binddn); ++ if (options.ssl == SSL_START_TLS) { ++ if ((rc = ldap_start_tls_s (ld, NULL, NULL)) != LDAP_SUCCESS) { ++ error ("ldap_starttls_s: %s", ldap_err2string (rc)); ++ return LDAP_OPERATIONS_ERROR; ++ } ++ } ++ ++#if !defined(HAVE_LDAP_PARSE_RESULT) || !defined(HAVE_LDAP_CONTROLS_FREE) ++ return ldap_simple_bind_s (ld, options.binddn, options.bindpw); ++#else ++ if (ldap_simple_bind(ld, options.binddn, options.bindpw) < 0) ++ fatal ("ldap_simple_bind %s", ldap_err2string (ldap_get_lderrno (ld, 0, 0))); ++ ++ timeout.tv_sec = options.bind_timelimit; ++ timeout.tv_usec = 0; ++ result = NULL; ++ if ((rc = ldap_result (ld, msgid, FALSE, &timeout, &result)) < 1) { ++ error ("ldap_result %s", ldap_err2string (ldap_get_lderrno (ld, 0, 0))); ++ ldap_msgfree (result); ++ return LDAP_OPERATIONS_ERROR; ++ } ++ debug3 ("LDAP rebind to %s succesfull", options.binddn); ++ return rc; ++#endif ++} ++#else ++ ++static int ++_rebind_proc (LDAP * ld, char **whop, char **credp, int *methodp, int freeit) ++{ ++ if (freeit) ++ return LDAP_SUCCESS; ++ ++ *whop = strdup (options.binddn); ++ *credp = strdup (options.bindpw); ++ *methodp = LDAP_AUTH_SIMPLE; ++ debug2 ("Doing LDAP rebind for %s", *whop); ++ return LDAP_SUCCESS; ++} ++#endif ++ ++void ++ldap_do_connect(void) ++{ ++ int rc, msgid, ld_errno = 0; ++ struct timeval timeout; ++#if defined(HAVE_LDAP_PARSE_RESULT) && defined(HAVE_LDAP_CONTROLS_FREE) ++ int parserc; ++ LDAPMessage *result; ++ LDAPControl **controls; ++ int reconnect = 0; ++#endif /* HAVE_LDAP_PARSE_RESULT && HAVE_LDAP_CONTROLS_FREE */ ++ ++ debug ("LDAP do connect"); ++ ++retry: ++ if (reconnect) { ++ debug3 ("Reconnecting with ld_errno %d", ld_errno); ++ if (options.bind_policy == 0 || ++ (ld_errno != LDAP_SERVER_DOWN && ld_errno != LDAP_TIMEOUT) || ++ reconnect > 5) ++ fatal ("Cannot connect to LDAP server"); ++ ++ if (reconnect > 1) ++ sleep (reconnect - 1); ++ ++ if (ld != NULL) { ++ ldap_unbind (ld); ++ ld = NULL; ++ } ++ logit("reconnecting to LDAP server..."); ++ } ++ ++ if (ld == NULL) { ++ int rc; ++ struct timeval tv; ++ ++#ifdef HAVE_LDAP_SET_OPTION ++ if (options.debug > 0) { ++#ifdef LBER_OPT_LOG_PRINT_FILE ++ if (options.logdir) { ++ char *logfilename; ++ int logfilenamelen; ++ ++ logfilenamelen = strlen (LDAP_LOGFILE) + strlen ("000000") + strlen (options.logdir); ++ logfilename = xmalloc (logfilenamelen); ++ snprintf (logfilename, logfilenamelen, LDAP_LOGFILE, options.logdir, (int) getpid ()); ++ logfilename[logfilenamelen - 1] = 0; ++ if ((logfile = fopen (logfilename, "a")) == NULL) ++ fatal ("cannot append to %s: %s", logfilename, strerror (errno)); ++ debug3 ("LDAP debug into %s", logfilename); ++ free (logfilename); ++ ber_set_option (NULL, LBER_OPT_LOG_PRINT_FILE, logfile); ++ } ++#endif ++ if (options.debug) { ++#ifdef LBER_OPT_DEBUG_LEVEL ++ ber_set_option (NULL, LBER_OPT_DEBUG_LEVEL, &options.debug); ++#endif /* LBER_OPT_DEBUG_LEVEL */ ++#ifdef LDAP_OPT_DEBUG_LEVEL ++ ldap_set_option (NULL, LDAP_OPT_DEBUG_LEVEL, &options.debug); ++#endif /* LDAP_OPT_DEBUG_LEVEL */ ++ debug3 ("Set LDAP debug to %d", options.debug); ++ } ++ } ++#endif /* HAVE_LDAP_SET_OPTION */ ++ ++ ld = NULL; ++#ifdef HAVE_LDAPSSL_INIT ++ if (options.host != NULL) { ++ if (options.ssl_on == SSL_LDAPS) { ++ if ((rc = ldapssl_client_init (options.sslpath, NULL)) != LDAP_SUCCESS) ++ fatal ("ldapssl_client_init %s", ldap_err2string (rc)); ++ debug3 ("LDAPssl client init"); ++ } ++ ++ if (options.ssl_on != SSL_OFF) { ++ if ((ld = ldapssl_init (options.host, options.port, TRUE)) == NULL) ++ fatal ("ldapssl_init failed"); ++ debug3 ("LDAPssl init"); ++ } ++ } ++#endif /* HAVE_LDAPSSL_INIT */ ++ ++ /* continue with opening */ ++ if (ld == NULL) { ++#if defined (HAVE_LDAP_START_TLS_S) || (defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_X_TLS)) ++ /* Some global TLS-specific options need to be set before we create our ++ * session context, so we set them here. */ ++ ++#ifdef LDAP_OPT_X_TLS_RANDOM_FILE ++ /* rand file */ ++ if (options.tls_randfile != NULL) { ++ if ((rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_RANDOM_FILE, ++ options.tls_randfile)) != LDAP_SUCCESS) ++ fatal ("ldap_set_option(LDAP_OPT_X_TLS_RANDOM_FILE): %s", ++ ldap_err2string (rc)); ++ debug3 ("Set TLS random file %s", options.tls_randfile); ++ } ++#endif /* LDAP_OPT_X_TLS_RANDOM_FILE */ ++ ++ /* ca cert file */ ++ if (options.tls_cacertfile != NULL) { ++ if ((rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CACERTFILE, ++ options.tls_cacertfile)) != LDAP_SUCCESS) ++ error ("ldap_set_option(LDAP_OPT_X_TLS_CACERTFILE): %s", ++ ldap_err2string (rc)); ++ debug3 ("Set TLS CA cert file %s ", options.tls_cacertfile); ++ } ++ ++ /* ca cert directory */ ++ if (options.tls_cacertdir != NULL) { ++ if ((rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CACERTDIR, ++ options.tls_cacertdir)) != LDAP_SUCCESS) ++ fatal ("ldap_set_option(LDAP_OPT_X_TLS_CACERTDIR): %s", ++ ldap_err2string (rc)); ++ debug3 ("Set TLS CA cert dir %s ", options.tls_cacertdir); ++ } ++ ++ /* require cert? */ ++ if ((rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, ++ &options.tls_checkpeer)) != LDAP_SUCCESS) ++ fatal ("ldap_set_option(LDAP_OPT_X_TLS_REQUIRE_CERT): %s", ++ ldap_err2string (rc)); ++ debug3 ("Set TLS check peer to %d ", options.tls_checkpeer); ++ ++ /* set cipher suite, certificate and private key: */ ++ if (options.tls_ciphers != NULL) { ++ if ((rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CIPHER_SUITE, ++ options.tls_ciphers)) != LDAP_SUCCESS) ++ fatal ("ldap_set_option(LDAP_OPT_X_TLS_CIPHER_SUITE): %s", ++ ldap_err2string (rc)); ++ debug3 ("Set TLS ciphers to %s ", options.tls_ciphers); ++ } ++ ++ /* cert file */ ++ if (options.tls_cert != NULL) { ++ if ((rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CERTFILE, ++ options.tls_cert)) != LDAP_SUCCESS) ++ fatal ("ldap_set_option(LDAP_OPT_X_TLS_CERTFILE): %s", ++ ldap_err2string (rc)); ++ debug3 ("Set TLS cert file %s ", options.tls_cert); ++ } ++ ++ /* key file */ ++ if (options.tls_key != NULL) { ++ if ((rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_KEYFILE, ++ options.tls_key)) != LDAP_SUCCESS) ++ fatal ("ldap_set_option(LDAP_OPT_X_TLS_KEYFILE): %s", ++ ldap_err2string (rc)); ++ debug3 ("Set TLS key file %s ", options.tls_key); ++ } ++#endif ++#ifdef HAVE_LDAP_INITIALIZE ++ if (options.uri != NULL) { ++ if ((rc = ldap_initialize (&ld, options.uri)) != LDAP_SUCCESS) ++ fatal ("ldap_initialize %s", ldap_err2string (rc)); ++ debug3 ("LDAP initialize %s", options.uri); ++ } ++ } ++#endif /* HAVE_LDAP_INTITIALIZE */ ++ ++ /* continue with opening */ ++ if ((ld == NULL) && (options.host != NULL)) { ++#ifdef HAVE_LDAP_INIT ++ if ((ld = ldap_init (options.host, options.port)) == NULL) ++ fatal ("ldap_init failed"); ++ debug3 ("LDAP init %s:%d", options.host, options.port); ++#else ++ if ((ld = ldap_open (options.host, options.port)) == NULL) ++ fatal ("ldap_open failed"); ++ debug3 ("LDAP open %s:%d", options.host, options.port); ++#endif /* HAVE_LDAP_INIT */ ++ } ++ ++ if (ld == NULL) ++ fatal ("no way to open ldap"); ++ ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_X_TLS) ++ if (options.ssl == SSL_LDAPS) { ++ if ((rc = ldap_set_option (ld, LDAP_OPT_X_TLS, &options.tls_checkpeer)) != LDAP_SUCCESS) ++ fatal ("ldap_set_option(LDAP_OPT_X_TLS) %s", ldap_err2string (rc)); ++ debug3 ("LDAP set LDAP_OPT_X_TLS_%d", options.tls_checkpeer); ++ } ++#endif /* LDAP_OPT_X_TLS */ ++ ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_PROTOCOL_VERSION) ++ (void) ldap_set_option (ld, LDAP_OPT_PROTOCOL_VERSION, ++ &options.ldap_version); ++#else ++ ld->ld_version = options.ldap_version; ++#endif ++ debug3 ("LDAP set version to %d", options.ldap_version); ++ ++#if LDAP_SET_REBIND_PROC_ARGS == 3 ++ ldap_set_rebind_proc (ld, _rebind_proc, NULL); ++#elif LDAP_SET_REBIND_PROC_ARGS == 2 ++ ldap_set_rebind_proc (ld, _rebind_proc); ++#else ++#warning unknown LDAP_SET_REBIND_PROC_ARGS ++#endif ++ debug3 ("LDAP set rebind proc"); ++ ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_DEREF) ++ (void) ldap_set_option (ld, LDAP_OPT_DEREF, &options.deref); ++#else ++ ld->ld_deref = options.deref; ++#endif ++ debug3 ("LDAP set deref to %d", options.deref); ++ ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_TIMELIMIT) ++ (void) ldap_set_option (ld, LDAP_OPT_TIMELIMIT, ++ &options.timelimit); ++#else ++ ld->ld_timelimit = options.timelimit; ++#endif ++ debug3 ("LDAP set timelimit to %d", options.timelimit); ++ ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_X_OPT_CONNECT_TIMEOUT) ++ /* ++ * This is a new option in the Netscape SDK which sets ++ * the TCP connect timeout. For want of a better value, ++ * we use the bind_timelimit to control this. ++ */ ++ timeout = options.bind_timelimit * 1000; ++ (void) ldap_set_option (ld, LDAP_X_OPT_CONNECT_TIMEOUT, &timeout); ++ debug3 ("LDAP set opt connect timeout to %d", timeout); ++#endif ++ ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_NETWORK_TIMEOUT) ++ tv.tv_sec = options.bind_timelimit; ++ tv.tv_usec = 0; ++ (void) ldap_set_option (ld, LDAP_OPT_NETWORK_TIMEOUT, &tv); ++ debug3 ("LDAP set opt network timeout to %ld.0", tv.tv_sec); ++#endif ++ ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_REFERRALS) ++ (void) ldap_set_option (ld, LDAP_OPT_REFERRALS, ++ options.referrals ? LDAP_OPT_ON : LDAP_OPT_OFF); ++ debug3 ("LDAP set referrals to %d", options.referrals); ++#endif ++ ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_RESTART) ++ (void) ldap_set_option (ld, LDAP_OPT_RESTART, ++ options.restart ? LDAP_OPT_ON : LDAP_OPT_OFF); ++ debug3 ("LDAP set restart to %d", options.restart); ++#endif ++ ++#ifdef HAVE_LDAP_START_TLS_S ++ if (options.ssl == SSL_START_TLS) { ++ int version; ++ ++ if (ldap_get_option (ld, LDAP_OPT_PROTOCOL_VERSION, &version) ++ == LDAP_SUCCESS) { ++ if (version < LDAP_VERSION3) { ++ version = LDAP_VERSION3; ++ (void) ldap_set_option (ld, LDAP_OPT_PROTOCOL_VERSION, ++ &version); ++ debug3 ("LDAP set version to %d", version); ++ } ++ } ++ ++ if ((rc = ldap_start_tls_s (ld, NULL, NULL)) != LDAP_SUCCESS) ++ fatal ("ldap_starttls_s: %s", ldap_err2string (rc)); ++ debug3 ("LDAP start TLS"); ++ } ++#endif /* HAVE_LDAP_START_TLS_S */ ++ } ++ ++ if ((msgid = ldap_simple_bind (ld, options.binddn, ++ options.bindpw)) == -1) { ++ ld_errno = ldap_get_lderrno (ld, 0, 0); ++ ++ error ("ldap_simple_bind %s", ldap_err2string (ld_errno)); ++ reconnect++; ++ goto retry; ++ } ++ debug3 ("LDAP simple bind (%s)", options.binddn); ++ ++ timeout.tv_sec = options.bind_timelimit; ++ timeout.tv_usec = 0; ++ if ((rc = ldap_result (ld, msgid, FALSE, &timeout, &result)) < 1) { ++ ld_errno = ldap_get_lderrno (ld, 0, 0); ++ ++ error ("ldap_result %s", ldap_err2string (ld_errno)); ++ reconnect++; ++ goto retry; ++ } ++ debug3 ("LDAP result in time"); ++ ++#if defined(HAVE_LDAP_PARSE_RESULT) && defined(HAVE_LDAP_CONTROLS_FREE) ++ controls = NULL; ++ if ((parserc = ldap_parse_result (ld, result, &rc, 0, 0, 0, &controls, TRUE)) != LDAP_SUCCESS) ++ fatal ("ldap_parse_result %s", ldap_err2string (parserc)); ++ debug3 ("LDAP parse result OK"); ++ ++ if (controls != NULL) { ++ ldap_controls_free (controls); ++ } ++#else ++ rc = ldap_result2error (session->ld, result, TRUE); ++#endif ++ if (rc != LDAP_SUCCESS) ++ fatal ("error trying to bind as user \"%s\" (%s)", ++ options.binddn, ldap_err2string (rc)); ++ ++ debug2 ("LDAP do connect OK"); ++} ++ ++void ++process_user (const char *user, FILE *output) ++{ ++ LDAPMessage *res, *e; ++ char *buffer; ++ int bufflen, rc, i; ++ struct timeval timeout; ++ ++ debug ("LDAP process user"); ++ ++ /* quick check for attempts to be evil */ ++ if ((strchr(user, '(') != NULL) || (strchr(user, ')') != NULL) || ++ (strchr(user, '*') != NULL) || (strchr(user, '\\') != NULL)) { ++ logit ("illegal user name %s not processed", user); ++ return; ++ } ++ ++ /* build filter for LDAP request */ ++ bufflen = strlen (LDAPSEARCH_FORMAT) + strlen (user); ++ if (options.ssh_filter != NULL) ++ bufflen += strlen (options.ssh_filter); ++ buffer = xmalloc (bufflen); ++ snprintf(buffer, bufflen, LDAPSEARCH_FORMAT, user, (options.ssh_filter != NULL) ? options.ssh_filter : NULL); ++ buffer[bufflen - 1] = 0; ++ ++ debug3 ("LDAP search scope = %d %s", options.scope, buffer); ++ ++ timeout.tv_sec = options.timelimit; ++ timeout.tv_usec = 0; ++ if ((rc = ldap_search_st(ld, options.base, options.scope, buffer, attrs, 0, &timeout, &res)) != LDAP_SUCCESS) { ++ error ("ldap_search_st(): %s", ldap_err2string (rc)); ++ free (buffer); ++ return; ++ } ++ ++ /* free */ ++ free (buffer); ++ ++ for (e = ldap_first_entry(ld, res); e != NULL; e = ldap_next_entry(ld, e)) { ++ int num; ++ struct berval **keys; ++ ++ keys = ldap_get_values_len(ld, e, PUBKEYATTR); ++ num = ldap_count_values_len(keys); ++ for (i = 0 ; i < num ; i++) { ++ char *cp; //, *options = NULL; ++ ++ for (cp = keys[i]->bv_val; *cp == ' ' || *cp == '\t'; cp++); ++ if (!*cp || *cp == '\n' || *cp == '#') ++ continue; ++ ++ /* We have found the desired key. */ ++ fprintf (output, "%s\n", keys[i]->bv_val); ++ } ++ ++ ldap_value_free_len(keys); ++ } ++ ++ ldap_msgfree(res); ++ debug2 ("LDAP process user finished"); ++} ++ ++void ++ldap_do_close(void) ++{ ++ int rc; ++ ++ debug ("LDAP do close"); ++ if ((rc = ldap_unbind_ext(ld, NULL, NULL)) != LDAP_SUCCESS) ++ fatal ("ldap_unbind_ext: %s", ++ ldap_err2string (rc)); ++ ++ ld = NULL; ++ debug2 ("LDAP do close OK"); ++ return; ++} ++ +Index: openssh-8.9p1/ldapbody.h +=================================================================== +--- /dev/null ++++ openssh-8.9p1/ldapbody.h +@@ -0,0 +1,37 @@ ++/* $OpenBSD: ldapbody.h,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ ++/* ++ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. ++ * ++ * 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. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. ++ */ ++ ++#ifndef LDAPBODY_H ++#define LDAPBODY_H ++ ++#include ++ ++void ldap_checkconfig(void); ++void ldap_do_connect(void); ++void process_user(const char *, FILE *); ++void ldap_do_close(void); ++ ++#endif /* LDAPBODY_H */ ++ +Index: openssh-8.9p1/ldapconf.c +=================================================================== +--- /dev/null ++++ openssh-8.9p1/ldapconf.c +@@ -0,0 +1,711 @@ ++/* $OpenBSD: ldapconf.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ ++/* ++ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. ++ * ++ * 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. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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 "ldapincludes.h" ++#include "ldap-helper.h" ++#include "log.h" ++#include "misc.h" ++#include "xmalloc.h" ++#include "ldapconf.h" ++#include ++#include ++ ++/* Keyword tokens. */ ++ ++typedef enum { ++ lBadOption, ++ lHost, lURI, lBase, lBindDN, lBindPW, lRootBindDN, ++ lScope, lDeref, lPort, lTimeLimit, lBind_TimeLimit, ++ lLdap_Version, lBind_Policy, lSSLPath, lSSL, lReferrals, ++ lRestart, lTLS_CheckPeer, lTLS_CaCertFile, ++ lTLS_CaCertDir, lTLS_Ciphers, lTLS_Cert, lTLS_Key, ++ lTLS_RandFile, lLogDir, lDebug, lSSH_Filter, ++ lDeprecated, lUnsupported ++} OpCodes; ++ ++/* Textual representations of the tokens. */ ++ ++static struct { ++ const char *name; ++ OpCodes opcode; ++} keywords[] = { ++ { "URI", lURI }, ++ { "Base", lBase }, ++ { "BindDN", lBindDN }, ++ { "BindPW", lBindPW }, ++ { "RootBindDN", lRootBindDN }, ++ { "Host", lHost }, ++ { "Port", lPort }, ++ { "Scope", lScope }, ++ { "Deref", lDeref }, ++ { "TimeLimit", lTimeLimit }, ++ { "TimeOut", lTimeLimit }, ++ { "Bind_Timelimit", lBind_TimeLimit }, ++ { "Network_TimeOut", lBind_TimeLimit }, ++/* ++ * Todo ++ * SIZELIMIT ++ */ ++ { "Ldap_Version", lLdap_Version }, ++ { "Version", lLdap_Version }, ++ { "Bind_Policy", lBind_Policy }, ++ { "SSLPath", lSSLPath }, ++ { "SSL", lSSL }, ++ { "Referrals", lReferrals }, ++ { "Restart", lRestart }, ++ { "TLS_CheckPeer", lTLS_CheckPeer }, ++ { "TLS_ReqCert", lTLS_CheckPeer }, ++ { "TLS_CaCertFile", lTLS_CaCertFile }, ++ { "TLS_CaCert", lTLS_CaCertFile }, ++ { "TLS_CaCertDir", lTLS_CaCertDir }, ++ { "TLS_Ciphers", lTLS_Ciphers }, ++ { "TLS_Cipher_Suite", lTLS_Ciphers }, ++ { "TLS_Cert", lTLS_Cert }, ++ { "TLS_Certificate", lTLS_Cert }, ++ { "TLS_Key", lTLS_Key }, ++ { "TLS_RandFile", lTLS_RandFile }, ++/* ++ * Todo ++ * TLS_CRLCHECK ++ * TLS_CRLFILE ++ */ ++ { "LogDir", lLogDir }, ++ { "Debug", lDebug }, ++ { "SSH_Filter", lSSH_Filter }, ++ { NULL, lBadOption } ++}; ++ ++/* Configuration ptions. */ ++ ++Options options; ++ ++/* ++ * Returns the number of the token pointed to by cp or oBadOption. ++ */ ++ ++static OpCodes ++parse_token(const char *cp, const char *filename, int linenum) ++{ ++ u_int i; ++ ++ for (i = 0; keywords[i].name; i++) ++ if (strcasecmp(cp, keywords[i].name) == 0) ++ return keywords[i].opcode; ++ ++ if (config_warning_config_file) ++ logit("%s: line %d: Bad configuration option: %s", ++ filename, linenum, cp); ++ return lBadOption; ++} ++ ++/* ++ * Processes a single option line as used in the configuration files. This ++ * only sets those values that have not already been set. ++ */ ++#define WHITESPACE " \t\r\n" ++ ++static int ++process_config_line(char *line, const char *filename, int linenum) ++{ ++ char *s, **charptr, **xstringptr, *endofnumber, *keyword, *arg; ++ char *rootbinddn = NULL; ++ int opcode, *intptr, value; ++ size_t len; ++ ++ /* Strip trailing whitespace */ ++ for (len = strlen(line) - 1; len > 0; len--) { ++ if (strchr(WHITESPACE, line[len]) == NULL) ++ break; ++ line[len] = '\0'; ++ } ++ ++ s = line; ++ /* Get the keyword. (Each line is supposed to begin with a keyword). */ ++ if ((keyword = strdelim(&s)) == NULL) ++ return 0; ++ /* Ignore leading whitespace. */ ++ if (*keyword == '\0') ++ keyword = strdelim(&s); ++ if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#') ++ return 0; ++ ++ opcode = parse_token(keyword, filename, linenum); ++ ++ switch (opcode) { ++ case lBadOption: ++ /* don't panic, but count bad options */ ++ return -1; ++ /* NOTREACHED */ ++ ++ case lHost: ++ xstringptr = &options.host; ++parse_xstring: ++ if (!s || *s == '\0') ++ fatal("%s line %d: missing dn",filename,linenum); ++ if (*xstringptr == NULL) ++ *xstringptr = xstrdup(s); ++ return 0; ++ ++ case lURI: ++ xstringptr = &options.uri; ++ goto parse_xstring; ++ ++ case lBase: ++ xstringptr = &options.base; ++ goto parse_xstring; ++ ++ case lBindDN: ++ xstringptr = &options.binddn; ++ goto parse_xstring; ++ ++ case lBindPW: ++ charptr = &options.bindpw; ++parse_string: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", filename, linenum); ++ if (*charptr == NULL) ++ *charptr = xstrdup(arg); ++ break; ++ ++ case lRootBindDN: ++ xstringptr = &rootbinddn; ++ goto parse_xstring; ++ ++ case lScope: ++ intptr = &options.scope; ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing sub/one/base argument.", ++ filename, linenum); ++ value = 0; /* To avoid compiler warning... */ ++ if (strcasecmp(arg, "sub") == 0 || ++ strcasecmp(arg, "subtree") == 0) ++ value = LDAP_SCOPE_SUBTREE; ++ else if (strcasecmp(arg, "one") == 0) ++ value = LDAP_SCOPE_ONELEVEL; ++ else if (strcasecmp(arg, "base") == 0) ++ value = LDAP_SCOPE_BASE; ++ else ++ fatal("%.200s line %d: Bad sub/one/base argument.", ++ filename, linenum); ++ if (*intptr == -1) ++ *intptr = value; ++ break; ++ ++ case lDeref: ++ intptr = &options.scope; ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing never/searching/finding/always argument.", ++ filename, linenum); ++ value = 0; /* To avoid compiler warning... */ ++ if (!strcasecmp(arg, "never")) ++ value = LDAP_DEREF_NEVER; ++ else if (!strcasecmp(arg, "searching")) ++ value = LDAP_DEREF_SEARCHING; ++ else if (!strcasecmp(arg, "finding")) ++ value = LDAP_DEREF_FINDING; ++ else if (!strcasecmp(arg, "always")) ++ value = LDAP_DEREF_ALWAYS; ++ else ++ fatal("%.200s line %d: Bad never/searching/finding/always argument.", ++ filename, linenum); ++ if (*intptr == -1) ++ *intptr = value; ++ break; ++ ++ case lPort: ++ intptr = &options.port; ++parse_int: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", filename, linenum); ++ if (arg[0] < '0' || arg[0] > '9') ++ fatal("%.200s line %d: Bad number.", filename, linenum); ++ ++ /* Octal, decimal, or hex format? */ ++ value = strtol(arg, &endofnumber, 0); ++ if (arg == endofnumber) ++ fatal("%.200s line %d: Bad number.", filename, linenum); ++ if (*intptr == -1) ++ *intptr = value; ++ break; ++ ++ case lTimeLimit: ++ intptr = &options.timelimit; ++parse_time: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%s line %d: missing time value.", ++ filename, linenum); ++ if ((value = convtime(arg)) == -1) ++ fatal("%s line %d: invalid time value.", ++ filename, linenum); ++ if (*intptr == -1) ++ *intptr = value; ++ break; ++ ++ case lBind_TimeLimit: ++ intptr = &options.bind_timelimit; ++ goto parse_time; ++ ++ case lLdap_Version: ++ intptr = &options.ldap_version; ++ goto parse_int; ++ ++ case lBind_Policy: ++ intptr = &options.bind_policy; ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing soft/hard argument.", ++ filename, linenum); ++ value = 0; /* To avoid compiler warning... */ ++ if (strcasecmp(arg, "hard") == 0 || ++ strcasecmp(arg, "hard_open") == 0 || ++ strcasecmp(arg, "hard_init") == 0) ++ value = 1; ++ else if (strcasecmp(arg, "soft") == 0) ++ value = 0; ++ else ++ fatal("%.200s line %d: Bad soft/hard argument.", ++ filename, linenum); ++ if (*intptr == -1) ++ break; ++ ++ case lSSLPath: ++ charptr = &options.sslpath; ++ goto parse_string; ++ ++ case lSSL: ++ intptr = &options.ssl; ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing yes/no/start_tls argument.", ++ filename, linenum); ++ value = 0; /* To avoid compiler warning... */ ++ if (strcasecmp(arg, "yes") == 0 || ++ strcasecmp(arg, "true") == 0 || ++ strcasecmp(arg, "on") == 0) ++ value = SSL_LDAPS; ++ else if (strcasecmp(arg, "no") == 0 || ++ strcasecmp(arg, "false") == 0 || ++ strcasecmp(arg, "off") == 0) ++ value = SSL_OFF; ++ else if (!strcasecmp (arg, "start_tls")) ++ value = SSL_START_TLS; ++ else ++ fatal("%.200s line %d: Bad yes/no/start_tls argument.", ++ filename, linenum); ++ if (*intptr == -1) ++ *intptr = value; ++ break; ++ ++ case lReferrals: ++ intptr = &options.referrals; ++parse_flag: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing yes/no argument.", ++ filename, linenum); ++ value = 0; /* To avoid compiler warning... */ ++ if (strcasecmp(arg, "yes") == 0 || ++ strcasecmp(arg, "true") == 0 || ++ strcasecmp(arg, "on") == 0) ++ value = 1; ++ else if (strcasecmp(arg, "no") == 0 || ++ strcasecmp(arg, "false") == 0 || ++ strcasecmp(arg, "off") == 0) ++ value = 0; ++ else ++ fatal("%.200s line %d: Bad yes/no argument.", ++ filename, linenum); ++ if (*intptr == -1) ++ *intptr = value; ++ break; ++ ++ case lRestart: ++ intptr = &options.restart; ++ goto parse_flag; ++ ++ case lTLS_CheckPeer: ++ intptr = &options.tls_checkpeer; ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing never/hard/demand/alow/try argument.", ++ filename, linenum); ++ value = 0; /* To avoid compiler warning... */ ++ if (strcasecmp(arg, "never") == 0 || ++ strcasecmp(arg, "no") == 0 || ++ strcasecmp(arg, "false") == 0 || ++ strcasecmp(arg, "off") == 0) ++ value = LDAP_OPT_X_TLS_NEVER; ++ else if (strcasecmp(arg, "hard") == 0 || ++ strcasecmp(arg, "yes") == 0 || ++ strcasecmp(arg, "true") == 0 || ++ strcasecmp(arg, "on") == 0) ++ value = LDAP_OPT_X_TLS_HARD; ++ else if (strcasecmp(arg, "demand") == 0) ++ value = LDAP_OPT_X_TLS_DEMAND; ++ else if (strcasecmp(arg, "allow") == 0) ++ value = LDAP_OPT_X_TLS_ALLOW; ++ else if (strcasecmp(arg, "try") == 0) ++ value = LDAP_OPT_X_TLS_TRY; ++ else ++ fatal("%.200s line %d: Bad never/hard/demand/alow/try argument.", ++ filename, linenum); ++ if (*intptr == -1) ++ break; ++ ++ case lTLS_CaCertFile: ++ charptr = &options.tls_cacertfile; ++ goto parse_string; ++ ++ case lTLS_CaCertDir: ++ charptr = &options.tls_cacertdir; ++ goto parse_string; ++ ++ case lTLS_Ciphers: ++ xstringptr = &options.tls_ciphers; ++ goto parse_xstring; ++ ++ case lTLS_Cert: ++ charptr = &options.tls_cert; ++ goto parse_string; ++ ++ case lTLS_Key: ++ charptr = &options.tls_key; ++ goto parse_string; ++ ++ case lTLS_RandFile: ++ charptr = &options.tls_randfile; ++ goto parse_string; ++ ++ case lLogDir: ++ charptr = &options.logdir; ++ goto parse_string; ++ ++ case lDebug: ++ intptr = &options.debug; ++ goto parse_int; ++ ++ case lSSH_Filter: ++ xstringptr = &options.ssh_filter; ++ goto parse_xstring; ++ ++ case lDeprecated: ++ debug("%s line %d: Deprecated option \"%s\"", ++ filename, linenum, keyword); ++ return 0; ++ ++ case lUnsupported: ++ error("%s line %d: Unsupported option \"%s\"", ++ filename, linenum, keyword); ++ return 0; ++ ++ default: ++ fatal("process_config_line: Unimplemented opcode %d", opcode); ++ } ++ ++ /* Check that there is no garbage at end of line. */ ++ if ((arg = strdelim(&s)) != NULL && *arg != '\0') { ++ fatal("%.200s line %d: garbage at end of line; \"%.200s\".", ++ filename, linenum, arg); ++ } ++ return 0; ++} ++ ++/* ++ * Reads the config file and modifies the options accordingly. Options ++ * should already be initialized before this call. This never returns if ++ * there is an error. If the file does not exist, this returns 0. ++ */ ++ ++void ++read_config_file(const char *filename) ++{ ++ FILE *f; ++ char line[1024]; ++ int active, linenum; ++ int bad_options = 0; ++ struct stat sb; ++ ++ if ((f = fopen(filename, "r")) == NULL) ++ fatal("fopen %s: %s", filename, strerror(errno)); ++ ++ if (fstat(fileno(f), &sb) == -1) ++ fatal("fstat %s: %s", filename, strerror(errno)); ++ if (((sb.st_uid != 0 && sb.st_uid != getuid()) || ++ (sb.st_mode & 022) != 0)) ++ fatal("Bad owner or permissions on %s", filename); ++ ++ debug("Reading configuration data %.200s", filename); ++ ++ /* ++ * Mark that we are now processing the options. This flag is turned ++ * on/off by Host specifications. ++ */ ++ active = 1; ++ linenum = 0; ++ while (fgets(line, sizeof(line), f)) { ++ /* Update line number counter. */ ++ linenum++; ++ if (process_config_line(line, filename, linenum) != 0) ++ bad_options++; ++ } ++ fclose(f); ++ if ((bad_options > 0) && config_exclusive_config_file) ++ fatal("%s: terminating, %d bad configuration options", ++ filename, bad_options); ++} ++ ++/* ++ * Initializes options to special values that indicate that they have not yet ++ * been set. Read_config_file will only set options with this value. Options ++ * are processed in the following order: command line, user config file, ++ * system config file. Last, fill_default_options is called. ++ */ ++ ++void ++initialize_options(void) ++{ ++ memset(&options, 'X', sizeof(options)); ++ options.host = NULL; ++ options.uri = NULL; ++ options.base = NULL; ++ options.binddn = NULL; ++ options.bindpw = NULL; ++ options.scope = -1; ++ options.deref = -1; ++ options.port = -1; ++ options.timelimit = -1; ++ options.bind_timelimit = -1; ++ options.ldap_version = -1; ++ options.bind_policy = -1; ++ options.sslpath = NULL; ++ options.ssl = -1; ++ options.referrals = -1; ++ options.restart = -1; ++ options.tls_checkpeer = -1; ++ options.tls_cacertfile = NULL; ++ options.tls_cacertdir = NULL; ++ options.tls_ciphers = NULL; ++ options.tls_cert = NULL; ++ options.tls_key = NULL; ++ options.tls_randfile = NULL; ++ options.logdir = NULL; ++ options.debug = -1; ++ options.ssh_filter = NULL; ++} ++ ++/* ++ * Called after processing other sources of option data, this fills those ++ * options for which no value has been specified with their default values. ++ */ ++ ++void ++fill_default_options(void) ++{ ++ if (options.uri != NULL) { ++ LDAPURLDesc *ludp; ++ ++ if (ldap_url_parse(options.uri, &ludp) == LDAP_SUCCESS) { ++ if (options.ssl == -1) { ++ if (strcmp(ludp->lud_scheme, "ldap") == 0) ++ options.ssl = 2; ++ if (strcmp(ludp->lud_scheme, "ldapi") == 0) ++ options.ssl = 0; ++ else if (strcmp(ludp->lud_scheme, "ldaps") == 0) ++ options.ssl = 1; ++ } ++ if (options.host == NULL) ++ options.host = xstrdup (ludp->lud_host); ++ if (options.port == -1) ++ options.port = ludp->lud_port; ++ ++ ldap_free_urldesc (ludp); ++ } ++ } ++ if (options.ssl == -1) ++ options.ssl = SSL_START_TLS; ++ if (options.port == -1) ++ options.port = (options.ssl == 0) ? 389 : 636; ++ if (options.uri == NULL) { ++ int len; ++#define MAXURILEN 4096 ++ ++ options.uri = xmalloc (MAXURILEN); ++ len = snprintf(options.uri, MAXURILEN, "ldap%s://%s:%d", ++ (options.ssl == 0) ? "" : "s", options.host, options.port); ++ options.uri[MAXURILEN - 1] = 0; ++ options.uri = xreallocarray(options.uri, len + 1, 1); ++ } ++ if (options.binddn == NULL) ++ options.binddn = ""; ++ if (options.bindpw == NULL) ++ options.bindpw = ""; ++ if (options.scope == -1) ++ options.scope = LDAP_SCOPE_SUBTREE; ++ if (options.deref == -1) ++ options.deref = LDAP_DEREF_NEVER; ++ if (options.timelimit == -1) ++ options.timelimit = 10; ++ if (options.bind_timelimit == -1) ++ options.bind_timelimit = 10; ++ if (options.ldap_version == -1) ++ options.ldap_version = 3; ++ if (options.bind_policy == -1) ++ options.bind_policy = 1; ++ if (options.referrals == -1) ++ options.referrals = 1; ++ if (options.restart == -1) ++ options.restart = 1; ++ if (options.tls_checkpeer == -1) ++ options.tls_checkpeer = LDAP_OPT_X_TLS_HARD; ++ if (options.debug == -1) ++ options.debug = 0; ++ if (options.ssh_filter == NULL) ++ options.ssh_filter = ""; ++} ++ ++static const char * ++lookup_opcode_name(OpCodes code) ++{ ++ u_int i; ++ ++ for (i = 0; keywords[i].name != NULL; i++) ++ if (keywords[i].opcode == code) ++ return(keywords[i].name); ++ return "UNKNOWN"; ++} ++ ++static void ++dump_cfg_string(OpCodes code, const char *val) ++{ ++ if (val == NULL) ++ debug3("%s ", lookup_opcode_name(code)); ++ else ++ debug3("%s %s", lookup_opcode_name(code), val); ++} ++ ++static void ++dump_cfg_int(OpCodes code, int val) ++{ ++ if (val == -1) ++ debug3("%s ", lookup_opcode_name(code)); ++ else ++ debug3("%s %d", lookup_opcode_name(code), val); ++} ++ ++struct names { ++ int value; ++ char *name; ++}; ++ ++static void ++dump_cfg_namedint(OpCodes code, int val, struct names *names) ++{ ++ u_int i; ++ ++ if (val == -1) ++ debug3("%s ", lookup_opcode_name(code)); ++ else { ++ for (i = 0; names[i].value != -1; i++) ++ if (names[i].value == val) { ++ debug3("%s %s", lookup_opcode_name(code), names[i].name); ++ return; ++ } ++ debug3("%s unknown: %d", lookup_opcode_name(code), val); ++ } ++} ++ ++static struct names _yesnotls[] = { ++ { 0, "No" }, ++ { 1, "Yes" }, ++ { 2, "Start_TLS" }, ++ { -1, NULL }}; ++ ++static struct names _scope[] = { ++ { LDAP_SCOPE_BASE, "Base" }, ++ { LDAP_SCOPE_ONELEVEL, "One" }, ++ { LDAP_SCOPE_SUBTREE, "Sub"}, ++ { -1, NULL }}; ++ ++static struct names _deref[] = { ++ { LDAP_DEREF_NEVER, "Never" }, ++ { LDAP_DEREF_SEARCHING, "Searching" }, ++ { LDAP_DEREF_FINDING, "Finding" }, ++ { LDAP_DEREF_ALWAYS, "Always" }, ++ { -1, NULL }}; ++ ++static struct names _yesno[] = { ++ { 0, "No" }, ++ { 1, "Yes" }, ++ { -1, NULL }}; ++ ++static struct names _bindpolicy[] = { ++ { 0, "Soft" }, ++ { 1, "Hard" }, ++ { -1, NULL }}; ++ ++static struct names _checkpeer[] = { ++ { LDAP_OPT_X_TLS_NEVER, "Never" }, ++ { LDAP_OPT_X_TLS_HARD, "Hard" }, ++ { LDAP_OPT_X_TLS_DEMAND, "Demand" }, ++ { LDAP_OPT_X_TLS_ALLOW, "Allow" }, ++ { LDAP_OPT_X_TLS_TRY, "TRY" }, ++ { -1, NULL }}; ++ ++void ++dump_config(void) ++{ ++ dump_cfg_string(lURI, options.uri); ++ dump_cfg_string(lHost, options.host); ++ dump_cfg_int(lPort, options.port); ++ dump_cfg_namedint(lSSL, options.ssl, _yesnotls); ++ dump_cfg_int(lLdap_Version, options.ldap_version); ++ dump_cfg_int(lTimeLimit, options.timelimit); ++ dump_cfg_int(lBind_TimeLimit, options.bind_timelimit); ++ dump_cfg_string(lBase, options.base); ++ dump_cfg_string(lBindDN, options.binddn); ++ dump_cfg_string(lBindPW, options.bindpw); ++ dump_cfg_namedint(lScope, options.scope, _scope); ++ dump_cfg_namedint(lDeref, options.deref, _deref); ++ dump_cfg_namedint(lReferrals, options.referrals, _yesno); ++ dump_cfg_namedint(lRestart, options.restart, _yesno); ++ dump_cfg_namedint(lBind_Policy, options.bind_policy, _bindpolicy); ++ dump_cfg_string(lSSLPath, options.sslpath); ++ dump_cfg_namedint(lTLS_CheckPeer, options.tls_checkpeer, _checkpeer); ++ dump_cfg_string(lTLS_CaCertFile, options.tls_cacertfile); ++ dump_cfg_string(lTLS_CaCertDir, options.tls_cacertdir); ++ dump_cfg_string(lTLS_Ciphers, options.tls_ciphers); ++ dump_cfg_string(lTLS_Cert, options.tls_cert); ++ dump_cfg_string(lTLS_Key, options.tls_key); ++ dump_cfg_string(lTLS_RandFile, options.tls_randfile); ++ dump_cfg_string(lLogDir, options.logdir); ++ dump_cfg_int(lDebug, options.debug); ++ dump_cfg_string(lSSH_Filter, options.ssh_filter); ++} ++ +Index: openssh-8.9p1/ldapconf.h +=================================================================== +--- /dev/null ++++ openssh-8.9p1/ldapconf.h +@@ -0,0 +1,71 @@ ++/* $OpenBSD: ldapconf.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ ++/* ++ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. ++ * ++ * 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. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. ++ */ ++ ++#ifndef LDAPCONF_H ++#define LDAPCONF_H ++ ++#define SSL_OFF 0 ++#define SSL_LDAPS 1 ++#define SSL_START_TLS 2 ++ ++/* Data structure for representing option data. */ ++ ++typedef struct { ++ char *host; ++ char *uri; ++ char *base; ++ char *binddn; ++ char *bindpw; ++ int scope; ++ int deref; ++ int port; ++ int timelimit; ++ int bind_timelimit; ++ int ldap_version; ++ int bind_policy; ++ char *sslpath; ++ int ssl; ++ int referrals; ++ int restart; ++ int tls_checkpeer; ++ char *tls_cacertfile; ++ char *tls_cacertdir; ++ char *tls_ciphers; ++ char *tls_cert; ++ char *tls_key; ++ char *tls_randfile; ++ char *logdir; ++ int debug; ++ char *ssh_filter; ++} Options; ++ ++extern Options options; ++ ++void read_config_file(const char *); ++void initialize_options(void); ++void fill_default_options(void); ++void dump_config(void); ++ ++#endif /* LDAPCONF_H */ +Index: openssh-8.9p1/ldapincludes.h +=================================================================== +--- /dev/null ++++ openssh-8.9p1/ldapincludes.h +@@ -0,0 +1,41 @@ ++/* $OpenBSD: ldapconf.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ ++/* ++ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. ++ * ++ * 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. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. ++ */ ++ ++#ifndef LDAPINCLUDES_H ++#define LDAPINCLUDES_H ++ ++#include "includes.h" ++ ++#ifdef HAVE_LBER_H ++#include ++#endif ++#ifdef HAVE_LDAP_H ++#include ++#endif ++#ifdef HAVE_LDAP_SSL_H ++#include ++#endif ++ ++#endif /* LDAPINCLUDES_H */ +Index: openssh-8.9p1/ldapmisc.c +=================================================================== +--- /dev/null ++++ openssh-8.9p1/ldapmisc.c +@@ -0,0 +1,79 @@ ++ ++#include "ldapincludes.h" ++#include "ldapmisc.h" ++ ++#ifndef HAVE_LDAP_GET_LDERRNO ++int ++ldap_get_lderrno (LDAP * ld, char **m, char **s) ++{ ++#ifdef HAVE_LDAP_GET_OPTION ++ int rc; ++#endif ++ int lderrno; ++ ++#if defined(HAVE_LDAP_GET_OPTION) && defined(LDAP_OPT_ERROR_NUMBER) ++ if ((rc = ldap_get_option (ld, LDAP_OPT_ERROR_NUMBER, &lderrno)) != LDAP_SUCCESS) ++ return rc; ++#else ++ lderrno = ld->ld_errno; ++#endif ++ ++ if (s != NULL) { ++#if defined(HAVE_LDAP_GET_OPTION) && defined(LDAP_OPT_ERROR_STRING) ++ if ((rc = ldap_get_option (ld, LDAP_OPT_ERROR_STRING, s)) != LDAP_SUCCESS) ++ return rc; ++#else ++ *s = ld->ld_error; ++#endif ++ } ++ ++ if (m != NULL) { ++#if defined(HAVE_LDAP_GET_OPTION) && defined(LDAP_OPT_MATCHED_DN) ++ if ((rc = ldap_get_option (ld, LDAP_OPT_MATCHED_DN, m)) != LDAP_SUCCESS) ++ return rc; ++#else ++ *m = ld->ld_matched; ++#endif ++ } ++ ++ return lderrno; ++} ++#endif ++ ++#ifndef HAVE_LDAP_SET_LDERRNO ++int ++ldap_set_lderrno (LDAP * ld, int lderrno, const char *m, const char *s) ++{ ++#ifdef HAVE_LDAP_SET_OPTION ++ int rc; ++#endif ++ ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_ERROR_NUMBER) ++ if ((rc = ldap_set_option (ld, LDAP_OPT_ERROR_NUMBER, &lderrno)) != LDAP_SUCCESS) ++ return rc; ++#else ++ ld->ld_errno = lderrno; ++#endif ++ ++ if (s != NULL) { ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_ERROR_STRING) ++ if ((rc = ldap_set_option (ld, LDAP_OPT_ERROR_STRING, s)) != LDAP_SUCCESS) ++ return rc; ++#else ++ ld->ld_error = s; ++#endif ++ } ++ ++ if (m != NULL) { ++#if defined(HAVE_LDAP_SET_OPTION) && defined(LDAP_OPT_MATCHED_DN) ++ if ((rc = ldap_set_option (ld, LDAP_OPT_MATCHED_DN, m)) != LDAP_SUCCESS) ++ return rc; ++#else ++ ld->ld_matched = m; ++#endif ++ } ++ ++ return LDAP_SUCCESS; ++} ++#endif ++ +Index: openssh-8.9p1/ldapmisc.h +=================================================================== +--- /dev/null ++++ openssh-8.9p1/ldapmisc.h +@@ -0,0 +1,35 @@ ++/* $OpenBSD: ldapbody.h,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ ++/* ++ * Copyright (c) 2009 Jan F. Chadima. All rights reserved. ++ * ++ * 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. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. ++ */ ++ ++#ifndef LDAPMISC_H ++#define LDAPMISC_H ++ ++#include "ldapincludes.h" ++ ++int ldap_get_lderrno (LDAP *, char **, char **); ++int ldap_set_lderrno (LDAP *, int, const char *, const char *); ++ ++#endif /* LDAPMISC_H */ ++ +Index: openssh-8.9p1/openbsd-compat/base64.c +=================================================================== +--- openssh-8.9p1.orig/openbsd-compat/base64.c ++++ openssh-8.9p1/openbsd-compat/base64.c +@@ -46,7 +46,7 @@ + + #include "includes.h" + +-#if (!defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP)) || (!defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON)) ++#if (!defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP)) || (!defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON)) || defined(USE_INTERNAL_B64) + + #include + #include +@@ -128,7 +128,7 @@ static const char Pad64 = '='; + characters followed by one "=" padding character. + */ + +-#if !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) ++#if !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) || defined(USE_INTERNAL_B64) + int + b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) + { +@@ -184,7 +184,7 @@ b64_ntop(u_char const *src, size_t srcle + } + #endif /* !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) */ + +-#if !defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON) ++#if !defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON) || defined(USE_INTERNAL_B64) + + /* skips all whitespace anywhere. + converts characters, four at a time, starting at (or after) +Index: openssh-8.9p1/openbsd-compat/base64.h +=================================================================== +--- openssh-8.9p1.orig/openbsd-compat/base64.h ++++ openssh-8.9p1/openbsd-compat/base64.h +@@ -45,16 +45,16 @@ + + #include "includes.h" + +-#ifndef HAVE___B64_NTOP +-# ifndef HAVE_B64_NTOP ++#if !defined(HAVE___B64_NTOP) || defined(USE_INTERNAL_B64) ++# if !defined(HAVE_B64_NTOP) || defined(USE_INTERNAL_B64) + int b64_ntop(u_char const *src, size_t srclength, char *target, + size_t targsize); + # endif /* !HAVE_B64_NTOP */ + # define __b64_ntop(a,b,c,d) b64_ntop(a,b,c,d) + #endif /* HAVE___B64_NTOP */ + +-#ifndef HAVE___B64_PTON +-# ifndef HAVE_B64_PTON ++#if !defined(HAVE___B64_PTON) || defined(USE_INTERNAL_B64) ++# if !defined(HAVE_B64_PTON) || defined(USE_INTERNAL_B64) + int b64_pton(char const *src, u_char *target, size_t targsize); + # endif /* !HAVE_B64_PTON */ + # define __b64_pton(a,b,c) b64_pton(a,b,c) +Index: openssh-8.9p1/openssh-lpk-openldap.schema +=================================================================== +--- /dev/null ++++ openssh-8.9p1/openssh-lpk-openldap.schema +@@ -0,0 +1,21 @@ ++# ++# LDAP Public Key Patch schema for use with openssh-ldappubkey ++# useful with PKA-LDAP also ++# ++# Author: Eric AUGE ++# ++# Based on the proposal of : Mark Ruijter ++# ++ ++ ++# octetString SYNTAX ++attributetype ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey' ++ DESC 'MANDATORY: OpenSSH Public key' ++ EQUALITY octetStringMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) ++ ++# printableString SYNTAX yes|no ++objectclass ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY ++ DESC 'MANDATORY: OpenSSH LPK objectclass' ++ MUST ( sshPublicKey $ uid ) ++ ) +Index: openssh-8.9p1/openssh-lpk-sun.schema +=================================================================== +--- /dev/null ++++ openssh-8.9p1/openssh-lpk-sun.schema +@@ -0,0 +1,23 @@ ++# ++# LDAP Public Key Patch schema for use with openssh-ldappubkey ++# useful with PKA-LDAP also ++# ++# Author: Eric AUGE ++# ++# Schema for Sun Directory Server. ++# Based on the original schema, modified by Stefan Fischer. ++# ++ ++dn: cn=schema ++ ++# octetString SYNTAX ++attributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey' ++ DESC 'MANDATORY: OpenSSH Public key' ++ EQUALITY octetStringMatch ++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) ++ ++# printableString SYNTAX yes|no ++objectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY ++ DESC 'MANDATORY: OpenSSH LPK objectclass' ++ MUST ( sshPublicKey $ uid ) ++ ) +Index: openssh-8.9p1/ssh-ldap-helper.8 +=================================================================== +--- /dev/null ++++ openssh-8.9p1/ssh-ldap-helper.8 +@@ -0,0 +1,79 @@ ++.\" $OpenBSD: ssh-ldap-helper.8,v 1.1 2010/02/10 23:20:38 markus Exp $ ++.\" ++.\" Copyright (c) 2010 Jan F. Chadima. All rights reserved. ++.\" ++.\" 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. ++.\" ++.Dd $Mdocdate: April 29 2010 $ ++.Dt SSH-LDAP-HELPER 8 ++.Os ++.Sh NAME ++.Nm ssh-ldap-helper ++.Nd sshd helper program for ldap support ++.Sh SYNOPSIS ++.Nm ssh-ldap-helper ++.Op Fl devw ++.Op Fl f Ar file ++.Op Fl s Ar user ++.Sh DESCRIPTION ++.Nm ++is used by ++.Xr sshd 1 ++to access keys provided by an LDAP. ++.Nm ++is disabled by default and can only be enabled in the ++sshd configuration file ++.Pa /etc/ssh/sshd_config ++by setting ++.Cm AuthorizedKeysCommand ++to ++.Dq @LIBEXECDIR@/ssh-ldap-wrapper . ++.Pp ++.Nm ++is not intended to be invoked by the user, but from ++.Xr sshd 8 via ++.Xr ssh-ldap-wrapper . ++.Pp ++The options are as follows: ++.Bl -tag -width Ds ++.It Fl d ++Set the debug mode; ++.Nm ++prints all logs to stderr instead of syslog. ++.It Fl e ++Implies \-w; ++.Nm ++halts if it encounters an unknown item in the ldap.conf file. ++.It Fl f ++.Nm ++uses this file as the ldap configuration file instead of /etc/ssh/ldap.conf (default). ++.It Fl s ++.Nm ++prints out the user's keys to stdout and exits. ++.It Fl v ++Implies \-d; ++increases verbosity. ++.It Fl w ++.Nm ++writes warnings about unknown items in the ldap.conf configuration file. ++.El ++.Sh SEE ALSO ++.Xr sshd 8 , ++.Xr sshd_config 5 , ++.Xr ssh-ldap.conf 5 , ++.Sh HISTORY ++.Nm ++first appeared in ++OpenSSH 5.5 + PKA-LDAP . ++.Sh AUTHORS ++.An Jan F. Chadima Aq jchadima@redhat.com +Index: openssh-8.9p1/ssh-ldap-wrapper +=================================================================== +--- /dev/null ++++ openssh-8.9p1/ssh-ldap-wrapper +@@ -0,0 +1,4 @@ ++#!/bin/sh ++ ++exec @LIBEXECDIR@/ssh-ldap-helper -s "$1" ++ +Index: openssh-8.9p1/ssh-ldap.conf.5 +=================================================================== +--- /dev/null ++++ openssh-8.9p1/ssh-ldap.conf.5 +@@ -0,0 +1,376 @@ ++.\" $OpenBSD: ssh-ldap.conf.5,v 1.1 2010/02/10 23:20:38 markus Exp $ ++.\" ++.\" Copyright (c) 2010 Jan F. Chadima. All rights reserved. ++.\" ++.\" 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. ++.\" ++.Dd $Mdocdate: may 12 2010 $ ++.Dt SSH-LDAP.CONF 5 ++.Os ++.Sh NAME ++.Nm ssh-ldap.conf ++.Nd configuration file for ssh-ldap-helper ++.Sh SYNOPSIS ++.Nm /etc/ssh/ldap.conf ++.Sh DESCRIPTION ++.Xr ssh-ldap-helper 8 ++reads configuration data from ++.Pa /etc/ssh/ldap.conf ++(or the file specified with ++.Fl f ++on the command line). ++The file contains keyword-argument pairs, one per line. ++Lines starting with ++.Ql # ++and empty lines are interpreted as comments. ++.Pp ++The value starts with the first non-blank character after ++the keyword's name, and terminates at the end of the line, ++or at the last sequence of blanks before the end of the line. ++Quoting values that contain blanks ++may be incorrect, as the quotes would become part of the value. ++The possible keywords and their meanings are as follows (note that ++keywords are case-insensitive, and arguments, on a case by case basis, may be case-sensitive). ++.Bl -tag -width Ds ++.It Cm URI ++The argument(s) are in the form ++.Pa ldap[si]://[name[:port]] ++and specify the URI(s) of an LDAP server(s) to which the ++.Xr ssh-ldap-helper 8 ++should connect. The URI scheme may be any of ++.Dq ldap , ++.Dq ldaps ++or ++.Dq ldapi , ++which refer to LDAP over TCP, LDAP over SSL (TLS) and LDAP ++over IPC (UNIX domain sockets), respectively. ++Each server's name can be specified as a ++domain-style name or an IP address literal. Optionally, the ++server's name can followed by a ':' and the port number the LDAP ++server is listening on. If no port number is provided, the default ++port for the scheme is used (389 for ldap://, 636 for ldaps://). ++For LDAP over IPC, name is the name of the socket, and no port ++is required, nor allowed; note that directory separators must be ++URL-encoded, like any other characters that are special to URLs; ++A space separated list of URIs may be provided. ++There is no default. ++.It Cm Base ++Specifies the default base Distinguished Name (DN) to use when performing ldap operations. ++The base must be specified as a DN in LDAP format. ++There is no default. ++.It Cm BindDN ++Specifies the default BIND DN to use when connecting to the ldap server. ++The bind DN must be specified as a Distinguished Name in LDAP format. ++There is no default. ++.It Cm BindPW ++Specifies the default password to use when connecting to the ldap server via ++.Cm BindDN . ++There is no default. ++.It Cm RootBindDN ++Intentionaly does nothing. Recognized for compatibility reasons. ++.It Cm Host ++The argument(s) specifies the name(s) of an LDAP server(s) to which the ++.Xr ssh-ldap-helper 8 ++should connect. Each server's name can be specified as a ++domain-style name or an IP address and optionally followed by a ':' and ++the port number the ldap server is listening on. A space-separated ++list of hosts may be provided. ++There is no default. ++.Cm Host ++is deprecated in favor of ++.Cm URI . ++.It Cm Port ++Specifies the default port used when connecting to LDAP servers(s). ++The port may be specified as a number. ++The default port is 389 for ldap:// or 636 for ldaps:// respectively. ++.Cm Port ++is deprecated in favor of ++.Cm URI . ++.It Cm Scope ++Specifies the starting point of an LDAP search and the depth from the base DN to which the search should descend. ++There are three options (values) that can be assigned to the ++.Cm Scope parameter: ++.Dq base , ++.Dq one ++and ++.Dq subtree . ++Alias for the subtree is ++.Dq sub . ++The value ++.Dq base ++is used to indicate searching only the entry at the base DN, resulting in only that entry being returned (keeping in mind that it also has to meet the search filter criteria!). ++The value ++.Dq one ++is used to indicate searching all entries one level under the base DN, but not including the base DN and not including any entries under that one level under the base DN. ++The value ++.Dq subtree ++is used to indicate searching of all entries at all levels under and including the specified base DN. ++The default is ++.Dq subtree . ++.It Cm Deref ++Specifies how alias dereferencing is done when performing a search. There are four ++possible values that can be assigned to the ++.Cm Deref ++parameter: ++.Dq never , ++.Dq searching , ++.Dq finding , ++and ++.Dq always . ++The value ++.Dq never ++means that the aliases are never dereferenced. ++The value ++.Dq searching ++means that the aliases are dereferenced in subordinates of the base object, but ++not in locating the base object of the search. ++The value ++.Dq finding ++means that the aliases are only dereferenced when locating the base object of the search. ++The value ++.Dq always ++means that the aliases are dereferenced both in searching and in locating the base object ++of the search. ++The default is ++.Dq never . ++.It Cm TimeLimit ++Specifies a time limit (in seconds) to use when performing searches. ++The number should be a non-negative integer. A ++.Cm TimeLimit ++of zero (0) specifies that the search time is unlimited. Please note that the server ++may still apply any server-side limit on the duration of a search operation. ++The default value is 10. ++.It Cm TimeOut ++Is an aliast to ++.Cm TimeLimit . ++.It Cm Bind_TimeLimit ++Specifies the timeout (in seconds) after which the poll(2)/select(2) ++following a connect(2) returns in case of no activity. ++The default value is 10. ++.It Cm Network_TimeOut ++Is an alias to ++.Cm Bind_TimeLimit . ++.It Cm Ldap_Version ++Specifies what version of the LDAP protocol should be used. ++The allowed values are 2 or 3. The default is 3. ++.It Cm Version ++Is an alias to ++.Cm Ldap_Version . ++.It Cm Bind_Policy ++Specifies the policy to use for reconnecting to an unavailable LDAP server. There are 2 available values: ++.Dq hard ++and ++.Dq soft. ++.Dq hard has 2 aliases ++.Dq hard_open ++and ++.Dq hard_init . ++The value ++.Dq hard ++means that reconects that the ++.Xr ssh-ldap-helper 8 ++tries to reconnect to the LDAP server 5 times before failure. There is exponential backoff before retrying. ++The value ++.Dq soft ++means that ++.Xr ssh-ldap-helper 8 ++fails immediately when it cannot connect to the LDAP seerver. ++The deault is ++.Dq hard . ++.It Cm SSLPath ++Specifies the path to the X.509 certificate database. ++There is no default. ++.It Cm SSL ++Specifies whether to use SSL/TLS or not. ++There are three allowed values: ++.Dq yes , ++.Dq no ++and ++.Dq start_tls ++Both ++.Dq true ++and ++.Dq on ++are the aliases for ++.Dq yes . ++.Dq false ++and ++.Dq off ++are the aliases for ++.Dq no . ++If ++.Dq start_tls ++is specified then StartTLS is used rather than raw LDAP over SSL. ++The default for ldap:// is ++.Dq start_tls , ++for ldaps:// ++.Dq yes ++and ++.Dq no ++for the ldapi:// . ++In case of host based configuration the default is ++.Dq start_tls . ++.It Cm Referrals ++Specifies if the client should automatically follow referrals returned ++by LDAP servers. ++The value can be or ++.Dq yes ++or ++.Dq no . ++.Dq true ++and ++.Dq on ++are the aliases for ++.Dq yes . ++.Dq false ++and ++.Dq off ++are the aliases for ++.Dq no . ++The default is yes. ++.It Cm Restart ++Specifies whether the LDAP client library should restart the select(2) system call when interrupted. ++The value can be or ++.Dq yes ++or ++.Dq no . ++.Dq true ++and ++.Dq on ++are the aliases for ++.Dq yes . ++.Dq false ++and ++.Dq off ++are the aliases for ++.Dq no . ++The default is yes. ++.It Cm TLS_CheckPeer ++Specifies what checks to perform on server certificates in a TLS session, ++if any. The value ++can be specified as one of the following keywords: ++.Dq never , ++.Dq hard , ++.Dq demand , ++.Dq allow ++and ++.Dq try . ++.Dq true , ++.Dq on ++and ++.Dq yes ++are aliases for ++.Dq hard . ++.Dq false , ++.Dq off ++and ++.Dq no ++are the aliases for ++.Dq never . ++The value ++.Dq never ++means that the client will not request or check any server certificate. ++The value ++.Dq allow ++means that the server certificate is requested. If no certificate is provided, ++the session proceeds normally. If a bad certificate is provided, it will ++be ignored and the session proceeds normally. ++The value ++.Dq try ++means that the server certificate is requested. If no certificate is provided, ++the session proceeds normally. If a bad certificate is provided, ++the session is immediately terminated. ++The value ++.Dq demand ++means that the server certificate is requested. If no ++certificate is provided, or a bad certificate is provided, the session ++is immediately terminated. ++The value ++.Dq hard ++is the same as ++.Dq demand . ++It requires an SSL connection. In the case of the plain conection the ++session is immediately terminated. ++The default is ++.Dq hard . ++.It Cm TLS_ReqCert ++Is an alias for ++.Cm TLS_CheckPeer . ++.It Cm TLS_CACertFile ++Specifies the file that contains certificates for all of the Certificate ++Authorities the client will recognize. ++There is no default. ++.It Cm TLS_CACert ++Is an alias for ++.Cm TLS_CACertFile . ++.It Cm TLS_CACertDIR ++Specifies the path of a directory that contains Certificate Authority ++certificates in separate individual files. The ++.Cm TLS_CACert ++is always used before ++.Cm TLS_CACertDir . ++The specified directory must be managed with the OpenSSL c_rehash utility. ++There is no default. ++.It Cm TLS_Ciphers ++Specifies acceptable cipher suite and preference order. ++The value should be a cipher specification for OpenSSL, ++e.g., ++.Dq HIGH:MEDIUM:+SSLv2 . ++The default is ++.Dq ALL . ++.It Cm TLS_Cipher_Suite ++Is an alias for ++.Cm TLS_Ciphers . ++.It Cm TLS_Cert ++Specifies the file that contains the client certificate. ++There is no default. ++.It Cm TLS_Certificate ++Is an alias for ++.Cm TLS_Cert . ++.It Cm TLS_Key ++Specifies the file that contains the private key that matches the certificate ++stored in the ++.Cm TLS_Cert ++file. Currently, the private key must not be protected with a password, so ++it is of critical importance that the key file is protected carefully. ++There is no default. ++.It Cm TLS_RandFile ++Specifies the file to obtain random bits from when /dev/[u]random is ++not available. Generally set to the name of the EGD/PRNGD socket. ++The environment variable RANDFILE can also be used to specify the filename. ++There is no default. ++.It Cm LogDir ++Specifies the directory used for logging by the LDAP client library. ++There is no default. ++.It Cm Debug ++Specifies the debug level used for logging by the LDAP client library. ++There is no default. ++.It Cm SSH_Filter ++Specifies the user filter applied on the LDAP serch. ++The default is no filter. ++.El ++.Sh FILES ++.Bl -tag -width Ds ++.It Pa /etc/ssh/ldap.conf ++Ldap configuration file for ++.Xr ssh-ldap-helper 8 . ++.El ++.Sh "SEE ALSO" ++.Xr ldap.conf 5 , ++.Xr ssh-ldap-helper 8 ++.Sh HISTORY ++.Nm ++first appeared in ++OpenSSH 5.5 + PKA-LDAP . ++.Sh AUTHORS ++.An Jan F. Chadima Aq jchadima@redhat.com diff --git a/openssh-7.7p1-no_fork-no_pid_file.patch b/openssh-7.7p1-no_fork-no_pid_file.patch new file mode 100644 index 0000000..1767963 --- /dev/null +++ b/openssh-7.7p1-no_fork-no_pid_file.patch @@ -0,0 +1,17 @@ +# HG changeset patch +# Parent bad0c8b3b8d72abb6960ed85b57ee42352371738 +Do not write a PID file when not daemonizing (e.g. when running from systemd) + +Index: openssh-8.8p1/sshd.c +=================================================================== +--- openssh-8.8p1.orig/sshd.c ++++ openssh-8.8p1/sshd.c +@@ -2129,7 +2129,7 @@ main(int ac, char **av) + * Write out the pid file after the sigterm handler + * is setup and the listen sockets are bound + */ +- if (options.pid_file != NULL && !debug_flag) { ++ if (!no_daemon_flag && options.pid_file != NULL && !debug_flag) { + FILE *f = fopen(options.pid_file, "w"); + + if (f == NULL) { diff --git a/openssh-7.7p1-pam_check_locks.patch b/openssh-7.7p1-pam_check_locks.patch new file mode 100644 index 0000000..4186015 --- /dev/null +++ b/openssh-7.7p1-pam_check_locks.patch @@ -0,0 +1,134 @@ +# HG changeset patch +# Parent 089f4fba0112d410a1bfa74398941f076681d446 +new option UsePAMCheckLocks to enforce checking for locked accounts while +UsePAM is used + +bnc#708678, FATE#312033 + +Index: openssh-8.8p1/auth.c +=================================================================== +--- openssh-8.8p1.orig/auth.c ++++ openssh-8.8p1/auth.c +@@ -113,7 +113,7 @@ allowed_user(struct ssh *ssh, struct pas + if (!pw || !pw->pw_name) + return 0; + +- if (!options.use_pam && platform_locked_account(pw)) { ++ if ((!options.use_pam || options.use_pam_check_locks) && platform_locked_account(pw)) { + logit("User %.100s not allowed because account is locked", + pw->pw_name); + return 0; +#@@ -133,7 +133,7 @@ allowed_user(struct ssh *ssh, struct pas +# #endif +# +# /* check for locked account */ +#- if (!options.use_pam && passwd && *passwd) { +#+ if ((!options.use_pam || options.use_pam_check_locks) && passwd && *passwd) { +# int locked = 0; +# +# #ifdef LOCKED_PASSWD_STRING +Index: openssh-8.8p1/servconf.c +=================================================================== +--- openssh-8.8p1.orig/servconf.c ++++ openssh-8.8p1/servconf.c +@@ -92,6 +92,7 @@ initialize_server_options(ServerOptions + + /* Portable-specific options */ + options->use_pam = -1; ++ options->use_pam_check_locks = -1; + + /* Standard Options */ + options->num_ports = 0; +@@ -278,6 +279,8 @@ fill_default_server_options(ServerOption + /* Portable-specific options */ + if (options->use_pam == -1) + options->use_pam = 0; ++ if (options->use_pam_check_locks == -1) ++ options->use_pam_check_locks = 0; + + /* Standard Options */ + if (options->num_host_key_files == 0) { +@@ -485,7 +488,7 @@ fill_default_server_options(ServerOption + typedef enum { + sBadOption, /* == unknown option */ + /* Portable-specific options */ +- sUsePAM, ++ sUsePAM, sUsePAMChecklocks, + /* Standard Options */ + sPort, sHostKeyFile, sLoginGraceTime, + sPermitRootLogin, sLogFacility, sLogLevel, sLogVerbose, +@@ -535,8 +538,10 @@ static struct { + /* Portable-specific options */ + #ifdef USE_PAM + { "usepam", sUsePAM, SSHCFG_GLOBAL }, ++ { "usepamchecklocks", sUsePAMChecklocks, SSHCFG_GLOBAL }, + #else + { "usepam", sUnsupported, SSHCFG_GLOBAL }, ++ { "usepamchecklocks", sUnsupported, SSHCFG_GLOBAL }, + #endif + { "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL }, + /* Standard Options */ +@@ -1331,6 +1336,9 @@ process_server_config_line_depth(ServerO + case sUsePAM: + intptr = &options->use_pam; + goto parse_flag; ++ case sUsePAMChecklocks: ++ intptr = &options->use_pam_check_locks; ++ goto parse_flag; + + /* Standard Options */ + case sBadOption: +Index: openssh-8.8p1/servconf.h +=================================================================== +--- openssh-8.8p1.orig/servconf.h ++++ openssh-8.8p1/servconf.h +@@ -200,6 +200,7 @@ typedef struct { + char *adm_forced_command; + + int use_pam; /* Enable auth via PAM */ ++ int use_pam_check_locks; /* internally check for locked accounts even when using PAM */ + + int permit_tun; + +Index: openssh-8.8p1/sshd_config.0 +=================================================================== +--- openssh-8.8p1.orig/sshd_config.0 ++++ openssh-8.8p1/sshd_config.0 +@@ -1074,6 +1074,14 @@ DESCRIPTION + If UsePAM is enabled, you will not be able to run sshd(8) as a + non-root user. The default is no. + ++ UsePAMCheckLocks ++ When set to ``yes'', the checks whether the account has been ++ locked with `passwd -l' are performed even when PAM authentication ++ is enabled via UsePAM. This is to ensure that it is not possible ++ to log in with e.g. a public key (in such a case PAM is used only ++ to set up the session and some PAM modules will not check whether ++ the account is locked in this scenario). The default is ``no''. ++ + VersionAddendum + Optionally specifies additional text to append to the SSH + protocol banner sent by the server upon connection. The default +Index: openssh-8.8p1/sshd_config.5 +=================================================================== +--- openssh-8.8p1.orig/sshd_config.5 ++++ openssh-8.8p1/sshd_config.5 +@@ -1775,6 +1775,18 @@ is enabled, you will not be able to run + as a non-root user. + The default is + .Cm no . ++.It Cm UsePAMCheckLocks ++When set to ++.Dq yes ++, the checks whether the account has been locked with ++.Pa passwd -l ++are performed even when PAM authentication is enabled via ++.Cm UsePAM . ++This is to ensure that it is not possible to log in with e.g. a ++public key (in such a case PAM is used only to set up the session and some PAM ++modules will not check whether the account is locked in this scenario). The ++default is ++.Dq no . + .It Cm VersionAddendum + Optionally specifies additional text to append to the SSH protocol banner + sent by the server upon connection. diff --git a/openssh-7.7p1-pts_names_formatting.patch b/openssh-7.7p1-pts_names_formatting.patch new file mode 100644 index 0000000..04ed646 --- /dev/null +++ b/openssh-7.7p1-pts_names_formatting.patch @@ -0,0 +1,30 @@ +# HG changeset patch +# Parent 7cd948c83939479d1ba88a3161991cb561306f3f +# use same lines naming as utempter (prevents problems with using different +# formats in ?tmp? files) +# --used to be called '-pts' + +Index: openssh-8.8p1/loginrec.c +=================================================================== +--- openssh-8.8p1.orig/loginrec.c ++++ openssh-8.8p1/loginrec.c +@@ -549,7 +549,7 @@ getlast_entry(struct logininfo *li) + * 1. The full filename (including '/dev') + * 2. The stripped name (excluding '/dev') + * 3. The abbreviated name (e.g. /dev/ttyp00 -> yp00 +- * /dev/pts/1 -> ts/1 ) ++ * /dev/pts/1 -> /1 ) + * + * Form 3 is used on some systems to identify a .tmp.? entry when + * attempting to remove it. Typically both addition and removal is +@@ -610,6 +610,10 @@ line_abbrevname(char *dst, const char *s + if (strncmp(src, "tty", 3) == 0) + src += 3; + #endif ++ if (strncmp(src, "pts/", 4) == 0) { ++ src += 3; ++ if (strlen(src) > 4) src++; ++ } + + len = strlen(src); + diff --git a/openssh-7.7p1-remove_xauth_cookies_on_exit.patch b/openssh-7.7p1-remove_xauth_cookies_on_exit.patch new file mode 100644 index 0000000..d14bb6e --- /dev/null +++ b/openssh-7.7p1-remove_xauth_cookies_on_exit.patch @@ -0,0 +1,46 @@ +# HG changeset patch +# Parent a60c0d88667efe0a64c030168950b69476af1622 +# --used to be called '-xauth' +try to remove xauth cookies on logout + +bnc#98815 + +Index: openssh-8.8p1/session.c +=================================================================== +--- openssh-8.8p1.orig/session.c ++++ openssh-8.8p1/session.c +@@ -2441,6 +2441,34 @@ session_close(struct ssh *ssh, Session * + ssh_remote_port(ssh), + s->self); + ++ if ((s->display != NULL) && (s->auth_proto != NULL) && ++ (s->auth_data != NULL) && (options.xauth_location != NULL)) { ++ pid_t pid; ++ FILE *f; ++ char cmd[1024]; ++ struct passwd * pw = s->pw; ++ ++ if (!(pid = fork())) { ++ permanently_set_uid(pw); ++ ++ /* Remove authority data from .Xauthority if appropriate. */ ++ debug("Running %.500s remove %.100s\n", ++ options.xauth_location, s->auth_display); ++ ++ snprintf(cmd, sizeof cmd, "unset XAUTHORITY && HOME=\"%.200s\" %s -q -", ++ s->pw->pw_dir, options.xauth_location); ++ f = popen(cmd, "w"); ++ if (f) { ++ fprintf(f, "remove %s\n", s->auth_display); ++ pclose(f); ++ } else ++ error("Could not run %s\n", cmd); ++ exit(0); ++ } else if (pid > 0) { ++ waitpid(pid, NULL, 0); ++ } ++ } ++ + if (s->ttyfd != -1) + session_pty_cleanup(s); + free(s->term); diff --git a/openssh-7.7p1-seccomp_ipc_flock.patch b/openssh-7.7p1-seccomp_ipc_flock.patch new file mode 100644 index 0000000..4b77258 --- /dev/null +++ b/openssh-7.7p1-seccomp_ipc_flock.patch @@ -0,0 +1,41 @@ +# HG changeset patch +# Parent 9d38b7292619a6d5faf554b1a88888fdfa535de7 +Patch from IBM enabling the use of OpenCryptoki, submitted upstreams: + +From: Eduardo Barretto +To: openssh-unix-dev@mindrot.org +Subject: [PATCH 1/3] Allow flock and ipc syscall for s390 architecture +Date: Tue, 9 May 2017 14:27:13 -0300 + +In order to use the OpenSSL-ibmpkcs11 engine it is needed to allow flock +and ipc calls, because this engine calls OpenCryptoki (a PKCS#11 +implementation) which calls the libraries that will communicate with the +crypto cards. OpenCryptoki makes use of flock and ipc and, as of now, +this is only need on s390 architecture. + +Signed-off-by: Eduardo Barretto + +Index: openssh-8.8p1/sandbox-seccomp-filter.c +=================================================================== +--- openssh-8.8p1.orig/sandbox-seccomp-filter.c ++++ openssh-8.8p1/sandbox-seccomp-filter.c +@@ -219,6 +219,9 @@ static const struct sock_filter preauth_ + #ifdef __NR_geteuid32 + SC_ALLOW(__NR_geteuid32), + #endif ++#if defined(__NR_flock) && defined(__s390__) ++ SC_ALLOW(__NR_flock), ++#endif + #ifdef __NR_getpgid + SC_ALLOW(__NR_getpgid), + #endif +@@ -237,6 +240,9 @@ static const struct sock_filter preauth_ + #ifdef __NR_getuid32 + SC_ALLOW(__NR_getuid32), + #endif ++#if defined(__NR_ipc) && defined(__s390__) ++ SC_ALLOW(__NR_ipc), ++#endif + #ifdef __NR_madvise + SC_ALLOW_ARG(__NR_madvise, 2, MADV_NORMAL), + # ifdef MADV_FREE diff --git a/openssh-7.7p1-seccomp_stat.patch b/openssh-7.7p1-seccomp_stat.patch new file mode 100644 index 0000000..ca85530 --- /dev/null +++ b/openssh-7.7p1-seccomp_stat.patch @@ -0,0 +1,21 @@ +# HG changeset patch +# Parent 5034ae16f6a5c9c7151d931dc1cce2a541fe010e +Allow the stat() syscall for OpenSSL re-seed patch +(which causes OpenSSL use stat() on some file) + +bnc#912436 + +Index: openssh-8.8p1/sandbox-seccomp-filter.c +=================================================================== +--- openssh-8.8p1.orig/sandbox-seccomp-filter.c ++++ openssh-8.8p1/sandbox-seccomp-filter.c +@@ -294,6 +294,9 @@ static const struct sock_filter preauth_ + #ifdef __NR_sigprocmask + SC_ALLOW(__NR_sigprocmask), + #endif ++#ifdef __NR_stat ++ SC_ALLOW(__NR_stat), ++#endif + #ifdef __NR_time + SC_ALLOW(__NR_time), + #endif diff --git a/openssh-7.7p1-send_locale.patch b/openssh-7.7p1-send_locale.patch new file mode 100644 index 0000000..4dd1c0a --- /dev/null +++ b/openssh-7.7p1-send_locale.patch @@ -0,0 +1,37 @@ +# HG changeset patch +# Parent db426aecefd1f4f8a7f9b9b6e8936cd8dd2f17fa +send locales in default configuration +bnc#65747 + +Index: openssh-8.8p1/ssh_config +=================================================================== +--- openssh-8.8p1.orig/ssh_config ++++ openssh-8.8p1/ssh_config +@@ -31,6 +31,11 @@ Host * + # expire after twenty minutes after remote login. + ForwardX11Trusted yes + ++# This enables sending locale enviroment variables LC_* LANG, see ssh_config(5). ++ SendEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES ++ SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT ++ SendEnv LC_IDENTIFICATION LC_ALL ++ + # PasswordAuthentication yes + # HostbasedAuthentication no + # GSSAPIAuthentication no +Index: openssh-8.8p1/sshd_config +=================================================================== +--- openssh-8.8p1.orig/sshd_config ++++ openssh-8.8p1/sshd_config +@@ -108,6 +108,11 @@ X11Forwarding yes + # override default of no subsystems + Subsystem sftp /usr/libexec/sftp-server + ++# This enables accepting locale enviroment variables LC_* LANG, see sshd_config(5). ++AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES ++AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT ++AcceptEnv LC_IDENTIFICATION LC_ALL ++ + # Example of overriding settings on a per-user basis + #Match User anoncvs + # X11Forwarding no diff --git a/openssh-7.7p1-sftp_force_permissions.patch b/openssh-7.7p1-sftp_force_permissions.patch new file mode 100644 index 0000000..db48829 --- /dev/null +++ b/openssh-7.7p1-sftp_force_permissions.patch @@ -0,0 +1,125 @@ +Index: openssh-8.8p1/sftp-server.8 +=================================================================== +--- openssh-8.8p1.orig/sftp-server.8 ++++ openssh-8.8p1/sftp-server.8 +@@ -38,6 +38,7 @@ + .Op Fl P Ar denied_requests + .Op Fl p Ar allowed_requests + .Op Fl u Ar umask ++.Op Fl m Ar force_file_dir_perms + .Ek + .Nm + .Fl Q Ar protocol_feature +@@ -138,6 +139,10 @@ Sets an explicit + .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_dir_perms ++Sets explicit permissions to be applied to newly-created files and directories ++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. + .El + .Pp + On some systems, +Index: openssh-8.8p1/sftp-server.c +=================================================================== +--- openssh-8.8p1.orig/sftp-server.c ++++ openssh-8.8p1/sftp-server.c +@@ -73,6 +73,10 @@ struct sshbuf *oqueue; + /* Version of client */ + static u_int version; + ++/* Force file and directory permissions */ ++int permforce = 0; ++long permforcemode; ++ + /* SSH2_FXP_INIT received */ + static int init_done; + +@@ -724,6 +728,7 @@ process_open(u_int32_t id) + Attrib a; + char *name; + int r, handle, fd, flags, mode, status = SSH2_FX_FAILURE; ++ mode_t old_umask = 0; + + if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || + (r = sshbuf_get_u32(iqueue, &pflags)) != 0 || /* portable flags */ +@@ -733,6 +738,10 @@ process_open(u_int32_t id) + debug3("request %u: open flags %d", id, pflags); + flags = flags_from_portable(pflags); + mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a.perm : 0666; ++ if (permforce == 1) { /* Force perm if -m is set */ ++ mode = permforcemode; ++ old_umask = umask(0); /* so umask does not interfere */ ++ } + logit("open \"%s\" flags %s mode 0%o", + name, string_from_portable(pflags), mode); + if (readonly && +@@ -754,6 +763,8 @@ process_open(u_int32_t id) + } + } + } ++ if (permforce == 1) ++ (void) umask(old_umask); /* restore umask to something sane */ + if (status != SSH2_FX_OK) + send_status(id, status); + free(name); +@@ -1183,6 +1194,7 @@ process_mkdir(u_int32_t id) + Attrib a; + char *name; + int r, mode, status = SSH2_FX_FAILURE; ++ mode_t old_umask = 0; + + if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || + (r = decode_attrib(iqueue, &a)) != 0) +@@ -1190,9 +1202,16 @@ process_mkdir(u_int32_t id) + + mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? + a.perm & 07777 : 0777; ++ if (permforce == 1) { /* Force perm if -m is set */ ++ mode = permforcemode; ++ old_umask = umask(0); /* so umask does not interfere */ ++ } ++ + debug3("request %u: mkdir", id); + logit("mkdir name \"%s\" mode 0%o", name, mode); + r = mkdir(name, mode); ++ if (permforce == 1) ++ (void) umask(old_umask); /* restore umask to something sane */ + status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK; + send_status(id, status); + free(name); +@@ -1700,7 +1719,7 @@ sftp_server_usage(void) + fprintf(stderr, + "usage: %s [-ehR] [-d start_directory] [-f log_facility] " + "[-l log_level]\n\t[-P denied_requests] " +- "[-p allowed_requests] [-u umask]\n" ++ "[-p allowed_requests] [-u umask] [-m force_file_dir_perms]\n" + " %s -Q protocol_feature\n", + __progname, __progname); + exit(1); +@@ -1728,7 +1747,7 @@ sftp_server_main(int argc, char **argv, + pw = pwcopy(user_pw); + + while (!skipargs && (ch = getopt(argc, argv, +- "d:f:l:P:p:Q:u:cehR")) != -1) { ++ "d:f:l:P:p:Q:u:m:cehR")) != -1) { + switch (ch) { + case 'Q': + if (strcasecmp(optarg, "requests") != 0) { +@@ -1790,6 +1809,15 @@ sftp_server_main(int argc, char **argv, + fatal("Invalid umask \"%s\"", optarg); + (void)umask((mode_t)mask); + break; ++ case 'm': ++ /* Force permissions on file and directory received via sftp */ ++ permforce = 1; ++ permforcemode = strtol(optarg, &cp, 8); ++ if (permforcemode < 0 || permforcemode > 0777 || ++ *cp != '\0' || (permforcemode == 0 && ++ errno != 0)) ++ fatal("Invalid file mode \"%s\"", optarg); ++ break; + case 'h': + default: + sftp_server_usage(); diff --git a/openssh-7.7p1-sftp_print_diagnostic_messages.patch b/openssh-7.7p1-sftp_print_diagnostic_messages.patch new file mode 100644 index 0000000..7b5ab04 --- /dev/null +++ b/openssh-7.7p1-sftp_print_diagnostic_messages.patch @@ -0,0 +1,60 @@ +# HG changeset patch +# Parent 60bdbe6dd8d6bc011883472363d56e1d97f68835 +Put back sftp client diagnostic messages in batch mode + +Index: openssh-8.8p1/sftp.1 +=================================================================== +--- openssh-8.8p1.orig/sftp.1 ++++ openssh-8.8p1/sftp.1 +@@ -287,6 +287,9 @@ Specifies the port to connect to on the + .It Fl p + Preserves modification times, access times, and modes from the + original files transferred. ++.It Fl Q ++Not-so-quiet batch mode: forces printing of diagnostic messages ++in batch mode. + .It Fl q + Quiet mode: disables the progress meter as well as warning and + diagnostic messages from +Index: openssh-8.8p1/sftp.c +=================================================================== +--- openssh-8.8p1.orig/sftp.c ++++ openssh-8.8p1/sftp.c +@@ -82,6 +82,9 @@ static volatile pid_t sshpid = -1; + /* Suppress diagnostic messages */ + int quiet = 0; + ++/* Force diagnositic messages in batch mode */ ++int loud = 0; ++ + /* This is set to 0 if the progressmeter is not desired. */ + int showprogress = 1; + +@@ -2381,7 +2384,7 @@ main(int argc, char **argv) + infile = stdin; + + while ((ch = getopt(argc, argv, +- "1246AafhNpqrvCc:D:i:l:o:s:S:b:B:F:J:P:R:X:")) != -1) { ++ "1246AafhNpQqrvCc:D:i:l:o:s:S:b:B:F:J:P:R:X:")) != -1) { + switch (ch) { + /* Passed through to ssh(1) */ + case 'A': +@@ -2399,6 +2402,9 @@ main(int argc, char **argv) + addargs(&args, "-%c", ch); + addargs(&args, "%s", optarg); + break; ++ case 'Q': ++ loud = 1; ++ break; + case 'q': + ll = SYSLOG_LEVEL_ERROR; + quiet = 1; +@@ -2483,6 +2489,8 @@ main(int argc, char **argv) + usage(); + } + } ++ if (batchmode && loud) ++ quiet = 0; + + /* Do this last because we want the user to be able to override it */ + addargs(&args, "-oForwardAgent no"); diff --git a/openssh-7.7p1-systemd-notify.patch b/openssh-7.7p1-systemd-notify.patch new file mode 100644 index 0000000..ae55aae --- /dev/null +++ b/openssh-7.7p1-systemd-notify.patch @@ -0,0 +1,87 @@ +# HG changeset patch +# Parent d296e85dc414b8cd1b4b55ad03d8216feb26531a +Send signals to systemd to prevent various race conditions +bsc#1048367 + +Index: openssh-8.8p1/configure.ac +=================================================================== +--- openssh-8.8p1.orig/configure.ac ++++ openssh-8.8p1/configure.ac +@@ -4751,6 +4751,30 @@ AC_ARG_WITH([kerberos5], +# AC_SUBST([GSSLIBS]) + AC_SUBST([K5LIBS]) + AC_SUBST([CHANNELLIBS]) + ++# Check whether user wants systemd support ++SYSTEMD_MSG="no" ++AC_ARG_WITH(systemd, ++ [ --with-systemd Enable systemd support], ++ [ if test "x$withval" != "xno" ; then ++ AC_PATH_TOOL([PKGCONFIG], [pkg-config], [no]) ++ if test "$PKGCONFIG" != "no"; then ++ AC_MSG_CHECKING([for libsystemd]) ++ if $PKGCONFIG --exists libsystemd; then ++ SYSTEMD_CFLAGS=`$PKGCONFIG --cflags libsystemd` ++ SYSTEMD_LIBS=`$PKGCONFIG --libs libsystemd` ++ CPPFLAGS="$CPPFLAGS $SYSTEMD_CFLAGS" ++ SSHDLIBS="$SSHDLIBS $SYSTEMD_LIBS" ++ AC_MSG_RESULT([yes]) ++ AC_DEFINE(HAVE_SYSTEMD, 1, [Define if you want systemd support.]) ++ SYSTEMD_MSG="yes" ++ else ++ AC_MSG_RESULT([no]) ++ fi ++ fi ++ fi ] ++) ++ ++ + # Looking for programs, paths and files + + PRIVSEP_PATH=/var/empty +@@ -5564,6 +5588,7 @@ echo " libldns support + echo " Solaris process contract support: $SPC_MSG" + echo " Solaris project support: $SP_MSG" + echo " Solaris privilege support: $SPP_MSG" ++echo " systemd support: $SYSTEMD_MSG" + echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG" + echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG" + echo " BSD Auth support: $BSD_AUTH_MSG" +Index: openssh-8.8p1/sshd.c +=================================================================== +--- openssh-8.8p1.orig/sshd.c ++++ openssh-8.8p1/sshd.c +@@ -85,6 +85,10 @@ + #include + #endif + ++#ifdef HAVE_SYSTEMD ++#include ++#endif ++ + #include "xmalloc.h" + #include "ssh.h" + #include "ssh2.h" +@@ -308,6 +312,10 @@ sighup_handler(int sig) + static void + sighup_restart(void) + { ++#ifdef HAVE_SYSTEMD ++ /* Signal systemd that we are reloading */ ++ sd_notify(0, "RELOADING=1"); ++#endif + logit("Received SIGHUP; restarting."); + if (options.pid_file != NULL) + unlink(options.pid_file); +@@ -2076,6 +2084,11 @@ main(int ac, char **av) + } + } + ++#ifdef HAVE_SYSTEMD ++ /* Signal systemd that we are ready to accept connections */ ++ sd_notify(0, "READY=1"); ++#endif ++ + /* Accept a connection and return in a forked child */ + server_accept_loop(&sock_in, &sock_out, + &newsock, config_s); diff --git a/openssh-7.8p1-role-mls.patch b/openssh-7.8p1-role-mls.patch new file mode 100644 index 0000000..a73ca13 --- /dev/null +++ b/openssh-7.8p1-role-mls.patch @@ -0,0 +1,885 @@ +Index: openssh-9.6p1/auth2.c +=================================================================== +--- openssh-9.6p1.orig/auth2.c ++++ openssh-9.6p1/auth2.c +@@ -273,6 +273,9 @@ input_userauth_request(int type, u_int32 + Authctxt *authctxt = ssh->authctxt; + Authmethod *m = NULL; + char *user = NULL, *service = NULL, *method = NULL, *style = NULL; ++#ifdef WITH_SELINUX ++ char *role = NULL; ++#endif + int r, authenticated = 0; + double tstart = monotime_double(); + +@@ -286,6 +289,11 @@ input_userauth_request(int type, u_int32 + debug("userauth-request for user %s service %s method %s", user, service, method); + debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); + ++#ifdef WITH_SELINUX ++ if ((role = strchr(user, '/')) != NULL) ++ *role++ = 0; ++#endif ++ + if ((style = strchr(user, ':')) != NULL) + *style++ = 0; + +@@ -313,8 +321,15 @@ input_userauth_request(int type, u_int32 + use_privsep ? " [net]" : ""); + authctxt->service = xstrdup(service); + authctxt->style = style ? xstrdup(style) : NULL; +- if (use_privsep) ++#ifdef WITH_SELINUX ++ authctxt->role = role ? xstrdup(role) : NULL; ++#endif ++ if (use_privsep) { + mm_inform_authserv(service, style); ++#ifdef WITH_SELINUX ++ mm_inform_authrole(role); ++#endif ++ } + userauth_banner(ssh); + if ((r = kex_server_update_ext_info(ssh)) != 0) + fatal_fr(r, "kex_server_update_ext_info failed"); +Index: openssh-9.6p1/auth2-gss.c +=================================================================== +--- openssh-9.6p1.orig/auth2-gss.c ++++ openssh-9.6p1/auth2-gss.c +@@ -331,6 +331,7 @@ input_gssapi_mic(int type, u_int32_t ple + Authctxt *authctxt = ssh->authctxt; + Gssctxt *gssctxt; + int r, authenticated = 0; ++ char *micuser; + struct sshbuf *b; + gss_buffer_desc mic, gssbuf; + const char *displayname; +@@ -348,7 +349,13 @@ input_gssapi_mic(int type, u_int32_t ple + fatal_f("sshbuf_new failed"); + mic.value = p; + mic.length = len; +- ssh_gssapi_buildmic(b, authctxt->user, authctxt->service, ++#ifdef WITH_SELINUX ++ if (authctxt->role && authctxt->role[0] != 0) ++ xasprintf(&micuser, "%s/%s", authctxt->user, authctxt->role); ++ else ++#endif ++ micuser = authctxt->user; ++ ssh_gssapi_buildmic(b, micuser, authctxt->service, + "gssapi-with-mic", ssh->kex->session_id); + + if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL) +@@ -362,6 +369,8 @@ input_gssapi_mic(int type, u_int32_t ple + logit("GSSAPI MIC check failed"); + + sshbuf_free(b); ++ if (micuser != authctxt->user) ++ free(micuser); + free(mic.value); + + if ((!use_privsep || mm_is_monitor()) && +Index: openssh-9.6p1/auth2-hostbased.c +=================================================================== +--- openssh-9.6p1.orig/auth2-hostbased.c ++++ openssh-9.6p1/auth2-hostbased.c +@@ -128,7 +128,16 @@ userauth_hostbased(struct ssh *ssh, cons + /* reconstruct packet */ + if ((r = sshbuf_put_stringb(b, ssh->kex->session_id)) != 0 || + (r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 || ++#ifdef WITH_SELINUX ++ (authctxt->role ++ ? ( (r = sshbuf_put_u32(b, strlen(authctxt->user)+strlen(authctxt->role)+1)) != 0 || ++ (r = sshbuf_put(b, authctxt->user, strlen(authctxt->user))) != 0 || ++ (r = sshbuf_put_u8(b, '/') != 0) || ++ (r = sshbuf_put(b, authctxt->role, strlen(authctxt->role))) != 0) ++ : (r = sshbuf_put_cstring(b, authctxt->user)) != 0) || ++#else + (r = sshbuf_put_cstring(b, authctxt->user)) != 0 || ++#endif + (r = sshbuf_put_cstring(b, authctxt->service)) != 0 || + (r = sshbuf_put_cstring(b, method)) != 0 || + (r = sshbuf_put_string(b, pkalg, alen)) != 0 || +Index: openssh-9.6p1/auth2-pubkey.c +=================================================================== +--- openssh-9.6p1.orig/auth2-pubkey.c ++++ openssh-9.6p1/auth2-pubkey.c +@@ -200,9 +200,16 @@ userauth_pubkey(struct ssh *ssh, const c + goto done; + } + /* reconstruct packet */ +- xasprintf(&userstyle, "%s%s%s", authctxt->user, ++ xasprintf(&userstyle, "%s%s%s%s%s", authctxt->user, + authctxt->style ? ":" : "", +- authctxt->style ? authctxt->style : ""); ++ authctxt->style ? authctxt->style : "", ++#ifdef WITH_SELINUX ++ authctxt->role ? "/" : "", ++ authctxt->role ? authctxt->role : "" ++#else ++ "", "" ++#endif ++ ); + if ((r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 || + (r = sshbuf_put_cstring(b, userstyle)) != 0 || + (r = sshbuf_put_cstring(b, authctxt->service)) != 0 || +Index: openssh-9.6p1/auth.h +=================================================================== +--- openssh-9.6p1.orig/auth.h ++++ openssh-9.6p1/auth.h +@@ -65,6 +65,9 @@ struct Authctxt { + char *service; + struct passwd *pw; /* set if 'valid' */ + char *style; ++#ifdef WITH_SELINUX ++ char *role; ++#endif + + /* Method lists for multiple authentication */ + char **auth_methods; /* modified from server config */ +Index: openssh-9.6p1/auth-pam.c +=================================================================== +--- openssh-9.6p1.orig/auth-pam.c ++++ openssh-9.6p1/auth-pam.c +@@ -1242,7 +1242,7 @@ is_pam_session_open(void) + * during the ssh authentication process. + */ + int +-do_pam_putenv(char *name, char *value) ++do_pam_putenv(char *name, const char *value) + { + int ret = 1; + char *compound; +Index: openssh-9.6p1/auth-pam.h +=================================================================== +--- openssh-9.6p1.orig/auth-pam.h ++++ openssh-9.6p1/auth-pam.h +@@ -33,7 +33,7 @@ u_int do_pam_account(void); + void do_pam_session(struct ssh *); + void do_pam_setcred(int ); + void do_pam_chauthtok(void); +-int do_pam_putenv(char *, char *); ++int do_pam_putenv(char *, const char *); + char ** fetch_pam_environment(void); + char ** fetch_pam_child_environment(void); + void free_pam_environment(char **); +Index: openssh-9.6p1/misc.c +=================================================================== +--- openssh-9.6p1.orig/misc.c ++++ openssh-9.6p1/misc.c +@@ -771,6 +771,7 @@ char * + colon(char *cp) + { + int flag = 0; ++ int start = 1; + + if (*cp == ':') /* Leading colon is part of file name. */ + return NULL; +@@ -786,6 +787,13 @@ colon(char *cp) + return (cp); + if (*cp == '/') + return NULL; ++ if (start) { ++ /* Slash on beginning or after dots only denotes file name. */ ++ if (*cp == '/') ++ return (0); ++ if (*cp != '.') ++ start = 0; ++ } + } + return NULL; + } +Index: openssh-9.6p1/monitor.c +=================================================================== +--- openssh-9.6p1.orig/monitor.c ++++ openssh-9.6p1/monitor.c +@@ -120,6 +120,9 @@ int mm_answer_sign(struct ssh *, int, st + int mm_answer_pwnamallow(struct ssh *, int, struct sshbuf *); + int mm_answer_auth2_read_banner(struct ssh *, int, struct sshbuf *); + int mm_answer_authserv(struct ssh *, int, struct sshbuf *); ++#ifdef WITH_SELINUX ++int mm_answer_authrole(struct ssh *, int, struct sshbuf *); ++#endif + 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 *); +@@ -200,6 +203,9 @@ struct mon_table mon_dispatch_proto20[] + {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, + {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, + {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, ++#ifdef WITH_SELINUX ++ {MONITOR_REQ_AUTHROLE, MON_ONCE, mm_answer_authrole}, ++#endif + {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner}, + {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, + #ifdef USE_PAM +@@ -834,6 +840,9 @@ mm_answer_pwnamallow(struct ssh *ssh, in + + /* Allow service/style information on the auth context */ + monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1); ++#ifdef WITH_SELINUX ++ monitor_permit(mon_dispatch, MONITOR_REQ_AUTHROLE, 1); ++#endif + monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1); + + #ifdef USE_PAM +@@ -908,6 +917,26 @@ key_base_type_match(const char *method, + return found; + } + ++#ifdef WITH_SELINUX ++int ++mm_answer_authrole(struct ssh *ssh, int sock, struct sshbuf *m) ++{ ++ int r; ++ monitor_permit_authentications(1); ++ ++ if ((r = sshbuf_get_cstring(m, &authctxt->role, NULL)) != 0) ++ fatal_f("buffer error: %s", ssh_err(r)); ++ debug3_f("role=%s", authctxt->role); ++ ++ if (strlen(authctxt->role) == 0) { ++ free(authctxt->role); ++ authctxt->role = NULL; ++ } ++ ++ return (0); ++} ++#endif ++ + int + mm_answer_authpassword(struct ssh *ssh, int sock, struct sshbuf *m) + { +@@ -1280,7 +1309,7 @@ monitor_valid_userblob(struct ssh *ssh, + struct sshbuf *b; + struct sshkey *hostkey = NULL; + const u_char *p; +- char *userstyle, *cp; ++ char *userstyle, *s, *cp; + size_t len; + u_char type; + int hostbound = 0, r, fail = 0; +@@ -1311,6 +1340,8 @@ monitor_valid_userblob(struct ssh *ssh, + fail++; + if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0) + fatal_fr(r, "parse userstyle"); ++ if ((s = strchr(cp, '/')) != NULL) ++ *s = '\0'; + xasprintf(&userstyle, "%s%s%s", authctxt->user, + authctxt->style ? ":" : "", + authctxt->style ? authctxt->style : ""); +@@ -1361,7 +1392,7 @@ monitor_valid_hostbasedblob(const u_char + { + struct sshbuf *b; + const u_char *p; +- char *cp, *userstyle; ++ char *cp, *s, *userstyle; + size_t len; + int r, fail = 0; + u_char type; +@@ -1382,6 +1413,8 @@ monitor_valid_hostbasedblob(const u_char + fail++; + if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0) + fatal_fr(r, "parse userstyle"); ++ if ((s = strchr(cp, '/')) != NULL) ++ *s = '\0'; + xasprintf(&userstyle, "%s%s%s", authctxt->user, + authctxt->style ? ":" : "", + authctxt->style ? authctxt->style : ""); +Index: openssh-9.6p1/monitor.h +=================================================================== +--- openssh-9.6p1.orig/monitor.h ++++ openssh-9.6p1/monitor.h +@@ -55,6 +55,10 @@ enum monitor_reqtype { + MONITOR_REQ_GSSCHECKMIC = 48, MONITOR_ANS_GSSCHECKMIC = 49, + MONITOR_REQ_TERM = 50, + ++#ifdef WITH_SELINUX ++ MONITOR_REQ_AUTHROLE = 80, ++#endif ++ + MONITOR_REQ_PAM_START = 100, + MONITOR_REQ_PAM_ACCOUNT = 102, MONITOR_ANS_PAM_ACCOUNT = 103, + MONITOR_REQ_PAM_INIT_CTX = 104, MONITOR_ANS_PAM_INIT_CTX = 105, +Index: openssh-9.6p1/monitor_wrap.c +=================================================================== +--- openssh-9.6p1.orig/monitor_wrap.c ++++ openssh-9.6p1/monitor_wrap.c +@@ -396,6 +396,27 @@ mm_inform_authserv(char *service, char * + sshbuf_free(m); + } + ++/* Inform the privileged process about role */ ++ ++#ifdef WITH_SELINUX ++void ++mm_inform_authrole(char *role) ++{ ++ int r; ++ struct sshbuf *m; ++ ++ debug3_f("entering"); ++ ++ if ((m = sshbuf_new()) == NULL) ++ fatal_f("sshbuf_new failed"); ++ if ((r = sshbuf_put_cstring(m, role ? role : "")) != 0) ++ fatal_f("buffer error: %s", ssh_err(r)); ++ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHROLE, m); ++ ++ sshbuf_free(m); ++} ++#endif ++ + /* Do the password authentication */ + int + mm_auth_password(struct ssh *ssh, char *password) +Index: openssh-9.6p1/monitor_wrap.h +=================================================================== +--- openssh-9.6p1.orig/monitor_wrap.h ++++ openssh-9.6p1/monitor_wrap.h +@@ -49,6 +49,9 @@ int mm_sshkey_sign(struct ssh *, struct + const u_char *, size_t, const char *, const char *, + const char *, u_int compat); + void mm_inform_authserv(char *, char *); ++#ifdef WITH_SELINUX ++void mm_inform_authrole(char *); ++#endif + struct passwd *mm_getpwnamallow(struct ssh *, const char *); + char *mm_auth2_read_banner(void); + int mm_auth_password(struct ssh *, char *); +Index: openssh-9.6p1/openbsd-compat/Makefile.in +=================================================================== +--- openssh-9.6p1.orig/openbsd-compat/Makefile.in ++++ openssh-9.6p1/openbsd-compat/Makefile.in +@@ -100,7 +100,8 @@ PORTS= port-aix.o \ + port-prngd.o \ + port-solaris.o \ + port-net.o \ +- port-uw.o ++ port-uw.o \ ++ port-linux-sshd.o + + .c.o: + $(CC) $(CFLAGS_NOPIE) $(PICFLAG) $(CPPFLAGS) -c $< +Index: openssh-9.6p1/openbsd-compat/port-linux.c +=================================================================== +--- openssh-9.6p1.orig/openbsd-compat/port-linux.c ++++ openssh-9.6p1/openbsd-compat/port-linux.c +@@ -101,37 +101,6 @@ ssh_selinux_getctxbyname(char *pwname) + return sc; + } + +-/* Set the execution context to the default for the specified user */ +-void +-ssh_selinux_setup_exec_context(char *pwname) +-{ +- char *user_ctx = NULL; +- +- if (!ssh_selinux_enabled()) +- return; +- +- debug3("%s: setting execution context", __func__); +- +- user_ctx = ssh_selinux_getctxbyname(pwname); +- if (setexeccon(user_ctx) != 0) { +- switch (security_getenforce()) { +- case -1: +- fatal("%s: security_getenforce() failed", __func__); +- case 0: +- error("%s: Failed to set SELinux execution " +- "context for %s", __func__, pwname); +- break; +- default: +- fatal("%s: Failed to set SELinux execution context " +- "for %s (in enforcing mode)", __func__, pwname); +- } +- } +- if (user_ctx != NULL) +- freecon(user_ctx); +- +- debug3("%s: done", __func__); +-} +- + /* Set the TTY context for the specified user */ + void + ssh_selinux_setup_pty(char *pwname, const char *tty) +@@ -144,7 +113,11 @@ ssh_selinux_setup_pty(char *pwname, cons + + debug3("%s: setting TTY context on %s", __func__, tty); + +- user_ctx = ssh_selinux_getctxbyname(pwname); ++ if (getexeccon(&user_ctx) != 0) { ++ error_f("getexeccon: %s", strerror(errno)); ++ goto out; ++ } ++ + + /* XXX: should these calls fatal() upon failure in enforcing mode? */ + +Index: openssh-9.6p1/openbsd-compat/port-linux.h +=================================================================== +--- openssh-9.6p1.orig/openbsd-compat/port-linux.h ++++ openssh-9.6p1/openbsd-compat/port-linux.h +@@ -20,9 +20,10 @@ + #ifdef WITH_SELINUX + int ssh_selinux_enabled(void); + void ssh_selinux_setup_pty(char *, const char *); +-void ssh_selinux_setup_exec_context(char *); + void ssh_selinux_change_context(const char *); + void ssh_selinux_setfscreatecon(const char *); ++ ++void sshd_selinux_setup_exec_context(char *); + #endif + + #ifdef LINUX_OOM_ADJUST +Index: openssh-9.6p1/openbsd-compat/port-linux-sshd.c +=================================================================== +--- /dev/null ++++ openssh-9.6p1/openbsd-compat/port-linux-sshd.c +@@ -0,0 +1,421 @@ ++/* ++ * Copyright (c) 2005 Daniel Walsh ++ * Copyright (c) 2014 Petr Lautrbach ++ * ++ * 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 - just SELinux support for sshd at present ++ */ ++ ++#include "includes.h" ++ ++#if defined(WITH_SELINUX) || defined(LINUX_OOM_ADJUST) ++#include ++#include ++#include ++#include ++#include ++ ++#include "log.h" ++#include "xmalloc.h" ++#include "misc.h" /* servconf.h needs misc.h for struct ForwardOptions */ ++#include "servconf.h" ++#include "port-linux.h" ++#include "sshkey.h" ++#include "hostfile.h" ++#include "auth.h" ++ ++#ifdef WITH_SELINUX ++#include ++#include ++#include ++#include ++ ++#ifdef HAVE_LINUX_AUDIT ++#include ++#include ++#endif ++ ++extern ServerOptions options; ++extern Authctxt *the_authctxt; ++extern int inetd_flag; ++extern int rexeced_flag; ++ ++/* Send audit message */ ++static int ++sshd_selinux_send_audit_message(int success, security_context_t default_context, ++ security_context_t selected_context) ++{ ++ int rc=0; ++#ifdef HAVE_LINUX_AUDIT ++ char *msg = NULL; ++ int audit_fd = audit_open(); ++ security_context_t default_raw=NULL; ++ security_context_t selected_raw=NULL; ++ rc = -1; ++ if (audit_fd < 0) { ++ if (errno == EINVAL || errno == EPROTONOSUPPORT || ++ errno == EAFNOSUPPORT) ++ return 0; /* No audit support in kernel */ ++ error("Error connecting to audit system."); ++ return rc; ++ } ++ if (selinux_trans_to_raw_context(default_context, &default_raw) < 0) { ++ error("Error translating default context."); ++ default_raw = NULL; ++ } ++ if (selinux_trans_to_raw_context(selected_context, &selected_raw) < 0) { ++ error("Error translating selected context."); ++ selected_raw = NULL; ++ } ++ if (asprintf(&msg, "sshd: default-context=%s selected-context=%s", ++ default_raw ? default_raw : (default_context ? default_context: "?"), ++ selected_context ? selected_raw : (selected_context ? selected_context :"?")) < 0) { ++ error("Error allocating memory."); ++ goto out; ++ } ++ if (audit_log_user_message(audit_fd, AUDIT_USER_ROLE_CHANGE, ++ msg, NULL, NULL, NULL, success) <= 0) { ++ error("Error sending audit message."); ++ goto out; ++ } ++ rc = 0; ++ out: ++ free(msg); ++ freecon(default_raw); ++ freecon(selected_raw); ++ close(audit_fd); ++#endif ++ return rc; ++} ++ ++static int ++mls_range_allowed(security_context_t src, security_context_t dst) ++{ ++ struct av_decision avd; ++ int retval; ++ access_vector_t bit; ++ security_class_t class; ++ ++ debug_f("src:%s dst:%s", src, dst); ++ class = string_to_security_class("context"); ++ if (!class) { ++ error("string_to_security_class failed to translate security class context"); ++ return 1; ++ } ++ bit = string_to_av_perm(class, "contains"); ++ if (!bit) { ++ error("string_to_av_perm failed to translate av perm contains"); ++ return 1; ++ } ++ retval = security_compute_av(src, dst, class, bit, &avd); ++ if (retval || ((bit & avd.allowed) != bit)) ++ return 0; ++ ++ return 1; ++} ++ ++static int ++get_user_context(const char *sename, const char *role, const char *lvl, ++ security_context_t *sc) { ++#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL ++ if (lvl == NULL || lvl[0] == '\0' || get_default_context_with_level(sename, lvl, NULL, sc) != 0) { ++ /* User may have requested a level completely outside of his ++ allowed range. We get a context just for auditing as the ++ range check below will certainly fail for default context. */ ++#endif ++ if (get_default_context(sename, NULL, sc) != 0) { ++ *sc = NULL; ++ return -1; ++ } ++#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL ++ } ++#endif ++ if (role != NULL && role[0]) { ++ context_t con; ++ char *type=NULL; ++ if (get_default_type(role, &type) != 0) { ++ error("get_default_type: failed to get default type for '%s'", ++ role); ++ goto out; ++ } ++ con = context_new(*sc); ++ if (!con) { ++ goto out; ++ } ++ context_role_set(con, role); ++ context_type_set(con, type); ++ freecon(*sc); ++ *sc = strdup(context_str(con)); ++ context_free(con); ++ if (!*sc) ++ return -1; ++ } ++#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL ++ if (lvl != NULL && lvl[0]) { ++ /* verify that the requested range is obtained */ ++ context_t con; ++ security_context_t obtained_raw; ++ security_context_t requested_raw; ++ con = context_new(*sc); ++ if (!con) { ++ goto out; ++ } ++ context_range_set(con, lvl); ++ if (selinux_trans_to_raw_context(*sc, &obtained_raw) < 0) { ++ context_free(con); ++ goto out; ++ } ++ if (selinux_trans_to_raw_context(context_str(con), &requested_raw) < 0) { ++ freecon(obtained_raw); ++ context_free(con); ++ goto out; ++ } ++ ++ debug("get_user_context: obtained context '%s' requested context '%s'", ++ obtained_raw, requested_raw); ++ if (strcmp(obtained_raw, requested_raw)) { ++ /* set the context to the real requested one but fail */ ++ freecon(requested_raw); ++ freecon(obtained_raw); ++ freecon(*sc); ++ *sc = strdup(context_str(con)); ++ context_free(con); ++ return -1; ++ } ++ freecon(requested_raw); ++ freecon(obtained_raw); ++ context_free(con); ++ } ++#endif ++ return 0; ++ out: ++ freecon(*sc); ++ *sc = NULL; ++ return -1; ++} ++ ++static void ++ssh_selinux_get_role_level(char **role, const char **level) ++{ ++ *role = NULL; ++ *level = NULL; ++ if (the_authctxt) { ++ if (the_authctxt->role != NULL) { ++ char *slash; ++ *role = xstrdup(the_authctxt->role); ++ if ((slash = strchr(*role, '/')) != NULL) { ++ *slash = '\0'; ++ *level = slash + 1; ++ } ++ } ++ } ++} ++ ++/* Return the default security context for the given username */ ++static int ++sshd_selinux_getctxbyname(char *pwname, ++ security_context_t *default_sc, security_context_t *user_sc) ++{ ++ char *sename, *lvl; ++ char *role; ++ const char *reqlvl; ++ int r = 0; ++ context_t con = NULL; ++ ++ ssh_selinux_get_role_level(&role, &reqlvl); ++ ++#ifdef HAVE_GETSEUSERBYNAME ++ if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) { ++ sename = NULL; ++ lvl = NULL; ++ } ++#else ++ sename = pwname; ++ lvl = ""; ++#endif ++ ++ if (r == 0) { ++#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL ++ r = get_default_context_with_level(sename, lvl, NULL, default_sc); ++#else ++ r = get_default_context(sename, NULL, default_sc); ++#endif ++ } ++ ++ if (r == 0) { ++ /* If launched from xinetd, we must use current level */ ++ if (inetd_flag && !rexeced_flag) { ++ security_context_t sshdsc=NULL; ++ ++ if (getcon_raw(&sshdsc) < 0) ++ fatal("failed to allocate security context"); ++ ++ if ((con=context_new(sshdsc)) == NULL) ++ fatal("failed to allocate selinux context"); ++ reqlvl = context_range_get(con); ++ freecon(sshdsc); ++ if (reqlvl !=NULL && lvl != NULL && strcmp(reqlvl, lvl) == 0) ++ /* we actually don't change level */ ++ reqlvl = ""; ++ ++ debug_f("current connection level '%s'", reqlvl); ++ ++ } ++ ++ if ((reqlvl != NULL && reqlvl[0]) || (role != NULL && role[0])) { ++ r = get_user_context(sename, role, reqlvl, user_sc); ++ ++ if (r == 0 && reqlvl != NULL && reqlvl[0]) { ++ security_context_t default_level_sc = *default_sc; ++ if (role != NULL && role[0]) { ++ if (get_user_context(sename, role, lvl, &default_level_sc) < 0) ++ default_level_sc = *default_sc; ++ } ++ /* verify that the requested range is contained in the user range */ ++ if (mls_range_allowed(default_level_sc, *user_sc)) { ++ logit("permit MLS level %s (user range %s)", reqlvl, lvl); ++ } else { ++ r = -1; ++ error("deny MLS level %s (user range %s)", reqlvl, lvl); ++ } ++ if (default_level_sc != *default_sc) ++ freecon(default_level_sc); ++ } ++ } else { ++ *user_sc = *default_sc; ++ } ++ } ++ if (r != 0) { ++ error_f("Failed to get default SELinux security " ++ "context for %s", pwname); ++ } ++ ++#ifdef HAVE_GETSEUSERBYNAME ++ free(sename); ++ free(lvl); ++#endif ++ ++ if (role != NULL) ++ free(role); ++ if (con) ++ context_free(con); ++ ++ return (r); ++} ++ ++/* Setup environment variables for pam_selinux */ ++static int ++sshd_selinux_setup_pam_variables(void) ++{ ++ const char *reqlvl; ++ char *role; ++ char *use_current; ++ int rv; ++ ++ debug3_f("setting execution context"); ++ ++ ssh_selinux_get_role_level(&role, &reqlvl); ++ ++ rv = do_pam_putenv("SELINUX_ROLE_REQUESTED", role ? role : ""); ++ ++ if (inetd_flag && !rexeced_flag) { ++ use_current = "1"; ++ } else { ++ use_current = ""; ++ rv = rv || do_pam_putenv("SELINUX_LEVEL_REQUESTED", reqlvl ? reqlvl: ""); ++ } ++ ++ rv = rv || do_pam_putenv("SELINUX_USE_CURRENT_RANGE", use_current); ++ ++ if (role != NULL) ++ free(role); ++ ++ return rv; ++} ++ ++/* Set the execution context to the default for the specified user */ ++void ++sshd_selinux_setup_exec_context(char *pwname) ++{ ++ security_context_t user_ctx = NULL; ++ int r = 0; ++ security_context_t default_ctx = NULL; ++ ++ if (!ssh_selinux_enabled()) ++ return; ++ ++ if (options.use_pam) { ++ /* do not compute context, just setup environment for pam_selinux */ ++ if (sshd_selinux_setup_pam_variables()) { ++ switch (security_getenforce()) { ++ case -1: ++ fatal_f("security_getenforce() failed"); ++ case 0: ++ error_f("SELinux PAM variable setup failure. Continuing in permissive mode."); ++ break; ++ default: ++ fatal_f("SELinux PAM variable setup failure. Aborting connection."); ++ } ++ } ++ return; ++ } ++ ++ debug3_f("setting execution context"); ++ ++ r = sshd_selinux_getctxbyname(pwname, &default_ctx, &user_ctx); ++ if (r >= 0) { ++ r = setexeccon(user_ctx); ++ if (r < 0) { ++ error_f("Failed to set SELinux execution context %s for %s", ++ user_ctx, pwname); ++ } ++#ifdef HAVE_SETKEYCREATECON ++ else if (setkeycreatecon(user_ctx) < 0) { ++ error_f("Failed to set SELinux keyring creation context %s for %s", ++ user_ctx, pwname); ++ } ++#endif ++ } ++ if (user_ctx == NULL) { ++ user_ctx = default_ctx; ++ } ++ if (r < 0 || user_ctx != default_ctx) { ++ /* audit just the case when user changed a role or there was ++ a failure */ ++ sshd_selinux_send_audit_message(r >= 0, default_ctx, user_ctx); ++ } ++ if (r < 0) { ++ switch (security_getenforce()) { ++ case -1: ++ fatal_f("security_getenforce() failed"); ++ case 0: ++ error_f("ELinux failure. Continuing in permissive mode."); ++ break; ++ default: ++ fatal_f("SELinux failure. Aborting connection."); ++ } ++ } ++ if (user_ctx != NULL && user_ctx != default_ctx) ++ freecon(user_ctx); ++ if (default_ctx != NULL) ++ freecon(default_ctx); ++ ++ debug3_f("done"); ++} ++ ++#endif ++#endif ++ +Index: openssh-9.6p1/platform.c +=================================================================== +--- openssh-9.6p1.orig/platform.c ++++ openssh-9.6p1/platform.c +@@ -185,7 +185,7 @@ platform_setusercontext_post_groups(stru + } + #endif /* HAVE_SETPCRED */ + #ifdef WITH_SELINUX +- ssh_selinux_setup_exec_context(pw->pw_name); ++ sshd_selinux_setup_exec_context(pw->pw_name); + #endif + } + +Index: openssh-9.6p1/sshd.c +=================================================================== +--- openssh-9.6p1.orig/sshd.c ++++ openssh-9.6p1/sshd.c +@@ -2387,6 +2387,9 @@ main(int ac, char **av) + restore_uid(); + } + #endif ++#ifdef WITH_SELINUX ++ sshd_selinux_setup_exec_context(authctxt->pw->pw_name); ++#endif + #ifdef USE_PAM + if (options.use_pam) { + do_pam_setcred(1); diff --git a/openssh-7.9p1-keygen-preserve-perms.patch b/openssh-7.9p1-keygen-preserve-perms.patch new file mode 100644 index 0000000..8c2cb07 --- /dev/null +++ b/openssh-7.9p1-keygen-preserve-perms.patch @@ -0,0 +1,39 @@ +commit 07ffb49749c310b82e44278ae05e081d6f4a82bf +Author: Hans Petter Jansson +Date: Fri Sep 27 01:57:16 2019 +0200 + + ssh-keygen: Preserve known_hosts permissions on rewrite + + Transfer the permissions of the old known_hosts file instead of + just going with what mkstemp() gives us. This is useful in corner + cases where known_hosts is shared between users. + +Index: openssh-8.8p1/ssh-keygen.c +=================================================================== +--- openssh-8.8p1.orig/ssh-keygen.c ++++ openssh-8.8p1/ssh-keygen.c +@@ -1384,6 +1384,11 @@ do_known_hosts(struct passwd *pw, const + if (inplace) + unlink(tmp); + } else if (inplace) { ++ struct stat st; ++ ++ /* Get metadata for existing file */ ++ r = stat(identity_file, &st); ++ + /* Backup existing file */ + if (unlink(old) == -1 && errno != ENOENT) + fatal("unlink %.100s: %s", old, strerror(errno)); +@@ -1398,6 +1403,12 @@ do_known_hosts(struct passwd *pw, const + unlink(old); + exit(1); + } ++ /* Preserve permissions; non-critical */ ++ if (r != -1) ++ r = chown(identity_file, st.st_uid, st.st_gid); ++ if (r != -1) ++ chmod(identity_file, ++ st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)); + + printf("%s updated.\n", identity_file); + printf("Original contents retained as %s\n", old); diff --git a/openssh-7.9p1-revert-new-qos-defaults.patch b/openssh-7.9p1-revert-new-qos-defaults.patch new file mode 100644 index 0000000..0a989b9 --- /dev/null +++ b/openssh-7.9p1-revert-new-qos-defaults.patch @@ -0,0 +1,76 @@ +commit 101aa2f70c937abb428c9433c39ba0fd9a91fe6b +Author: Hans Petter Jansson +Date: Thu Jun 20 23:54:11 2019 +0200 + + Revert IPQoS DSCP AF21/CS1 from upstream due to bugs in other software + + Reverts OpenBSD-Commit-ID: d11d2a4484f461524ef0c20870523dfcdeb52181 + +Index: openssh-8.8p1/readconf.c +=================================================================== +--- openssh-8.8p1.orig/readconf.c ++++ openssh-8.8p1/readconf.c +@@ -2679,9 +2679,9 @@ fill_default_options(Options * options) + if (options->visual_host_key == -1) + options->visual_host_key = 0; + if (options->ip_qos_interactive == -1) +- options->ip_qos_interactive = IPTOS_DSCP_AF21; ++ options->ip_qos_interactive = IPTOS_LOWDELAY; + if (options->ip_qos_bulk == -1) +- options->ip_qos_bulk = IPTOS_DSCP_CS1; ++ options->ip_qos_bulk = IPTOS_THROUGHPUT; + if (options->request_tty == -1) + options->request_tty = REQUEST_TTY_AUTO; + if (options->session_type == -1) +Index: openssh-8.8p1/servconf.c +=================================================================== +--- openssh-8.8p1.orig/servconf.c ++++ openssh-8.8p1/servconf.c +@@ -459,9 +459,9 @@ fill_default_server_options(ServerOption + if (options->permit_tun == -1) + options->permit_tun = SSH_TUNMODE_NO; + if (options->ip_qos_interactive == -1) +- options->ip_qos_interactive = IPTOS_DSCP_AF21; ++ options->ip_qos_interactive = IPTOS_LOWDELAY; + if (options->ip_qos_bulk == -1) +- options->ip_qos_bulk = IPTOS_DSCP_CS1; ++ options->ip_qos_bulk = IPTOS_THROUGHPUT; + if (options->version_addendum == NULL) + options->version_addendum = xstrdup(""); + if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1) +Index: openssh-8.8p1/ssh_config.5 +=================================================================== +--- openssh-8.8p1.orig/ssh_config.5 ++++ openssh-8.8p1/ssh_config.5 +@@ -1182,11 +1182,9 @@ If one argument is specified, it is used + If two values are specified, the first is automatically selected for + interactive sessions and the second for non-interactive sessions. + The default is +-.Cm af21 +-(Low-Latency Data) ++.Cm lowdelay + for interactive sessions and +-.Cm cs1 +-(Lower Effort) ++.Cm throughput + for non-interactive sessions. + .It Cm KbdInteractiveAuthentication + Specifies whether to use keyboard-interactive authentication. +Index: openssh-8.8p1/sshd_config.5 +=================================================================== +--- openssh-8.8p1.orig/sshd_config.5 ++++ openssh-8.8p1/sshd_config.5 +@@ -903,11 +903,9 @@ If one argument is specified, it is used + If two values are specified, the first is automatically selected for + interactive sessions and the second for non-interactive sessions. + The default is +-.Cm af21 +-(Low-Latency Data) ++.Cm lowdelay + for interactive sessions and +-.Cm cs1 +-(Lower Effort) ++.Cm throughput + for non-interactive sessions. + .It Cm KbdInteractiveAuthentication + Specifies whether to allow keyboard-interactive authentication. diff --git a/openssh-8.0p1-gssapi-keyex.patch b/openssh-8.0p1-gssapi-keyex.patch new file mode 100644 index 0000000..e760f13 --- /dev/null +++ b/openssh-8.0p1-gssapi-keyex.patch @@ -0,0 +1,3966 @@ +Index: openssh-9.6p1/Makefile.in +=================================================================== +--- openssh-9.6p1.orig/Makefile.in ++++ openssh-9.6p1/Makefile.in +@@ -114,6 +114,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ + kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ + kexgexc.o kexgexs.o \ + kexsntrup761x25519.o sntrup761.o kexgen.o \ ++ kexgssc.o \ + sftp-realpath.o platform-pledge.o platform-tracing.o platform-misc.o \ + sshbuf-io.o + +@@ -132,7 +133,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passw + auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \ + auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-pubkeyfile.o \ + monitor.o monitor_wrap.o auth-krb5.o \ +- auth2-gss.o gss-serv.o gss-serv-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 \ + srclimit.o sftp-server.o sftp-common.o \ + sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \ +Index: openssh-9.6p1/auth.c +=================================================================== +--- openssh-9.6p1.orig/auth.c ++++ openssh-9.6p1/auth.c +@@ -357,7 +357,8 @@ auth_root_allowed(struct ssh *ssh, const + case PERMIT_NO_PASSWD: + if (strcmp(method, "publickey") == 0 || + strcmp(method, "hostbased") == 0 || +- strcmp(method, "gssapi-with-mic") == 0) ++ strcmp(method, "gssapi-with-mic") == 0 || ++ strcmp(method, "gssapi-keyex") == 0) + return 1; + break; + case PERMIT_FORCED_ONLY: +@@ -638,97 +639,6 @@ fakepw(void) + } + + /* +- * Returns the remote DNS hostname as a string. The returned string must not +- * be freed. NB. this will usually trigger a DNS query the first time it is +- * called. +- * This function does additional checks on the hostname to mitigate some +- * attacks on based on conflation of hostnames and IP addresses. +- */ +- +-static char * +-remote_hostname(struct ssh *ssh) +-{ +- struct sockaddr_storage from; +- socklen_t fromlen; +- struct addrinfo hints, *ai, *aitop; +- char name[NI_MAXHOST], ntop2[NI_MAXHOST]; +- const char *ntop = ssh_remote_ipaddr(ssh); +- +- /* Get IP address of client. */ +- fromlen = sizeof(from); +- memset(&from, 0, sizeof(from)); +- if (getpeername(ssh_packet_get_connection_in(ssh), +- (struct sockaddr *)&from, &fromlen) == -1) { +- debug("getpeername failed: %.100s", strerror(errno)); +- return xstrdup(ntop); +- } +- +- ipv64_normalise_mapped(&from, &fromlen); +- if (from.ss_family == AF_INET6) +- fromlen = sizeof(struct sockaddr_in6); +- +- debug3("Trying to reverse map address %.100s.", ntop); +- /* Map the IP address to a host name. */ +- if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name), +- NULL, 0, NI_NAMEREQD) != 0) { +- /* Host name not found. Use ip address. */ +- return xstrdup(ntop); +- } +- +- /* +- * if reverse lookup result looks like a numeric hostname, +- * someone is trying to trick us by PTR record like following: +- * 1.1.1.10.in-addr.arpa. IN PTR 2.3.4.5 +- */ +- memset(&hints, 0, sizeof(hints)); +- hints.ai_socktype = SOCK_DGRAM; /*dummy*/ +- hints.ai_flags = AI_NUMERICHOST; +- if (getaddrinfo(name, NULL, &hints, &ai) == 0) { +- logit("Nasty PTR record \"%s\" is set up for %s, ignoring", +- name, ntop); +- freeaddrinfo(ai); +- return xstrdup(ntop); +- } +- +- /* Names are stored in lowercase. */ +- lowercase(name); +- +- /* +- * Map it back to an IP address and check that the given +- * address actually is an address of this host. This is +- * necessary because anyone with access to a name server can +- * define arbitrary names for an IP address. Mapping from +- * name to IP address can be trusted better (but can still be +- * fooled if the intruder has access to the name server of +- * the domain). +- */ +- memset(&hints, 0, sizeof(hints)); +- hints.ai_family = from.ss_family; +- hints.ai_socktype = SOCK_STREAM; +- if (getaddrinfo(name, NULL, &hints, &aitop) != 0) { +- logit("reverse mapping checking getaddrinfo for %.700s " +- "[%s] failed.", name, ntop); +- return xstrdup(ntop); +- } +- /* Look for the address from the list of addresses. */ +- for (ai = aitop; ai; ai = ai->ai_next) { +- if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2, +- sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 && +- (strcmp(ntop, ntop2) == 0)) +- break; +- } +- freeaddrinfo(aitop); +- /* If we reached the end of the list, the address was not there. */ +- if (ai == NULL) { +- /* Address not found for the host name. */ +- logit("Address %.100s maps to %.600s, but this does not " +- "map back to the address.", ntop, name); +- return xstrdup(ntop); +- } +- return xstrdup(name); +-} +- +-/* + * Return the canonical name of the host in the other side of the current + * connection. The host name is cached, so it is efficient to call this + * several times. +Index: openssh-9.6p1/auth2-gss.c +=================================================================== +--- openssh-9.6p1.orig/auth2-gss.c ++++ openssh-9.6p1/auth2-gss.c +@@ -1,7 +1,7 @@ + /* $OpenBSD: auth2-gss.c,v 1.34 2023/03/31 04:22:27 djm Exp $ */ + + /* +- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. ++ * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -58,6 +58,48 @@ static int input_gssapi_exchange_complet + static int input_gssapi_errtok(int, u_int32_t, struct ssh *); + + /* ++ * The 'gssapi_keyex' userauth mechanism. ++ */ ++static int ++userauth_gsskeyex(struct ssh *ssh) ++{ ++ Authctxt *authctxt = ssh->authctxt; ++ int r, authenticated = 0; ++ struct sshbuf *b = NULL; ++ gss_buffer_desc mic, gssbuf; ++ u_char *p; ++ size_t len; ++ ++ if ((r = sshpkt_get_string(ssh, &p, &len)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("%s: %s", __func__, ssh_err(r)); ++ ++ if ((b = sshbuf_new()) == NULL) ++ fatal("%s: sshbuf_new failed", __func__); ++ ++ mic.value = p; ++ mic.length = len; ++ ++ ssh_gssapi_buildmic(b, authctxt->user, authctxt->service, ++ "gssapi-keyex", ssh->kex->session_id); ++ ++ if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL) ++ fatal("%s: sshbuf_mutable_ptr failed", __func__); ++ gssbuf.length = sshbuf_len(b); ++ ++ /* gss_kex_context is NULL with privsep, so we can't check it here */ ++ if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, ++ &gssbuf, &mic)))) ++ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, ++ authctxt->pw, 1)); ++ ++ sshbuf_free(b); ++ free(mic.value); ++ ++ return (authenticated); ++} ++ ++/* + * We only support those mechanisms that we know about (ie ones that we know + * how to check local user kuserok and the like) + */ +@@ -267,7 +309,8 @@ input_gssapi_exchange_complete(int type, + if ((r = sshpkt_get_end(ssh)) != 0) + fatal_fr(r, "parse packet"); + +- authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); ++ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, ++ authctxt->pw, 1)); + + if ((!use_privsep || mm_is_monitor()) && + (displayname = ssh_gssapi_displayname()) != NULL) +@@ -313,7 +356,8 @@ input_gssapi_mic(int type, u_int32_t ple + gssbuf.length = sshbuf_len(b); + + if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic)))) +- authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); ++ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, ++ authctxt->pw, 0)); + else + logit("GSSAPI MIC check failed"); + +@@ -333,6 +377,12 @@ input_gssapi_mic(int type, u_int32_t ple + return 0; + } + ++Authmethod method_gsskeyex = { ++ "gssapi-keyex", ++ userauth_gsskeyex, ++ &options.gss_authentication ++}; ++ + Authmethod method_gssapi = { + "gssapi-with-mic", + NULL, +Index: openssh-9.6p1/auth2.c +=================================================================== +--- openssh-9.6p1.orig/auth2.c ++++ openssh-9.6p1/auth2.c +@@ -71,6 +71,7 @@ extern Authmethod method_passwd; + extern Authmethod method_kbdint; + extern Authmethod method_hostbased; + #ifdef GSSAPI ++extern Authmethod method_gsskeyex; + extern Authmethod method_gssapi; + #endif + +@@ -78,6 +79,7 @@ Authmethod *authmethods[] = { + &method_none, + &method_pubkey, + #ifdef GSSAPI ++ &method_gsskeyex, + &method_gssapi, + #endif + &method_passwd, +Index: openssh-9.6p1/canohost.c +=================================================================== +--- openssh-9.6p1.orig/canohost.c ++++ openssh-9.6p1/canohost.c +@@ -35,6 +35,99 @@ + #include "canohost.h" + #include "misc.h" + ++/* ++ * Returns the remote DNS hostname as a string. The returned string must not ++ * be freed. NB. this will usually trigger a DNS query the first time it is ++ * called. ++ * This function does additional checks on the hostname to mitigate some ++ * attacks on legacy rhosts-style authentication. ++ * XXX is RhostsRSAAuthentication vulnerable to these? ++ * XXX Can we remove these checks? (or if not, remove RhostsRSAAuthentication?) ++ */ ++ ++char * ++remote_hostname(struct ssh *ssh) ++{ ++ struct sockaddr_storage from; ++ socklen_t fromlen; ++ struct addrinfo hints, *ai, *aitop; ++ char name[NI_MAXHOST], ntop2[NI_MAXHOST]; ++ const char *ntop = ssh_remote_ipaddr(ssh); ++ ++ /* Get IP address of client. */ ++ fromlen = sizeof(from); ++ memset(&from, 0, sizeof(from)); ++ if (getpeername(ssh_packet_get_connection_in(ssh), ++ (struct sockaddr *)&from, &fromlen) == -1) { ++ debug("getpeername failed: %.100s", strerror(errno)); ++ return xstrdup(ntop); ++ } ++ ++ ipv64_normalise_mapped(&from, &fromlen); ++ if (from.ss_family == AF_INET6) ++ fromlen = sizeof(struct sockaddr_in6); ++ ++ debug3("Trying to reverse map address %.100s.", ntop); ++ /* Map the IP address to a host name. */ ++ if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name), ++ NULL, 0, NI_NAMEREQD) != 0) { ++ /* Host name not found. Use ip address. */ ++ return xstrdup(ntop); ++ } ++ ++ /* ++ * if reverse lookup result looks like a numeric hostname, ++ * someone is trying to trick us by PTR record like following: ++ * 1.1.1.10.in-addr.arpa. IN PTR 2.3.4.5 ++ */ ++ memset(&hints, 0, sizeof(hints)); ++ hints.ai_socktype = SOCK_DGRAM; /*dummy*/ ++ hints.ai_flags = AI_NUMERICHOST; ++ if (getaddrinfo(name, NULL, &hints, &ai) == 0) { ++ logit("Nasty PTR record \"%s\" is set up for %s, ignoring", ++ name, ntop); ++ freeaddrinfo(ai); ++ return xstrdup(ntop); ++ } ++ ++ /* Names are stored in lowercase. */ ++ lowercase(name); ++ ++ /* ++ * Map it back to an IP address and check that the given ++ * address actually is an address of this host. This is ++ * necessary because anyone with access to a name server can ++ * define arbitrary names for an IP address. Mapping from ++ * name to IP address can be trusted better (but can still be ++ * fooled if the intruder has access to the name server of ++ * the domain). ++ */ ++ memset(&hints, 0, sizeof(hints)); ++ hints.ai_family = from.ss_family; ++ hints.ai_socktype = SOCK_STREAM; ++ if (getaddrinfo(name, NULL, &hints, &aitop) != 0) { ++ logit("reverse mapping checking getaddrinfo for %.700s " ++ "[%s] failed.", name, ntop); ++ return xstrdup(ntop); ++ } ++ /* Look for the address from the list of addresses. */ ++ for (ai = aitop; ai; ai = ai->ai_next) { ++ if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2, ++ sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 && ++ (strcmp(ntop, ntop2) == 0)) ++ break; ++ } ++ freeaddrinfo(aitop); ++ /* If we reached the end of the list, the address was not there. */ ++ if (ai == NULL) { ++ /* Address not found for the host name. */ ++ logit("Address %.100s maps to %.600s, but this does not " ++ "map back to the address.", ntop, name); ++ return xstrdup(ntop); ++ } ++ return xstrdup(name); ++} ++ + void + ipv64_normalise_mapped(struct sockaddr_storage *addr, socklen_t *len) + { +Index: openssh-9.6p1/canohost.h +=================================================================== +--- openssh-9.6p1.orig/canohost.h ++++ openssh-9.6p1/canohost.h +@@ -15,6 +15,9 @@ + #ifndef _CANOHOST_H + #define _CANOHOST_H + ++struct ssh; ++ ++char *remote_hostname(struct ssh *); + char *get_peer_ipaddr(int); + int get_peer_port(int); + char *get_local_ipaddr(int); +Index: openssh-9.6p1/clientloop.c +=================================================================== +--- openssh-9.6p1.orig/clientloop.c ++++ openssh-9.6p1/clientloop.c +@@ -121,6 +121,10 @@ + /* Uncertainty (in percent) of keystroke timing intervals */ + #define SSH_KEYSTROKE_TIMING_FUZZ 10 + ++#ifdef GSSAPI ++#include "ssh-gss.h" ++#endif ++ + /* import options */ + extern Options options; + +@@ -1594,6 +1598,14 @@ client_loop(struct ssh *ssh, int have_pt + /* Do channel operations. */ + channel_after_poll(ssh, pfd, npfd_active); + ++#ifdef GSSAPI ++ if (options.gss_renewal_rekey && ++ ssh_gssapi_credentials_updated(NULL)) { ++ debug("credentials updated - forcing rekey"); ++ need_rekeying = 1; ++ } ++#endif ++ + /* Buffer input from the connection. */ + if (conn_in_ready) + client_process_net_input(ssh); +Index: openssh-9.6p1/configure.ac +=================================================================== +--- openssh-9.6p1.orig/configure.ac ++++ openssh-9.6p1/configure.ac +@@ -766,6 +766,30 @@ int main(void) { if (NSVersionOfRunTimeL + [Use tunnel device compatibility to OpenBSD]) + AC_DEFINE([SSH_TUN_PREPEND_AF], [1], + [Prepend the address family to IP tunnel traffic]) ++ AC_MSG_CHECKING([if we have the Security Authorization Session API]) ++ AC_TRY_COMPILE([#include ], ++ [SessionCreate(0, 0);], ++ [ac_cv_use_security_session_api="yes" ++ AC_DEFINE([USE_SECURITY_SESSION_API], [1], ++ [platform has the Security Authorization Session API]) ++ LIBS="$LIBS -framework Security" ++ AC_MSG_RESULT([yes])], ++ [ac_cv_use_security_session_api="no" ++ AC_MSG_RESULT([no])]) ++ AC_MSG_CHECKING([if we have an in-memory credentials cache]) ++ AC_TRY_COMPILE( ++ [#include ], ++ [cc_context_t c; ++ (void) cc_initialize (&c, 0, NULL, NULL);], ++ [AC_DEFINE([USE_CCAPI], [1], ++ [platform uses an in-memory credentials cache]) ++ LIBS="$LIBS -framework Security" ++ AC_MSG_RESULT([yes]) ++ if test "x$ac_cv_use_security_session_api" = "xno"; then ++ AC_MSG_ERROR([*** Need a security framework to use the credentials cache API ***]) ++ fi], ++ [AC_MSG_RESULT([no])] ++ ) + m4_pattern_allow([AU_IPv]) + AC_CHECK_DECL([AU_IPv4], [], + AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records]) +Index: openssh-9.6p1/gss-genr.c +=================================================================== +--- openssh-9.6p1.orig/gss-genr.c ++++ openssh-9.6p1/gss-genr.c +@@ -1,7 +1,7 @@ + /* $OpenBSD: gss-genr.c,v 1.28 2021/01/27 10:05:28 djm Exp $ */ + + /* +- * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. ++ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -43,8 +43,34 @@ + #include "log.h" + #include "ssh2.h" + ++#include "cipher.h" ++#include "sshkey.h" ++#include "kex.h" ++#include "digest.h" ++#include "packet.h" ++ + #include "ssh-gss.h" + ++typedef struct { ++ char *encoded; ++ gss_OID oid; ++} ssh_gss_kex_mapping; ++ ++/* ++ * XXX - It would be nice to find a more elegant way of handling the ++ * XXX passing of the key exchange context to the userauth routines ++ */ ++ ++Gssctxt *gss_kex_context = NULL; ++ ++static ssh_gss_kex_mapping *gss_enc2oid = NULL; ++ ++int ++ssh_gssapi_oid_table_ok(void) ++{ ++ return (gss_enc2oid != NULL); ++} ++ + /* sshbuf_get for gss_buffer_desc */ + int + ssh_gssapi_get_buffer_desc(struct sshbuf *b, gss_buffer_desc *g) +@@ -60,6 +86,161 @@ ssh_gssapi_get_buffer_desc(struct sshbuf + return 0; + } + ++/* sshpkt_get of gss_buffer_desc */ ++int ++ssh_gssapi_sshpkt_get_buffer_desc(struct ssh *ssh, gss_buffer_desc *g) ++{ ++ int r; ++ u_char *p; ++ size_t len; ++ ++ if ((r = sshpkt_get_string(ssh, &p, &len)) != 0) ++ return r; ++ g->value = p; ++ g->length = len; ++ return 0; ++} ++ ++/* ++ * Return a list of the gss-group1-sha1 mechanisms supported by this program ++ * ++ * We test mechanisms to ensure that we can use them, to avoid starting ++ * a key exchange with a bad mechanism ++ */ ++ ++char * ++ssh_gssapi_client_mechanisms(const char *host, const char *client, ++ const char *kex) { ++ gss_OID_set gss_supported = NULL; ++ OM_uint32 min_status; ++ ++ if (GSS_ERROR(gss_indicate_mechs(&min_status, &gss_supported))) ++ return NULL; ++ ++ return ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism, ++ 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 *kex) { ++ struct sshbuf *buf = NULL; ++ size_t i; ++ int r, oidpos, enclen; ++ char *mechs, *encoded; ++ u_char digest[SSH_DIGEST_MAX_LENGTH]; ++ char deroid[2]; ++ struct ssh_digest_ctx *md = NULL; ++ char *s, *cp, *p; ++ ++ if (gss_enc2oid != NULL) { ++ for (i = 0; gss_enc2oid[i].encoded != NULL; i++) ++ free(gss_enc2oid[i].encoded); ++ free(gss_enc2oid); ++ } ++ ++ gss_enc2oid = xmalloc(sizeof(ssh_gss_kex_mapping) * ++ (gss_supported->count + 1)); ++ ++ if ((buf = sshbuf_new()) == NULL) ++ 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)) { ++ ++ deroid[0] = SSH_GSS_OIDTYPE; ++ deroid[1] = gss_supported->elements[i].length; ++ ++ if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL || ++ (r = ssh_digest_update(md, deroid, 2)) != 0 || ++ (r = ssh_digest_update(md, ++ gss_supported->elements[i].elements, ++ gss_supported->elements[i].length)) != 0 || ++ (r = ssh_digest_final(md, digest, sizeof(digest))) != 0) ++ fatal("%s: digest failed: %s", __func__, ++ ssh_err(r)); ++ ssh_digest_free(md); ++ md = NULL; ++ ++ encoded = xmalloc(ssh_digest_bytes(SSH_DIGEST_MD5) ++ * 2); ++ enclen = __b64_ntop(digest, ++ ssh_digest_bytes(SSH_DIGEST_MD5), encoded, ++ ssh_digest_bytes(SSH_DIGEST_MD5) * 2); ++ ++ cp = strncpy(s, kex, strlen(kex)); ++ for ((p = strsep(&cp, ",")); p && *p != '\0'; ++ (p = strsep(&cp, ","))) { ++ if (sshbuf_len(buf) != 0 && ++ (r = sshbuf_put_u8(buf, ',')) != 0) ++ fatal("%s: sshbuf_put_u8 error: %s", ++ __func__, ssh_err(r)); ++ if ((r = sshbuf_put(buf, p, strlen(p))) != 0 || ++ (r = sshbuf_put(buf, encoded, enclen)) != 0) ++ fatal("%s: sshbuf_put 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; ++ ++ if ((mechs = sshbuf_dup_string(buf)) == NULL) ++ fatal("%s: sshbuf_dup_string failed", __func__); ++ ++ sshbuf_free(buf); ++ ++ if (strlen(mechs) == 0) { ++ free(mechs); ++ mechs = NULL; ++ } ++ ++ return (mechs); ++} ++ ++gss_OID ++ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) { ++ int i = 0; ++ ++#define SKIP_KEX_NAME(type) \ ++ case type: \ ++ if (strlen(name) < sizeof(type##_ID)) \ ++ return GSS_C_NO_OID; \ ++ name += sizeof(type##_ID) - 1; \ ++ break; ++ ++ switch (kex_type) { ++ SKIP_KEX_NAME(KEX_GSS_GRP1_SHA1) ++ SKIP_KEX_NAME(KEX_GSS_GRP14_SHA1) ++ SKIP_KEX_NAME(KEX_GSS_GRP14_SHA256) ++ SKIP_KEX_NAME(KEX_GSS_GRP16_SHA512) ++ SKIP_KEX_NAME(KEX_GSS_GEX_SHA1) ++ SKIP_KEX_NAME(KEX_GSS_NISTP256_SHA256) ++ SKIP_KEX_NAME(KEX_GSS_C25519_SHA256) ++ default: ++ return GSS_C_NO_OID; ++ } ++ ++#undef SKIP_KEX_NAME ++ ++ while (gss_enc2oid[i].encoded != NULL && ++ strcmp(name, gss_enc2oid[i].encoded) != 0) ++ i++; ++ ++ if (gss_enc2oid[i].oid != NULL && ctx != NULL) ++ ssh_gssapi_set_oid(ctx, gss_enc2oid[i].oid); ++ ++ return gss_enc2oid[i].oid; ++} ++ + /* Check that the OID in a data stream matches that in the context */ + int + ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len) +@@ -216,7 +397,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int de + } + + ctx->major = gss_init_sec_context(&ctx->minor, +- GSS_C_NO_CREDENTIAL, &ctx->context, ctx->name, ctx->oid, ++ ctx->client_creds, &ctx->context, ctx->name, ctx->oid, + GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag, + 0, NULL, recv_tok, NULL, send_tok, flags, NULL); + +@@ -246,8 +427,42 @@ ssh_gssapi_import_name(Gssctxt *ctx, con + } + + OM_uint32 ++ssh_gssapi_client_identity(Gssctxt *ctx, const char *name) ++{ ++ gss_buffer_desc gssbuf; ++ gss_name_t gssname; ++ OM_uint32 status; ++ gss_OID_set oidset; ++ ++ gssbuf.value = (void *) name; ++ gssbuf.length = strlen(gssbuf.value); ++ ++ gss_create_empty_oid_set(&status, &oidset); ++ gss_add_oid_set_member(&status, ctx->oid, &oidset); ++ ++ ctx->major = gss_import_name(&ctx->minor, &gssbuf, ++ GSS_C_NT_USER_NAME, &gssname); ++ ++ if (!ctx->major) ++ ctx->major = gss_acquire_cred(&ctx->minor, ++ gssname, 0, oidset, GSS_C_INITIATE, ++ &ctx->client_creds, NULL, NULL); ++ ++ gss_release_name(&status, &gssname); ++ gss_release_oid_set(&status, &oidset); ++ ++ if (ctx->major) ++ ssh_gssapi_error(ctx); ++ ++ return(ctx->major); ++} ++ ++OM_uint32 + ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) + { ++ if (ctx == NULL) ++ return -1; ++ + if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context, + GSS_C_QOP_DEFAULT, buffer, hash))) + ssh_gssapi_error(ctx); +@@ -255,6 +470,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer + return (ctx->major); + } + ++/* Priviledged when used by server */ ++OM_uint32 ++ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) ++{ ++ if (ctx == NULL) ++ return -1; ++ ++ ctx->major = gss_verify_mic(&ctx->minor, ctx->context, ++ gssbuf, gssmic, NULL); ++ ++ return (ctx->major); ++} ++ + void + ssh_gssapi_buildmic(struct sshbuf *b, const char *user, const char *service, + const char *context, const struct sshbuf *session_id) +@@ -271,11 +499,16 @@ ssh_gssapi_buildmic(struct sshbuf *b, co + } + + int +-ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) ++ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host, ++ const char *client) + { + gss_buffer_desc token = GSS_C_EMPTY_BUFFER; + OM_uint32 major, minor; + gss_OID_desc spnego_oid = {6, (void *)"\x2B\x06\x01\x05\x05\x02"}; ++ Gssctxt *intctx = NULL; ++ ++ if (ctx == NULL) ++ ctx = &intctx; + + /* RFC 4462 says we MUST NOT do SPNEGO */ + if (oid->length == spnego_oid.length && +@@ -285,6 +518,10 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx + ssh_gssapi_build_ctx(ctx); + ssh_gssapi_set_oid(*ctx, oid); + major = ssh_gssapi_import_name(*ctx, host); ++ ++ if (!GSS_ERROR(major) && client) ++ major = ssh_gssapi_client_identity(*ctx, client); ++ + if (!GSS_ERROR(major)) { + major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, + NULL); +@@ -294,10 +531,66 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx + GSS_C_NO_BUFFER); + } + +- if (GSS_ERROR(major)) ++ if (GSS_ERROR(major) || intctx != NULL) + ssh_gssapi_delete_ctx(ctx); + + return (!GSS_ERROR(major)); + } + ++int ++ssh_gssapi_credentials_updated(Gssctxt *ctxt) { ++ static gss_name_t saved_name = GSS_C_NO_NAME; ++ static OM_uint32 saved_lifetime = 0; ++ static gss_OID saved_mech = GSS_C_NO_OID; ++ static gss_name_t name; ++ static OM_uint32 last_call = 0; ++ OM_uint32 lifetime, now, major, minor; ++ int equal; ++ ++ now = time(NULL); ++ ++ if (ctxt) { ++ debug("Rekey has happened - updating saved versions"); ++ ++ if (saved_name != GSS_C_NO_NAME) ++ gss_release_name(&minor, &saved_name); ++ ++ major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL, ++ &saved_name, &saved_lifetime, NULL, NULL); ++ ++ if (!GSS_ERROR(major)) { ++ saved_mech = ctxt->oid; ++ saved_lifetime+= now; ++ } else { ++ /* Handle the error */ ++ } ++ return 0; ++ } ++ ++ if (now - last_call < 10) ++ return 0; ++ ++ last_call = now; ++ ++ if (saved_mech == GSS_C_NO_OID) ++ return 0; ++ ++ major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL, ++ &name, &lifetime, NULL, NULL); ++ if (major == GSS_S_CREDENTIALS_EXPIRED) ++ return 0; ++ else if (GSS_ERROR(major)) ++ return 0; ++ ++ major = gss_compare_name(&minor, saved_name, name, &equal); ++ gss_release_name(&minor, &name); ++ if (GSS_ERROR(major)) ++ return 0; ++ ++ if (equal && (saved_lifetime < lifetime + now - 10)) ++ return 1; ++ ++ return 0; ++} ++ + #endif /* GSSAPI */ +Index: openssh-9.6p1/gss-serv-krb5.c +=================================================================== +--- openssh-9.6p1.orig/gss-serv-krb5.c ++++ openssh-9.6p1/gss-serv-krb5.c +@@ -1,7 +1,7 @@ + /* $OpenBSD: gss-serv-krb5.c,v 1.9 2018/07/09 21:37:55 markus Exp $ */ + + /* +- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. ++ * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -120,7 +120,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl + krb5_error_code problem; + krb5_principal princ; + OM_uint32 maj_status, min_status; +- int len; ++ const char *new_ccname, *new_cctype; + const char *errmsg; + + if (client->creds == NULL) { +@@ -180,11 +180,26 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl + return; + } + +- client->store.filename = xstrdup(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"; +- len = strlen(client->store.filename) + 6; +- client->store.envval = xmalloc(len); +- snprintf(client->store.envval, len, "FILE:%s", client->store.filename); ++#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); ++ if (strcmp(new_cctype, "DIR") == 0) { ++ char *p; ++ p = strrchr(client->store.envval, '/'); ++ if (p) ++ *p = '\0'; ++ } ++ 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) +@@ -193,9 +208,76 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl + + krb5_cc_close(krb_context, ccache); + ++ client->store.data = krb_context; ++ + return; + } + ++int ++ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store, ++ ssh_gssapi_client *client) ++{ ++ krb5_ccache ccache = NULL; ++ krb5_principal principal = NULL; ++ char *name = NULL; ++ krb5_error_code problem; ++ OM_uint32 maj_status, min_status; ++ ++ if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) { ++ logit("krb5_cc_resolve(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ return 0; ++ } ++ ++ /* Find out who the principal in this cache is */ ++ if ((problem = krb5_cc_get_principal(krb_context, ccache, ++ &principal))) { ++ logit("krb5_cc_get_principal(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ if ((problem = krb5_unparse_name(krb_context, principal, &name))) { ++ logit("krb5_unparse_name(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ krb5_free_principal(krb_context, principal); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ ++ if (strcmp(name,client->exportedname.value)!=0) { ++ debug("Name in local credentials cache differs. Not storing"); ++ krb5_free_principal(krb_context, principal); ++ krb5_cc_close(krb_context, ccache); ++ krb5_free_unparsed_name(krb_context, name); ++ return 0; ++ } ++ krb5_free_unparsed_name(krb_context, name); ++ ++ /* Name matches, so lets get on with it! */ ++ ++ if ((problem = krb5_cc_initialize(krb_context, ccache, principal))) { ++ logit("krb5_cc_initialize(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ krb5_free_principal(krb_context, principal); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ krb5_free_principal(krb_context, principal); ++ ++ if ((maj_status = gss_krb5_copy_ccache(&min_status, client->creds, ++ ccache))) { ++ logit("gss_krb5_copy_ccache() failed. Sorry!"); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ return 1; ++} ++ + ssh_gssapi_mech gssapi_kerberos_mech = { + "toWM5Slw5Ew8Mqkay+al2g==", + "Kerberos", +@@ -203,7 +285,8 @@ ssh_gssapi_mech gssapi_kerberos_mech = { + NULL, + &ssh_gssapi_krb5_userok, + NULL, +- &ssh_gssapi_krb5_storecreds ++ &ssh_gssapi_krb5_storecreds, ++ &ssh_gssapi_krb5_updatecreds + }; + + #endif /* KRB5 */ +Index: openssh-9.6p1/gss-serv.c +=================================================================== +--- openssh-9.6p1.orig/gss-serv.c ++++ openssh-9.6p1/gss-serv.c +@@ -1,7 +1,7 @@ + /* $OpenBSD: gss-serv.c,v 1.32 2020/03/13 03:17:07 djm Exp $ */ + + /* +- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. ++ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -44,17 +44,19 @@ + #include "session.h" + #include "misc.h" + #include "servconf.h" ++#include "uidswap.h" + + #include "ssh-gss.h" ++#include "monitor_wrap.h" + + extern ServerOptions options; + + static ssh_gssapi_client gssapi_client = +- { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, +- GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL, NULL}}; ++ { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, GSS_C_NO_CREDENTIAL, ++ GSS_C_NO_NAME, NULL, {NULL, NULL, NULL, NULL, NULL}, 0, 0}; + + ssh_gssapi_mech gssapi_null_mech = +- { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL}; ++ { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL, NULL}; + + #ifdef KRB5 + extern ssh_gssapi_mech gssapi_kerberos_mech; +@@ -141,6 +143,29 @@ ssh_gssapi_server_ctx(Gssctxt **ctx, gss + } + + /* Unprivileged */ ++char * ++ssh_gssapi_server_mechanisms(void) { ++ if (supported_oids == NULL) ++ ssh_gssapi_prepare_supported_oids(); ++ return (ssh_gssapi_kex_mechs(supported_oids, ++ &ssh_gssapi_server_check_mech, NULL, NULL, ++ options.gss_kex_algorithms)); ++} ++ ++/* Unprivileged */ ++int ++ssh_gssapi_server_check_mech(Gssctxt **dum, gss_OID oid, const char *data, ++ const char *dummy) { ++ Gssctxt *ctx = NULL; ++ int res; ++ ++ res = !GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx, oid))); ++ ssh_gssapi_delete_ctx(&ctx); ++ ++ return (res); ++} ++ ++/* Unprivileged */ + void + ssh_gssapi_supported_oids(gss_OID_set *oidset) + { +@@ -150,7 +175,9 @@ ssh_gssapi_supported_oids(gss_OID_set *o + gss_OID_set supported; + + gss_create_empty_oid_set(&min_status, oidset); +- gss_indicate_mechs(&min_status, &supported); ++ ++ if (GSS_ERROR(gss_indicate_mechs(&min_status, &supported))) ++ return; + + while (supported_mechs[i]->name != NULL) { + if (GSS_ERROR(gss_test_oid_set_member(&min_status, +@@ -276,8 +303,48 @@ OM_uint32 + ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) + { + int i = 0; ++ int equal = 0; ++ gss_name_t new_name = GSS_C_NO_NAME; ++ gss_buffer_desc ename = GSS_C_EMPTY_BUFFER; ++ ++ if (options.gss_store_rekey && client->used && ctx->client_creds) { ++ if (client->mech->oid.length != ctx->oid->length || ++ (memcmp(client->mech->oid.elements, ++ ctx->oid->elements, ctx->oid->length) !=0)) { ++ debug("Rekeyed credentials have different mechanism"); ++ return GSS_S_COMPLETE; ++ } ++ ++ if ((ctx->major = gss_inquire_cred_by_mech(&ctx->minor, ++ ctx->client_creds, ctx->oid, &new_name, ++ NULL, NULL, NULL))) { ++ ssh_gssapi_error(ctx); ++ return (ctx->major); ++ } ++ ++ ctx->major = gss_compare_name(&ctx->minor, client->name, ++ new_name, &equal); ++ ++ if (GSS_ERROR(ctx->major)) { ++ ssh_gssapi_error(ctx); ++ return (ctx->major); ++ } ++ ++ if (!equal) { ++ debug("Rekeyed credentials have different name"); ++ return GSS_S_COMPLETE; ++ } + +- gss_buffer_desc ename; ++ debug("Marking rekeyed credentials for export"); ++ ++ gss_release_name(&ctx->minor, &client->name); ++ gss_release_cred(&ctx->minor, &client->creds); ++ client->name = new_name; ++ client->creds = ctx->client_creds; ++ ctx->client_creds = GSS_C_NO_CREDENTIAL; ++ client->updated = 1; ++ return GSS_S_COMPLETE; ++ } + + client->mech = NULL; + +@@ -292,6 +359,13 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g + if (client->mech == NULL) + return GSS_S_FAILURE; + ++ if (ctx->client_creds && ++ (ctx->major = gss_inquire_cred_by_mech(&ctx->minor, ++ ctx->client_creds, ctx->oid, &client->name, NULL, NULL, NULL))) { ++ ssh_gssapi_error(ctx); ++ return (ctx->major); ++ } ++ + if ((ctx->major = gss_display_name(&ctx->minor, ctx->client, + &client->displayname, NULL))) { + ssh_gssapi_error(ctx); +@@ -309,6 +383,8 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g + return (ctx->major); + } + ++ gss_release_buffer(&ctx->minor, &ename); ++ + /* We can't copy this structure, so we just move the pointer to it */ + client->creds = ctx->client_creds; + ctx->client_creds = GSS_C_NO_CREDENTIAL; +@@ -319,11 +395,20 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g + void + ssh_gssapi_cleanup_creds(void) + { +- if (gssapi_client.store.filename != NULL) { +- /* Unlink probably isn't sufficient */ +- debug("removing gssapi cred file\"%s\"", +- gssapi_client.store.filename); +- unlink(gssapi_client.store.filename); ++ krb5_ccache ccache = NULL; ++ krb5_error_code problem; ++ ++ if (gssapi_client.store.data != NULL) { ++ if ((problem = krb5_cc_resolve(gssapi_client.store.data, gssapi_client.store.envval, &ccache))) { ++ debug("%s: krb5_cc_resolve(): %.100s", __func__, ++ krb5_get_err_text(gssapi_client.store.data, problem)); ++ } else if ((problem = krb5_cc_destroy(gssapi_client.store.data, ccache))) { ++ debug("%s: krb5_cc_destroy(): %.100s", __func__, ++ krb5_get_err_text(gssapi_client.store.data, problem)); ++ } else { ++ krb5_free_context(gssapi_client.store.data); ++ gssapi_client.store.data = NULL; ++ } + } + } + +@@ -356,19 +441,23 @@ ssh_gssapi_do_child(char ***envp, u_int + + /* Privileged */ + int +-ssh_gssapi_userok(char *user) ++ssh_gssapi_userok(char *user, struct passwd *pw, int kex) + { + OM_uint32 lmin; + ++ (void) kex; /* used in privilege separation */ ++ + if (gssapi_client.exportedname.length == 0 || + gssapi_client.exportedname.value == NULL) { + debug("No suitable client data"); + return 0; + } + if (gssapi_client.mech && gssapi_client.mech->userok) +- if ((*gssapi_client.mech->userok)(&gssapi_client, user)) ++ if ((*gssapi_client.mech->userok)(&gssapi_client, user)) { ++ gssapi_client.used = 1; ++ gssapi_client.store.owner = pw; + return 1; +- else { ++ } else { + /* Destroy delegated credentials if userok fails */ + gss_release_buffer(&lmin, &gssapi_client.displayname); + gss_release_buffer(&lmin, &gssapi_client.exportedname); +@@ -382,14 +471,90 @@ ssh_gssapi_userok(char *user) + return (0); + } + +-/* Privileged */ +-OM_uint32 +-ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) ++/* These bits are only used for rekeying. The unpriviledged child is running ++ * as the user, the monitor is root. ++ * ++ * In the child, we want to : ++ * *) Ask the monitor to store our credentials into the store we specify ++ * *) If it succeeds, maybe do a PAM update ++ */ ++ ++/* Stuff for PAM */ ++ ++#ifdef USE_PAM ++static int ssh_gssapi_simple_conv(int n, const struct pam_message **msg, ++ struct pam_response **resp, void *data) + { +- ctx->major = gss_verify_mic(&ctx->minor, ctx->context, +- gssbuf, gssmic, NULL); ++ return (PAM_CONV_ERR); ++} ++#endif + +- return (ctx->major); ++void ++ssh_gssapi_rekey_creds(void) { ++ int ok; ++#ifdef USE_PAM ++ int ret; ++ pam_handle_t *pamh = NULL; ++ struct pam_conv pamconv = {ssh_gssapi_simple_conv, NULL}; ++ char *envstr; ++#endif ++ ++ if (gssapi_client.store.filename == NULL && ++ gssapi_client.store.envval == NULL && ++ gssapi_client.store.envvar == NULL) ++ return; ++ ++ ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store)); ++ ++ if (!ok) ++ return; ++ ++ debug("Rekeyed credentials stored successfully"); ++ ++ /* Actually managing to play with the ssh pam stack from here will ++ * be next to impossible. In any case, we may want different options ++ * for rekeying. So, use our own :) ++ */ ++#ifdef USE_PAM ++ if (!use_privsep) { ++ debug("Not even going to try and do PAM with privsep disabled"); ++ return; ++ } ++ ++ ret = pam_start("sshd-rekey", gssapi_client.store.owner->pw_name, ++ &pamconv, &pamh); ++ if (ret) ++ return; ++ ++ xasprintf(&envstr, "%s=%s", gssapi_client.store.envvar, ++ gssapi_client.store.envval); ++ ++ ret = pam_putenv(pamh, envstr); ++ if (!ret) ++ pam_setcred(pamh, PAM_REINITIALIZE_CRED); ++ pam_end(pamh, PAM_SUCCESS); ++#endif ++} ++ ++int ++ssh_gssapi_update_creds(ssh_gssapi_ccache *store) { ++ int ok = 0; ++ ++ /* Check we've got credentials to store */ ++ if (!gssapi_client.updated) ++ return 0; ++ ++ gssapi_client.updated = 0; ++ ++ temporarily_use_uid(gssapi_client.store.owner); ++ if (gssapi_client.mech && gssapi_client.mech->updatecreds) ++ ok = (*gssapi_client.mech->updatecreds)(store, &gssapi_client); ++ else ++ debug("No update function for this mechanism"); ++ ++ restore_uid(); ++ ++ return ok; + } + + /* Privileged */ +Index: openssh-9.6p1/kex.c +=================================================================== +--- openssh-9.6p1.orig/kex.c ++++ openssh-9.6p1/kex.c +@@ -64,6 +64,10 @@ + #include "digest.h" + #include "xmalloc.h" + ++#ifdef GSSAPI ++#include "ssh-gss.h" ++#endif ++ + #include "fips.h" + + /* prototype */ +@@ -121,6 +125,19 @@ static const struct kexalg kexalgs_all[] + #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ + { NULL, 0, -1, -1}, + }; ++static const struct kexalg gss_kexalgs[] = { ++#ifdef GSSAPI ++ { KEX_GSS_GEX_SHA1_ID, KEX_GSS_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, ++ { KEX_GSS_GRP1_SHA1_ID, KEX_GSS_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, ++ { KEX_GSS_GRP14_SHA1_ID, KEX_GSS_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, ++ { KEX_GSS_GRP14_SHA256_ID, KEX_GSS_GRP14_SHA256, 0, SSH_DIGEST_SHA256 }, ++ { KEX_GSS_GRP16_SHA512_ID, KEX_GSS_GRP16_SHA512, 0, SSH_DIGEST_SHA512 }, ++ { KEX_GSS_NISTP256_SHA256_ID, KEX_GSS_NISTP256_SHA256, ++ NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, ++ { KEX_GSS_C25519_SHA256_ID, KEX_GSS_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, ++#endif ++ { NULL, 0, -1, -1 }, ++}; + + static const struct kexalg kexalgs_fips140_2[] = { + #ifdef WITH_OPENSSL +@@ -148,12 +165,12 @@ static const struct kexalg kexalgs_fips1 + + /* Returns array of macs available depending on selected FIPS mode */ + static const struct kexalg * +-fips_select_kexalgs(void) ++fips_select_kexalgs(const struct kexalg *algs) + { + int fips = fips_mode(); + switch (fips) { + case 0: +- return kexalgs_all; ++ return algs; + case 1: + return kexalgs_fips140_2; + default: +@@ -164,13 +181,13 @@ fips_select_kexalgs(void) + } + + char * +-kex_alg_list(char sep) ++kex_alg_list_internal(char sep, const struct kexalg *algs) + { + char *ret = NULL, *tmp; + size_t nlen, rlen = 0; + const struct kexalg *k; + +- for (k = fips_select_kexalgs(); k->name != NULL; k++) { ++ for (k = fips_select_kexalgs(algs); k->name != NULL; k++) { + if (ret != NULL) + ret[rlen++] = sep; + nlen = strlen(k->name); +@@ -185,15 +202,31 @@ kex_alg_list(char sep) + return ret; + } + ++char * ++kex_alg_list(char sep) ++{ ++ return kex_alg_list_internal(sep, kexalgs_all); ++} ++ ++char * ++kex_gss_alg_list(char sep) ++{ ++ return kex_alg_list_internal(sep, gss_kexalgs); ++} ++ + static const struct kexalg * + kex_alg_by_name(const char *name) + { + const struct kexalg *k; + +- for (k = fips_select_kexalgs(); k->name != NULL; k++) { ++ for (k = fips_select_kexalgs(kexalgs_all); k->name != NULL; k++) { + if (strcmp(k->name, name) == 0) + return k; + } ++ for (k = gss_kexalgs; k->name != NULL; k++) { ++ if (strncmp(k->name, name, strlen(k->name)) == 0) ++ return k; ++ } + return NULL; + } + +@@ -375,6 +408,29 @@ kex_assemble_names(char **listp, const c + return r; + } + ++/* Validate GSS KEX method name list */ ++int ++kex_gss_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; ++} ++ + /* + * Fill out a proposal array with dynamically allocated values, which may + * be modified as required for compatibility reasons. +@@ -1010,6 +1066,9 @@ kex_free(struct kex *kex) + sshbuf_free(kex->session_id); + sshbuf_free(kex->initial_sig); + sshkey_free(kex->initial_hostkey); ++#ifdef GSSAPI ++ free(kex->gss_host); ++#endif /* GSSAPI */ + free(kex->failed_choice); + free(kex->hostkey_alg); + free(kex->name); +Index: openssh-9.6p1/kex.h +=================================================================== +--- openssh-9.6p1.orig/kex.h ++++ openssh-9.6p1/kex.h +@@ -102,6 +102,15 @@ enum kex_exchange { + KEX_ECDH_SHA2, + KEX_C25519_SHA256, + KEX_KEM_SNTRUP761X25519_SHA512, ++#ifdef GSSAPI ++ KEX_GSS_GRP1_SHA1, ++ KEX_GSS_GRP14_SHA1, ++ KEX_GSS_GRP14_SHA256, ++ KEX_GSS_GRP16_SHA512, ++ KEX_GSS_GEX_SHA1, ++ KEX_GSS_NISTP256_SHA256, ++ KEX_GSS_C25519_SHA256, ++#endif + KEX_MAX + }; + +@@ -164,6 +173,12 @@ struct kex { + u_int flags; + int hash_alg; + int ec_nid; ++#ifdef GSSAPI ++ int gss_deleg_creds; ++ int gss_trust_dns; ++ char *gss_host; ++ char *gss_client; ++#endif + char *failed_choice; + int (*verify_host_key)(struct sshkey *, struct ssh *); + struct sshkey *(*load_host_public_key)(int, int, struct ssh *); +@@ -185,8 +200,10 @@ struct kex { + + int kex_names_valid(const char *); + char *kex_alg_list(char); ++char *kex_gss_alg_list(char); + char *kex_names_cat(const char *, const char *); + int kex_assemble_names(char **, const char *, const char *); ++int kex_gss_names_valid(const char *); + void kex_proposal_populate_entries(struct ssh *, char *prop[PROPOSAL_MAX], + const char *, const char *, const char *, const char *, const char *); + void kex_proposal_free_entries(char *prop[PROPOSAL_MAX]); +@@ -219,6 +236,12 @@ int kexgex_client(struct ssh *); + int kexgex_server(struct ssh *); + int kex_gen_client(struct ssh *); + int kex_gen_server(struct ssh *); ++#ifdef GSSAPI ++int kexgssgex_client(struct ssh *); ++int kexgssgex_server(struct ssh *); ++int kexgss_client(struct ssh *); ++int kexgss_server(struct ssh *); ++#endif + + int kex_dh_keypair(struct kex *); + int kex_dh_enc(struct kex *, const struct sshbuf *, struct sshbuf **, +@@ -251,6 +274,12 @@ int kexgex_hash(int, const struct sshbu + const BIGNUM *, const u_char *, size_t, + u_char *, size_t *); + ++int kex_gen_hash(int hash_alg, const struct sshbuf *client_version, ++ const struct sshbuf *server_version, const struct sshbuf *client_kexinit, ++ const struct sshbuf *server_kexinit, const struct sshbuf *server_host_key_blob, ++ const struct sshbuf *client_pub, const struct sshbuf *server_pub, ++ const struct sshbuf *shared_secret, u_char *hash, size_t *hashlen); ++ + void kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE]) + __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) + __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); +Index: openssh-9.6p1/kexdh.c +=================================================================== +--- openssh-9.6p1.orig/kexdh.c ++++ openssh-9.6p1/kexdh.c +@@ -49,13 +49,23 @@ kex_dh_keygen(struct kex *kex) + { + switch (kex->kex_type) { + case KEX_DH_GRP1_SHA1: ++#ifdef GSSAPI ++ case KEX_GSS_GRP1_SHA1: ++#endif + kex->dh = dh_new_group1(); + break; + case KEX_DH_GRP14_SHA1: + case KEX_DH_GRP14_SHA256: ++#ifdef GSSAPI ++ case KEX_GSS_GRP14_SHA1: ++ case KEX_GSS_GRP14_SHA256: ++#endif + kex->dh = dh_new_group14(); + break; + case KEX_DH_GRP16_SHA512: ++#ifdef GSSAPI ++ case KEX_GSS_GRP16_SHA512: ++#endif + kex->dh = dh_new_group16(); + break; + case KEX_DH_GRP18_SHA512: +Index: openssh-9.6p1/kexgen.c +=================================================================== +--- openssh-9.6p1.orig/kexgen.c ++++ openssh-9.6p1/kexgen.c +@@ -44,7 +44,7 @@ + static int input_kex_gen_init(int, u_int32_t, struct ssh *); + static int input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh); + +-static int ++int + kex_gen_hash( + int hash_alg, + const struct sshbuf *client_version, +Index: openssh-9.6p1/kexgssc.c +=================================================================== +--- /dev/null ++++ openssh-9.6p1/kexgssc.c +@@ -0,0 +1,595 @@ ++/* ++ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. ++ * ++ * 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. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 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" ++ ++#if defined(GSSAPI) && defined(WITH_OPENSSL) ++ ++#include "includes.h" ++ ++#include ++#include ++ ++#include ++ ++#include "xmalloc.h" ++#include "sshbuf.h" ++#include "ssh2.h" ++#include "sshkey.h" ++#include "cipher.h" ++#include "kex.h" ++#include "log.h" ++#include "packet.h" ++#include "dh.h" ++#include "digest.h" ++#include "ssherr.h" ++ ++#include "ssh-gss.h" ++ ++int ++kexgss_client(struct ssh *ssh) ++{ ++ struct kex *kex = ssh->kex; ++ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER, ++ recv_tok = GSS_C_EMPTY_BUFFER, ++ gssbuf, msg_tok = GSS_C_EMPTY_BUFFER, *token_ptr; ++ Gssctxt *ctxt; ++ OM_uint32 maj_status, min_status, ret_flags; ++ struct sshbuf *server_blob = NULL; ++ struct sshbuf *shared_secret = NULL; ++ struct sshbuf *server_host_key_blob = NULL; ++ struct sshbuf *empty = sshbuf_new(); ++ u_char *msg; ++ int type = 0; ++ int first = 1; ++ u_char hash[SSH_DIGEST_MAX_LENGTH]; ++ size_t hashlen; ++ u_char c; ++ int r; ++ ++ /* Initialise our GSSAPI world */ ++ ssh_gssapi_build_ctx(&ctxt); ++ if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type) ++ == GSS_C_NO_OID) ++ fatal("Couldn't identify host exchange"); ++ ++ if (ssh_gssapi_import_name(ctxt, kex->gss_host)) ++ fatal("Couldn't import hostname"); ++ ++ if (kex->gss_client && ++ ssh_gssapi_client_identity(ctxt, kex->gss_client)) ++ fatal("Couldn't acquire client credentials"); ++ ++ /* Step 1 */ ++ switch (kex->kex_type) { ++ case KEX_GSS_GRP1_SHA1: ++ case KEX_GSS_GRP14_SHA1: ++ case KEX_GSS_GRP14_SHA256: ++ case KEX_GSS_GRP16_SHA512: ++ r = kex_dh_keypair(kex); ++ break; ++ case KEX_GSS_NISTP256_SHA256: ++ r = kex_ecdh_keypair(kex); ++ break; ++ case KEX_GSS_C25519_SHA256: ++ r = kex_c25519_keypair(kex); ++ break; ++ default: ++ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); ++ } ++ if (r != 0) ++ return r; ++ ++ token_ptr = GSS_C_NO_BUFFER; ++ ++ do { ++ debug("Calling gss_init_sec_context"); ++ ++ maj_status = ssh_gssapi_init_ctx(ctxt, ++ kex->gss_deleg_creds, token_ptr, &send_tok, ++ &ret_flags); ++ ++ if (GSS_ERROR(maj_status)) { ++ /* XXX Useles code: Missing send? */ ++ if (send_tok.length != 0) { ++ if ((r = sshpkt_start(ssh, ++ SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, ++ send_tok.length)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ } ++ fatal("gss_init_context failed"); ++ } ++ ++ /* If we've got an old receive buffer get rid of it */ ++ if (token_ptr != GSS_C_NO_BUFFER) ++ gss_release_buffer(&min_status, &recv_tok); ++ ++ if (maj_status == GSS_S_COMPLETE) { ++ /* If mutual state flag is not true, kex fails */ ++ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) ++ fatal("Mutual authentication failed"); ++ ++ /* If integ avail flag is not true kex fails */ ++ if (!(ret_flags & GSS_C_INTEG_FLAG)) ++ fatal("Integrity check failed"); ++ } ++ ++ /* ++ * If we have data to send, then the last message that we ++ * received cannot have been a 'complete'. ++ */ ++ if (send_tok.length != 0) { ++ if (first) { ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_INIT)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, ++ send_tok.length)) != 0 || ++ (r = sshpkt_put_stringb(ssh, kex->client_pub)) != 0) ++ fatal("failed to construct packet: %s", ssh_err(r)); ++ first = 0; ++ } else { ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, ++ send_tok.length)) != 0) ++ fatal("failed to construct packet: %s", ssh_err(r)); ++ } ++ if ((r = sshpkt_send(ssh)) != 0) ++ fatal("failed to send packet: %s", ssh_err(r)); ++ gss_release_buffer(&min_status, &send_tok); ++ ++ /* If we've sent them data, they should reply */ ++ do { ++ type = ssh_packet_read(ssh); ++ if (type == SSH2_MSG_KEXGSS_HOSTKEY) { ++ debug("Received KEXGSS_HOSTKEY"); ++ if (server_host_key_blob) ++ fatal("Server host key received more than once"); ++ if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0) ++ fatal("Failed to read server host key: %s", ssh_err(r)); ++ } ++ } while (type == SSH2_MSG_KEXGSS_HOSTKEY); ++ ++ switch (type) { ++ case SSH2_MSG_KEXGSS_CONTINUE: ++ debug("Received GSSAPI_CONTINUE"); ++ if (maj_status == GSS_S_COMPLETE) ++ fatal("GSSAPI Continue received from server when complete"); ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, ++ &recv_tok)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("Failed to read token: %s", ssh_err(r)); ++ break; ++ case SSH2_MSG_KEXGSS_COMPLETE: ++ debug("Received GSSAPI_COMPLETE"); ++ if (msg_tok.value != NULL) ++ fatal("Received GSSAPI_COMPLETE twice?"); ++ if ((r = sshpkt_getb_froms(ssh, &server_blob)) != 0 || ++ (r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, ++ &msg_tok)) != 0) ++ fatal("Failed to read message: %s", ssh_err(r)); ++ ++ /* Is there a token included? */ ++ if ((r = sshpkt_get_u8(ssh, &c)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ if (c) { ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc( ++ ssh, &recv_tok)) != 0) ++ fatal("Failed to read token: %s", ssh_err(r)); ++ /* If we're already complete - protocol error */ ++ if (maj_status == GSS_S_COMPLETE) ++ sshpkt_disconnect(ssh, "Protocol error: received token when complete"); ++ } else { ++ /* No token included */ ++ if (maj_status != GSS_S_COMPLETE) ++ sshpkt_disconnect(ssh, "Protocol error: did not receive final token"); ++ } ++ if ((r = sshpkt_get_end(ssh)) != 0) { ++ fatal("Expecting end of packet."); ++ } ++ break; ++ case SSH2_MSG_KEXGSS_ERROR: ++ debug("Received Error"); ++ if ((r = sshpkt_get_u32(ssh, &maj_status)) != 0 || ++ (r = sshpkt_get_u32(ssh, &min_status)) != 0 || ++ (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 || ++ (r = sshpkt_get_string(ssh, NULL, NULL)) != 0 || /* lang tag */ ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt_get failed: %s", ssh_err(r)); ++ fatal("GSSAPI Error: \n%.400s", msg); ++ default: ++ sshpkt_disconnect(ssh, "Protocol error: didn't expect packet type %d", ++ type); ++ } ++ token_ptr = &recv_tok; ++ } else { ++ /* No data, and not complete */ ++ if (maj_status != GSS_S_COMPLETE) ++ fatal("Not complete, and no token output"); ++ } ++ } while (maj_status & GSS_S_CONTINUE_NEEDED); ++ ++ /* ++ * We _must_ have received a COMPLETE message in reply from the ++ * server, which will have set server_blob and msg_tok ++ */ ++ ++ if (type != SSH2_MSG_KEXGSS_COMPLETE) ++ fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it"); ++ ++ /* compute shared secret */ ++ switch (kex->kex_type) { ++ case KEX_GSS_GRP1_SHA1: ++ case KEX_GSS_GRP14_SHA1: ++ case KEX_GSS_GRP14_SHA256: ++ case KEX_GSS_GRP16_SHA512: ++ r = kex_dh_dec(kex, server_blob, &shared_secret); ++ break; ++ case KEX_GSS_C25519_SHA256: ++ if (sshbuf_ptr(server_blob)[sshbuf_len(server_blob)] & 0x80) ++ fatal("The received key has MSB of last octet set!"); ++ r = kex_c25519_dec(kex, server_blob, &shared_secret); ++ break; ++ case KEX_GSS_NISTP256_SHA256: ++ if (sshbuf_len(server_blob) != 65) ++ fatal("The received NIST-P256 key did not match" ++ "expected length (expected 65, got %zu)", sshbuf_len(server_blob)); ++ ++ if (sshbuf_ptr(server_blob)[0] != POINT_CONVERSION_UNCOMPRESSED) ++ fatal("The received NIST-P256 key does not have first octet 0x04"); ++ ++ r = kex_ecdh_dec(kex, server_blob, &shared_secret); ++ break; ++ default: ++ r = SSH_ERR_INVALID_ARGUMENT; ++ break; ++ } ++ if (r != 0) ++ goto out; ++ ++ hashlen = sizeof(hash); ++ if ((r = kex_gen_hash( ++ kex->hash_alg, ++ kex->client_version, ++ kex->server_version, ++ kex->my, ++ kex->peer, ++ (server_host_key_blob ? server_host_key_blob : empty), ++ kex->client_pub, ++ server_blob, ++ shared_secret, ++ hash, &hashlen)) != 0) ++ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); ++ ++ gssbuf.value = hash; ++ gssbuf.length = hashlen; ++ ++ /* Verify that the hash matches the MIC we just got. */ ++ if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok))) ++ sshpkt_disconnect(ssh, "Hash's MIC didn't verify"); ++ ++ gss_release_buffer(&min_status, &msg_tok); ++ ++ if (kex->gss_deleg_creds) ++ ssh_gssapi_credentials_updated(ctxt); ++ ++ if (gss_kex_context == NULL) ++ gss_kex_context = ctxt; ++ else ++ ssh_gssapi_delete_ctx(&ctxt); ++ ++ if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) ++ r = kex_send_newkeys(ssh); ++ ++out: ++ explicit_bzero(hash, sizeof(hash)); ++ explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key)); ++ sshbuf_free(empty); ++ sshbuf_free(server_host_key_blob); ++ sshbuf_free(server_blob); ++ sshbuf_free(shared_secret); ++ sshbuf_free(kex->client_pub); ++ kex->client_pub = NULL; ++ return r; ++} ++ ++int ++kexgssgex_client(struct ssh *ssh) ++{ ++ struct kex *kex = ssh->kex; ++ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER, ++ recv_tok = GSS_C_EMPTY_BUFFER, gssbuf, ++ msg_tok = GSS_C_EMPTY_BUFFER, *token_ptr; ++ Gssctxt *ctxt; ++ OM_uint32 maj_status, min_status, ret_flags; ++ struct sshbuf *shared_secret = NULL; ++ BIGNUM *p = NULL; ++ BIGNUM *g = NULL; ++ struct sshbuf *buf = NULL; ++ struct sshbuf *server_host_key_blob = NULL; ++ struct sshbuf *server_blob = NULL; ++ BIGNUM *dh_server_pub = NULL; ++ u_char *msg; ++ int type = 0; ++ int first = 1; ++ u_char hash[SSH_DIGEST_MAX_LENGTH]; ++ size_t hashlen; ++ const BIGNUM *pub_key, *dh_p, *dh_g; ++ int nbits = 0, min = DH_GRP_MIN, max = DH_GRP_MAX; ++ struct sshbuf *empty = sshbuf_new(); ++ u_char c; ++ int r; ++ ++ /* Initialise our GSSAPI world */ ++ ssh_gssapi_build_ctx(&ctxt); ++ if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type) ++ == GSS_C_NO_OID) ++ fatal("Couldn't identify host exchange"); ++ ++ if (ssh_gssapi_import_name(ctxt, kex->gss_host)) ++ fatal("Couldn't import hostname"); ++ ++ if (kex->gss_client && ++ ssh_gssapi_client_identity(ctxt, kex->gss_client)) ++ fatal("Couldn't acquire client credentials"); ++ ++ debug("Doing group exchange"); ++ nbits = dh_estimate(kex->dh_need * 8); ++ ++ kex->min = DH_GRP_MIN; ++ kex->max = DH_GRP_MAX; ++ kex->nbits = nbits; ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_GROUPREQ)) != 0 || ++ (r = sshpkt_put_u32(ssh, min)) != 0 || ++ (r = sshpkt_put_u32(ssh, nbits)) != 0 || ++ (r = sshpkt_put_u32(ssh, max)) != 0 || ++ (r = sshpkt_send(ssh)) != 0) ++ fatal("Failed to construct a packet: %s", ssh_err(r)); ++ ++ if ((r = ssh_packet_read_expect(ssh, SSH2_MSG_KEXGSS_GROUP)) != 0) ++ fatal("Error: %s", ssh_err(r)); ++ ++ if ((r = sshpkt_get_bignum2(ssh, &p)) != 0 || ++ (r = sshpkt_get_bignum2(ssh, &g)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("shpkt_get_bignum2 failed: %s", ssh_err(r)); ++ ++ if (BN_num_bits(p) < min || BN_num_bits(p) > max) ++ fatal("GSSGRP_GEX group out of range: %d !< %d !< %d", ++ min, BN_num_bits(p), max); ++ ++ if ((kex->dh = dh_new_group(g, p)) == NULL) ++ fatal("dn_new_group() failed"); ++ p = g = NULL; /* belong to kex->dh now */ ++ ++ if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) ++ goto out; ++ DH_get0_key(kex->dh, &pub_key, NULL); ++ ++ token_ptr = GSS_C_NO_BUFFER; ++ ++ do { ++ /* Step 2 - call GSS_Init_sec_context() */ ++ debug("Calling gss_init_sec_context"); ++ ++ maj_status = ssh_gssapi_init_ctx(ctxt, ++ kex->gss_deleg_creds, token_ptr, &send_tok, ++ &ret_flags); ++ ++ if (GSS_ERROR(maj_status)) { ++ /* XXX Useles code: Missing send? */ ++ if (send_tok.length != 0) { ++ if ((r = sshpkt_start(ssh, ++ SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, ++ send_tok.length)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ } ++ fatal("gss_init_context failed"); ++ } ++ ++ /* If we've got an old receive buffer get rid of it */ ++ if (token_ptr != GSS_C_NO_BUFFER) ++ gss_release_buffer(&min_status, &recv_tok); ++ ++ if (maj_status == GSS_S_COMPLETE) { ++ /* If mutual state flag is not true, kex fails */ ++ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) ++ fatal("Mutual authentication failed"); ++ ++ /* If integ avail flag is not true kex fails */ ++ if (!(ret_flags & GSS_C_INTEG_FLAG)) ++ fatal("Integrity check failed"); ++ } ++ ++ /* ++ * If we have data to send, then the last message that we ++ * received cannot have been a 'complete'. ++ */ ++ if (send_tok.length != 0) { ++ if (first) { ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_INIT)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, ++ send_tok.length)) != 0 || ++ (r = sshpkt_put_bignum2(ssh, pub_key)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ first = 0; ++ } else { ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh,send_tok.value, ++ send_tok.length)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ } ++ if ((r = sshpkt_send(ssh)) != 0) ++ fatal("sshpkt_send failed: %s", ssh_err(r)); ++ gss_release_buffer(&min_status, &send_tok); ++ ++ /* If we've sent them data, they should reply */ ++ do { ++ type = ssh_packet_read(ssh); ++ if (type == SSH2_MSG_KEXGSS_HOSTKEY) { ++ debug("Received KEXGSS_HOSTKEY"); ++ if (server_host_key_blob) ++ fatal("Server host key received more than once"); ++ if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ } ++ } while (type == SSH2_MSG_KEXGSS_HOSTKEY); ++ ++ switch (type) { ++ case SSH2_MSG_KEXGSS_CONTINUE: ++ debug("Received GSSAPI_CONTINUE"); ++ if (maj_status == GSS_S_COMPLETE) ++ fatal("GSSAPI Continue received from server when complete"); ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, ++ &recv_tok)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ break; ++ case SSH2_MSG_KEXGSS_COMPLETE: ++ debug("Received GSSAPI_COMPLETE"); ++ if (msg_tok.value != NULL) ++ fatal("Received GSSAPI_COMPLETE twice?"); ++ if ((r = sshpkt_getb_froms(ssh, &server_blob)) != 0 || ++ (r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, ++ &msg_tok)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ ++ /* Is there a token included? */ ++ if ((r = sshpkt_get_u8(ssh, &c)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ if (c) { ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc( ++ ssh, &recv_tok)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ /* If we're already complete - protocol error */ ++ if (maj_status == GSS_S_COMPLETE) ++ sshpkt_disconnect(ssh, "Protocol error: received token when complete"); ++ } else { ++ /* No token included */ ++ if (maj_status != GSS_S_COMPLETE) ++ sshpkt_disconnect(ssh, "Protocol error: did not receive final token"); ++ } ++ break; ++ case SSH2_MSG_KEXGSS_ERROR: ++ debug("Received Error"); ++ if ((r = sshpkt_get_u32(ssh, &maj_status)) != 0 || ++ (r = sshpkt_get_u32(ssh, &min_status)) != 0 || ++ (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 || ++ (r = sshpkt_get_string(ssh, NULL, NULL)) != 0 || /* lang tag */ ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ fatal("GSSAPI Error: \n%.400s", msg); ++ default: ++ sshpkt_disconnect(ssh, "Protocol error: didn't expect packet type %d", ++ type); ++ } ++ token_ptr = &recv_tok; ++ } else { ++ /* No data, and not complete */ ++ if (maj_status != GSS_S_COMPLETE) ++ fatal("Not complete, and no token output"); ++ } ++ } while (maj_status & GSS_S_CONTINUE_NEEDED); ++ ++ /* ++ * We _must_ have received a COMPLETE message in reply from the ++ * server, which will have set dh_server_pub and msg_tok ++ */ ++ ++ if (type != SSH2_MSG_KEXGSS_COMPLETE) ++ fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it"); ++ ++ /* 7. C verifies that the key Q_S is valid */ ++ /* 8. C computes shared secret */ ++ if ((buf = sshbuf_new()) == NULL || ++ (r = sshbuf_put_stringb(buf, server_blob)) != 0 || ++ (r = sshbuf_get_bignum2(buf, &dh_server_pub)) != 0) ++ goto out; ++ sshbuf_free(buf); ++ ++ if ((shared_secret = sshbuf_new()) == NULL) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ ++ if ((r = kex_dh_compute_key(kex, dh_server_pub, shared_secret)) != 0) ++ goto out; ++ ++ DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); ++ hashlen = sizeof(hash); ++ if ((r = kexgex_hash( ++ kex->hash_alg, ++ kex->client_version, ++ kex->server_version, ++ kex->my, ++ kex->peer, ++ (server_host_key_blob ? server_host_key_blob : empty), ++ kex->min, kex->nbits, kex->max, ++ dh_p, dh_g, ++ pub_key, ++ dh_server_pub, ++ sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), ++ hash, &hashlen)) != 0) ++ fatal("Failed to calculate hash: %s", ssh_err(r)); ++ ++ gssbuf.value = hash; ++ gssbuf.length = hashlen; ++ ++ /* Verify that the hash matches the MIC we just got. */ ++ if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok))) ++ sshpkt_disconnect(ssh, "Hash's MIC didn't verify"); ++ ++ gss_release_buffer(&min_status, &msg_tok); ++ ++ /* save session id */ ++ if (kex->session_id == NULL) { ++ kex->session_id = sshbuf_new (); ++ if ((r = sshbuf_put(kex->session_id, hash, hashlen)) != 0) ++ goto out; ++ } ++ ++ if (kex->gss_deleg_creds) ++ ssh_gssapi_credentials_updated(ctxt); ++ ++ if (gss_kex_context == NULL) ++ gss_kex_context = ctxt; ++ else ++ ssh_gssapi_delete_ctx(&ctxt); ++ ++ /* Finally derive the keys and send them */ ++ if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) ++ r = kex_send_newkeys(ssh); ++out: ++ sshbuf_free(server_blob); ++ sshbuf_free(empty); ++ explicit_bzero(hash, sizeof(hash)); ++ DH_free(kex->dh); ++ kex->dh = NULL; ++ BN_clear_free(dh_server_pub); ++ sshbuf_free(shared_secret); ++ sshbuf_free(server_host_key_blob); ++ return r; ++} ++#endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */ +Index: openssh-9.6p1/kexgsss.c +=================================================================== +--- /dev/null ++++ openssh-9.6p1/kexgsss.c +@@ -0,0 +1,474 @@ ++/* ++ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. ++ * ++ * 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. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 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" ++ ++#if defined(GSSAPI) && defined(WITH_OPENSSL) ++ ++#include ++ ++#include ++#include ++ ++#include "xmalloc.h" ++#include "sshbuf.h" ++#include "ssh2.h" ++#include "sshkey.h" ++#include "cipher.h" ++#include "kex.h" ++#include "log.h" ++#include "packet.h" ++#include "dh.h" ++#include "ssh-gss.h" ++#include "monitor_wrap.h" ++#include "misc.h" /* servconf.h needs misc.h for struct ForwardOptions */ ++#include "servconf.h" ++#include "ssh-gss.h" ++#include "digest.h" ++#include "ssherr.h" ++ ++extern ServerOptions options; ++ ++int ++kexgss_server(struct ssh *ssh) ++{ ++ struct kex *kex = ssh->kex; ++ OM_uint32 maj_status, min_status; ++ ++ /* ++ * Some GSSAPI implementations use the input value of ret_flags (an ++ * output variable) as a means of triggering mechanism specific ++ * features. Initializing it to zero avoids inadvertently ++ * activating this non-standard behaviour. ++ */ ++ ++ OM_uint32 ret_flags = 0; ++ gss_buffer_desc gssbuf, recv_tok, msg_tok; ++ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; ++ Gssctxt *ctxt = NULL; ++ struct sshbuf *shared_secret = NULL; ++ struct sshbuf *client_pubkey = NULL; ++ struct sshbuf *server_pubkey = NULL; ++ struct sshbuf *empty = sshbuf_new(); ++ int type = 0; ++ gss_OID oid; ++ char *mechs; ++ u_char hash[SSH_DIGEST_MAX_LENGTH]; ++ size_t hashlen; ++ int r; ++ ++ /* Initialise GSSAPI */ ++ ++ /* If we're rekeying, privsep means that some of the private structures ++ * in the GSSAPI code are no longer available. This kludges them back ++ * into life ++ */ ++ if (!ssh_gssapi_oid_table_ok()) { ++ mechs = ssh_gssapi_server_mechanisms(); ++ free(mechs); ++ } ++ ++ debug2("%s: Identifying %s", __func__, kex->name); ++ oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type); ++ if (oid == GSS_C_NO_OID) ++ fatal("Unknown gssapi mechanism"); ++ ++ debug2("%s: Acquiring credentials", __func__); ++ ++ if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) ++ fatal("Unable to acquire credentials for the server"); ++ ++ do { ++ debug("Wait SSH2_MSG_KEXGSS_INIT"); ++ type = ssh_packet_read(ssh); ++ switch(type) { ++ case SSH2_MSG_KEXGSS_INIT: ++ if (client_pubkey != NULL) ++ fatal("Received KEXGSS_INIT after initialising"); ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, ++ &recv_tok)) != 0 || ++ (r = sshpkt_getb_froms(ssh, &client_pubkey)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ ++ switch (kex->kex_type) { ++ case KEX_GSS_GRP1_SHA1: ++ case KEX_GSS_GRP14_SHA1: ++ case KEX_GSS_GRP14_SHA256: ++ case KEX_GSS_GRP16_SHA512: ++ r = kex_dh_enc(kex, client_pubkey, &server_pubkey, ++ &shared_secret); ++ break; ++ case KEX_GSS_NISTP256_SHA256: ++ r = kex_ecdh_enc(kex, client_pubkey, &server_pubkey, ++ &shared_secret); ++ break; ++ case KEX_GSS_C25519_SHA256: ++ r = kex_c25519_enc(kex, client_pubkey, &server_pubkey, ++ &shared_secret); ++ break; ++ default: ++ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); ++ } ++ if (r != 0) ++ goto out; ++ ++ /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ ++ break; ++ case SSH2_MSG_KEXGSS_CONTINUE: ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, ++ &recv_tok)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ break; ++ default: ++ sshpkt_disconnect(ssh, ++ "Protocol error: didn't expect packet type %d", ++ type); ++ } ++ ++ maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, ++ &send_tok, &ret_flags)); ++ ++ gss_release_buffer(&min_status, &recv_tok); ++ ++ if (maj_status != GSS_S_COMPLETE && send_tok.length == 0) ++ fatal("Zero length token output when incomplete"); ++ ++ if (client_pubkey == NULL) ++ fatal("No client public key"); ++ ++ if (maj_status & GSS_S_CONTINUE_NEEDED) { ++ debug("Sending GSSAPI_CONTINUE"); ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || ++ (r = sshpkt_send(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ gss_release_buffer(&min_status, &send_tok); ++ } ++ } while (maj_status & GSS_S_CONTINUE_NEEDED); ++ ++ if (GSS_ERROR(maj_status)) { ++ if (send_tok.length > 0) { ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || ++ (r = sshpkt_send(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ } ++ fatal("accept_ctx died"); ++ } ++ ++ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) ++ fatal("Mutual Authentication flag wasn't set"); ++ ++ if (!(ret_flags & GSS_C_INTEG_FLAG)) ++ fatal("Integrity flag wasn't set"); ++ ++ hashlen = sizeof(hash); ++ if ((r = kex_gen_hash( ++ kex->hash_alg, ++ kex->client_version, ++ kex->server_version, ++ kex->peer, ++ kex->my, ++ empty, ++ client_pubkey, ++ server_pubkey, ++ shared_secret, ++ hash, &hashlen)) != 0) ++ goto out; ++ ++ gssbuf.value = hash; ++ gssbuf.length = hashlen; ++ ++ if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt, &gssbuf, &msg_tok)))) ++ fatal("Couldn't get MIC"); ++ ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_COMPLETE)) != 0 || ++ (r = sshpkt_put_stringb(ssh, server_pubkey)) != 0 || ++ (r = sshpkt_put_string(ssh, msg_tok.value, msg_tok.length)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ ++ if (send_tok.length != 0) { ++ if ((r = sshpkt_put_u8(ssh, 1)) != 0 || /* true */ ++ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ } else { ++ if ((r = sshpkt_put_u8(ssh, 0)) != 0) /* false */ ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ } ++ if ((r = sshpkt_send(ssh)) != 0) ++ fatal("sshpkt_send failed: %s", ssh_err(r)); ++ ++ gss_release_buffer(&min_status, &send_tok); ++ gss_release_buffer(&min_status, &msg_tok); ++ ++ if (gss_kex_context == NULL) ++ gss_kex_context = ctxt; ++ else ++ ssh_gssapi_delete_ctx(&ctxt); ++ ++ if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) ++ r = kex_send_newkeys(ssh); ++ ++ /* If this was a rekey, then save out any delegated credentials we ++ * just exchanged. */ ++ if (options.gss_store_rekey) ++ ssh_gssapi_rekey_creds(); ++out: ++ sshbuf_free(empty); ++ explicit_bzero(hash, sizeof(hash)); ++ sshbuf_free(shared_secret); ++ sshbuf_free(client_pubkey); ++ sshbuf_free(server_pubkey); ++ return r; ++} ++ ++int ++kexgssgex_server(struct ssh *ssh) ++{ ++ struct kex *kex = ssh->kex; ++ OM_uint32 maj_status, min_status; ++ ++ /* ++ * Some GSSAPI implementations use the input value of ret_flags (an ++ * output variable) as a means of triggering mechanism specific ++ * features. Initializing it to zero avoids inadvertently ++ * activating this non-standard behaviour. ++ */ ++ ++ OM_uint32 ret_flags = 0; ++ gss_buffer_desc gssbuf, recv_tok, msg_tok; ++ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; ++ Gssctxt *ctxt = NULL; ++ struct sshbuf *shared_secret = NULL; ++ int type = 0; ++ gss_OID oid; ++ char *mechs; ++ u_char hash[SSH_DIGEST_MAX_LENGTH]; ++ size_t hashlen; ++ BIGNUM *dh_client_pub = NULL; ++ const BIGNUM *pub_key, *dh_p, *dh_g; ++ int min = -1, max = -1, nbits = -1; ++ int cmin = -1, cmax = -1; /* client proposal */ ++ struct sshbuf *empty = sshbuf_new(); ++ int r; ++ ++ /* Initialise GSSAPI */ ++ ++ /* If we're rekeying, privsep means that some of the private structures ++ * in the GSSAPI code are no longer available. This kludges them back ++ * into life ++ */ ++ if (!ssh_gssapi_oid_table_ok()) ++ if ((mechs = ssh_gssapi_server_mechanisms())) ++ free(mechs); ++ ++ debug2("%s: Identifying %s", __func__, kex->name); ++ oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type); ++ if (oid == GSS_C_NO_OID) ++ fatal("Unknown gssapi mechanism"); ++ ++ debug2("%s: Acquiring credentials", __func__); ++ ++ if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) ++ fatal("Unable to acquire credentials for the server"); ++ ++ /* 5. S generates an ephemeral key pair (do the allocations early) */ ++ debug("Doing group exchange"); ++ ssh_packet_read_expect(ssh, SSH2_MSG_KEXGSS_GROUPREQ); ++ /* store client proposal to provide valid signature */ ++ if ((r = sshpkt_get_u32(ssh, &cmin)) != 0 || ++ (r = sshpkt_get_u32(ssh, &nbits)) != 0 || ++ (r = sshpkt_get_u32(ssh, &cmax)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ kex->nbits = nbits; ++ kex->min = cmin; ++ kex->max = cmax; ++ min = MAX(DH_GRP_MIN, cmin); ++ max = MIN(DH_GRP_MAX, cmax); ++ nbits = MAXIMUM(DH_GRP_MIN, nbits); ++ nbits = MINIMUM(DH_GRP_MAX, nbits); ++ if (max < min || nbits < min || max < nbits) ++ fatal("GSS_GEX, bad parameters: %d !< %d !< %d", ++ min, nbits, max); ++ kex->dh = PRIVSEP(choose_dh(min, nbits, max)); ++ if (kex->dh == NULL) { ++ sshpkt_disconnect(ssh, "Protocol error: no matching group found"); ++ fatal("Protocol error: no matching group found"); ++ } ++ ++ DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_GROUP)) != 0 || ++ (r = sshpkt_put_bignum2(ssh, dh_p)) != 0 || ++ (r = sshpkt_put_bignum2(ssh, dh_g)) != 0 || ++ (r = sshpkt_send(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ ++ if ((r = ssh_packet_write_wait(ssh)) != 0) ++ fatal("ssh_packet_write_wait: %s", ssh_err(r)); ++ ++ /* Compute our exchange value in parallel with the client */ ++ if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) ++ goto out; ++ ++ do { ++ debug("Wait SSH2_MSG_GSSAPI_INIT"); ++ type = ssh_packet_read(ssh); ++ switch(type) { ++ case SSH2_MSG_KEXGSS_INIT: ++ if (dh_client_pub != NULL) ++ fatal("Received KEXGSS_INIT after initialising"); ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, ++ &recv_tok)) != 0 || ++ (r = sshpkt_get_bignum2(ssh, &dh_client_pub)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ ++ /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ ++ break; ++ case SSH2_MSG_KEXGSS_CONTINUE: ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, ++ &recv_tok)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ break; ++ default: ++ sshpkt_disconnect(ssh, ++ "Protocol error: didn't expect packet type %d", ++ type); ++ } ++ ++ maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, ++ &send_tok, &ret_flags)); ++ ++ gss_release_buffer(&min_status, &recv_tok); ++ ++ if (maj_status != GSS_S_COMPLETE && send_tok.length == 0) ++ fatal("Zero length token output when incomplete"); ++ ++ if (dh_client_pub == NULL) ++ fatal("No client public key"); ++ ++ if (maj_status & GSS_S_CONTINUE_NEEDED) { ++ debug("Sending GSSAPI_CONTINUE"); ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || ++ (r = sshpkt_send(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ gss_release_buffer(&min_status, &send_tok); ++ } ++ } while (maj_status & GSS_S_CONTINUE_NEEDED); ++ ++ if (GSS_ERROR(maj_status)) { ++ if (send_tok.length > 0) { ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || ++ (r = sshpkt_send(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ } ++ fatal("accept_ctx died"); ++ } ++ ++ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) ++ fatal("Mutual Authentication flag wasn't set"); ++ ++ if (!(ret_flags & GSS_C_INTEG_FLAG)) ++ fatal("Integrity flag wasn't set"); ++ ++ /* calculate shared secret */ ++ if ((shared_secret = sshbuf_new()) == NULL) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ if ((r = kex_dh_compute_key(kex, dh_client_pub, shared_secret)) != 0) ++ goto out; ++ ++ DH_get0_key(kex->dh, &pub_key, NULL); ++ DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); ++ hashlen = sizeof(hash); ++ if ((r = kexgex_hash( ++ kex->hash_alg, ++ kex->client_version, ++ kex->server_version, ++ kex->peer, ++ kex->my, ++ empty, ++ cmin, nbits, cmax, ++ dh_p, dh_g, ++ dh_client_pub, ++ pub_key, ++ sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), ++ hash, &hashlen)) != 0) ++ fatal("kexgex_hash failed: %s", ssh_err(r)); ++ ++ gssbuf.value = hash; ++ gssbuf.length = hashlen; ++ ++ if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt, &gssbuf, &msg_tok)))) ++ fatal("Couldn't get MIC"); ++ ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_COMPLETE)) != 0 || ++ (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 || ++ (r = sshpkt_put_string(ssh, msg_tok.value, msg_tok.length)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ ++ if (send_tok.length != 0) { ++ if ((r = sshpkt_put_u8(ssh, 1)) != 0 || /* true */ ++ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ } else { ++ if ((r = sshpkt_put_u8(ssh, 0)) != 0) /* false */ ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ } ++ if ((r = sshpkt_send(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ ++ gss_release_buffer(&min_status, &send_tok); ++ gss_release_buffer(&min_status, &msg_tok); ++ ++ if (gss_kex_context == NULL) ++ gss_kex_context = ctxt; ++ else ++ ssh_gssapi_delete_ctx(&ctxt); ++ ++ /* Finally derive the keys and send them */ ++ if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) ++ r = kex_send_newkeys(ssh); ++ ++ /* If this was a rekey, then save out any delegated credentials we ++ * just exchanged. */ ++ if (options.gss_store_rekey) ++ ssh_gssapi_rekey_creds(); ++out: ++ sshbuf_free(empty); ++ explicit_bzero(hash, sizeof(hash)); ++ DH_free(kex->dh); ++ kex->dh = NULL; ++ BN_clear_free(dh_client_pub); ++ sshbuf_free(shared_secret); ++ return r; ++} ++#endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */ +Index: openssh-9.6p1/monitor.c +=================================================================== +--- openssh-9.6p1.orig/monitor.c ++++ openssh-9.6p1/monitor.c +@@ -142,6 +142,8 @@ int mm_answer_gss_setup_ctx(struct ssh * + int mm_answer_gss_accept_ctx(struct ssh *, int, struct sshbuf *); + int mm_answer_gss_userok(struct ssh *, int, struct sshbuf *); + int mm_answer_gss_checkmic(struct ssh *, int, struct sshbuf *); ++int mm_answer_gss_sign(struct ssh*, int, struct sshbuf *); ++int mm_answer_gss_updatecreds(struct ssh*, int, struct sshbuf *); + #endif + + #ifdef SSH_AUDIT_EVENTS +@@ -214,11 +216,18 @@ struct mon_table mon_dispatch_proto20[] + {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx}, + {MONITOR_REQ_GSSUSEROK, MON_ONCE|MON_AUTHDECIDE, mm_answer_gss_userok}, + {MONITOR_REQ_GSSCHECKMIC, MON_ONCE, mm_answer_gss_checkmic}, ++ {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign}, + #endif + {0, 0, NULL} + }; + + struct mon_table mon_dispatch_postauth20[] = { ++#ifdef GSSAPI ++ {MONITOR_REQ_GSSSETUP, 0, mm_answer_gss_setup_ctx}, ++ {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx}, ++ {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign}, ++ {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds}, ++#endif + #ifdef WITH_OPENSSL + {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, + #endif +@@ -287,6 +296,10 @@ monitor_child_preauth(struct ssh *ssh, s + /* Permit requests for moduli and signatures */ + monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); ++#ifdef GSSAPI ++ /* and for the GSSAPI key exchange */ ++ monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1); ++#endif + + /* The first few requests do not require asynchronous access */ + while (!authenticated) { +@@ -403,6 +416,10 @@ monitor_child_postauth(struct ssh *ssh, + monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); ++#ifdef GSSAPI ++ /* and for the GSSAPI key exchange */ ++ monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1); ++#endif + + if (auth_opts->permit_pty_flag) { + monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); +@@ -1745,6 +1762,17 @@ monitor_apply_keystate(struct ssh *ssh, + # ifdef OPENSSL_HAS_ECC + kex->kex[KEX_ECDH_SHA2] = kex_gen_server; + # endif ++# ifdef GSSAPI ++ if (options.gss_keyex) { ++ kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; ++ kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; ++ kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_server; ++ kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_server; ++ kex->kex[KEX_GSS_GEX_SHA1] = kexgssgex_server; ++ kex->kex[KEX_GSS_NISTP256_SHA256] = kexgss_server; ++ kex->kex[KEX_GSS_C25519_SHA256] = kexgss_server; ++ } ++# endif + #endif /* WITH_OPENSSL */ + kex->kex[KEX_C25519_SHA256] = kex_gen_server; + kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; +@@ -1837,8 +1865,8 @@ mm_answer_gss_setup_ctx(struct ssh *ssh, + u_char *p; + int r; + +- if (!options.gss_authentication) +- fatal_f("GSSAPI authentication not enabled"); ++ if (!options.gss_authentication && !options.gss_keyex) ++ fatal_f("GSSAPI not enabled"); + + if ((r = sshbuf_get_string(m, &p, &len)) != 0) + fatal_fr(r, "parse"); +@@ -1870,8 +1898,8 @@ mm_answer_gss_accept_ctx(struct ssh *ssh + OM_uint32 flags = 0; /* GSI needs this */ + int r; + +- if (!options.gss_authentication) +- fatal_f("GSSAPI authentication not enabled"); ++ if (!options.gss_authentication && !options.gss_keyex) ++ fatal_f("GSSAPI not enabled"); + + if ((r = ssh_gssapi_get_buffer_desc(m, &in)) != 0) + fatal_fr(r, "ssh_gssapi_get_buffer_desc"); +@@ -1891,6 +1919,7 @@ mm_answer_gss_accept_ctx(struct ssh *ssh + monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0); + monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); ++ monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1); + } + return (0); + } +@@ -1902,8 +1931,8 @@ mm_answer_gss_checkmic(struct ssh *ssh, + OM_uint32 ret; + int r; + +- if (!options.gss_authentication) +- fatal_f("GSSAPI authentication not enabled"); ++ if (!options.gss_authentication && !options.gss_keyex) ++ fatal_f("GSSAPI not enabled"); + + if ((r = ssh_gssapi_get_buffer_desc(m, &gssbuf)) != 0 || + (r = ssh_gssapi_get_buffer_desc(m, &mic)) != 0) +@@ -1929,13 +1958,17 @@ mm_answer_gss_checkmic(struct ssh *ssh, + int + mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) + { +- int r, authenticated; ++ int r, authenticated, kex; + const char *displayname; + +- if (!options.gss_authentication) +- fatal_f("GSSAPI authentication not enabled"); ++ if (!options.gss_authentication && !options.gss_keyex) ++ fatal_f("GSSAPI not enabled"); + +- authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user); ++ if ((r = sshbuf_get_u32(m, &kex)) != 0) ++ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ ++ authenticated = authctxt->valid && ++ ssh_gssapi_userok(authctxt->user, authctxt->pw, kex); + + sshbuf_reset(m); + if ((r = sshbuf_put_u32(m, authenticated)) != 0) +@@ -1944,7 +1977,11 @@ mm_answer_gss_userok(struct ssh *ssh, in + debug3_f("sending result %d", authenticated); + mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m); + +- auth_method = "gssapi-with-mic"; ++ if (kex) { ++ auth_method = "gssapi-keyex"; ++ } else { ++ auth_method = "gssapi-with-mic"; ++ } + + if ((displayname = ssh_gssapi_displayname()) != NULL) + auth2_record_info(authctxt, "%s", displayname); +@@ -1952,5 +1989,85 @@ mm_answer_gss_userok(struct ssh *ssh, in + /* Monitor loop will terminate if authenticated */ + return (authenticated); + } ++ ++int ++mm_answer_gss_sign(struct ssh *ssh, int socket, struct sshbuf *m) ++{ ++ gss_buffer_desc data; ++ gss_buffer_desc hash = GSS_C_EMPTY_BUFFER; ++ OM_uint32 major, minor; ++ size_t len; ++ u_char *p = NULL; ++ int r; ++ ++ if (!options.gss_authentication && !options.gss_keyex) ++ fatal("%s: GSSAPI not enabled", __func__); ++ ++ if ((r = sshbuf_get_string(m, &p, &len)) != 0) ++ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ data.value = p; ++ data.length = len; ++ /* Lengths of SHA-1, SHA-256 and SHA-512 hashes that are used */ ++ if (data.length != 20 && data.length != 32 && data.length != 64) ++ fatal("%s: data length incorrect: %d", __func__, ++ (int) data.length); ++ ++ /* Save the session ID on the first time around */ ++ if (session_id2_len == 0) { ++ session_id2_len = data.length; ++ session_id2 = xmalloc(session_id2_len); ++ memcpy(session_id2, data.value, session_id2_len); ++ } ++ major = ssh_gssapi_sign(gsscontext, &data, &hash); ++ ++ free(data.value); ++ ++ sshbuf_reset(m); ++ ++ if ((r = sshbuf_put_u32(m, major)) != 0 || ++ (r = sshbuf_put_string(m, hash.value, hash.length)) != 0) ++ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ ++ mm_request_send(socket, MONITOR_ANS_GSSSIGN, m); ++ ++ gss_release_buffer(&minor, &hash); ++ ++ /* Turn on getpwnam permissions */ ++ monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); ++ ++ /* And credential updating, for when rekeying */ ++ monitor_permit(mon_dispatch, MONITOR_REQ_GSSUPCREDS, 1); ++ ++ return (0); ++} ++ ++int ++mm_answer_gss_updatecreds(struct ssh *ssh, int socket, struct sshbuf *m) { ++ ssh_gssapi_ccache store; ++ int r, ok; ++ ++ if (!options.gss_authentication && !options.gss_keyex) ++ fatal("%s: GSSAPI not enabled", __func__); ++ ++ if ((r = sshbuf_get_string(m, (u_char **)&store.filename, NULL)) != 0 || ++ (r = sshbuf_get_string(m, (u_char **)&store.envvar, NULL)) != 0 || ++ (r = sshbuf_get_string(m, (u_char **)&store.envval, NULL)) != 0) ++ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ ++ ok = ssh_gssapi_update_creds(&store); ++ ++ free(store.filename); ++ free(store.envvar); ++ free(store.envval); ++ ++ sshbuf_reset(m); ++ if ((r = sshbuf_put_u32(m, ok)) != 0) ++ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ ++ mm_request_send(socket, MONITOR_ANS_GSSUPCREDS, m); ++ ++ return(0); ++} ++ + #endif /* GSSAPI */ + +Index: openssh-9.6p1/monitor.h +=================================================================== +--- openssh-9.6p1.orig/monitor.h ++++ openssh-9.6p1/monitor.h +@@ -63,6 +63,8 @@ enum monitor_reqtype { + MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111, + MONITOR_REQ_AUDIT_EVENT = 112, MONITOR_REQ_AUDIT_COMMAND = 113, + ++ MONITOR_REQ_GSSSIGN = 150, MONITOR_ANS_GSSSIGN = 151, ++ MONITOR_REQ_GSSUPCREDS = 152, MONITOR_ANS_GSSUPCREDS = 153, + }; + + struct ssh; +Index: openssh-9.6p1/monitor_wrap.c +=================================================================== +--- openssh-9.6p1.orig/monitor_wrap.c ++++ openssh-9.6p1/monitor_wrap.c +@@ -998,13 +998,15 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss + } + + int +-mm_ssh_gssapi_userok(char *user) ++mm_ssh_gssapi_userok(char *user, struct passwd *pw, int kex) + { + struct sshbuf *m; + int r, authenticated = 0; + + if ((m = sshbuf_new()) == NULL) + fatal_f("sshbuf_new failed"); ++ if ((r = sshbuf_put_u32(m, kex)) != 0) ++ fatal("%s: buffer error: %s", __func__, ssh_err(r)); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, m); + mm_request_receive_expect(pmonitor->m_recvfd, +@@ -1017,4 +1019,57 @@ mm_ssh_gssapi_userok(char *user) + debug3_f("user %sauthenticated", authenticated ? "" : "not "); + return (authenticated); + } ++ ++OM_uint32 ++mm_ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *data, gss_buffer_desc *hash) ++{ ++ struct sshbuf *m; ++ OM_uint32 major; ++ int r; ++ ++ if ((m = sshbuf_new()) == NULL) ++ fatal("%s: sshbuf_new failed", __func__); ++ if ((r = sshbuf_put_string(m, data->value, data->length)) != 0) ++ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ ++ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSIGN, m); ++ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSIGN, m); ++ ++ if ((r = sshbuf_get_u32(m, &major)) != 0 || ++ (r = ssh_gssapi_get_buffer_desc(m, hash)) != 0) ++ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ ++ sshbuf_free(m); ++ ++ return (major); ++} ++ ++int ++mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *store) ++{ ++ struct sshbuf *m; ++ int r, ok; ++ ++ if ((m = sshbuf_new()) == NULL) ++ fatal("%s: sshbuf_new failed", __func__); ++ ++ if ((r = sshbuf_put_cstring(m, ++ store->filename ? store->filename : "")) != 0 || ++ (r = sshbuf_put_cstring(m, ++ store->envvar ? store->envvar : "")) != 0 || ++ (r = sshbuf_put_cstring(m, ++ store->envval ? store->envval : "")) != 0) ++ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ ++ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUPCREDS, m); ++ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUPCREDS, m); ++ ++ if ((r = sshbuf_get_u32(m, &ok)) != 0) ++ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ ++ sshbuf_free(m); ++ ++ return (ok); ++} ++ + #endif /* GSSAPI */ +Index: openssh-9.6p1/monitor_wrap.h +=================================================================== +--- openssh-9.6p1.orig/monitor_wrap.h ++++ openssh-9.6p1/monitor_wrap.h +@@ -65,8 +65,10 @@ int mm_sshkey_verify(const struct sshkey + OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID); + OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *, + gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *); +-int mm_ssh_gssapi_userok(char *user); ++int mm_ssh_gssapi_userok(char *user, struct passwd *, int kex); + OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); ++OM_uint32 mm_ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); ++int mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *); + #endif + + #ifdef USE_PAM +Index: openssh-9.6p1/readconf.c +=================================================================== +--- openssh-9.6p1.orig/readconf.c ++++ openssh-9.6p1/readconf.c +@@ -70,6 +70,7 @@ + #include "uidswap.h" + #include "myproposal.h" + #include "digest.h" ++#include "ssh-gss.h" + + #include "fips.h" + +@@ -166,6 +167,8 @@ typedef enum { + oClearAllForwardings, oNoHostAuthenticationForLocalhost, + oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, + oAddressFamily, oGssAuthentication, oGssDelegateCreds, ++ oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey, ++ oGssServerIdentity, oGssKexAlgorithms, + oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, + oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist, + oHashKnownHosts, +@@ -212,10 +215,22 @@ static struct { + /* Sometimes-unsupported options */ + #if defined(GSSAPI) + { "gssapiauthentication", oGssAuthentication }, ++ { "gssapikeyexchange", oGssKeyEx }, + { "gssapidelegatecredentials", oGssDelegateCreds }, ++ { "gssapitrustdns", oGssTrustDns }, ++ { "gssapiclientidentity", oGssClientIdentity }, ++ { "gssapiserveridentity", oGssServerIdentity }, ++ { "gssapirenewalforcesrekey", oGssRenewalRekey }, ++ { "gssapikexalgorithms", oGssKexAlgorithms }, + # else + { "gssapiauthentication", oUnsupported }, ++ { "gssapikeyexchange", oUnsupported }, + { "gssapidelegatecredentials", oUnsupported }, ++ { "gssapitrustdns", oUnsupported }, ++ { "gssapiclientidentity", oUnsupported }, ++ { "gssapiserveridentity", oUnsupported }, ++ { "gssapirenewalforcesrekey", oUnsupported }, ++ { "gssapikexalgorithms", oUnsupported }, + #endif + #ifdef ENABLE_PKCS11 + { "pkcs11provider", oPKCS11Provider }, +@@ -1212,10 +1227,42 @@ parse_time: + intptr = &options->gss_authentication; + goto parse_flag; + ++ case oGssKeyEx: ++ intptr = &options->gss_keyex; ++ goto parse_flag; ++ + case oGssDelegateCreds: + intptr = &options->gss_deleg_creds; + goto parse_flag; + ++ case oGssTrustDns: ++ intptr = &options->gss_trust_dns; ++ goto parse_flag; ++ ++ case oGssClientIdentity: ++ charptr = &options->gss_client_identity; ++ goto parse_string; ++ ++ case oGssServerIdentity: ++ charptr = &options->gss_server_identity; ++ goto parse_string; ++ ++ case oGssRenewalRekey: ++ intptr = &options->gss_renewal_rekey; ++ goto parse_flag; ++ ++ case oGssKexAlgorithms: ++ arg = argv_next(&ac, &av); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", ++ filename, linenum); ++ if (!kex_gss_names_valid(arg)) ++ fatal("%.200s line %d: Bad GSSAPI KexAlgorithms '%s'.", ++ filename, linenum, arg ? arg : ""); ++ if (*activep && options->gss_kex_algorithms == NULL) ++ options->gss_kex_algorithms = xstrdup(arg); ++ break; ++ + case oBatchMode: + intptr = &options->batch_mode; + goto parse_flag; +@@ -2524,7 +2571,13 @@ initialize_options(Options * options) + options->fwd_opts.streamlocal_bind_unlink = -1; + options->pubkey_authentication = -1; + options->gss_authentication = -1; ++ options->gss_keyex = -1; + options->gss_deleg_creds = -1; ++ options->gss_trust_dns = -1; ++ 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; +@@ -2687,8 +2740,18 @@ fill_default_options(Options * options) + options->pubkey_authentication = SSH_PUBKEY_AUTH_ALL; + if (options->gss_authentication == -1) + options->gss_authentication = 0; ++ if (options->gss_keyex == -1) ++ options->gss_keyex = 0; + if (options->gss_deleg_creds == -1) + options->gss_deleg_creds = 0; ++ if (options->gss_trust_dns == -1) ++ 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) +@@ -3518,7 +3581,14 @@ dump_client_config(Options *o, const cha + dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports); + #ifdef GSSAPI + dump_cfg_fmtint(oGssAuthentication, o->gss_authentication); ++ dump_cfg_fmtint(oGssKeyEx, o->gss_keyex); + dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds); ++ dump_cfg_fmtint(oGssTrustDns, o->gss_trust_dns); ++ dump_cfg_fmtint(oGssRenewalRekey, o->gss_renewal_rekey); ++ dump_cfg_string(oGssClientIdentity, o->gss_client_identity); ++ dump_cfg_string(oGssServerIdentity, o->gss_server_identity); ++ dump_cfg_string(oGssKexAlgorithms, o->gss_kex_algorithms ? ++ o->gss_kex_algorithms : GSS_KEX_DEFAULT_KEX); + #endif /* GSSAPI */ + dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts); + dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication); +Index: openssh-9.6p1/readconf.h +=================================================================== +--- openssh-9.6p1.orig/readconf.h ++++ openssh-9.6p1/readconf.h +@@ -40,7 +40,13 @@ typedef struct { + int pubkey_authentication; /* Try ssh2 pubkey authentication. */ + int hostbased_authentication; /* ssh2's rhosts_rsa */ + int gss_authentication; /* Try GSS authentication */ ++ int gss_keyex; /* Try GSS key exchange */ + int gss_deleg_creds; /* Delegate GSS credentials */ ++ int gss_trust_dns; /* Trust DNS for GSS canonicalization */ ++ 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. */ +Index: openssh-9.6p1/servconf.c +=================================================================== +--- openssh-9.6p1.orig/servconf.c ++++ openssh-9.6p1/servconf.c +@@ -68,6 +68,7 @@ + #include "auth.h" + #include "myproposal.h" + #include "digest.h" ++#include "ssh-gss.h" + #include "fips.h" + + static void add_listen_addr(ServerOptions *, const char *, +@@ -136,8 +137,11 @@ initialize_server_options(ServerOptions + options->kerberos_ticket_cleanup = -1; + options->kerberos_get_afs_token = -1; + options->gss_authentication=-1; ++ options->gss_keyex = -1; + options->gss_cleanup_creds = -1; + options->gss_strict_acceptor = -1; ++ options->gss_store_rekey = -1; ++ options->gss_kex_algorithms = NULL; + options->password_authentication = -1; + options->kbd_interactive_authentication = -1; + options->permit_empty_passwd = -1; +@@ -381,10 +385,18 @@ fill_default_server_options(ServerOption + options->kerberos_get_afs_token = 0; + if (options->gss_authentication == -1) + options->gss_authentication = 0; ++ if (options->gss_keyex == -1) ++ options->gss_keyex = 0; + if (options->gss_cleanup_creds == -1) + options->gss_cleanup_creds = 1; + if (options->gss_strict_acceptor == -1) + 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->password_authentication == -1) + options->password_authentication = 1; + if (options->kbd_interactive_authentication == -1) +@@ -543,6 +555,7 @@ typedef enum { + sHostKeyAlgorithms, sPerSourceMaxStartups, sPerSourceNetBlockSize, + sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, + sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, ++ sGssKeyEx, sGssKexAlgorithms, sGssStoreRekey, + sAcceptEnv, sSetEnv, sPermitTunnel, + sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory, + sUsePrivilegeSeparation, sAllowAgentForwarding, +@@ -627,12 +640,22 @@ static struct { + #ifdef GSSAPI + { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, + { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, ++ { "gssapicleanupcreds", sGssCleanupCreds, SSHCFG_GLOBAL }, + { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL }, ++ { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL }, ++ { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL }, ++ { "gssapikexalgorithms", sGssKexAlgorithms, SSHCFG_GLOBAL }, + #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 }, + #endif ++ { "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL }, ++ { "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL }, + { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, + { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, + { "challengeresponseauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, /* alias */ +@@ -1646,6 +1669,10 @@ process_server_config_line_depth(ServerO + intptr = &options->gss_authentication; + goto parse_flag; + ++ case sGssKeyEx: ++ intptr = &options->gss_keyex; ++ goto parse_flag; ++ + case sGssCleanupCreds: + intptr = &options->gss_cleanup_creds; + goto parse_flag; +@@ -1654,6 +1681,22 @@ process_server_config_line_depth(ServerO + intptr = &options->gss_strict_acceptor; + goto parse_flag; + ++ case sGssStoreRekey: ++ intptr = &options->gss_store_rekey; ++ goto parse_flag; ++ ++ case sGssKexAlgorithms: ++ arg = argv_next(&ac, &av); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", ++ filename, linenum); ++ if (!kex_gss_names_valid(arg)) ++ fatal("%.200s line %d: Bad GSSAPI KexAlgorithms '%s'.", ++ filename, linenum, arg ? arg : ""); ++ if (*activep && options->gss_kex_algorithms == NULL) ++ options->gss_kex_algorithms = xstrdup(arg); ++ break; ++ + case sPasswordAuthentication: + intptr = &options->password_authentication; + goto parse_flag; +@@ -3088,6 +3131,10 @@ dump_config(ServerOptions *o) + #ifdef GSSAPI + dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); + dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); ++ 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, +Index: openssh-9.6p1/servconf.h +=================================================================== +--- openssh-9.6p1.orig/servconf.h ++++ openssh-9.6p1/servconf.h +@@ -139,8 +139,11 @@ typedef struct { + int kerberos_get_afs_token; /* If true, try to get AFS token if + * authenticated with Kerberos. */ + int gss_authentication; /* If true, permit GSSAPI authentication */ ++ int gss_keyex; /* If true, permit GSSAPI key exchange */ + 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 */ +Index: openssh-9.6p1/session.c +=================================================================== +--- openssh-9.6p1.orig/session.c ++++ openssh-9.6p1/session.c +@@ -2726,13 +2726,19 @@ do_cleanup(struct ssh *ssh, Authctxt *au + + #ifdef KRB5 + if (options.kerberos_ticket_cleanup && +- authctxt->krb5_ctx) ++ authctxt->krb5_ctx) { ++ temporarily_use_uid(authctxt->pw); + krb5_cleanup_proc(authctxt); ++ restore_uid(); ++ } + #endif + + #ifdef GSSAPI +- if (options.gss_cleanup_creds) ++ if (options.gss_cleanup_creds) { ++ temporarily_use_uid(authctxt->pw); + ssh_gssapi_cleanup_creds(); ++ restore_uid(); ++ } + #endif + + /* remove agent socket */ +Index: openssh-9.6p1/ssh-gss.h +=================================================================== +--- openssh-9.6p1.orig/ssh-gss.h ++++ openssh-9.6p1/ssh-gss.h +@@ -1,6 +1,6 @@ + /* $OpenBSD: ssh-gss.h,v 1.15 2021/01/27 10:05:28 djm Exp $ */ + /* +- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. ++ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -61,10 +61,30 @@ + + #define SSH_GSS_OIDTYPE 0x06 + ++#define SSH2_MSG_KEXGSS_INIT 30 ++#define SSH2_MSG_KEXGSS_CONTINUE 31 ++#define SSH2_MSG_KEXGSS_COMPLETE 32 ++#define SSH2_MSG_KEXGSS_HOSTKEY 33 ++#define SSH2_MSG_KEXGSS_ERROR 34 ++#define SSH2_MSG_KEXGSS_GROUPREQ 40 ++#define SSH2_MSG_KEXGSS_GROUP 41 ++#define KEX_GSS_GRP1_SHA1_ID "gss-group1-sha1-" ++#define KEX_GSS_GRP14_SHA1_ID "gss-group14-sha1-" ++#define KEX_GSS_GRP14_SHA256_ID "gss-group14-sha256-" ++#define KEX_GSS_GRP16_SHA512_ID "gss-group16-sha512-" ++#define KEX_GSS_GEX_SHA1_ID "gss-gex-sha1-" ++#define KEX_GSS_NISTP256_SHA256_ID "gss-nistp256-sha256-" ++#define KEX_GSS_C25519_SHA256_ID "gss-curve25519-sha256-" ++ ++#define GSS_KEX_DEFAULT_KEX \ ++ KEX_GSS_GEX_SHA1_ID "," \ ++ KEX_GSS_GRP14_SHA1_ID ++ + typedef struct { + char *filename; + char *envvar; + char *envval; ++ struct passwd *owner; + void *data; + } ssh_gssapi_ccache; + +@@ -72,8 +92,11 @@ typedef struct { + gss_buffer_desc displayname; + gss_buffer_desc exportedname; + gss_cred_id_t creds; ++ gss_name_t name; + struct ssh_gssapi_mech_struct *mech; + ssh_gssapi_ccache store; ++ int used; ++ int updated; + } ssh_gssapi_client; + + typedef struct ssh_gssapi_mech_struct { +@@ -84,6 +107,7 @@ typedef struct ssh_gssapi_mech_struct { + int (*userok) (ssh_gssapi_client *, char *); + int (*localname) (ssh_gssapi_client *, char **); + void (*storecreds) (ssh_gssapi_client *); ++ int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *); + } ssh_gssapi_mech; + + typedef struct { +@@ -94,10 +118,11 @@ typedef struct { + gss_OID oid; /* client */ + gss_cred_id_t creds; /* server */ + gss_name_t client; /* server */ +- gss_cred_id_t client_creds; /* server */ ++ gss_cred_id_t client_creds; /* both */ + } Gssctxt; + + extern ssh_gssapi_mech *supported_mechs[]; ++extern Gssctxt *gss_kex_context; + + int ssh_gssapi_check_oid(Gssctxt *, void *, size_t); + void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t); +@@ -109,6 +134,7 @@ OM_uint32 ssh_gssapi_test_oid_supported( + + struct sshbuf; + int ssh_gssapi_get_buffer_desc(struct sshbuf *, gss_buffer_desc *); ++int ssh_gssapi_sshpkt_get_buffer_desc(struct ssh *, gss_buffer_desc *); + + OM_uint32 ssh_gssapi_import_name(Gssctxt *, const char *); + OM_uint32 ssh_gssapi_init_ctx(Gssctxt *, int, +@@ -123,17 +149,33 @@ void ssh_gssapi_delete_ctx(Gssctxt **); + OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); + void ssh_gssapi_buildmic(struct sshbuf *, const char *, + const char *, const char *, const struct sshbuf *); +-int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *); ++int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *, const char *); ++OM_uint32 ssh_gssapi_client_identity(Gssctxt *, const char *); ++int ssh_gssapi_credentials_updated(Gssctxt *); + + /* 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 *, const char *); ++char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, 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 *); + OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID); +-int ssh_gssapi_userok(char *name); ++int ssh_gssapi_userok(char *, struct passwd *, int kex); + OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); + void ssh_gssapi_do_child(char ***, u_int *); + void ssh_gssapi_cleanup_creds(void); + void ssh_gssapi_storecreds(void); + const char *ssh_gssapi_displayname(void); + ++char *ssh_gssapi_server_mechanisms(void); ++int ssh_gssapi_oid_table_ok(void); ++ ++int ssh_gssapi_update_creds(ssh_gssapi_ccache *store); ++void ssh_gssapi_rekey_creds(void); ++ + #endif /* GSSAPI */ + + #endif /* _SSH_GSS_H */ +Index: openssh-9.6p1/ssh.1 +=================================================================== +--- openssh-9.6p1.orig/ssh.1 ++++ openssh-9.6p1/ssh.1 +@@ -536,7 +536,13 @@ For full details of the options listed b + .It GatewayPorts + .It GlobalKnownHostsFile + .It GSSAPIAuthentication ++.It GSSAPIKeyExchange ++.It GSSAPIClientIdentity + .It GSSAPIDelegateCredentials ++.It GSSAPIKexAlgorithms ++.It GSSAPIRenewalForcesRekey ++.It GSSAPIServerIdentity ++.It GSSAPITrustDns + .It HashKnownHosts + .It Host + .It HostbasedAcceptedAlgorithms +@@ -624,6 +630,8 @@ flag), + (supported message integrity codes), + .Ar kex + (key exchange algorithms), ++.Ar kex-gss ++(GSSAPI key exchange algorithms), + .Ar key + (key types), + .Ar key-ca-sign +Index: openssh-9.6p1/ssh.c +=================================================================== +--- openssh-9.6p1.orig/ssh.c ++++ openssh-9.6p1/ssh.c +@@ -833,6 +833,8 @@ main(int ac, char **av) + else if (strcmp(optarg, "kex") == 0 || + strcasecmp(optarg, "KexAlgorithms") == 0) + cp = kex_alg_list('\n'); ++ else if (strcmp(optarg, "kex-gss") == 0) ++ cp = kex_gss_alg_list('\n'); + else if (strcmp(optarg, "key") == 0) + cp = sshkey_alg_list(0, 0, 0, '\n'); + else if (strcmp(optarg, "key-cert") == 0) +@@ -862,7 +864,7 @@ main(int ac, char **av) + cp[n] = '\n'; + } else if (strcmp(optarg, "help") == 0) { + cp = xstrdup( +- "cipher\ncipher-auth\ncompression\nkex\n" ++ "cipher\ncipher-auth\ncompression\nkex\nkex-gss\n" + "key\nkey-cert\nkey-plain\nkey-sig\nmac\n" + "protocol-version\nsig"); + } +Index: openssh-9.6p1/ssh_config +=================================================================== +--- openssh-9.6p1.orig/ssh_config ++++ openssh-9.6p1/ssh_config +@@ -40,6 +40,8 @@ Host * + # HostbasedAuthentication no + # GSSAPIAuthentication no + # GSSAPIDelegateCredentials no ++# GSSAPIKeyExchange no ++# GSSAPITrustDNS no + # BatchMode no + # CheckHostIP no + # AddressFamily any +Index: openssh-9.6p1/ssh_config.5 +=================================================================== +--- openssh-9.6p1.orig/ssh_config.5 ++++ openssh-9.6p1/ssh_config.5 +@@ -930,10 +930,67 @@ The default is + Specifies whether user authentication based on GSSAPI is allowed. + The default is + .Cm no . ++.It Cm GSSAPIClientIdentity ++If set, specifies the GSSAPI client identity that ssh should use when ++connecting to the server. The default is unset, which means that the default ++identity will be used. + .It Cm GSSAPIDelegateCredentials + Forward (delegate) credentials to the server. + The default is + .Cm no . ++.It Cm GSSAPIKeyExchange ++Specifies whether key exchange based on GSSAPI may be used. When using ++GSSAPI key exchange the server need not have a host key. ++The default is ++.Dq no . ++.It Cm GSSAPIRenewalForcesRekey ++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 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 ++expected GSSAPI server identity will be determined from the target ++hostname. ++.It Cm GSSAPITrustDns ++Set to ++.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 ++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-, ++gss-group14-sha256-, ++gss-group16-sha512-, ++gss-nistp256-sha256-, ++gss-curve25519-sha256- ++.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 +Index: openssh-9.6p1/sshconnect2.c +=================================================================== +--- openssh-9.6p1.orig/sshconnect2.c ++++ openssh-9.6p1/sshconnect2.c +@@ -80,8 +80,6 @@ + #endif + + /* import */ +-extern char *client_version_string; +-extern char *server_version_string; + extern Options options; + + /* +@@ -224,10 +222,44 @@ ssh_kex2(struct ssh *ssh, char *host, st + char *s, *all_key, *hkalgs = NULL; + int r, use_known_hosts_order = 0; + ++#if defined(GSSAPI) && defined(WITH_OPENSSL) ++ char *orig = NULL, *gss = NULL; ++ char *gss_host = NULL; ++#endif ++ + xxx_host = host; + xxx_hostaddr = hostaddr; + xxx_conn_info = cinfo; + ++#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); ++ 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 ++ + if (options.rekey_limit || options.rekey_interval) + ssh_packet_set_rekey_limits(ssh, options.rekey_limit, + options.rekey_interval); +@@ -275,17 +307,47 @@ ssh_kex2(struct ssh *ssh, char *host, st + # ifdef OPENSSL_HAS_ECC + ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client; + # endif +-#endif ++# ifdef GSSAPI ++ if (options.gss_keyex) { ++ ssh->kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client; ++ ssh->kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client; ++ ssh->kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_client; ++ ssh->kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_client; ++ ssh->kex->kex[KEX_GSS_GEX_SHA1] = kexgssgex_client; ++ ssh->kex->kex[KEX_GSS_NISTP256_SHA256] = kexgss_client; ++ ssh->kex->kex[KEX_GSS_C25519_SHA256] = kexgss_client; ++ } ++# endif ++#endif /* WITH_OPENSSL */ + ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; + ssh->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_client; + ssh->kex->verify_host_key=&verify_host_key_callback; + ++#if defined(GSSAPI) && defined(WITH_OPENSSL) ++ if (options.gss_keyex) { ++ ssh->kex->gss_deleg_creds = options.gss_deleg_creds; ++ ssh->kex->gss_trust_dns = options.gss_trust_dns; ++ ssh->kex->gss_client = options.gss_client_identity; ++ ssh->kex->gss_host = gss_host; ++ } ++#endif ++ + ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &ssh->kex->done); + + /* remove ext-info from the KEX proposals for rekeying */ + free(myproposal[PROPOSAL_KEX_ALGS]); + myproposal[PROPOSAL_KEX_ALGS] = + compat_kex_proposal(ssh, options.kex_algorithms); ++#if defined(GSSAPI) && defined(WITH_OPENSSL) ++ /* repair myproposal after it was crumpled by the */ ++ /* ext-info removal above */ ++ if (gss) { ++ orig = myproposal[PROPOSAL_KEX_ALGS]; ++ xasprintf(&myproposal[PROPOSAL_KEX_ALGS], ++ "%s,%s", gss, orig); ++ free(gss); ++ } ++#endif + if ((r = kex_prop2buf(ssh->kex->my, myproposal)) != 0) + fatal_r(r, "kex_prop2buf"); + +@@ -379,6 +441,7 @@ static int input_gssapi_response(int typ + static int input_gssapi_token(int type, u_int32_t, struct ssh *); + static int input_gssapi_error(int, u_int32_t, struct ssh *); + static int input_gssapi_errtok(int, u_int32_t, struct ssh *); ++static int userauth_gsskeyex(struct ssh *); + #endif + + void userauth(struct ssh *, char *); +@@ -395,6 +458,11 @@ static char *authmethods_get(void); + + Authmethod authmethods[] = { + #ifdef GSSAPI ++ {"gssapi-keyex", ++ userauth_gsskeyex, ++ NULL, ++ &options.gss_keyex, ++ NULL}, + {"gssapi-with-mic", + userauth_gssapi, + userauth_gssapi_cleanup, +@@ -766,12 +834,23 @@ userauth_gssapi(struct ssh *ssh) + OM_uint32 min; + int r, ok = 0; + gss_OID mech = NULL; ++ char *gss_host; ++ ++ if (options.gss_server_identity) ++ gss_host = xstrdup(options.gss_server_identity); ++ else if (options.gss_trust_dns) ++ gss_host = remote_hostname(ssh); ++ else ++ gss_host = xstrdup(authctxt->host); + + /* Try one GSSAPI method at a time, rather than sending them all at + * once. */ + + if (authctxt->gss_supported_mechs == NULL) +- gss_indicate_mechs(&min, &authctxt->gss_supported_mechs); ++ if (GSS_ERROR(gss_indicate_mechs(&min, &authctxt->gss_supported_mechs))) { ++ free(gss_host); ++ return 0; ++ } + + /* Check to see whether the mechanism is usable before we offer it */ + while (authctxt->mech_tried < authctxt->gss_supported_mechs->count && +@@ -780,13 +859,15 @@ userauth_gssapi(struct ssh *ssh) + elements[authctxt->mech_tried]; + /* My DER encoding requires length<128 */ + if (mech->length < 128 && ssh_gssapi_check_mechanism(&gssctxt, +- mech, authctxt->host)) { ++ mech, gss_host, options.gss_client_identity)) { + ok = 1; /* Mechanism works */ + } else { + authctxt->mech_tried++; + } + } + ++ free(gss_host); ++ + if (!ok || mech == NULL) + return 0; + +@@ -1020,6 +1101,55 @@ input_gssapi_error(int type, u_int32_t p + free(lang); + return r; + } ++ ++int ++userauth_gsskeyex(struct ssh *ssh) ++{ ++ struct sshbuf *b = NULL; ++ Authctxt *authctxt = ssh->authctxt; ++ gss_buffer_desc gssbuf; ++ gss_buffer_desc mic = GSS_C_EMPTY_BUFFER; ++ OM_uint32 ms; ++ int r; ++ ++ static int attempt = 0; ++ if (attempt++ >= 1) ++ return (0); ++ ++ if (gss_kex_context == NULL) { ++ debug("No valid Key exchange context"); ++ return (0); ++ } ++ ++ if ((b = sshbuf_new()) == NULL) ++ fatal("%s: sshbuf_new failed", __func__); ++ ++ ssh_gssapi_buildmic(b, authctxt->server_user, authctxt->service, ++ "gssapi-keyex", ssh->kex->session_id); ++ ++ if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL) ++ fatal("%s: sshbuf_mutable_ptr failed", __func__); ++ gssbuf.length = sshbuf_len(b); ++ ++ if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) { ++ sshbuf_free(b); ++ return (0); ++ } ++ ++ if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || ++ (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || ++ (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || ++ (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || ++ (r = sshpkt_put_string(ssh, mic.value, mic.length)) != 0 || ++ (r = sshpkt_send(ssh)) != 0) ++ fatal("%s: %s", __func__, ssh_err(r)); ++ ++ sshbuf_free(b); ++ gss_release_buffer(&ms, &mic); ++ ++ return (1); ++} ++ + #endif /* GSSAPI */ + + static int +Index: openssh-9.6p1/sshd.c +=================================================================== +--- openssh-9.6p1.orig/sshd.c ++++ openssh-9.6p1/sshd.c +@@ -808,8 +808,8 @@ notify_hostkeys(struct ssh *ssh) + } + debug3_f("sent %u hostkeys", nkeys); + if (nkeys == 0) +- fatal_f("no hostkeys"); +- if ((r = sshpkt_send(ssh)) != 0) ++ debug3("%s: no hostkeys", __func__); ++ else if ((r = sshpkt_send(ssh)) != 0) + sshpkt_fatal(ssh, r, "%s: send", __func__); + sshbuf_free(buf); + } +@@ -1944,7 +1944,8 @@ main(int ac, char **av) + free(fp); + } + accumulate_host_timing_secret(cfg, NULL); +- if (!sensitive_data.have_ssh2_key) { ++ /* The GSSAPI key exchange can run without a host key */ ++ if (!sensitive_data.have_ssh2_key && !options.gss_keyex) { + logit("sshd: no hostkeys available -- exiting."); + exit(1); + } +@@ -2421,6 +2422,48 @@ do_ssh2_kex(struct ssh *ssh) + + free(hkalgs); + ++#if defined(GSSAPI) && defined(WITH_OPENSSL) ++ { ++ char *orig; ++ char *gss = NULL; ++ char *newstr = NULL; ++ orig = myproposal[PROPOSAL_KEX_ALGS]; ++ ++ /* ++ * If we don't have a host key, then there's no point advertising ++ * the other key exchange algorithms ++ */ ++ ++ if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0) ++ orig = NULL; ++ ++ if (options.gss_keyex) ++ gss = ssh_gssapi_server_mechanisms(); ++ else ++ gss = NULL; ++ ++ if (gss && orig) ++ xasprintf(&newstr, "%s,%s", gss, orig); ++ else if (gss) ++ newstr = gss; ++ else if (orig) ++ newstr = orig; ++ ++ /* ++ * If we've got GSSAPI mechanisms, then we've got the 'null' host ++ * key alg, but we can't tell people about it unless its the only ++ * host key algorithm we support ++ */ ++ if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0) ++ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null"; ++ ++ if (newstr) ++ myproposal[PROPOSAL_KEX_ALGS] = newstr; ++ else ++ fatal("No supported key exchange algorithms"); ++ } ++#endif ++ + /* start key exchange */ + if ((r = kex_setup(ssh, myproposal)) != 0) + fatal_r(r, "kex_setup"); +@@ -2438,7 +2481,18 @@ do_ssh2_kex(struct ssh *ssh) + # ifdef OPENSSL_HAS_ECC + kex->kex[KEX_ECDH_SHA2] = kex_gen_server; + # endif +-#endif ++# ifdef GSSAPI ++ if (options.gss_keyex) { ++ kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; ++ kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; ++ kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_server; ++ kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_server; ++ kex->kex[KEX_GSS_GEX_SHA1] = kexgssgex_server; ++ kex->kex[KEX_GSS_NISTP256_SHA256] = kexgss_server; ++ kex->kex[KEX_GSS_C25519_SHA256] = kexgss_server; ++ } ++# endif ++#endif /* WITH_OPENSSL */ + kex->kex[KEX_C25519_SHA256] = kex_gen_server; + kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; + kex->load_host_public_key=&get_hostkey_public_by_type; +Index: openssh-9.6p1/sshd_config +=================================================================== +--- openssh-9.6p1.orig/sshd_config ++++ openssh-9.6p1/sshd_config +@@ -69,6 +69,8 @@ AuthorizedKeysFile .ssh/authorized_keys + # GSSAPI options + #GSSAPIAuthentication no + #GSSAPICleanupCredentials yes ++#GSSAPIStrictAcceptorCheck yes ++#GSSAPIKeyExchange no + + # Set this to 'yes' to enable PAM authentication, account processing, + # and session processing. If this is enabled, PAM authentication will +Index: openssh-9.6p1/sshd_config.5 +=================================================================== +--- openssh-9.6p1.orig/sshd_config.5 ++++ openssh-9.6p1/sshd_config.5 +@@ -733,6 +733,11 @@ Specifies whether to automatically destr + on logout. + The default is + .Cm yes . ++.It Cm GSSAPIKeyExchange ++Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange ++doesn't rely on ssh keys to verify host identity. ++The default is ++.Cm no . + .It Cm GSSAPIStrictAcceptorCheck + Determines whether to be strict about the identity of the GSSAPI acceptor + a client authenticates against. +@@ -747,6 +752,31 @@ machine's default store. + This facility is provided to assist with operation on multi homed machines. + The default is + .Cm yes . ++.It Cm GSSAPIStoreCredentialsOnRekey ++Controls whether the user's GSSAPI credentials should be updated following a ++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 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-, ++gss-group14-sha256-, ++gss-group16-sha512-, ++gss-nistp256-sha256-, ++gss-curve25519-sha256- ++.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 HostbasedAcceptedAlgorithms + Specifies the signature algorithms that will be accepted for hostbased + authentication as a list of comma-separated patterns. +Index: openssh-9.6p1/sshkey.c +=================================================================== +--- openssh-9.6p1.orig/sshkey.c ++++ openssh-9.6p1/sshkey.c +@@ -128,6 +128,17 @@ extern const struct sshkey_impl sshkey_d + extern const struct sshkey_impl sshkey_xmss_impl; + extern const struct sshkey_impl sshkey_xmss_cert_impl; + #endif ++const struct sshkey_impl sshkey_null_impl = { ++ /* .name = */ "null", ++ /* .shortname = */ "null", ++ /* .sigalg = */ NULL, ++ /* .type = */ KEY_NULL, ++ /* .nid = */ 0, ++ /* .cert = */ 0, ++ /* .sigonly = */ 0, ++ /* .keybits = */ 0, ++ /* .funcs = */ NULL, ++}; + + const struct sshkey_impl * const keyimpls[] = { + &sshkey_ed25519_impl, +@@ -165,6 +176,7 @@ const struct sshkey_impl * const keyimpl + &sshkey_xmss_impl, + &sshkey_xmss_cert_impl, + #endif ++ &sshkey_null_impl, + NULL + }; + +@@ -320,7 +332,7 @@ sshkey_alg_list(int certs_only, int plai + + for (i = 0; keyimpls[i] != NULL; i++) { + impl = keyimpls[i]; +- if (impl->name == NULL) ++ if (impl->name == NULL || impl->type == KEY_NULL) + continue; + if (!include_sigonly && impl->sigonly) + continue; +Index: openssh-9.6p1/sshkey.h +=================================================================== +--- openssh-9.6p1.orig/sshkey.h ++++ openssh-9.6p1/sshkey.h +@@ -71,6 +71,7 @@ enum sshkey_types { + KEY_ECDSA_SK_CERT, + KEY_ED25519_SK, + KEY_ED25519_SK_CERT, ++ KEY_NULL, + KEY_UNSPEC + }; + +Index: openssh-9.6p1/packet.c +=================================================================== +--- openssh-9.6p1.orig/packet.c ++++ openssh-9.6p1/packet.c +@@ -1425,6 +1425,29 @@ ssh_packet_read(struct ssh *ssh) + return type; + } + ++/* ++ * Waits until a packet has been received, verifies that its type matches ++ * that given, and gives a fatal error and exits if there is a mismatch. ++ */ ++ ++int ++ssh_packet_read_expect(struct ssh *ssh, u_int expected_type) ++{ ++ int r; ++ u_char type; ++ ++ if ((r = ssh_packet_read_seqnr(ssh, &type, NULL)) != 0) ++ return r; ++ if (type != expected_type) { ++ if ((r = sshpkt_disconnect(ssh, ++ "Protocol error: expected packet type %d, got %d", ++ expected_type, type)) != 0) ++ return r; ++ return SSH_ERR_PROTOCOL_ERROR; ++ } ++ return 0; ++} ++ + static int + ssh_packet_read_poll2_mux(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) + { +Index: openssh-9.6p1/packet.h +=================================================================== +--- openssh-9.6p1.orig/packet.h ++++ openssh-9.6p1/packet.h +@@ -124,6 +124,7 @@ int ssh_packet_send2_wrapped(struct ssh + int ssh_packet_send2(struct ssh *); + + int ssh_packet_read(struct ssh *); ++int ssh_packet_read_expect(struct ssh *, u_int type); + int ssh_packet_read_poll(struct ssh *); + int ssh_packet_read_poll2(struct ssh *, u_char *, u_int32_t *seqnr_p); + int ssh_packet_process_incoming(struct ssh *, const char *buf, u_int len); diff --git a/openssh-8.1p1-audit.patch b/openssh-8.1p1-audit.patch new file mode 100644 index 0000000..6479633 --- /dev/null +++ b/openssh-8.1p1-audit.patch @@ -0,0 +1,2476 @@ +Index: openssh-8.9p1/Makefile.in +=================================================================== +--- openssh-8.9p1.orig/Makefile.in ++++ openssh-8.9p1/Makefile.in +@@ -116,7 +116,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ + kexsntrup761x25519.o sntrup761.o kexgen.o \ + kexgssc.o \ + sftp-realpath.o platform-pledge.o platform-tracing.o platform-misc.o \ +- sshbuf-io.o ++ sshbuf-io.o auditstub.o + + SKOBJS= ssh-sk-client.o + +Index: openssh-8.9p1/audit-bsm.c +=================================================================== +--- openssh-8.9p1.orig/audit-bsm.c ++++ openssh-8.9p1/audit-bsm.c +@@ -373,13 +373,26 @@ audit_connection_from(const char *host, + #endif + } + ++int ++audit_run_command(struct ssh *ssh, const char *command) ++{ ++ /* not implemented */ ++ return 0; ++} ++ + void +-audit_run_command(const char *command) ++audit_end_command(struct ssh *ssh, int handle, const char *command) + { + /* not implemented */ + } + + void ++audit_count_session_open(void) ++{ ++ /* not necessary */ ++} ++ ++void + audit_session_open(struct logininfo *li) + { + /* not implemented */ +@@ -391,6 +404,12 @@ audit_session_close(struct logininfo *li + /* not implemented */ + } + ++int ++audit_keyusage(struct ssh *ssh, int host_user, char *fp, int rv) ++{ ++ /* not implemented */ ++} ++ + void + audit_event(struct ssh *ssh, ssh_audit_event_t event) + { +@@ -452,4 +471,28 @@ audit_event(struct ssh *ssh, ssh_audit_e + debug("%s: unhandled event %d", __func__, event); + } + } ++ ++void ++audit_unsupported_body(struct ssh *ssh, int what) ++{ ++ /* not implemented */ ++} ++ ++void ++audit_kex_body(struct ssh *ssh, int ctos, char *enc, char *mac, char *compress, char *pfs, pid_t pid, uid_t uid) ++{ ++ /* not implemented */ ++} ++ ++void ++audit_session_key_free_body(struct ssh * ssh, int ctos, pid_t pid, uid_t uid) ++{ ++ /* not implemented */ ++} ++ ++void ++audit_destroy_sensitive_data(struct ssh *ssh, const char *fp, pid_t pid, uid_t uid) ++{ ++ /* not implemented */ ++} + #endif /* BSM */ +Index: openssh-8.9p1/audit-linux.c +=================================================================== +--- openssh-8.9p1.orig/audit-linux.c ++++ openssh-8.9p1/audit-linux.c +@@ -33,27 +33,40 @@ + + #include "log.h" + #include "audit.h" ++#include "sshkey.h" ++#include "hostfile.h" ++#include "auth.h" ++#include "misc.h" /* servconf.h needs misc.h for struct ForwardOptions */ ++#include "servconf.h" + #include "canohost.h" + #include "packet.h" +- ++#include "cipher.h" ++#include "channels.h" ++#include "session.h" ++ ++#define AUDIT_LOG_SIZE 256 ++ ++extern ServerOptions options; ++extern Authctxt *the_authctxt; ++extern u_int utmp_len; + const char *audit_username(void); + +-int +-linux_audit_record_event(int uid, const char *username, const char *hostname, +- const char *ip, const char *ttyn, int success) ++static void ++linux_audit_user_logxxx(int uid, const char *username, ++ const char *ip, const char *ttyn, int success, int event) + { + int audit_fd, rc, saved_errno; + + if ((audit_fd = audit_open()) < 0) { + if (errno == EINVAL || errno == EPROTONOSUPPORT || + errno == EAFNOSUPPORT) +- return 1; /* No audit support in kernel */ ++ return; /* No audit support in kernel */ + else +- return 0; /* Must prevent login */ ++ goto fatal_report; /* Must prevent login */ + } +- rc = audit_log_acct_message(audit_fd, AUDIT_USER_LOGIN, ++ rc = audit_log_acct_message(audit_fd, event, + NULL, "login", username ? username : "(unknown)", +- username == NULL ? uid : -1, hostname, ip, ttyn, success); ++ username == NULL ? uid : -1, NULL, ip, ttyn, success); + saved_errno = errno; + close(audit_fd); + +@@ -65,9 +78,96 @@ linux_audit_record_event(int uid, const + rc = 0; + errno = saved_errno; + +- return rc >= 0; ++ if (rc < 0) { ++fatal_report: ++ fatal("linux_audit_write_entry failed: %s", strerror(errno)); ++ } ++} ++ ++static void ++linux_audit_user_auth(int uid, const char *username, ++ const char *ip, const char *ttyn, int success, int event) ++{ ++ int audit_fd, rc, saved_errno; ++ static const char *event_name[] = { ++ "maxtries exceeded", ++ "root denied", ++ "success", ++ "none", ++ "password", ++ "challenge-response", ++ "pubkey", ++ "hostbased", ++ "gssapi", ++ "invalid user", ++ "nologin", ++ "connection closed", ++ "connection abandoned", ++ "unknown" ++ }; ++ ++ audit_fd = audit_open(); ++ if (audit_fd < 0) { ++ if (errno == EINVAL || errno == EPROTONOSUPPORT || ++ errno == EAFNOSUPPORT) ++ return; /* No audit support in kernel */ ++ else ++ goto fatal_report; /* Must prevent login */ ++ } ++ ++ if ((event < 0) || (event > SSH_AUDIT_UNKNOWN)) ++ event = SSH_AUDIT_UNKNOWN; ++ ++ rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH, ++ NULL, event_name[event], username ? username : "(unknown)", ++ username == NULL ? uid : -1, NULL, ip, ttyn, success); ++ saved_errno = errno; ++ close(audit_fd); ++ /* ++ * Do not report error if the error is EPERM and sshd is run as non ++ * root user. ++ */ ++ if ((rc == -EPERM) && (geteuid() != 0)) ++ rc = 0; ++ errno = saved_errno; ++ if (rc < 0) { ++fatal_report: ++ fatal("linux_audit_write_entry failed: %s", strerror(errno)); ++ } ++} ++ ++int ++audit_keyusage(struct ssh *ssh, int host_user, char *fp, int rv) ++{ ++ char buf[AUDIT_LOG_SIZE]; ++ int audit_fd, rc, saved_errno; ++ ++ audit_fd = audit_open(); ++ if (audit_fd < 0) { ++ if (errno == EINVAL || errno == EPROTONOSUPPORT || ++ errno == EAFNOSUPPORT) ++ return 1; /* No audit support in kernel */ ++ else ++ return 0; /* Must prevent login */ ++ } ++ snprintf(buf, sizeof(buf), "%s_auth grantors=auth-key", host_user ? "pubkey" : "hostbased"); ++ rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH, NULL, ++ buf, audit_username(), -1, NULL, ssh_remote_ipaddr(ssh), NULL, rv); ++ if ((rc < 0) && ((rc != -1) || (getuid() == 0))) ++ goto out; ++ snprintf(buf, sizeof(buf), "op=negotiate kind=auth-key fp=%s", fp); ++ rc = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER, buf, NULL, ++ ssh_remote_ipaddr(ssh), NULL, rv); ++out: ++ saved_errno = errno; ++ audit_close(audit_fd); ++ errno = saved_errno; ++ /* do not report error if the error is EPERM and sshd is run as non root user */ ++ return (rc >= 0) || ((rc == -EPERM) && (getuid() != 0)); + } + ++static int user_login_count = 0; ++ + /* Below is the sshd audit API code */ + + void +@@ -76,49 +176,210 @@ audit_connection_from(const char *host, + /* not implemented */ + } + ++int ++audit_run_command(struct ssh *ssh, const char *command) ++{ ++ if (!user_login_count++) ++ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ ssh_remote_ipaddr(ssh), ++ "ssh", 1, AUDIT_USER_LOGIN); ++ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ ssh_remote_ipaddr(ssh), ++ "ssh", 1, AUDIT_USER_START); ++ return 0; ++} ++ + void +-audit_run_command(const char *command) ++audit_end_command(struct ssh *ssh, int handle, const char *command) + { +- /* not implemented */ ++ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ ssh_remote_ipaddr(ssh), ++ "ssh", 1, AUDIT_USER_END); ++ if (user_login_count && !--user_login_count) ++ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ ssh_remote_ipaddr(ssh), ++ "ssh", 1, AUDIT_USER_LOGOUT); ++} ++ ++void ++audit_count_session_open(void) ++{ ++ user_login_count++; + } + + void + audit_session_open(struct logininfo *li) + { +- if (linux_audit_record_event(li->uid, NULL, li->hostname, NULL, +- li->line, 1) == 0) +- fatal("linux_audit_write_entry failed: %s", strerror(errno)); ++ if (!user_login_count++) ++ linux_audit_user_logxxx(li->uid, NULL, li->hostname, ++ li->line, 1, AUDIT_USER_LOGIN); ++ linux_audit_user_logxxx(li->uid, NULL, li->hostname, ++ li->line, 1, AUDIT_USER_START); + } + + void + audit_session_close(struct logininfo *li) + { +- /* not implemented */ ++ linux_audit_user_logxxx(li->uid, NULL, li->hostname, ++ li->line, 1, AUDIT_USER_END); ++ if (user_login_count && !--user_login_count) ++ linux_audit_user_logxxx(li->uid, NULL, li->hostname, ++ li->line, 1, AUDIT_USER_LOGOUT); + } + + void + audit_event(struct ssh *ssh, ssh_audit_event_t event) + { + switch(event) { +- case SSH_AUTH_SUCCESS: +- case SSH_CONNECTION_CLOSE: + case SSH_NOLOGIN: +- case SSH_LOGIN_EXCEED_MAXTRIES: + case SSH_LOGIN_ROOT_DENIED: ++ linux_audit_user_auth(-1, audit_username(), ++ ssh_remote_ipaddr(ssh), "ssh", 0, event); ++ linux_audit_user_logxxx(-1, audit_username(), ++ ssh_remote_ipaddr(ssh), "ssh", 0, AUDIT_USER_LOGIN); + break; +- case SSH_AUTH_FAIL_NONE: + case SSH_AUTH_FAIL_PASSWD: ++ if (options.use_pam) ++ break; ++ case SSH_LOGIN_EXCEED_MAXTRIES: + case SSH_AUTH_FAIL_KBDINT: + case SSH_AUTH_FAIL_PUBKEY: + case SSH_AUTH_FAIL_HOSTBASED: + case SSH_AUTH_FAIL_GSSAPI: ++ linux_audit_user_auth(-1, audit_username(), ++ ssh_remote_ipaddr(ssh), "ssh", 0, event); ++ break; ++ ++ case SSH_CONNECTION_CLOSE: ++ if (user_login_count) { ++ while (user_login_count--) ++ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ ssh_remote_ipaddr(ssh), ++ "ssh", 1, AUDIT_USER_END); ++ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ ssh_remote_ipaddr(ssh), ++ "ssh", 1, AUDIT_USER_LOGOUT); ++ } ++ break; ++ ++ case SSH_CONNECTION_ABANDON: + case SSH_INVALID_USER: +- linux_audit_record_event(-1, audit_username(), NULL, +- ssh_remote_ipaddr(ssh), "sshd", 0); ++ linux_audit_user_logxxx(-1, audit_username(), ++ ssh_remote_ipaddr(ssh), "ssh", 0, AUDIT_USER_LOGIN); + break; + default: + debug("%s: unhandled event %d", __func__, event); + break; + } + } ++ ++void ++audit_unsupported_body(struct ssh *ssh, int what) ++{ ++#ifdef AUDIT_CRYPTO_SESSION ++ char buf[AUDIT_LOG_SIZE]; ++ const static char *name[] = { "cipher", "mac", "comp" }; ++ char *s; ++ int audit_fd; ++ ++ snprintf(buf, sizeof(buf), "op=unsupported-%s direction=? cipher=? ksize=? rport=%d laddr=%s lport=%d ", ++ name[what], ssh_remote_port(ssh), (s = get_local_ipaddr(ssh_packet_get_connection_in(ssh))), ++ ssh_local_port(ssh)); ++ free(s); ++ audit_fd = audit_open(); ++ if (audit_fd < 0) ++ /* no problem, the next instruction will be fatal() */ ++ return; ++ audit_log_user_message(audit_fd, AUDIT_CRYPTO_SESSION, ++ buf, NULL, ssh_remote_ipaddr(ssh), NULL, 0); ++ audit_close(audit_fd); ++#endif ++} ++ ++const static char *direction[] = { "from-server", "from-client", "both" }; ++ ++void ++audit_kex_body(struct ssh *ssh, int ctos, char *enc, char *mac, char *compress, ++ char *pfs, pid_t pid, uid_t uid) ++{ ++#ifdef AUDIT_CRYPTO_SESSION ++ char buf[AUDIT_LOG_SIZE]; ++ int audit_fd, audit_ok; ++ const struct sshcipher *cipher = cipher_by_name(enc); ++ char *s; ++ ++ snprintf(buf, sizeof(buf), "op=start direction=%s cipher=%s ksize=%d mac=%s pfs=%s spid=%jd suid=%jd rport=%d laddr=%s lport=%d ", ++ direction[ctos], enc, cipher ? 8 * cipher->key_len : 0, mac, pfs, ++ (intmax_t)pid, (intmax_t)uid, ++ ssh_remote_port(ssh), (s = get_local_ipaddr(ssh_packet_get_connection_in(ssh))), ssh_local_port(ssh)); ++ free(s); ++ audit_fd = audit_open(); ++ if (audit_fd < 0) { ++ if (errno == EINVAL || errno == EPROTONOSUPPORT || ++ errno == EAFNOSUPPORT) ++ return; /* No audit support in kernel */ ++ else ++ fatal("cannot open audit"); /* Must prevent login */ ++ } ++ audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_SESSION, ++ buf, NULL, ssh_remote_ipaddr(ssh), NULL, 1); ++ audit_close(audit_fd); ++ /* do not abort if the error is EPERM and sshd is run as non root user */ ++ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0))) ++ fatal("cannot write into audit"); /* Must prevent login */ ++#endif ++} ++ ++void ++audit_session_key_free_body(struct ssh *ssh, int ctos, pid_t pid, uid_t uid) ++{ ++ char buf[AUDIT_LOG_SIZE]; ++ int audit_fd, audit_ok; ++ char *s; ++ ++ snprintf(buf, sizeof(buf), "op=destroy kind=session fp=? direction=%s spid=%jd suid=%jd rport=%d laddr=%s lport=%d ", ++ direction[ctos], (intmax_t)pid, (intmax_t)uid, ++ ssh_remote_port(ssh), ++ (s = get_local_ipaddr(ssh_packet_get_connection_in(ssh))), ++ ssh_local_port(ssh)); ++ free(s); ++ audit_fd = audit_open(); ++ if (audit_fd < 0) { ++ if (errno != EINVAL && errno != EPROTONOSUPPORT && ++ errno != EAFNOSUPPORT) ++ error("cannot open audit"); ++ return; ++ } ++ audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER, ++ buf, NULL, ssh_remote_ipaddr(ssh), NULL, 1); ++ audit_close(audit_fd); ++ /* do not abort if the error is EPERM and sshd is run as non root user */ ++ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0))) ++ error("cannot write into audit"); ++} ++ ++void ++audit_destroy_sensitive_data(struct ssh *ssh, const char *fp, pid_t pid, uid_t uid) ++{ ++ char buf[AUDIT_LOG_SIZE]; ++ int audit_fd, audit_ok; ++ ++ snprintf(buf, sizeof(buf), "op=destroy kind=server fp=%s direction=? spid=%jd suid=%jd ", ++ fp, (intmax_t)pid, (intmax_t)uid); ++ audit_fd = audit_open(); ++ if (audit_fd < 0) { ++ if (errno != EINVAL && errno != EPROTONOSUPPORT && ++ errno != EAFNOSUPPORT) ++ error("cannot open audit"); ++ return; ++ } ++ audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER, ++ buf, NULL, ++ listening_for_clients() ? NULL : ssh_remote_ipaddr(ssh), ++ NULL, 1); ++ audit_close(audit_fd); ++ /* do not abort if the error is EPERM and sshd is run as non root user */ ++ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0))) ++ error("cannot write into audit"); ++} + #endif /* USE_LINUX_AUDIT */ +Index: openssh-8.9p1/audit.c +=================================================================== +--- openssh-8.9p1.orig/audit.c ++++ openssh-8.9p1/audit.c +@@ -34,6 +34,12 @@ + #include "log.h" + #include "hostfile.h" + #include "auth.h" ++#include "ssh-gss.h" ++#include "monitor_wrap.h" ++#include "xmalloc.h" ++#include "misc.h" ++#include "servconf.h" ++#include "ssherr.h" + + /* + * Care must be taken when using this since it WILL NOT be initialized when +@@ -41,6 +47,7 @@ + * audit_event(CONNECTION_ABANDON) is called. Test for NULL before using. + */ + extern Authctxt *the_authctxt; ++extern ServerOptions options; + + /* Maybe add the audit class to struct Authmethod? */ + ssh_audit_event_t +@@ -69,13 +76,10 @@ audit_classify_auth(const char *method) + const char * + audit_username(void) + { +- static const char unknownuser[] = "(unknown user)"; +- static const char invaliduser[] = "(invalid user)"; ++ static const char unknownuser[] = "(unknown)"; + +- if (the_authctxt == NULL || the_authctxt->user == NULL) ++ if (the_authctxt == NULL || the_authctxt->user == NULL || !the_authctxt->valid) + return (unknownuser); +- if (!the_authctxt->valid) +- return (invaliduser); + return (the_authctxt->user); + } + +@@ -109,6 +113,35 @@ audit_event_lookup(ssh_audit_event_t ev) + return(event_lookup[i].name); + } + ++void ++audit_key(struct ssh *ssh, int host_user, int *rv, const struct sshkey *key) ++{ ++ char *fp; ++ ++ fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_HEX); ++ if (audit_keyusage(ssh, host_user, fp, (*rv == 0)) == 0) ++ *rv = -SSH_ERR_INTERNAL_ERROR; ++ free(fp); ++} ++ ++void ++audit_unsupported(struct ssh *ssh, int what) ++{ ++ PRIVSEP(audit_unsupported_body(ssh, what)); ++} ++ ++void ++audit_kex(struct ssh *ssh, int ctos, char *enc, char *mac, char *comp, char *pfs) ++{ ++ PRIVSEP(audit_kex_body(ssh, ctos, enc, mac, comp, pfs, getpid(), getuid())); ++} ++ ++void ++audit_session_key_free(struct ssh *ssh, int ctos) ++{ ++ PRIVSEP(audit_session_key_free_body(ssh, ctos, getpid(), getuid())); ++} ++ + # ifndef CUSTOM_SSH_AUDIT_EVENTS + /* + * Null implementations of audit functions. +@@ -138,6 +171,17 @@ audit_event(struct ssh *ssh, ssh_audit_e + } + + /* ++ * Called when a child process has called, or will soon call, ++ * audit_session_open. ++ */ ++void ++audit_count_session_open(void) ++{ ++ debug("audit count session open euid %d user %s", geteuid(), ++ audit_username()); ++} ++ ++/* + * Called when a user session is started. Argument is the tty allocated to + * the session, or NULL if no tty was allocated. + * +@@ -172,13 +216,82 @@ audit_session_close(struct logininfo *li + /* + * This will be called when a user runs a non-interactive command. Note that + * it may be called multiple times for a single connection since SSH2 allows +- * multiple sessions within a single connection. ++ * multiple sessions within a single connection. Returns a "handle" for ++ * audit_end_command. + */ +-void +-audit_run_command(const char *command) ++int ++audit_run_command(struct ssh *ssh, const char *command) + { + debug("audit run command euid %d user %s command '%.200s'", geteuid(), + audit_username(), command); ++ return 0; ++} ++ ++/* ++ * This will be called when the non-interactive command finishes. Note that ++ * it may be called multiple times for a single connection since SSH2 allows ++ * multiple sessions within a single connection. "handle" should come from ++ * the corresponding audit_run_command. ++ */ ++void ++audit_end_command(struct ssh *ssh, int handle, const char *command) ++{ ++ debug("audit end nopty exec euid %d user %s command '%.200s'", geteuid(), ++ audit_username(), command); ++} ++ ++/* ++ * This will be called when user is successfully autherized by the RSA1/RSA/DSA key. ++ * ++ * Type is the key type, len is the key length(byte) and fp is the fingerprint of the key. ++ */ ++int ++audit_keyusage(struct ssh *ssh, int host_user, char *fp, int rv) ++{ ++ debug("audit %s key usage euid %d user %s fingerprint %s, result %d", ++ host_user ? "pubkey" : "hostbased", geteuid(), audit_username(), ++ fp, rv); ++} ++ ++/* ++ * This will be called when the protocol negotiation fails. ++ */ ++void ++audit_unsupported_body(struct ssh *ssh, int what) ++{ ++ debug("audit unsupported protocol euid %d type %d", geteuid(), what); ++} ++ ++/* ++ * This will be called on succesfull protocol negotiation. ++ */ ++void ++audit_kex_body(struct ssh *ssh, int ctos, char *enc, char *mac, char *compress, char *pfs, pid_t pid, ++ uid_t uid) ++{ ++ debug("audit protocol negotiation euid %d direction %d cipher %s mac %s compresion %s pfs %s from pid %ld uid %u", ++ (unsigned)geteuid(), ctos, enc, mac, compress, pfs, (long)pid, ++ (unsigned)uid); ++} ++ ++/* ++ * This will be called on succesfull session key discard ++ */ ++void ++audit_session_key_free_body(struct ssh *, int ctos, pid_t pid, uid_t uid) ++{ ++ debug("audit session key discard euid %u direction %d from pid %ld uid %u", ++ (unsigned)geteuid(), ctos, (long)pid, (unsigned)uid); ++} ++ ++/* ++ * This will be called on destroy private part of the server key ++ */ ++void ++audit_destroy_sensitive_data(struct ssh *ssh, const char *fp, pid_t pid, uid_t uid) ++{ ++ debug("audit destroy sensitive data euid %d fingerprint %s from pid %ld uid %u", ++ geteuid(), fp, (long)pid, (unsigned)uid); + } + # endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */ + #endif /* SSH_AUDIT_EVENTS */ +Index: openssh-8.9p1/audit.h +=================================================================== +--- openssh-8.9p1.orig/audit.h ++++ openssh-8.9p1/audit.h +@@ -26,6 +26,7 @@ + # define _SSH_AUDIT_H + + #include "loginrec.h" ++#include "sshkey.h" + + struct ssh; + +@@ -45,13 +46,32 @@ enum ssh_audit_event_type { + SSH_CONNECTION_ABANDON, /* closed without completing auth */ + SSH_AUDIT_UNKNOWN + }; ++ ++enum ssh_audit_kex { ++ SSH_AUDIT_UNSUPPORTED_CIPHER, ++ SSH_AUDIT_UNSUPPORTED_MAC, ++ SSH_AUDIT_UNSUPPORTED_COMPRESSION ++}; + typedef enum ssh_audit_event_type ssh_audit_event_t; + ++int listening_for_clients(void); ++ + void audit_connection_from(const char *, int); + void audit_event(struct ssh *, ssh_audit_event_t); ++void audit_count_session_open(void); + void audit_session_open(struct logininfo *); + void audit_session_close(struct logininfo *); +-void audit_run_command(const char *); ++int audit_run_command(struct ssh *, const char *); ++void audit_end_command(struct ssh *, int, const char *); + ssh_audit_event_t audit_classify_auth(const char *); ++int audit_keyusage(struct ssh *, int, char *, int); ++void audit_key(struct ssh *, int, int *, const struct sshkey *); ++void audit_unsupported(struct ssh *, int); ++void audit_kex(struct ssh *, int, char *, char *, char *, char *); ++void audit_unsupported_body(struct ssh *, int); ++void audit_kex_body(struct ssh *, int, char *, char *, char *, char *, pid_t, uid_t); ++void audit_session_key_free(struct ssh *, int ctos); ++void audit_session_key_free_body(struct ssh *, int ctos, pid_t, uid_t); ++void audit_destroy_sensitive_data(struct ssh *, const char *, pid_t, uid_t); + + #endif /* _SSH_AUDIT_H */ +Index: openssh-8.9p1/auditstub.c +=================================================================== +--- /dev/null ++++ openssh-8.9p1/auditstub.c +@@ -0,0 +1,52 @@ ++/* $Id: auditstub.c,v 1.1 jfch Exp $ */ ++ ++/* ++ * Copyright 2010 Red Hat, Inc. All rights reserved. ++ * Use is subject to license terms. ++ * ++ * 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. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. ++ * ++ * Red Hat author: Jan F. Chadima ++ */ ++ ++#include ++ ++struct ssh; ++ ++void ++audit_unsupported(struct ssh *ssh, int n) ++{ ++} ++ ++void ++audit_kex(struct ssh *ssh, int ctos, char *enc, char *mac, char *comp, char *pfs) ++{ ++} ++ ++void ++audit_session_key_free(struct ssh *ssh, int ctos) ++{ ++} ++ ++void ++audit_session_key_free_body(struct ssh *ssh, int ctos, pid_t pid, uid_t uid) ++{ ++} +Index: openssh-8.9p1/auth.c +=================================================================== +--- openssh-8.9p1.orig/auth.c ++++ openssh-8.9p1/auth.c +@@ -599,9 +599,6 @@ getpwnamallow(struct ssh *ssh, const cha + record_failed_login(ssh, user, + auth_get_canonical_hostname(ssh, options.use_dns), "ssh"); + #endif +-#ifdef SSH_AUDIT_EVENTS +- audit_event(ssh, SSH_INVALID_USER); +-#endif /* SSH_AUDIT_EVENTS */ + return (NULL); + } + if (!allowed_user(ssh, pw)) +Index: openssh-8.9p1/auth.h +=================================================================== +--- openssh-8.9p1.orig/auth.h ++++ openssh-8.9p1/auth.h +@@ -190,6 +190,8 @@ struct passwd * getpwnamallow(struct ssh + + char *expand_authorized_keys(const char *, struct passwd *pw); + char *authorized_principals_file(struct passwd *); ++int user_key_verify(struct ssh *, const struct sshkey *, const u_char *, size_t, ++ const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **); + + int auth_key_is_revoked(struct sshkey *); + +@@ -209,6 +211,8 @@ struct sshkey *get_hostkey_private_by_ty + int get_hostkey_index(struct sshkey *, int, struct ssh *); + int sshd_hostkey_sign(struct ssh *, struct sshkey *, struct sshkey *, + u_char **, size_t *, const u_char *, size_t, const char *); ++int hostbased_key_verify(struct ssh *, const struct sshkey *, const u_char *, size_t, ++ const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **); + + /* Key / cert options linkage to auth layer */ + const struct sshauthopt *auth_options(struct ssh *); +Index: openssh-8.9p1/auth2-hostbased.c +=================================================================== +--- openssh-8.9p1.orig/auth2-hostbased.c ++++ openssh-8.9p1/auth2-hostbased.c +@@ -149,7 +149,7 @@ userauth_hostbased(struct ssh *ssh, cons + authenticated = 0; + if (PRIVSEP(hostbased_key_allowed(ssh, authctxt->pw, cuser, + chost, key)) && +- PRIVSEP(sshkey_verify(key, sig, slen, ++ PRIVSEP(hostbased_key_verify(ssh, key, sig, slen, + sshbuf_ptr(b), sshbuf_len(b), pkalg, ssh->compat, NULL)) == 0) + authenticated = 1; + +@@ -166,6 +166,19 @@ done: + return authenticated; + } + ++int ++hostbased_key_verify(struct ssh *ssh, const struct sshkey *key, const u_char *sig, ++ size_t slen, const u_char *data, size_t datalen, const char *pkalg, u_int compat, struct sshkey_sig_details **sigdet) ++{ ++ int rv; ++ ++ rv = sshkey_verify(key, sig, slen, data, datalen, pkalg, compat, sigdet); ++#ifdef SSH_AUDIT_EVENTS ++ audit_key(ssh, 0, &rv, key); ++#endif ++ return rv; ++} ++ + /* return 1 if given hostkey is allowed */ + int + hostbased_key_allowed(struct ssh *ssh, struct passwd *pw, +Index: openssh-8.9p1/auth2-pubkey.c +=================================================================== +--- openssh-8.9p1.orig/auth2-pubkey.c ++++ openssh-8.9p1/auth2-pubkey.c +@@ -223,7 +223,7 @@ userauth_pubkey(struct ssh *ssh, const c + /* test for correct signature */ + authenticated = 0; + if (PRIVSEP(user_key_allowed(ssh, pw, key, 1, &authopts)) && +- PRIVSEP(sshkey_verify(key, sig, slen, ++ PRIVSEP(user_key_verify(ssh, key, sig, slen, + sshbuf_ptr(b), sshbuf_len(b), + (ssh->compat & SSH_BUG_SIGTYPE) == 0 ? pkalg : NULL, + ssh->compat, &sig_details)) == 0) { +@@ -316,6 +316,19 @@ done: + return authenticated; + } + ++int ++user_key_verify(struct ssh *ssh, const struct sshkey *key, const u_char *sig, ++ size_t slen, const u_char *data, size_t datalen, const char *pkalg, u_int compat, struct sshkey_sig_details **sigdet) ++{ ++ int rv; ++ ++ rv = sshkey_verify(key, sig, slen, data, datalen, pkalg, compat, sigdet); ++#ifdef SSH_AUDIT_EVENTS ++ audit_key(ssh, 1, &rv, key); ++#endif ++ return rv; ++} ++ + static int + match_principals_file(struct passwd *pw, char *file, + struct sshkey_cert *cert, struct sshauthopt **authoptsp) +Index: openssh-8.9p1/auth2.c +=================================================================== +--- openssh-8.9p1.orig/auth2.c ++++ openssh-8.9p1/auth2.c +@@ -294,9 +294,6 @@ input_userauth_request(int type, u_int32 + authctxt->valid = 0; + /* Invalid user, fake password information */ + authctxt->pw = fakepw(); +-#ifdef SSH_AUDIT_EVENTS +- PRIVSEP(audit_event(ssh, SSH_INVALID_USER)); +-#endif + } + #ifdef USE_PAM + if (options.use_pam) +Index: openssh-8.9p1/cipher.c +=================================================================== +--- openssh-8.9p1.orig/cipher.c ++++ openssh-8.9p1/cipher.c +@@ -58,25 +58,6 @@ + #define EVP_CIPHER_CTX void + #endif + +-struct sshcipher { +- char *name; +- u_int block_size; +- u_int key_len; +- u_int iv_len; /* defaults to block_size */ +- u_int auth_len; +- u_int flags; +-#define CFLAG_CBC (1<<0) +-#define CFLAG_CHACHAPOLY (1<<1) +-#define CFLAG_AESCTR (1<<2) +-#define CFLAG_NONE (1<<3) +-#define CFLAG_INTERNAL CFLAG_NONE /* Don't use "none" for packets */ +-#ifdef WITH_OPENSSL +- const EVP_CIPHER *(*evptype)(void); +-#else +- void *ignored; +-#endif +-}; +- + static const struct sshcipher ciphers_all[] = { + #ifdef WITH_OPENSSL + #ifndef OPENSSL_NO_DES +@@ -460,7 +441,7 @@ cipher_get_length(struct sshcipher_ctx * + void + cipher_free(struct sshcipher_ctx *cc) + { +- if (cc == NULL) ++ if (cc == NULL || cc->cipher == NULL) + return; + if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { + chachapoly_free(cc->cp_ctx); +Index: openssh-8.9p1/cipher.h +=================================================================== +--- openssh-8.9p1.orig/cipher.h ++++ openssh-8.9p1/cipher.h +@@ -47,7 +47,25 @@ + #define CIPHER_ENCRYPT 1 + #define CIPHER_DECRYPT 0 + +-struct sshcipher; ++struct sshcipher { ++ char *name; ++ u_int block_size; ++ u_int key_len; ++ u_int iv_len; /* defaults to block_size */ ++ u_int auth_len; ++ u_int flags; ++#define CFLAG_CBC (1<<0) ++#define CFLAG_CHACHAPOLY (1<<1) ++#define CFLAG_AESCTR (1<<2) ++#define CFLAG_NONE (1<<3) ++#define CFLAG_INTERNAL CFLAG_NONE /* Don't use "none" for packets */ ++#ifdef WITH_OPENSSL ++ const EVP_CIPHER *(*evptype)(void); ++#else ++ void *ignored; ++#endif ++}; ++ + struct sshcipher_ctx { + int plaintext; + int encrypt; +Index: openssh-8.9p1/kex.c +=================================================================== +--- openssh-8.9p1.orig/kex.c ++++ openssh-8.9p1/kex.c +@@ -62,6 +62,7 @@ + #include "sshbuf.h" + #include "digest.h" + #include "xmalloc.h" ++#include "audit.h" + + #ifdef GSSAPI + #include "ssh-gss.h" +@@ -879,12 +880,16 @@ kex_start_rekex(struct ssh *ssh) + } + + static int +-choose_enc(struct sshenc *enc, char *client, char *server) ++choose_enc(struct ssh *ssh, struct sshenc *enc, char *client, char *server) + { + char *name = match_list(client, server, NULL); + +- if (name == NULL) ++ if (name == NULL) { ++#ifdef SSH_AUDIT_EVENTS ++ audit_unsupported(ssh, SSH_AUDIT_UNSUPPORTED_CIPHER); ++#endif + return SSH_ERR_NO_CIPHER_ALG_MATCH; ++ } + if ((enc->cipher = cipher_by_name(name)) == NULL) { + error_f("unsupported cipher %s", name); + free(name); +@@ -905,8 +910,12 @@ choose_mac(struct ssh *ssh, struct sshma + { + char *name = match_list(client, server, NULL); + +- if (name == NULL) ++ if (name == NULL) { ++#ifdef SSH_AUDIT_EVENTS ++ audit_unsupported(ssh, SSH_AUDIT_UNSUPPORTED_MAC); ++#endif + return SSH_ERR_NO_MAC_ALG_MATCH; ++ } + if (mac_setup(mac, name) < 0) { + error_f("unsupported MAC %s", name); + free(name); +@@ -919,12 +928,16 @@ choose_mac(struct ssh *ssh, struct sshma + } + + static int +-choose_comp(struct sshcomp *comp, char *client, char *server) ++choose_comp(struct ssh *ssh, struct sshcomp *comp, char *client, char *server) + { + char *name = match_list(client, server, NULL); + +- if (name == NULL) ++ if (name == NULL) { ++#ifdef SSH_AUDIT_EVENTS ++ audit_unsupported(ssh, SSH_AUDIT_UNSUPPORTED_COMPRESSION); ++#endif + return SSH_ERR_NO_COMPRESS_ALG_MATCH; ++ } + #ifdef WITH_ZLIB + if (strcmp(name, "zlib@openssh.com") == 0) { + comp->type = COMP_DELAYED; +@@ -1087,7 +1100,7 @@ kex_choose_conf(struct ssh *ssh) + nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC; + nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC; + ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC; +- if ((r = choose_enc(&newkeys->enc, cprop[nenc], ++ if ((r = choose_enc(ssh, &newkeys->enc, cprop[nenc], + sprop[nenc])) != 0) { + kex->failed_choice = peer[nenc]; + peer[nenc] = NULL; +@@ -1102,7 +1115,7 @@ kex_choose_conf(struct ssh *ssh) + peer[nmac] = NULL; + goto out; + } +- if ((r = choose_comp(&newkeys->comp, cprop[ncomp], ++ if ((r = choose_comp(ssh, &newkeys->comp, cprop[ncomp], + sprop[ncomp])) != 0) { + kex->failed_choice = peer[ncomp]; + peer[ncomp] = NULL; +@@ -1125,6 +1138,10 @@ kex_choose_conf(struct ssh *ssh) + dh_need = MAXIMUM(dh_need, newkeys->enc.block_size); + dh_need = MAXIMUM(dh_need, newkeys->enc.iv_len); + dh_need = MAXIMUM(dh_need, newkeys->mac.key_len); ++ debug("kex: %s need=%d dh_need=%d", kex->name, need, dh_need); ++#ifdef SSH_AUDIT_EVENTS ++ audit_kex(ssh, mode, newkeys->enc.name, newkeys->mac.name, newkeys->comp.name, kex->name); ++#endif + } + /* XXX need runden? */ + kex->we_need = need; +@@ -1292,6 +1309,36 @@ dump_digest(const char *msg, const u_cha + } + #endif + ++static void ++enc_destroy(struct sshenc *enc) ++{ ++ if (enc == NULL) ++ return; ++ ++ if (enc->key) { ++ memset(enc->key, 0, enc->key_len); ++ free(enc->key); ++ } ++ ++ if (enc->iv) { ++ memset(enc->iv, 0, enc->iv_len); ++ free(enc->iv); ++ } ++ ++ memset(enc, 0, sizeof(*enc)); ++} ++ ++void ++newkeys_destroy(struct newkeys *newkeys) ++{ ++ if (newkeys == NULL) ++ return; ++ ++ enc_destroy(&newkeys->enc); ++ mac_destroy(&newkeys->mac); ++ memset(&newkeys->comp, 0, sizeof(newkeys->comp)); ++} ++ + /* + * Send a plaintext error message to the peer, suffixed by \r\n. + * Only used during banner exchange, and there only for the server. +Index: openssh-8.9p1/kex.h +=================================================================== +--- openssh-8.9p1.orig/kex.h ++++ openssh-8.9p1/kex.h +@@ -233,6 +233,8 @@ int kexgss_client(struct ssh *); + int kexgss_server(struct ssh *); + #endif + ++void newkeys_destroy(struct newkeys *newkeys); ++ + int kex_dh_keypair(struct kex *); + int kex_dh_enc(struct kex *, const struct sshbuf *, struct sshbuf **, + struct sshbuf **); +Index: openssh-8.9p1/mac.c +=================================================================== +--- openssh-8.9p1.orig/mac.c ++++ openssh-8.9p1/mac.c +@@ -277,6 +277,20 @@ mac_clear(struct sshmac *mac) + mac->umac_ctx = NULL; + } + ++void ++mac_destroy(struct sshmac *mac) ++{ ++ if (mac == NULL) ++ return; ++ ++ if (mac->key) { ++ memset(mac->key, 0, mac->key_len); ++ free(mac->key); ++ } ++ ++ memset(mac, 0, sizeof(*mac)); ++} ++ + /* XXX copied from ciphers_valid */ + #define MAC_SEP "," + int +Index: openssh-8.9p1/mac.h +=================================================================== +--- openssh-8.9p1.orig/mac.h ++++ openssh-8.9p1/mac.h +@@ -49,5 +49,6 @@ int mac_compute(struct sshmac *, u_int3 + int mac_check(struct sshmac *, u_int32_t, const u_char *, size_t, + const u_char *, size_t); + void mac_clear(struct sshmac *); ++void mac_destroy(struct sshmac *); + + #endif /* SSHMAC_H */ +Index: openssh-8.9p1/monitor.c +=================================================================== +--- openssh-8.9p1.orig/monitor.c ++++ openssh-8.9p1/monitor.c +@@ -93,6 +93,7 @@ + #include "compat.h" + #include "ssh2.h" + #include "authfd.h" ++#include "audit.h" + #include "match.h" + #include "ssherr.h" + #include "sk-api.h" +@@ -107,6 +108,8 @@ extern u_int utmp_len; + extern struct sshbuf *loginmsg; + extern struct sshauthopt *auth_opts; /* XXX move to permanent ssh->authctxt? */ + ++extern void destroy_sensitive_data(struct ssh *, int); ++ + /* State exported from the child */ + static struct sshbuf *child_state; + +@@ -152,6 +155,11 @@ int mm_answer_gss_updatecreds(struct ssh + #ifdef SSH_AUDIT_EVENTS + int mm_answer_audit_event(struct ssh *, int, struct sshbuf *); + int mm_answer_audit_command(struct ssh *, int, struct sshbuf *); ++int mm_answer_audit_end_command(struct ssh *, int, struct sshbuf *); ++int mm_answer_audit_unsupported_body(struct ssh *, int, struct sshbuf *); ++int mm_answer_audit_kex_body(struct ssh *, int, struct sshbuf *); ++int mm_answer_audit_session_key_free_body(struct ssh *, int, struct sshbuf *); ++int mm_answer_audit_server_key_free(struct ssh *, int, struct sshbuf *); + #endif + + static Authctxt *authctxt; +@@ -207,6 +215,10 @@ struct mon_table mon_dispatch_proto20[] + #endif + #ifdef SSH_AUDIT_EVENTS + {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, ++ {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, ++ {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, ++ {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body}, ++ {MONITOR_REQ_AUDIT_SERVER_KEY_FREE, MON_PERMIT, mm_answer_audit_server_key_free}, + #endif + #ifdef BSD_AUTH + {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, +@@ -241,6 +253,11 @@ struct mon_table mon_dispatch_postauth20 + #ifdef SSH_AUDIT_EVENTS + {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, + {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command}, ++ {MONITOR_REQ_AUDIT_END_COMMAND, MON_PERMIT, mm_answer_audit_end_command}, ++ {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, ++ {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, ++ {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body}, ++ {MONITOR_REQ_AUDIT_SERVER_KEY_FREE, MON_PERMIT, mm_answer_audit_server_key_free}, + #endif + {0, 0, NULL} + }; +@@ -1419,8 +1436,10 @@ mm_answer_keyverify(struct ssh *ssh, int + int r, ret, req_presence = 0, req_verify = 0, valid_data = 0; + int encoded_ret; + struct sshkey_sig_details *sig_details = NULL; ++ int type = 0; + +- if ((r = sshbuf_get_string_direct(m, &blob, &bloblen)) != 0 || ++ if ((r = sshbuf_get_u32(m, &type)) != 0 || ++ (r = sshbuf_get_string_direct(m, &blob, &bloblen)) != 0 || + (r = sshbuf_get_string_direct(m, &signature, &signaturelen)) != 0 || + (r = sshbuf_get_string_direct(m, &data, &datalen)) != 0 || + (r = sshbuf_get_cstring(m, &sigalg, NULL)) != 0) +@@ -1429,6 +1448,8 @@ mm_answer_keyverify(struct ssh *ssh, int + if (hostbased_cuser == NULL || hostbased_chost == NULL || + !monitor_allowed_key(blob, bloblen)) + fatal_f("bad key, not previously allowed"); ++ if (type != key_blobtype) ++ fatal_f("bad key type"); + + /* Empty signature algorithm means NULL. */ + if (*sigalg == '\0') { +@@ -1444,14 +1465,19 @@ mm_answer_keyverify(struct ssh *ssh, int + case MM_USERKEY: + valid_data = monitor_valid_userblob(ssh, data, datalen); + auth_method = "publickey"; ++ ret = user_key_verify(ssh, key, signature, signaturelen, data, ++ datalen, sigalg, ssh->compat, &sig_details); + break; + case MM_HOSTKEY: + valid_data = monitor_valid_hostbasedblob(data, datalen, + hostbased_cuser, hostbased_chost); + auth_method = "hostbased"; ++ ret = hostbased_key_verify(ssh, key, signature, signaturelen, data, ++ datalen, sigalg, ssh->compat, &sig_details); + break; + default: + valid_data = 0; ++ ret = 0; + break; + } + if (!valid_data) +@@ -1463,8 +1489,6 @@ mm_answer_keyverify(struct ssh *ssh, int + SSH_FP_DEFAULT)) == NULL) + fatal_f("sshkey_fingerprint failed"); + +- ret = sshkey_verify(key, signature, signaturelen, data, datalen, +- sigalg, ssh->compat, &sig_details); + debug3_f("%s %s signature using %s %s%s%s", auth_method, + sshkey_type(key), sigalg == NULL ? "default" : sigalg, + (ret == 0) ? "verified" : "unverified", +@@ -1552,13 +1576,19 @@ mm_record_login(struct ssh *ssh, Session + } + + static void +-mm_session_close(Session *s) ++mm_session_close(struct ssh *ssh, Session *s) + { + debug3_f("session %d pid %ld", s->self, (long)s->pid); + if (s->ttyfd != -1) { + debug3_f("tty %s ptyfd %d", s->tty, s->ptyfd); + session_pty_cleanup2(s); + } ++#ifdef SSH_AUDIT_EVENTS ++ if (s->command != NULL) { ++ debug3_f("command %d", s->command_handle); ++ session_end_command2(ssh, s); ++ } ++#endif + session_unused(s->self); + } + +@@ -1625,7 +1655,7 @@ mm_answer_pty(struct ssh *ssh, int sock, + + error: + if (s != NULL) +- mm_session_close(s); ++ mm_session_close(ssh, s); + if ((r = sshbuf_put_u32(m, 0)) != 0) + fatal_fr(r, "assemble 0"); + mm_request_send(sock, MONITOR_ANS_PTY, m); +@@ -1644,7 +1674,7 @@ mm_answer_pty_cleanup(struct ssh *ssh, i + if ((r = sshbuf_get_cstring(m, &tty, NULL)) != 0) + fatal_fr(r, "parse tty"); + if ((s = session_by_tty(tty)) != NULL) +- mm_session_close(s); ++ mm_session_close(ssh, s); + sshbuf_reset(m); + free(tty); + return (0); +@@ -1666,6 +1696,8 @@ mm_answer_term(struct ssh *ssh, int sock + sshpam_cleanup(); + #endif + ++ destroy_sensitive_data(ssh, 0); ++ + while (waitpid(pmonitor->m_pid, &status, 0) == -1) + if (errno != EINTR) + exit(1); +@@ -1712,12 +1744,47 @@ mm_answer_audit_command(struct ssh *ssh, + { + char *cmd; + int r; ++ Session *s; + + debug3("%s entering", __func__); + if ((r = sshbuf_get_cstring(m, &cmd, NULL)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ + /* sanity check command, if so how? */ +- audit_run_command(cmd); ++ s = session_new(); ++ if (s == NULL) ++ fatal("%s: error allocating a session", __func__); ++ s->command = cmd; ++#ifdef SSH_AUDIT_EVENTS ++ s->command_handle = audit_run_command(ssh, cmd); ++#endif ++ ++ sshbuf_reset(m); ++ sshbuf_put_u32(m, s->self); ++ ++ mm_request_send(socket, MONITOR_ANS_AUDIT_COMMAND, m); ++ ++ return (0); ++} ++ ++int ++mm_answer_audit_end_command(struct ssh *ssh, int socket, struct sshbuf *m) ++{ ++ int handle, r; ++ size_t len; ++ u_char *cmd = NULL; ++ Session *s; ++ ++ debug3("%s entering", __func__); ++ if ((r = sshbuf_get_u32(m, &handle)) != 0 || ++ (r = sshbuf_get_string(m, &cmd, &len)) != 0) ++ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ ++ s = session_by_id(handle); ++ if (s == NULL || s->ttyfd != -1 || s->command == NULL || ++ strcmp(s->command, cmd) != 0) ++ fatal("%s: invalid handle", __func__); ++ mm_session_close(ssh, s); + free(cmd); + return (0); + } +@@ -1789,6 +1856,7 @@ monitor_apply_keystate(struct ssh *ssh, + void + mm_get_keystate(struct ssh *ssh, struct monitor *pmonitor) + { ++ struct sshbuf *m; + debug3_f("Waiting for new keys"); + + if ((child_state = sshbuf_new()) == NULL) +@@ -1796,6 +1864,18 @@ mm_get_keystate(struct ssh *ssh, struct + mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, + child_state); + debug3_f("GOT new keys"); ++ ++#ifdef SSH_AUDIT_EVENTS ++ m = sshbuf_new(); ++ mm_request_receive_expect(pmonitor->m_sendfd, ++ MONITOR_REQ_AUDIT_SESSION_KEY_FREE, m); ++ mm_answer_audit_session_key_free_body(ssh, pmonitor->m_sendfd, m); ++ sshbuf_free(m); ++#endif ++ ++ /* Drain any buffered messages from the child */ ++ while (pmonitor->m_log_recvfd >= 0 && monitor_read_log(pmonitor) == 0) ++ ; + } + + +@@ -2073,3 +2153,102 @@ mm_answer_gss_updatecreds(struct ssh *ss + + #endif /* GSSAPI */ + ++#ifdef SSH_AUDIT_EVENTS ++int ++mm_answer_audit_unsupported_body(struct ssh *ssh, int sock, struct sshbuf *m) ++{ ++ int what, r; ++ ++ if ((r = sshbuf_get_u32(m, &what)) != 0) ++ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ ++ audit_unsupported_body(ssh, what); ++ ++ sshbuf_reset(m); ++ ++ mm_request_send(sock, MONITOR_ANS_AUDIT_UNSUPPORTED, m); ++ return 0; ++} ++ ++int ++mm_answer_audit_kex_body(struct ssh *ssh, int sock, struct sshbuf *m) ++{ ++ int ctos, r; ++ char *cipher, *mac, *compress, *pfs; ++ u_int64_t tmp; ++ pid_t pid; ++ uid_t uid; ++ ++ if ((r = sshbuf_get_u32(m, &ctos)) != 0 || ++ (r = sshbuf_get_cstring(m, &cipher, NULL)) != 0 || ++ (r = sshbuf_get_cstring(m, &mac, NULL)) != 0 || ++ (r = sshbuf_get_cstring(m, &compress, NULL)) != 0 || ++ (r = sshbuf_get_cstring(m, &pfs, NULL)) != 0 || ++ (r = sshbuf_get_u64(m, &tmp)) != 0) ++ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ pid = (pid_t) tmp; ++ if ((r = sshbuf_get_u64(m, &tmp)) != 0) ++ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ uid = (pid_t) tmp; ++ ++ audit_kex_body(ssh, ctos, cipher, mac, compress, pfs, pid, uid); ++ ++ free(cipher); ++ free(mac); ++ free(compress); ++ free(pfs); ++ sshbuf_reset(m); ++ ++ mm_request_send(sock, MONITOR_ANS_AUDIT_KEX, m); ++ return 0; ++} ++ ++int ++mm_answer_audit_session_key_free_body(struct ssh *ssh, int sock, struct sshbuf *m) ++{ ++ int ctos, r; ++ u_int64_t tmp; ++ pid_t pid; ++ uid_t uid; ++ ++ if ((r = sshbuf_get_u32(m, &ctos)) != 0 || ++ (r = sshbuf_get_u64(m, &tmp)) != 0) ++ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ pid = (pid_t) tmp; ++ if ((r = sshbuf_get_u64(m, &tmp)) != 0) ++ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ uid = (uid_t) tmp; ++ ++ audit_session_key_free_body(ssh, ctos, pid, uid); ++ ++ sshbuf_reset(m); ++ ++ mm_request_send(sock, MONITOR_ANS_AUDIT_SESSION_KEY_FREE, m); ++ return 0; ++} ++ ++int ++mm_answer_audit_server_key_free(struct ssh *ssh, int sock, struct sshbuf *m) ++{ ++ size_t len, r; ++ char *fp; ++ u_int64_t tmp; ++ pid_t pid; ++ uid_t uid; ++ ++ if ((r = sshbuf_get_cstring(m, &fp, &len)) != 0 || ++ (r = sshbuf_get_u64(m, &tmp)) != 0) ++ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ pid = (pid_t) tmp; ++ if ((r = sshbuf_get_u64(m, &tmp)) != 0) ++ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ uid = (uid_t) tmp; ++ ++ audit_destroy_sensitive_data(ssh, fp, pid, uid); ++ ++ free(fp); ++ sshbuf_reset(m); ++ ++ return 0; ++} ++#endif /* SSH_AUDIT_EVENTS */ +Index: openssh-8.9p1/monitor.h +=================================================================== +--- openssh-8.9p1.orig/monitor.h ++++ openssh-8.9p1/monitor.h +@@ -61,7 +61,13 @@ enum monitor_reqtype { + MONITOR_REQ_PAM_QUERY = 106, MONITOR_ANS_PAM_QUERY = 107, + MONITOR_REQ_PAM_RESPOND = 108, MONITOR_ANS_PAM_RESPOND = 109, + MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111, +- MONITOR_REQ_AUDIT_EVENT = 112, MONITOR_REQ_AUDIT_COMMAND = 113, ++ MONITOR_REQ_AUDIT_EVENT = 112, ++ MONITOR_REQ_AUDIT_COMMAND = 114, MONITOR_ANS_AUDIT_COMMAND = 115, ++ MONITOR_REQ_AUDIT_END_COMMAND = 116, ++ MONITOR_REQ_AUDIT_UNSUPPORTED = 118, MONITOR_ANS_AUDIT_UNSUPPORTED = 119, ++ MONITOR_REQ_AUDIT_KEX = 120, MONITOR_ANS_AUDIT_KEX = 121, ++ MONITOR_REQ_AUDIT_SESSION_KEY_FREE = 122, MONITOR_ANS_AUDIT_SESSION_KEY_FREE = 123, ++ MONITOR_REQ_AUDIT_SERVER_KEY_FREE = 124, + + MONITOR_REQ_GSSSIGN = 150, MONITOR_ANS_GSSSIGN = 151, + MONITOR_REQ_GSSUPCREDS = 152, MONITOR_ANS_GSSUPCREDS = 153, +Index: openssh-8.9p1/monitor_wrap.c +=================================================================== +--- openssh-8.9p1.orig/monitor_wrap.c ++++ openssh-8.9p1/monitor_wrap.c +@@ -499,7 +499,7 @@ mm_key_allowed(enum mm_keytype type, con + */ + + int +-mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen, ++mm_sshkey_verify(enum mm_keytype type, const struct sshkey *key, const u_char *sig, size_t siglen, + const u_char *data, size_t datalen, const char *sigalg, u_int compat, + struct sshkey_sig_details **sig_detailsp) + { +@@ -515,7 +515,8 @@ mm_sshkey_verify(const struct sshkey *ke + *sig_detailsp = NULL; + if ((m = sshbuf_new()) == NULL) + fatal_f("sshbuf_new failed"); +- if ((r = sshkey_puts(key, m)) != 0 || ++ if ((r = sshbuf_put_u32(m, type)) != 0 || ++ (r = sshkey_puts(key, m)) != 0 || + (r = sshbuf_put_string(m, sig, siglen)) != 0 || + (r = sshbuf_put_string(m, data, datalen)) != 0 || + (r = sshbuf_put_cstring(m, sigalg == NULL ? "" : sigalg)) != 0) +@@ -548,6 +549,20 @@ mm_sshkey_verify(const struct sshkey *ke + return 0; + } + ++int ++mm_hostbased_key_verify(struct ssh *ssh, const struct sshkey *key, const u_char *sig, size_t siglen, ++ const u_char *data, size_t datalen, const char *pkalg, u_int compat, struct sshkey_sig_details **sigdet) ++{ ++ return mm_sshkey_verify(MM_HOSTKEY, key, sig, siglen, data, datalen, pkalg, compat, sigdet); ++} ++ ++int ++mm_user_key_verify(struct ssh *ssh, const struct sshkey *key, const u_char *sig, size_t siglen, ++ const u_char *data, size_t datalen, const char *pkalg, u_int compat, struct sshkey_sig_details **sigdet) ++{ ++ return mm_sshkey_verify(MM_USERKEY, key, sig, siglen, data, datalen, pkalg, compat, sigdet); ++} ++ + void + mm_send_keystate(struct ssh *ssh, struct monitor *monitor) + { +@@ -900,11 +915,12 @@ mm_audit_event(struct ssh *ssh, ssh_audi + sshbuf_free(m); + } + +-void +-mm_audit_run_command(const char *command) ++int ++mm_audit_run_command(struct ssh *ssh, const char *command) + { + struct sshbuf *m; + int r; ++ int handle; + + debug3("%s entering command %s", __func__, command); + +@@ -914,6 +930,30 @@ mm_audit_run_command(const char *command + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, m); ++ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_COMMAND, m); ++ ++ if ((r = sshbuf_get_u32(m, &handle)) != 0) ++ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ sshbuf_free(m); ++ ++ return (handle); ++} ++ ++void ++mm_audit_end_command(struct ssh *ssh, int handle, const char *command) ++{ ++ int r; ++ struct sshbuf *m; ++ ++ debug3("%s entering command %s", __func__, command); ++ ++ if ((m = sshbuf_new()) == NULL) ++ fatal("%s: sshbuf_new failed", __func__); ++ if ((r = sshbuf_put_u32(m, handle)) != 0 || ++ (r = sshbuf_put_cstring(m, command)) != 0) ++ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ ++ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_END_COMMAND, m); + sshbuf_free(m); + } + #endif /* SSH_AUDIT_EVENTS */ +@@ -1074,3 +1114,130 @@ mm_ssh_gssapi_update_creds(ssh_gssapi_cc + } + + #endif /* GSSAPI */ ++#ifdef SSH_AUDIT_EVENTS ++void ++mm_audit_unsupported_body(struct ssh *ssh, int what) ++{ ++ int r; ++ struct sshbuf *m; ++ ++ if ((m = sshbuf_new()) == NULL) ++ fatal("%s: sshbuf_new failed", __func__); ++ if ((r = sshbuf_put_u32(m, what)) != 0) ++ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ ++ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_UNSUPPORTED, m); ++ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_UNSUPPORTED, ++ m); ++ ++ sshbuf_free(m); ++} ++ ++void ++mm_audit_kex_body(struct ssh *ssh, int ctos, char *cipher, char *mac, char *compress, char *fps, pid_t pid, ++ uid_t uid) ++{ ++ int r; ++ struct sshbuf *m; ++ ++ if ((m = sshbuf_new()) == NULL) ++ fatal("%s: sshbuf_new failed", __func__); ++ if ((r = sshbuf_put_u32(m, ctos)) != 0 || ++ (r = sshbuf_put_cstring(m, cipher)) != 0 || ++ (r = sshbuf_put_cstring(m, (mac ? mac : ""))) != 0 || ++ (r = sshbuf_put_cstring(m, compress)) != 0 || ++ (r = sshbuf_put_cstring(m, fps)) != 0 || ++ (r = sshbuf_put_u64(m, pid)) != 0 || ++ (r = sshbuf_put_u64(m, uid)) != 0) ++ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ ++ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_KEX, m); ++ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_KEX, ++ m); ++ ++ sshbuf_free(m); ++} ++ ++void ++mm_audit_session_key_free_body(struct ssh *ssh, int ctos, pid_t pid, uid_t uid) ++{ ++ int r; ++ struct sshbuf *m; ++ ++ if ((m = sshbuf_new()) == NULL) ++ fatal("%s: sshbuf_new failed", __func__); ++ if ((r = sshbuf_put_u32(m, ctos)) != 0 || ++ (r = sshbuf_put_u64(m, pid)) != 0 || ++ (r = sshbuf_put_u64(m, uid)) != 0) ++ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ ++ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_SESSION_KEY_FREE, m); ++ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_SESSION_KEY_FREE, ++ m); ++ sshbuf_free(m); ++} ++ ++void ++mm_audit_destroy_sensitive_data(struct ssh *ssh, const char *fp, pid_t pid, uid_t uid) ++{ ++ int r; ++ struct sshbuf *m; ++ ++ if ((m = sshbuf_new()) == NULL) ++ fatal("%s: sshbuf_new failed", __func__); ++ if ((r = sshbuf_put_cstring(m, fp)) != 0 || ++ (r = sshbuf_put_u64(m, pid)) != 0 || ++ (r = sshbuf_put_u64(m, uid)) != 0) ++ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ ++ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_SERVER_KEY_FREE, m); ++ sshbuf_free(m); ++} ++ ++int mm_forward_audit_messages(int fdin) ++{ ++ u_char buf[4]; ++ u_int blen, msg_len; ++ struct sshbuf *m; ++ int ret = 0; ++ ++ debug3("%s: entering", __func__); ++ m = sshbuf_new(); ++ do { ++ int r; ++ ++ blen = atomicio(read, fdin, buf, sizeof(buf)); ++ if (blen == 0) /* closed pipe */ ++ break; ++ if (blen != sizeof(buf)) { ++ error("%s: Failed to read the buffer from child", __func__); ++ ret = -1; ++ break; ++ } ++ ++ msg_len = get_u32(buf); ++ if (msg_len > 256 * 1024) ++ fatal("%s: read: bad msg_len %d", __func__, msg_len); ++ sshbuf_reset(m); ++ if ((r = sshbuf_reserve(m, msg_len, NULL)) != 0) ++ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ if (atomicio(read, fdin, sshbuf_mutable_ptr(m), msg_len) != msg_len) { ++ error("%s: Failed to read the the buffer conent from the child", __func__); ++ ret = -1; ++ break; ++ } ++ if (atomicio(vwrite, pmonitor->m_recvfd, buf, blen) != blen || ++ atomicio(vwrite, pmonitor->m_recvfd, sshbuf_mutable_ptr(m), msg_len) != msg_len) { ++ error("%s: Failed to write the messag to the monitor", __func__); ++ ret = -1; ++ break; ++ } ++ } while (1); ++ sshbuf_free(m); ++ return ret; ++} ++void mm_set_monitor_pipe(int fd) ++{ ++ pmonitor->m_recvfd = fd; ++} ++#endif /* SSH_AUDIT_EVENTS */ +Index: openssh-8.9p1/monitor_wrap.h +=================================================================== +--- openssh-8.9p1.orig/monitor_wrap.h ++++ openssh-8.9p1/monitor_wrap.h +@@ -58,7 +58,9 @@ int mm_user_key_allowed(struct ssh *, st + struct sshauthopt **); + int mm_hostbased_key_allowed(struct ssh *, struct passwd *, const char *, + const char *, struct sshkey *); +-int mm_sshkey_verify(const struct sshkey *, const u_char *, size_t, ++int mm_hostbased_key_verify(struct ssh *, const struct sshkey *, const u_char *, size_t, ++ const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **); ++int mm_user_key_verify(struct ssh *, const struct sshkey *, const u_char *, size_t, + const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **); + + #ifdef GSSAPI +@@ -83,7 +85,14 @@ void mm_sshpam_free_ctx(void *); + #ifdef SSH_AUDIT_EVENTS + #include "audit.h" + void mm_audit_event(struct ssh *, ssh_audit_event_t); +-void mm_audit_run_command(const char *); ++int mm_audit_run_command(struct ssh *ssh, const char *); ++void mm_audit_end_command(struct ssh *ssh, int, const char *); ++void mm_audit_unsupported_body(struct ssh *, int); ++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 + + struct Session; +Index: openssh-8.9p1/packet.c +=================================================================== +--- openssh-8.9p1.orig/packet.c ++++ openssh-8.9p1/packet.c +@@ -81,6 +81,7 @@ + #endif + + #include "xmalloc.h" ++#include "audit.h" + #include "compat.h" + #include "ssh2.h" + #include "cipher.h" +@@ -506,6 +507,13 @@ ssh_packet_get_connection_out(struct ssh + return ssh->state->connection_out; + } + ++static int ++packet_state_has_keys (const struct session_state *state) ++{ ++ return state != NULL && ++ (state->newkeys[MODE_IN] != NULL || state->newkeys[MODE_OUT] != NULL); ++} ++ + /* + * Returns the IP-address of the remote host as a string. The returned + * string must not be freed. +@@ -579,26 +587,23 @@ ssh_packet_rdomain_in(struct ssh *ssh) + /* Closes the connection and clears and frees internal data structures. */ + + static void +-ssh_packet_close_internal(struct ssh *ssh, int do_close) ++ssh_packet_close_internal(struct ssh *ssh, int do_close, int do_audit) + { + struct session_state *state = ssh->state; + u_int mode; ++ u_int had_keys = packet_state_has_keys(state); + + if (!state->initialized) + return; + state->initialized = 0; +- if (do_close) { +- if (state->connection_in == state->connection_out) { +- close(state->connection_out); +- } else { +- close(state->connection_in); +- close(state->connection_out); +- } +- } + sshbuf_free(state->input); ++ state->input = NULL; + sshbuf_free(state->output); ++ state->output = NULL; + sshbuf_free(state->outgoing_packet); ++ state->outgoing_packet = NULL; + sshbuf_free(state->incoming_packet); ++ state->incoming_packet = NULL; + for (mode = 0; mode < MODE_MAX; mode++) { + kex_free_newkeys(state->newkeys[mode]); /* current keys */ + state->newkeys[mode] = NULL; +@@ -634,8 +639,18 @@ ssh_packet_close_internal(struct ssh *ss + #endif /* WITH_ZLIB */ + cipher_free(state->send_context); + cipher_free(state->receive_context); ++ if (do_audit && had_keys && state->server_side) { ++ /* Assuming this is called only from privsep child */ ++ audit_session_key_free(ssh, MODE_MAX); ++ } + state->send_context = state->receive_context = NULL; + if (do_close) { ++ if (state->connection_in == state->connection_out) { ++ close(state->connection_out); ++ } else { ++ close(state->connection_in); ++ close(state->connection_out); ++ } + free(ssh->local_ipaddr); + ssh->local_ipaddr = NULL; + free(ssh->remote_ipaddr); +@@ -650,13 +665,19 @@ ssh_packet_close_internal(struct ssh *ss + void + ssh_packet_close(struct ssh *ssh) + { +- ssh_packet_close_internal(ssh, 1); ++ ssh_packet_close_internal(ssh, 1, 1); + } + + void + ssh_packet_clear_keys(struct ssh *ssh) + { +- ssh_packet_close_internal(ssh, 0); ++ ssh_packet_close_internal(ssh, 0, 1); ++} ++ ++void ++ssh_packet_clear_keys_noaudit(struct ssh *ssh) ++{ ++ ssh_packet_close_internal(ssh, 0, 0); + } + + /* Sets remote side protocol flags. */ +@@ -892,6 +913,7 @@ ssh_set_newkeys(struct ssh *ssh, int mod + (unsigned long long)state->p_send.bytes, + (unsigned long long)state->p_send.blocks); + kex_free_newkeys(state->newkeys[mode]); ++ audit_session_key_free(ssh, mode); + state->newkeys[mode] = NULL; + } + /* note that both bytes and the seqnr are not reset */ +@@ -2183,6 +2205,73 @@ ssh_packet_get_output(struct ssh *ssh) + return (void *)ssh->state->output; + } + ++static void ++newkeys_destroy_and_free(struct newkeys *newkeys) ++{ ++ if (newkeys == NULL) ++ return; ++ ++ free(newkeys->enc.name); ++ ++ if (newkeys->mac.enabled) { ++ mac_clear(&newkeys->mac); ++ free(newkeys->mac.name); ++ } ++ ++ free(newkeys->comp.name); ++ ++ newkeys_destroy(newkeys); ++ free(newkeys); ++} ++ ++static void ++packet_destroy_state(struct session_state *state) ++{ ++ if (state == NULL) ++ return; ++ ++ cipher_free(state->receive_context); ++ state->receive_context = NULL; ++ cipher_free(state->send_context); ++ state->send_context = NULL; ++ ++ sshbuf_free(state->input); ++ state->input = NULL; ++ sshbuf_free(state->output); ++ state->output = NULL; ++ sshbuf_free(state->outgoing_packet); ++ state->outgoing_packet = NULL; ++ sshbuf_free(state->incoming_packet); ++ state->incoming_packet = NULL; ++ if (state->compression_buffer) { ++ sshbuf_free(state->compression_buffer); ++ state->compression_buffer = NULL; ++ } ++ newkeys_destroy_and_free(state->newkeys[MODE_IN]); ++ state->newkeys[MODE_IN] = NULL; ++ newkeys_destroy_and_free(state->newkeys[MODE_OUT]); ++ state->newkeys[MODE_OUT] = NULL; ++ mac_destroy(state->packet_discard_mac); ++// TAILQ_HEAD(, packet) outgoing; ++// memset(state, 0, sizeof(state)); ++} ++ ++void ++packet_destroy_all(struct ssh *ssh, int audit_it, int privsep) ++{ ++ if (audit_it) ++ audit_it = packet_state_has_keys(ssh->state); ++ packet_destroy_state(ssh->state); ++ if (audit_it) { ++#ifdef SSH_AUDIT_EVENTS ++ if (privsep) ++ audit_session_key_free(ssh, MODE_MAX); ++ else ++ audit_session_key_free_body(ssh, MODE_MAX, getpid(), getuid()); ++#endif ++ } ++} ++ + /* Reset after_authentication and reset compression in post-auth privsep */ + static int + ssh_packet_set_postauth(struct ssh *ssh) +Index: openssh-8.9p1/packet.h +=================================================================== +--- openssh-8.9p1.orig/packet.h ++++ openssh-8.9p1/packet.h +@@ -102,6 +102,7 @@ int ssh_packet_get_connection_out(s + void ssh_packet_close(struct ssh *); + void ssh_packet_set_input_hook(struct ssh *, ssh_packet_hook_fn *, void *); + void ssh_packet_clear_keys(struct ssh *); ++void ssh_packet_clear_keys_noaudit(struct ssh *); + void ssh_clear_newkeys(struct ssh *, int); + + int ssh_packet_is_rekeying(struct ssh *); +@@ -220,4 +221,5 @@ const u_char *sshpkt_ptr(struct ssh *, s + # undef EC_POINT + #endif + ++void packet_destroy_all(struct ssh *, int, int); + #endif /* PACKET_H */ +Index: openssh-8.9p1/session.c +=================================================================== +--- openssh-8.9p1.orig/session.c ++++ openssh-8.9p1/session.c +@@ -135,7 +135,7 @@ extern char *__progname; + extern int debug_flag; + extern u_int utmp_len; + extern int startup_pipe; +-extern void destroy_sensitive_data(void); ++extern void destroy_sensitive_data(struct ssh *, int); + extern struct sshbuf *loginmsg; + extern struct sshauthopt *auth_opts; + extern char *tun_fwd_ifnames; /* serverloop.c */ +@@ -157,6 +157,10 @@ static Session *sessions = NULL; + login_cap_t *lc; + #endif + ++#ifdef SSH_AUDIT_EVENTS ++int paudit[2]; ++#endif ++ + static int is_child = 0; + static int in_chroot = 0; + +@@ -642,6 +646,14 @@ do_exec_pty(struct ssh *ssh, Session *s, + /* Parent. Close the slave side of the pseudo tty. */ + close(ttyfd); + ++#if !defined(HAVE_OSF_SIA) && defined(SSH_AUDIT_EVENTS) ++ /* do_login in the child did not affect state in this process, ++ compensate. From an architectural standpoint, this is extremely ++ ugly. */ ++ if (command != NULL) ++ audit_count_session_open(); ++#endif ++ + /* Enter interactive session. */ + s->ptymaster = ptymaster; + ssh_packet_set_interactive(ssh, 1, +@@ -706,15 +718,21 @@ do_exec(struct ssh *ssh, Session *s, con + s->self); + + #ifdef SSH_AUDIT_EVENTS ++ if (s->command != NULL || s->command_handle != -1) ++ fatal("do_exec: command already set"); + if (command != NULL) +- PRIVSEP(audit_run_command(command)); ++ s->command = xstrdup(command); + else if (s->ttyfd == -1) { + char *shell = s->pw->pw_shell; + + if (shell[0] == '\0') /* empty shell means /bin/sh */ + shell =_PATH_BSHELL; +- PRIVSEP(audit_run_command(shell)); ++ s->command = xstrdup(shell); + } ++ if (s->command != NULL && s->ptyfd == -1) ++ s->command_handle = PRIVSEP(audit_run_command(ssh, s->command)); ++ if (pipe(paudit) < 0) ++ fatal("pipe: %s", strerror(errno)); + #endif + if (s->ttyfd != -1) + ret = do_exec_pty(ssh, s, command); +@@ -730,6 +748,20 @@ do_exec(struct ssh *ssh, Session *s, con + */ + sshbuf_reset(loginmsg); + ++#ifdef SSH_AUDIT_EVENTS ++ close(paudit[1]); ++ if (use_privsep && ret == 0) { ++ /* ++ * Read the audit messages from forked child and send them ++ * back to monitor. We don't want to communicate directly, ++ * because the messages might get mixed up. ++ * Continue after the pipe gets closed (all messages sent). ++ */ ++ ret = mm_forward_audit_messages(paudit[0]); ++ } ++ close(paudit[0]); ++#endif /* SSH_AUDIT_EVENTS */ ++ + return ret; + } + +@@ -1530,11 +1562,30 @@ do_child(struct ssh *ssh, Session *s, co + int env_size; + int r = 0; + ++#ifdef SSH_AUDIT_EVENTS ++ int pparent = paudit[1]; ++ close(paudit[0]); ++ /* Hack the monitor pipe to avoid race condition with parent */ ++ if (use_privsep) ++ mm_set_monitor_pipe(pparent); ++#endif ++ + sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id)); + + /* remove hostkey from the child's memory */ +- destroy_sensitive_data(); +- ssh_packet_clear_keys(ssh); ++ destroy_sensitive_data(ssh, use_privsep); ++ ssh_packet_clear_keys_noaudit(ssh); ++ /* ++ * We can audit this, because we hacked the pipe to direct the ++ * messages over postauth child. But this message requires an answer ++ * which we can't do using a one-way pipe. ++ */ ++ packet_destroy_all(ssh, 0, 1); ++ ++#ifdef SSH_AUDIT_EVENTS ++ /* Notify parent that we are done */ ++ close(pparent); ++#endif + + /* Force a password change */ + if (s->authctxt->force_pwchange) { +@@ -1743,6 +1794,9 @@ session_unused(int id) + sessions[id].ttyfd = -1; + sessions[id].ptymaster = -1; + sessions[id].x11_chanids = NULL; ++#ifdef SSH_AUDIT_EVENTS ++ sessions[id].command_handle = -1; ++#endif + sessions[id].next_unused = sessions_first_unused; + sessions_first_unused = id; + } +@@ -1822,6 +1876,19 @@ session_open(Authctxt *authctxt, int cha + } + + Session * ++session_by_id(int id) ++{ ++ if (id >= 0 && id < sessions_nalloc) { ++ Session *s = &sessions[id]; ++ if (s->used) ++ return s; ++ } ++ debug("%s: unknown id %d", __func__, id); ++ session_dump(); ++ return NULL; ++} ++ ++Session * + session_by_tty(char *tty) + { + int i; +@@ -2429,6 +2496,32 @@ session_exit_message(struct ssh *ssh, Se + chan_write_failed(ssh, c); + } + ++#ifdef SSH_AUDIT_EVENTS ++void ++session_end_command2(struct ssh *ssh, Session *s) ++{ ++ if (s->command != NULL) { ++ if (s->command_handle != -1) ++ audit_end_command(ssh, s->command_handle, s->command); ++ free(s->command); ++ s->command = NULL; ++ s->command_handle = -1; ++ } ++} ++ ++static void ++session_end_command(struct ssh *ssh, Session *s) ++{ ++ if (s->command != NULL) { ++ if (s->command_handle != -1) ++ PRIVSEP(audit_end_command(ssh, s->command_handle, s->command)); ++ free(s->command); ++ s->command = NULL; ++ s->command_handle = -1; ++ } ++} ++#endif ++ + void + session_close(struct ssh *ssh, Session *s) + { +@@ -2470,6 +2563,10 @@ session_close(struct ssh *ssh, Session * + + if (s->ttyfd != -1) + session_pty_cleanup(s); ++#ifdef SSH_AUDIT_EVENTS ++ if (s->command) ++ session_end_command(ssh, s); ++#endif + free(s->term); + free(s->display); + free(s->x11_chanids); +@@ -2544,14 +2641,14 @@ session_close_by_channel(struct ssh *ssh + } + + void +-session_destroy_all(struct ssh *ssh, void (*closefunc)(Session *)) ++session_destroy_all(struct ssh *ssh, void (*closefunc)(struct ssh *ssh, Session *)) + { + int i; + for (i = 0; i < sessions_nalloc; i++) { + Session *s = &sessions[i]; + if (s->used) { + if (closefunc != NULL) +- closefunc(s); ++ closefunc(ssh, s); + else + session_close(ssh, s); + } +@@ -2677,6 +2774,15 @@ do_authenticated2(struct ssh *ssh, Authc + server_loop2(ssh, authctxt); + } + ++static void ++do_cleanup_one_session(struct ssh *ssh, Session *s) ++{ ++ session_pty_cleanup2(s); ++#ifdef SSH_AUDIT_EVENTS ++ session_end_command2(ssh, s); ++#endif ++} ++ + void + do_cleanup(struct ssh *ssh, Authctxt *authctxt) + { +@@ -2740,7 +2846,7 @@ do_cleanup(struct ssh *ssh, Authctxt *au + * or if running in monitor. + */ + if (!use_privsep || mm_is_monitor()) +- session_destroy_all(ssh, session_pty_cleanup2); ++ session_destroy_all(ssh, do_cleanup_one_session); + } + + /* Return a name for the remote host that fits inside utmp_size */ +Index: openssh-8.9p1/session.h +=================================================================== +--- openssh-8.9p1.orig/session.h ++++ openssh-8.9p1/session.h +@@ -61,6 +61,12 @@ struct Session { + char *name; + char *val; + } *env; ++ ++ /* exec */ ++#ifdef SSH_AUDIT_EVENTS ++ int command_handle; ++ char *command; ++#endif + }; + + void do_authenticated(struct ssh *, Authctxt *); +@@ -71,10 +77,12 @@ void session_unused(int); + int session_input_channel_req(struct ssh *, Channel *, const char *); + void session_close_by_pid(struct ssh *ssh, pid_t, int); + void session_close_by_channel(struct ssh *, int, int, void *); +-void session_destroy_all(struct ssh *, void (*)(Session *)); ++void session_destroy_all(struct ssh *, void (*)(struct ssh*, Session *)); + void session_pty_cleanup2(Session *); ++void session_end_command2(struct ssh *ssh, Session *); + + Session *session_new(void); ++Session *session_by_id(int); + Session *session_by_tty(char *); + void session_close(struct ssh *, Session *); + void do_setusercontext(struct passwd *); +Index: openssh-8.9p1/sshd.c +=================================================================== +--- openssh-8.9p1.orig/sshd.c ++++ openssh-8.9p1/sshd.c +@@ -125,6 +125,7 @@ + #include "ssh-gss.h" + #endif + #include "monitor_wrap.h" ++#include "audit.h" + #include "ssh-sandbox.h" + #include "auth-options.h" + #include "version.h" +@@ -265,8 +266,8 @@ struct sshbuf *loginmsg; + struct passwd *privsep_pw = NULL; + + /* Prototypes for various functions defined later in this file. */ +-void destroy_sensitive_data(void); +-void demote_sensitive_data(void); ++void destroy_sensitive_data(struct ssh *, int); ++void demote_sensitive_data(struct ssh *); + static void do_ssh2_kex(struct ssh *); + + static char *listener_proctitle; +@@ -284,6 +285,15 @@ close_listen_socks(void) + num_listen_socks = 0; + } + ++/* ++ * Is this process listening for clients (i.e. not specific to any specific ++ * client connection?) ++ */ ++int listening_for_clients(void) ++{ ++ return num_listen_socks >= 0; ++} ++ + static void + close_startup_pipes(void) + { +@@ -382,18 +392,45 @@ grace_alarm_handler(int sig) + ssh_remote_port(the_active_state)); + } + +-/* Destroy the host and server keys. They will no longer be needed. */ ++/* ++ * Destroy the host and server keys. They will no longer be needed. Careful, ++ * this can be called from cleanup_exit() - i.e. from just about anywhere. ++ */ + void +-destroy_sensitive_data(void) ++destroy_sensitive_data(struct ssh *ssh, int privsep) + { + u_int i; ++#ifdef SSH_AUDIT_EVENTS ++ pid_t pid; ++ uid_t uid; + ++ pid = getpid(); ++ uid = getuid(); ++#endif + for (i = 0; i < options.num_host_key_files; i++) { + if (sensitive_data.host_keys[i]) { ++ char *fp; ++ ++ if (sshkey_is_private(sensitive_data.host_keys[i])) ++ fp = sshkey_fingerprint(sensitive_data.host_keys[i], options.fingerprint_hash, SSH_FP_HEX); ++ else ++ fp = NULL; + sshkey_free(sensitive_data.host_keys[i]); + sensitive_data.host_keys[i] = NULL; ++ if (fp != NULL) { ++#ifdef SSH_AUDIT_EVENTS ++ if (privsep) ++ PRIVSEP(audit_destroy_sensitive_data(ssh, fp, ++ pid, uid)); ++ else ++ audit_destroy_sensitive_data(ssh, fp, ++ pid, uid); ++#endif ++ free(fp); ++ } + } +- if (sensitive_data.host_certificates[i]) { ++ if (sensitive_data.host_certificates ++ && sensitive_data.host_certificates[i]) { + sshkey_free(sensitive_data.host_certificates[i]); + sensitive_data.host_certificates[i] = NULL; + } +@@ -402,20 +439,38 @@ destroy_sensitive_data(void) + + /* Demote private to public keys for network child */ + void +-demote_sensitive_data(void) ++demote_sensitive_data(struct ssh *ssh) + { + struct sshkey *tmp; + u_int i; + int r; ++#ifdef SSH_AUDIT_EVENTS ++ pid_t pid; ++ uid_t uid; + ++ pid = getpid(); ++ uid = getuid(); ++#endif + for (i = 0; i < options.num_host_key_files; i++) { + if (sensitive_data.host_keys[i]) { ++ char *fp; ++ ++ if (sshkey_is_private(sensitive_data.host_keys[i])) ++ fp = sshkey_fingerprint(sensitive_data.host_keys[i], options.fingerprint_hash, SSH_FP_HEX); ++ else ++ fp = NULL; + if ((r = sshkey_from_private( + sensitive_data.host_keys[i], &tmp)) != 0) + fatal_r(r, "could not demote host %s key", + sshkey_type(sensitive_data.host_keys[i])); + sshkey_free(sensitive_data.host_keys[i]); + sensitive_data.host_keys[i] = tmp; ++ if (fp != NULL) { ++#ifdef SSH_AUDIT_EVENTS ++ audit_destroy_sensitive_data(ssh, fp, pid, uid); ++#endif ++ free(fp); ++ } + } + /* Certs do not need demotion */ + } +@@ -443,7 +498,7 @@ reseed_prngs(void) + } + + static void +-privsep_preauth_child(void) ++privsep_preauth_child(struct ssh *ssh) + { + gid_t gidset[1]; + +@@ -458,7 +513,7 @@ privsep_preauth_child(void) + reseed_prngs(); + + /* Demote the private keys to public keys. */ +- demote_sensitive_data(); ++ demote_sensitive_data(ssh); + + /* Demote the child */ + if (privsep_chroot) { +@@ -493,7 +548,7 @@ privsep_preauth(struct ssh *ssh) + + if (use_privsep == PRIVSEP_ON) + box = ssh_sandbox_init(pmonitor); +- pid = fork(); ++ pmonitor->m_pid = pid = fork(); + if (pid == -1) { + fatal("fork of unprivileged child failed"); + } else if (pid != 0) { +@@ -538,7 +593,7 @@ privsep_preauth(struct ssh *ssh) + /* Arrange for logging to be sent to the monitor */ + set_log_handler(mm_log_handler, pmonitor); + +- privsep_preauth_child(); ++ privsep_preauth_child(ssh); + setproctitle("%s", "[net]"); + if (box != NULL) + ssh_sandbox_child(box); +@@ -582,7 +637,7 @@ privsep_postauth(struct ssh *ssh, Authct + pmonitor->m_sendfd = -1; + + /* Demote the private keys to public keys. */ +- demote_sensitive_data(); ++ demote_sensitive_data(ssh); + + reseed_prngs(); + +@@ -1136,7 +1191,7 @@ server_listen(void) + * from this function are in a forked subprocess. + */ + static void +-server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) ++server_accept_loop(struct ssh *ssh, int *sock_in, int *sock_out, int *newsock, int *config_s) + { + struct pollfd *pfd = NULL; + int i, j, ret, npfd; +@@ -1179,6 +1234,7 @@ server_accept_loop(int *sock_in, int *so + if (received_sigterm) { + logit("Received signal %d; terminating.", + (int) received_sigterm); ++ destroy_sensitive_data(ssh, 0); + close_listen_socks(); + if (options.pid_file != NULL) + unlink(options.pid_file); +@@ -2088,7 +2144,7 @@ main(int ac, char **av) + #endif + + /* Accept a connection and return in a forked child */ +- server_accept_loop(&sock_in, &sock_out, ++ server_accept_loop(ssh, &sock_in, &sock_out, + &newsock, config_s); + } + +@@ -2311,6 +2367,9 @@ main(int ac, char **av) + do_authenticated(ssh, authctxt); + + /* The connection has been terminated. */ ++ packet_destroy_all(ssh, 1, 1); ++ destroy_sensitive_data(ssh, 1); ++ + ssh_packet_get_bytes(ssh, &ibytes, &obytes); + verbose("Transferred: sent %llu, received %llu bytes", + (unsigned long long)obytes, (unsigned long long)ibytes); +@@ -2491,6 +2550,15 @@ do_ssh2_kex(struct ssh *ssh) + void + cleanup_exit(int i) + { ++ static int in_cleanup = 0; ++ int is_privsep_child; ++ ++ /* cleanup_exit can be called at the very least from the privsep ++ wrappers used for auditing. Make sure we don't recurse ++ indefinitely. */ ++ if (in_cleanup) ++ _exit(i); ++ in_cleanup = 1; + if (the_active_state != NULL && the_authctxt != NULL) { + do_cleanup(the_active_state, the_authctxt); + if (use_privsep && privsep_is_preauth && +@@ -2503,9 +2571,16 @@ cleanup_exit(int i) + } + } + } ++ is_privsep_child = use_privsep && pmonitor != NULL && pmonitor->m_pid == 0; ++ if (sensitive_data.host_keys != NULL && the_active_state != NULL) ++ destroy_sensitive_data(the_active_state, is_privsep_child); ++ if (the_active_state != NULL) ++ packet_destroy_all(the_active_state, 1, is_privsep_child); + #ifdef SSH_AUDIT_EVENTS + /* done after do_cleanup so it can cancel the PAM auth 'thread' */ +- if (the_active_state != NULL && (!use_privsep || mm_is_monitor())) ++ if (the_active_state != NULL && ++ (the_authctxt == NULL || !the_authctxt->authenticated) && ++ (!use_privsep || mm_is_monitor())) + audit_event(the_active_state, SSH_CONNECTION_ABANDON); + #endif + _exit(i); +Index: openssh-8.9p1/sshkey.c +=================================================================== +--- openssh-8.9p1.orig/sshkey.c ++++ openssh-8.9p1/sshkey.c +@@ -400,6 +400,38 @@ sshkey_type_is_valid_ca(int type) + } + + int ++sshkey_is_private(const struct sshkey *k) ++{ ++ switch (k->type) { ++#ifdef WITH_OPENSSL ++ case KEY_RSA_CERT: ++ case KEY_RSA: { ++ const BIGNUM *d; ++ RSA_get0_key(k->rsa, NULL, NULL, &d); ++ return d != NULL; ++ } ++ case KEY_DSA_CERT: ++ case KEY_DSA: { ++ const BIGNUM *priv_key; ++ DSA_get0_key(k->dsa, NULL, &priv_key); ++ return priv_key != NULL; ++ } ++#ifdef OPENSSL_HAS_ECC ++ case KEY_ECDSA_CERT: ++ case KEY_ECDSA: ++ return EC_KEY_get0_private_key(k->ecdsa) != NULL; ++#endif /* OPENSSL_HAS_ECC */ ++#endif /* WITH_OPENSSL */ ++ case KEY_ED25519_CERT: ++ case KEY_ED25519: ++ return (k->ed25519_pk != NULL); ++ default: ++ /* fatal("key_is_private: bad key type %d", k->type); */ ++ return 0; ++ } ++} ++ ++int + sshkey_is_cert(const struct sshkey *k) + { + if (k == NULL) +Index: openssh-8.9p1/sshkey.h +=================================================================== +--- openssh-8.9p1.orig/sshkey.h ++++ openssh-8.9p1/sshkey.h +@@ -189,6 +189,7 @@ int sshkey_shield_private(struct sshke + int sshkey_unshield_private(struct sshkey *); + + int sshkey_type_from_name(const char *); ++int sshkey_is_private(const struct sshkey *); + int sshkey_is_cert(const struct sshkey *); + int sshkey_is_sk(const struct sshkey *); + int sshkey_type_is_cert(int); diff --git a/openssh-8.1p1-ed25519-use-openssl-rng.patch b/openssh-8.1p1-ed25519-use-openssl-rng.patch new file mode 100644 index 0000000..fe11530 --- /dev/null +++ b/openssh-8.1p1-ed25519-use-openssl-rng.patch @@ -0,0 +1,74 @@ +commit d281831d887044ede45d458c3dda74be9ae017e3 +Author: Hans Petter Jansson +Date: Fri Sep 25 23:26:58 2020 +0200 + + Use OpenSSL's FIPS approved RAND_bytes() to get randomness for Ed25519 + +diff --git a/ed25519.c b/ed25519.c +index 767ec24..5d506a9 100644 +--- a/ed25519.c ++++ b/ed25519.c +@@ -9,6 +9,13 @@ + + #include "crypto_api.h" + ++#ifdef WITH_OPENSSL ++#include ++#include ++#endif ++ ++#include "log.h" ++ + #define int8 crypto_int8 + #define uint8 crypto_uint8 + #define int16 crypto_int16 +@@ -33,7 +40,15 @@ int crypto_sign_ed25519_keypair( + sc25519 scsk; + ge25519 gepk; + ++#ifdef WITH_OPENSSL ++ /* Use FIPS approved RNG */ ++ if (RAND_bytes(sk, 32) <= 0) ++ fatal("Couldn't obtain random bytes (error 0x%lx)", ++ (unsigned long)ERR_get_error()); ++#else + randombytes(sk,32); ++#endif ++ + crypto_hash_sha512(az,sk,32); + az[0] &= 248; + az[31] &= 127; +diff --git a/kexc25519.c b/kexc25519.c +index f13d766..2604eda 100644 +--- a/kexc25519.c ++++ b/kexc25519.c +@@ -33,6 +33,13 @@ + #include + #include + ++#ifdef WITH_OPENSSL ++#include ++#include ++#endif ++ ++#include "log.h" ++ + #include "sshkey.h" + #include "kex.h" + #include "sshbuf.h" +@@ -51,7 +58,15 @@ kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE]) + { + static const u_char basepoint[CURVE25519_SIZE] = {9}; + ++#ifdef WITH_OPENSSL ++ /* Use FIPS approved RNG */ ++ if (RAND_bytes(key, CURVE25519_SIZE) <= 0) ++ fatal("Couldn't obtain random bytes (error 0x%lx)", ++ (unsigned long)ERR_get_error()); ++#else + arc4random_buf(key, CURVE25519_SIZE); ++#endif ++ + crypto_scalarmult_curve25519(pub, key, basepoint); + } + diff --git a/openssh-8.1p1-seccomp-clock_gettime64.patch b/openssh-8.1p1-seccomp-clock_gettime64.patch new file mode 100644 index 0000000..25b96fc --- /dev/null +++ b/openssh-8.1p1-seccomp-clock_gettime64.patch @@ -0,0 +1,25 @@ +From b110cefdfbf5a20f49b774a55062d6ded2fb6e22 Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Tue, 7 Jan 2020 16:26:45 -0800 +Subject: [PATCH] seccomp: Allow clock_gettime64() in sandbox. + +This helps sshd accept connections on mips platforms with +upcoming glibc ( 2.31 ) +--- + sandbox-seccomp-filter.c | 3 +++ + 1 file changed, 3 insertions(+) + +Index: openssh-8.8p1/sandbox-seccomp-filter.c +=================================================================== +--- openssh-8.8p1.orig/sandbox-seccomp-filter.c ++++ openssh-8.8p1/sandbox-seccomp-filter.c +@@ -279,6 +279,9 @@ static const struct sock_filter preauth_ + #ifdef __NR_clock_nanosleep_time64 + SC_ALLOW(__NR_clock_nanosleep_time64), + #endif ++#ifdef __NR_clock_gettime64 ++ SC_ALLOW(__NR_clock_gettime64), ++#endif + #ifdef __NR__newselect + SC_ALLOW(__NR__newselect), + #endif diff --git a/openssh-8.1p1-seccomp-clock_nanosleep.patch b/openssh-8.1p1-seccomp-clock_nanosleep.patch new file mode 100644 index 0000000..099225d --- /dev/null +++ b/openssh-8.1p1-seccomp-clock_nanosleep.patch @@ -0,0 +1,14 @@ +Index: openssh-8.8p1/sandbox-seccomp-filter.c +=================================================================== +--- openssh-8.8p1.orig/sandbox-seccomp-filter.c ++++ openssh-8.8p1/sandbox-seccomp-filter.c +@@ -273,6 +273,9 @@ static const struct sock_filter preauth_ + #ifdef __NR_clock_gettime64 + SC_ALLOW(__NR_clock_gettime64), + #endif ++#ifdef __NR_clock_nanosleep ++ SC_ALLOW(__NR_clock_nanosleep), ++#endif + #ifdef __NR__newselect + SC_ALLOW(__NR__newselect), + #endif diff --git a/openssh-8.1p1-seccomp-clock_nanosleep_time64.patch b/openssh-8.1p1-seccomp-clock_nanosleep_time64.patch new file mode 100644 index 0000000..0f3c774 --- /dev/null +++ b/openssh-8.1p1-seccomp-clock_nanosleep_time64.patch @@ -0,0 +1,24 @@ +From 5af6fd5461bb709304e6979c8b7856c7af921c9e Mon Sep 17 00:00:00 2001 +From: Darren Tucker +Date: Mon, 16 Dec 2019 13:55:56 +1100 +Subject: [PATCH] Allow clock_nanosleep_time64 in seccomp sandbox. + +Needed on Linux ARM. bz#3100, patch from jjelen@redhat.com. +--- + sandbox-seccomp-filter.c | 3 +++ + 1 file changed, 3 insertions(+) + +Index: openssh-8.8p1/sandbox-seccomp-filter.c +=================================================================== +--- openssh-8.8p1.orig/sandbox-seccomp-filter.c ++++ openssh-8.8p1/sandbox-seccomp-filter.c +@@ -276,6 +276,9 @@ static const struct sock_filter preauth_ + #ifdef __NR_clock_nanosleep + SC_ALLOW(__NR_clock_nanosleep), + #endif ++#ifdef __NR_clock_nanosleep_time64 ++ SC_ALLOW(__NR_clock_nanosleep_time64), ++#endif + #ifdef __NR__newselect + SC_ALLOW(__NR__newselect), + #endif diff --git a/openssh-8.1p1-use-openssl-kdf.patch b/openssh-8.1p1-use-openssl-kdf.patch new file mode 100644 index 0000000..51326da --- /dev/null +++ b/openssh-8.1p1-use-openssl-kdf.patch @@ -0,0 +1,158 @@ +Index: openssh-8.8p1/kex.c +=================================================================== +--- openssh-8.8p1.orig/kex.c ++++ openssh-8.8p1/kex.c +@@ -40,6 +40,7 @@ + #ifdef WITH_OPENSSL + #include + #include ++#include + #endif + + #include "ssh.h" +@@ -1115,8 +1116,93 @@ kex_choose_conf(struct ssh *ssh) + return r; + } + ++#ifdef WITH_OPENSSL ++ ++static const EVP_MD * ++get_openssl_md_for_hash_alg (int hash_alg) ++{ ++ if (hash_alg < 0 || hash_alg >= SSH_DIGEST_MAX) ++ return NULL; ++ ++ switch (hash_alg) ++ { ++ case SSH_DIGEST_MD5: ++ return EVP_md5(); ++ 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(); ++ default: ++ break; ++ } ++ ++ return NULL; ++} ++ + static int +-derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen, ++derive_key_via_openssl(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 *hashctx = NULL; ++ const EVP_MD *md = NULL; ++ u_char *digest = NULL; ++ int r = SSH_ERR_LIBCRYPTO_ERROR; ++ ++ hashctx = EVP_KDF_CTX_new_id (EVP_KDF_SSHKDF); ++ if (!hashctx) ++ goto out; ++ ++ md = get_openssl_md_for_hash_alg (kex->hash_alg); ++ if (!md) ++ goto out; ++ ++ if (EVP_KDF_ctrl (hashctx, EVP_KDF_CTRL_SET_MD, ++ md) != 1 ++ || EVP_KDF_ctrl (hashctx, EVP_KDF_CTRL_SET_KEY, ++ sshbuf_ptr(shared_secret), sshbuf_len(shared_secret)) != 1 ++ || EVP_KDF_ctrl (hashctx, EVP_KDF_CTRL_SET_SSHKDF_TYPE, ++ (int) id) != 1 ++ || EVP_KDF_ctrl (hashctx, EVP_KDF_CTRL_SET_SSHKDF_XCGHASH, ++ hash, (size_t) hashlen) != 1 ++ || EVP_KDF_ctrl (hashctx, EVP_KDF_CTRL_SET_SSHKDF_SESSION_ID, ++ sshbuf_ptr(kex->session_id), ++ (size_t) sshbuf_len(kex->session_id)) != 1) ++ goto out; ++ ++ digest = calloc (1, need); ++ if (!digest) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ ++ if (EVP_KDF_derive (hashctx, digest, need) != 1) ++ goto out; ++ ++ *keyp = digest; ++ digest = NULL; ++ r = 0; ++ ++ out: ++ if (hashctx) ++ EVP_KDF_CTX_free(hashctx); ++ ++ if (digest) ++ free(digest); ++ ++ return r; ++} ++ ++#else ++# error This version of openssh must be built with openssl to benefit from FIPS certification. ++#endif ++ ++static int ++derive_key_via_internal(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; +@@ -1179,6 +1265,50 @@ derive_key(struct ssh *ssh, int id, u_in + return r; + } + ++/* Belt and suspenders; we want the output from openssl because it's FIPS certified. However, ++ * if there's a bug in the implementation, we should not proceed. Minimize risk by requiring ++ * the implementations agree. */ ++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) ++{ ++#ifdef WITH_OPENSSL ++ ++ u_char *buf_openssl = NULL, *buf_internal = NULL; ++ int r; ++ ++ r = derive_key_via_openssl (ssh, id, need, hash, hashlen, shared_secret, &buf_openssl); ++ if (r != 0) ++ goto out; ++ ++ r = derive_key_via_internal (ssh, id, need, hash, hashlen, shared_secret, &buf_internal); ++ if (r != 0) ++ goto out; ++ ++ if (memcmp (buf_openssl, buf_internal, need)) ++ { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ ++ *keyp = buf_openssl; ++ buf_openssl = NULL; ++ ++ out: ++ if (buf_openssl) ++ free (buf_openssl); ++ if (buf_internal) ++ free (buf_internal); ++ ++ return r; ++ ++#else ++ ++ return derive_key_via_internal (ssh, id, need, hash, hashlen, shared_secret, keyp); ++ ++#endif ++} ++ + #define NKEYS 6 + int + kex_derive_keys(struct ssh *ssh, u_char *hash, u_int hashlen, diff --git a/openssh-8.4p1-pam_motd.patch b/openssh-8.4p1-pam_motd.patch new file mode 100644 index 0000000..51e703b --- /dev/null +++ b/openssh-8.4p1-pam_motd.patch @@ -0,0 +1,13 @@ +diff -u openssh-8.4p1.orig/sshd_config openssh-8.4p1/sshd_config +--- openssh-8.4p1.orig/sshd_config 2020-09-27 09:25:01.000000000 +0200 ++++ openssh-8.4p1/sshd_config 2021-05-18 19:15:39.190701511 +0200 +@@ -88,8 +88,7 @@ + #X11DisplayOffset 10 + #X11UseLocalhost yes + #PermitTTY yes +-#PrintMotd yes +-#PrintLastLog yes ++PrintMotd no + #TCPKeepAlive yes + #PermitUserEnvironment no + #Compression delayed diff --git a/openssh-8.4p1-ssh_config_d.patch b/openssh-8.4p1-ssh_config_d.patch new file mode 100644 index 0000000..7ff6120 --- /dev/null +++ b/openssh-8.4p1-ssh_config_d.patch @@ -0,0 +1,40 @@ +Index: openssh-8.9p1/ssh_config +=================================================================== +--- openssh-8.9p1.orig/ssh_config ++++ openssh-8.9p1/ssh_config +@@ -17,6 +17,13 @@ + # list of available options, their meanings and defaults, please see the + # ssh_config(5) man page. + ++# To modify the system-wide ssh configuration, create a "*.conf" file under ++# "/etc/ssh/ssh_config.d/" which will be automatically included below. ++# Don't edit this configuration file itself if possible to avoid update ++# problems. ++Include /etc/ssh/ssh_config.d/*.conf ++Include /usr/etc/ssh/ssh_config.d/*.conf ++ + Host * + # ForwardAgent no + # ForwardX11 no +Index: openssh-8.9p1/sshd_config +=================================================================== +--- openssh-8.9p1.orig/sshd_config ++++ openssh-8.9p1/sshd_config +@@ -5,10 +5,17 @@ + + # This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin + ++# To modify the system-wide sshd configuration, create a "*.conf" file under ++# "/etc/ssh/sshd_config.d/" which will be automatically included below. ++# Don't edit this configuration file itself if possible to avoid update ++# problems. ++Include /etc/ssh/sshd_config.d/*.conf ++ + # The strategy used for options in the default sshd_config shipped with + # OpenSSH is to specify options with their default value where + # possible, but leave them commented. Uncommented options override the + # default value. ++Include /usr/etc/ssh/sshd_config.d/*.conf + + #Port 22 + #AddressFamily any diff --git a/openssh-8.4p1-vendordir.patch b/openssh-8.4p1-vendordir.patch new file mode 100644 index 0000000..3b38457 --- /dev/null +++ b/openssh-8.4p1-vendordir.patch @@ -0,0 +1,208 @@ +Gemeinsame Unterverzeichnisse: openssh-8.4p1/contrib und openssh-8.4p1-vendor/contrib. +Index: openssh-8.9p1/dh.c +=================================================================== +--- openssh-8.9p1.orig/dh.c ++++ openssh-8.9p1/dh.c +@@ -54,7 +54,17 @@ void dh_set_moduli_file(const char *file + + static const char * get_moduli_filename(void) + { +- return moduli_filename ? moduli_filename : _PATH_DH_MODULI; ++ struct stat st; ++ ++ if (moduli_filename) ++ return moduli_filename; ++ ++ if (stat(_PATH_VENDOR_DH_MODULI, &st) == 0 && ++ stat(_PATH_DH_MODULI, &st) == -1) { ++ return _PATH_VENDOR_DH_MODULI; ++ } ++ ++ return _PATH_DH_MODULI; + } + + static int +Index: openssh-8.9p1/pathnames.h +=================================================================== +--- openssh-8.9p1.orig/pathnames.h ++++ openssh-8.9p1/pathnames.h +@@ -18,6 +18,8 @@ + #define SSHDIR ETCDIR "/ssh" + #endif + ++#define VENDORDIR "/usr/etc/ssh" ++ + #ifndef _PATH_SSH_PIDDIR + #define _PATH_SSH_PIDDIR "/var/run" + #endif +@@ -35,13 +37,17 @@ + * should be world-readable. + */ + #define _PATH_SERVER_CONFIG_FILE SSHDIR "/sshd_config" ++#define _PATH_SERVER_VENDOR_CONFIG_FILE VENDORDIR "/sshd_config" + #define _PATH_HOST_CONFIG_FILE SSHDIR "/ssh_config" ++#define _PATH_HOST_VENDOR_CONFIG_FILE VENDORDIR "/ssh_config" + #define _PATH_HOST_DSA_KEY_FILE SSHDIR "/ssh_host_dsa_key" + #define _PATH_HOST_ECDSA_KEY_FILE SSHDIR "/ssh_host_ecdsa_key" + #define _PATH_HOST_ED25519_KEY_FILE SSHDIR "/ssh_host_ed25519_key" + #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_VENDOR_DH_MODULI VENDORDIR "/moduli" ++ + + #ifndef _PATH_SSH_PROGRAM + #define _PATH_SSH_PROGRAM "/usr/bin/ssh" +Index: openssh-8.9p1/ssh.c +=================================================================== +--- openssh-8.9p1.orig/ssh.c ++++ openssh-8.9p1/ssh.c +@@ -549,6 +549,7 @@ static void + process_config_files(const char *host_name, struct passwd *pw, int final_pass, + int *want_final_pass) + { ++ struct stat st; + char buf[PATH_MAX]; + int r; + +@@ -567,10 +568,23 @@ process_config_files(const char *host_na + &options, SSHCONF_CHECKPERM | SSHCONF_USERCONF | + (final_pass ? SSHCONF_FINAL : 0), want_final_pass); + +- /* Read systemwide configuration file after user config. */ +- (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, +- host, host_name, &options, +- final_pass ? SSHCONF_FINAL : 0, want_final_pass); ++ /* If only the vendor configuration file exists, use that. ++ * Else use the standard configuration file. ++ */ ++ if (stat(_PATH_HOST_VENDOR_CONFIG_FILE, &st) == 0 && ++ stat(_PATH_HOST_CONFIG_FILE, &st) == -1) { ++ /* Read vendor distributed configuration file. */ ++ (void)read_config_file(_PATH_HOST_VENDOR_CONFIG_FILE, ++ pw, host, host_name, &options, ++ final_pass ? SSHCONF_FINAL : 0, ++ want_final_pass); ++ } else { ++ /* Read systemwide configuration file after user config. */ ++ (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, ++ host, host_name, &options, ++ final_pass ? SSHCONF_FINAL : 0, ++ want_final_pass); ++ } + } + } + +Index: openssh-8.9p1/ssh_config.5 +=================================================================== +--- openssh-8.9p1.orig/ssh_config.5 ++++ openssh-8.9p1/ssh_config.5 +@@ -54,6 +54,9 @@ user's configuration file + .It + system-wide configuration file + .Pq Pa /etc/ssh/ssh_config ++.It ++vendor configuration file ++.Pq Pa /usr/etc/ssh/ssh_config + .El + .Pp + Unless noted otherwise, for each parameter, the first obtained value +@@ -2220,6 +2223,11 @@ This file provides defaults for those + values that are not specified in the user's configuration file, and + for those users who do not have a configuration file. + This file must be world-readable. ++.It Pa /usr/etc/ssh/ssh_config ++Vendor specific configuraiton file. ++This file provides the vendor defaults and is used as fallback if the ++.Ic /etc/ssh/ssh_config ++configuration file does not exist. + .El + .Sh SEE ALSO + .Xr ssh 1 +Index: openssh-8.9p1/sshd.c +=================================================================== +--- openssh-8.9p1.orig/sshd.c ++++ openssh-8.9p1/sshd.c +@@ -148,7 +148,7 @@ extern char *__progname; + ServerOptions options; + + /* Name of the server configuration file. */ +-char *config_file_name = _PATH_SERVER_CONFIG_FILE; ++char *config_file_name = NULL; + + /* + * Debug mode flag. This can be set on the command line. If debug +@@ -1591,6 +1591,7 @@ prepare_proctitle(int ac, char **av) + int + main(int ac, char **av) + { ++ struct stat st; + struct ssh *ssh = NULL; + extern char *optarg; + extern int optind; +@@ -1806,7 +1807,21 @@ main(int ac, char **av) + */ + (void)atomicio(vwrite, startup_pipe, "\0", 1); + } ++ } else if (config_file_name == NULL) { ++ /* If only the vendor configuration file exists, use that. ++ * Else use the standard configuration file. ++ */ ++ if (stat(_PATH_SERVER_VENDOR_CONFIG_FILE, &st) == 0 && ++ stat(_PATH_SERVER_CONFIG_FILE, &st) == -1) { ++ /* fill with global distributor settings */ ++ config_file_name = _PATH_SERVER_VENDOR_CONFIG_FILE; ++ } else { ++ /* load global admin settings */ ++ config_file_name = _PATH_SERVER_CONFIG_FILE; ++ } ++ load_server_config(config_file_name, cfg); + } else if (strcasecmp(config_file_name, "none") != 0) ++ /* load config specified on commandline */ + load_server_config(config_file_name, cfg); + + parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name, +Index: openssh-8.9p1/sshd_config.5 +=================================================================== +--- openssh-8.9p1.orig/sshd_config.5 ++++ openssh-8.9p1/sshd_config.5 +@@ -44,7 +44,9 @@ + .Xr sshd 8 + reads configuration data from + .Pa /etc/ssh/sshd_config +-(or the file specified with ++( ++.Pa /usr/etc/ssh/sshd_config ++if the file does not exist or the file specified with + .Fl f + on the command line). + The file contains keyword-argument pairs, one per line. +Index: openssh-8.9p1/ssh-keysign.c +=================================================================== +--- openssh-8.9p1.orig/ssh-keysign.c ++++ openssh-8.9p1/ssh-keysign.c +@@ -186,6 +186,7 @@ main(int argc, char **argv) + u_char *signature, *data, rver; + char *host, *fp, *pkalg; + size_t slen, dlen; ++ struct stat st; + + if (pledge("stdio rpath getpw dns id", NULL) != 0) + fatal("%s: pledge: %s", __progname, strerror(errno)); +@@ -219,8 +220,14 @@ main(int argc, char **argv) + + /* verify that ssh-keysign is enabled by the admin */ + initialize_options(&options); +- (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, "", "", +- &options, 0, NULL); ++ ++ if (stat(_PATH_HOST_CONFIG_FILE, &st) == 0) ++ (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, "", "", ++ &options, 0, NULL); ++ else ++ (void)read_config_file(_PATH_HOST_VENDOR_CONFIG_FILE, pw, "", "", ++ &options, 0, NULL); ++ + (void)fill_default_options(&options); + if (options.enable_ssh_keysign != 1) + fatal("ssh-keysign not enabled in %s", diff --git a/openssh-9.6p1.tar.gz b/openssh-9.6p1.tar.gz new file mode 100644 index 0000000..d753ff2 --- /dev/null +++ b/openssh-9.6p1.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:910211c07255a8c5ad654391b40ee59800710dd8119dd5362de09385aa7a777c +size 1857862 diff --git a/openssh-9.6p1.tar.gz.asc b/openssh-9.6p1.tar.gz.asc new file mode 100644 index 0000000..1b20242 --- /dev/null +++ b/openssh-9.6p1.tar.gz.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEcWi5g4FaXu9ZpK39Kj9BTnNgYLoFAmWAXvAACgkQKj9BTnNg +YLrypA/6A1O8e80XnzVWIFhXkbv/biGL10Q5ZMvjQvND6mbkphNWZ4G4QOEh0nBG +rseD3Fce7me9pfeLYVhaNXO9R3OYAXxjbWfQwI7FpBU4QUCnbH53PG32B6ESq7pl +0vlDqdqI7aBAyMpp+8WFD+EvHWUVA77JtfU4MFw7myKJacrVrDUygDaZkJKOhqKf +N1Nurz4YppdQ5zIK1ElL0jlRJXm08flLFRg8fD5/5rwabpUbZIY9b5qZzGKgnR7I +sxUBlDkfLnvKIlKzUXbRvOHazvFAHYH1ltJZGlJUc/+H/ZaPigWf4IR+E1FB9c2O +zxaZhlbwGKyD+p7l08F9n8T21taxpBCW1Uxkx7MLTz8k9huPNpdX5l8VM4Gotmn8 +I4V3Fevyx+M3XJYeKtkspa51h0GqF3gNFPLxW7ERGaIuqwoxuHxIEKwYE+JPmQag +UDma5LDrSrasa8Rw8g5urGE48PeDQ5muPy8Bi9eIGZU5JLqX6TNgz7QDDs/dQsHB +iny4wQOLmdIA78IGttiCo0rqikEvFtFDFR4mCUTC8K0nQKzWwGewO3gRTcHttzyU +xMalxw+wt9cUJ8gb1E9p7OeMUuXdaHMmem8/PcFCar/vKx1mdV/On6evnp3P8yQA +la8WnbcP0+zJg0GGwGszpFlOMjWCDB0kUTBCT+MR+IWbj/pVZVA= +=G9YA +-----END PGP SIGNATURE----- diff --git a/openssh-askpass-gnome.changes b/openssh-askpass-gnome.changes new file mode 100644 index 0000000..edbc3d4 --- /dev/null +++ b/openssh-askpass-gnome.changes @@ -0,0 +1,334 @@ +------------------------------------------------------------------- +Sun Feb 25 18:26:23 UTC 2024 - Hans Petter Jansson + +- Update to openssh 9.6p1: + * No changes for askpass, see main package changelog for + details. + +------------------------------------------------------------------- +Fri Jul 21 05:13:56 UTC 2023 - Simon Lees + +- Update to openssh 9.3p2 + * No changes for askpass, see main package changelog for + details + +------------------------------------------------------------------- +Sun May 28 09:16:44 UTC 2023 - Andreas Stieger + +- openssh-askpass-gnome: require only openssh-clients, not the full + openssh (including -server), to avoid pulling in excessive + dependencies when installing git on Gnome (boo#1211446) + +------------------------------------------------------------------- +Thu May 11 07:01:54 UTC 2023 - Antonio Larrosa + +- Update to openssh 9.3p1 + * No changes for askpass, see main package changelog for + details + +------------------------------------------------------------------- +Tue Sep 28 19:05:15 UTC 2021 - Hans Petter Jansson + +- Version upgrade to 8.8p1 + * No changes for askpass, see main package changelog for + details + +------------------------------------------------------------------- +Thu Sep 17 20:41:39 UTC 2020 - Jan Engelhardt + +- Upgrade some old specfile constructs/macros. + +------------------------------------------------------------------- +Thu Sep 10 22:44:00 UTC 2020 - Hans Petter Jansson + +- Supplement openssh-clients instead of openssh (bsc#1176434). + +------------------------------------------------------------------- +Thu Jul 18 14:07:56 UTC 2019 - Fabian Vogt + +- Supplement libgtk-3-0 instead to avoid installation on a textmode install + (boo#1142000) + +------------------------------------------------------------------- +Thu Feb 14 10:36:03 UTC 2019 - Tomáš Chvátal + +- Supplement the openssh and libx11 together to ensure this package + is installed on machines where there is X stack + +------------------------------------------------------------------- +Mon Oct 22 08:59:02 UTC 2018 - Pedro Monreal Gonzalez + +- Version update to 7.9p1 + * No actual changes for the askpass + * See main package changelog for details + +------------------------------------------------------------------- +Tue Oct 9 10:52:15 UTC 2018 - Tomáš Chvátal + +- Update to 7.8p1: + * no actual changes for the askpass +- Format with spec-cleaner +- Respect cflags +- Use gtk3 rather than gtk2 which is being phased out + +------------------------------------------------------------------- +Mon May 21 15:19:03 UTC 2018 - pcerny@suse.com + +- Upgrade to 7.7p1 (bsc#1094068) + +------------------------------------------------------------------- +Wed Jan 31 22:54:55 UTC 2018 - pcerny@suse.com + +- .spec file cleanup + +------------------------------------------------------------------- +Fri Nov 3 12:27:18 UTC 2017 - pcerny@suse.com + +- upgrade to 7.6p1 + see main package changelog for details + +------------------------------------------------------------------- +Mon Jul 25 13:45:53 UTC 2016 - meissner@suse.com + +- fixed url + +------------------------------------------------------------------- +Sun Apr 17 23:27:51 UTC 2016 - pcerny@suse.com + +- upgrade to 7.2p2 + +------------------------------------------------------------------- +Tue Feb 10 13:28:56 UTC 2015 - pcerny@suse.com + +- changing license to 2-clause BSD to match source + +------------------------------------------------------------------- +Fri Apr 11 21:50:51 UTC 2014 - pcerny@suse.com + +- Update of the underlying OpenSSH to 6.6p1 + +------------------------------------------------------------------- +Wed Feb 12 01:24:16 UTC 2014 - pcerny@suse.com + +- Update of the underlying OpenSSH to 6.5p1 + +------------------------------------------------------------------- +Fri Jan 24 15:13:09 UTC 2014 - pcerny@suse.com + +- Update of the underlying OpenSSH to 6.4p1 + +------------------------------------------------------------------- +Thu Sep 19 02:02:56 UTC 2013 - pcerny@suse.com + +- spec file cleanup (don't pointelssly build whole OpenSSH) + +------------------------------------------------------------------- +Sat Aug 3 18:12:20 UTC 2013 - crrodriguez@opensuse.org + +- Update for 6.2p2 + +------------------------------------------------------------------- +Tue Nov 13 10:51:12 UTC 2012 - meissner@suse.com + +- Updated to 6.1p1, a bugfix release + Features: + * sshd(8): This release turns on pre-auth sandboxing sshd by default for + new installs, by setting UsePrivilegeSeparation=sandbox in sshd_config. + * ssh-keygen(1): Add options to specify starting line number and number of + lines to process when screening moduli candidates, allowing processing + of different parts of a candidate moduli file in parallel + * sshd(8): The Match directive now supports matching on the local (listen) + address and port upon which the incoming connection was received via + LocalAddress and LocalPort clauses. + * sshd(8): Extend sshd_config Match directive to allow setting AcceptEnv + and {Allow,Deny}{Users,Groups} + * Add support for RFC6594 SSHFP DNS records for ECDSA key types. bz#1978 + * ssh-keygen(1): Allow conversion of RSA1 keys to public PEM and PKCS8 + * sshd(8): Allow the sshd_config PermitOpen directive to accept "none" as + an argument to refuse all port-forwarding requests. + * sshd(8): Support "none" as an argument for AuthorizedPrincipalsFile + * ssh-keyscan(1): Look for ECDSA keys by default. bz#1971 + * sshd(8): Add "VersionAddendum" to sshd_config to allow server operators + to append some arbitrary text to the server SSH protocol banner. + Bugfixes: + * ssh(1)/sshd(8): Don't spin in accept() in situations of file + descriptor exhaustion. Instead back off for a while. + * ssh(1)/sshd(8): Remove hmac-sha2-256-96 and hmac-sha2-512-96 MACs as + they were removed from the specification. bz#2023, + * sshd(8): Handle long comments in config files better. bz#2025 + * ssh(1): Delay setting tty_flag so RequestTTY options are correctly + picked up. bz#1995 + * sshd(8): Fix handling of /etc/nologin incorrectly being applied to root + on platforms that use login_cap. + Portable OpenSSH: + * sshd(8): Allow sshd pre-auth sandboxing to fall-back to the rlimit + sandbox from the Linux SECCOMP filter sandbox when the latter is + not available in the kernel. + * ssh(1): Fix NULL dereference when built with LDNS and using DNSSEC to + retrieve a CNAME SSHFP record. + * Fix cross-compilation problems related to pkg-config. bz#1996 + +------------------------------------------------------------------- +Wed Jun 27 09:51:19 UTC 2012 - coolo@suse.com + +- the gnome askpass does not require the x11 askpass - especially not + in the version of openssh (it's at 1.X) + +------------------------------------------------------------------- +Tue May 29 07:14:53 UTC 2012 - meissner@suse.com + +- use correct tarball url +- update to 6.0p1. + +------------------------------------------------------------------- +Wed Mar 28 11:42:32 UTC 2012 - aj@suse.de + +- Add build require on autoconf and automake. + +------------------------------------------------------------------- +Wed Dec 21 10:31:42 UTC 2011 - coolo@suse.com + +- remove call to suse_update_config (very old work around) + +------------------------------------------------------------------- +Wed Oct 19 00:40:15 UTC 2011 - pcerny@suse.com + +- Update to 5.9p1 + +------------------------------------------------------------------- +Fri Feb 4 11:19:14 UTC 2011 - lchiquitto@novell.com + +- Update to 5.8p1 + +------------------------------------------------------------------- +Mon Jan 24 11:51:10 UTC 2011 - lchiquitto@novell.com + +- Update to 5.7p1 + +------------------------------------------------------------------- +Wed Jan 12 13:37:38 CET 2011 - sbrabec@suse.cz + +- Removed relics of no more implemented opensc support. + +------------------------------------------------------------------- +Tue Aug 24 15:50:17 CEST 2010 - anicka@suse.cz + +- update to 5.6p1 + +------------------------------------------------------------------- +Fri Mar 26 11:04:59 CET 2010 - anicka@suse.cz + +- update to 5.4p1 +- remove -pam-fix4.diff (in upstream now) + +------------------------------------------------------------------- +Mon Feb 23 17:27:22 CET 2009 - anicka@suse.cz + +- update to 5.2p1 + +------------------------------------------------------------------- +Wed Apr 9 14:35:42 CEST 2008 - anicka@suse.cz + +- update to 5.0p1 + +------------------------------------------------------------------- +Wed Apr 2 15:06:01 CEST 2008 - anicka@suse.cz + +- update to 4.9p1 + +------------------------------------------------------------------- +Wed Dec 5 10:56:07 CET 2007 - anicka@suse.cz + +- - update to 4.7p1 + * Add "-K" flag for ssh to set GSSAPIAuthentication=yes and + GSSAPIDelegateCredentials=yes. This is symmetric with -k + * make scp try to skip FIFOs rather than blocking when nothing is + listening. + * increase default channel windows + * put the MAC list into a display + * many bugfixes + +------------------------------------------------------------------- +Tue Dec 12 14:44:41 CET 2006 - anicka@suse.cz + +- update to 4.5p1 + * Use privsep_pw if we have it, but only require it if we + absolutely need it. + * Correctly check for bad signatures in the monitor, otherwise + the monitor and the unpriv process can get out of sync. + * Clear errno before calling the strtol functions. + * exit instead of doing a blocking tcp send if we detect + a client/server timeout, since the tcp sendqueue might + be already full (of alive requests) + * include signal.h, errno.h, sys/in.h + * some more bugfixes + +------------------------------------------------------------------- +Wed Oct 4 12:56:40 CEST 2006 - postadal@suse.cz + +- updated to version 4.4p1 [#208662] + * fixed pre-authentication DoS, that would cause sshd(8) to spin + until the login grace time expired + * fixed unsafe signal hander, which was vulnerable to a race condition + that could be exploited to perform a pre-authentication DoS + * fixed a GSSAPI authentication abort that could be used to determine + the validity of usernames on some platforms + * implemented conditional configuration in sshd_config(5) using the + "Match" directive + * added support for Diffie-Hellman group exchange key agreement with a + final hash of SHA256 + * added a "ForceCommand", "PermitOpen" directive to sshd_config(5) + * added optional logging of transactions to sftp-server(8) + * ssh(1) will now record port numbers for hosts stored in + ~/.ssh/authorized_keys when a non-standard port has been requested + * added an "ExitOnForwardFailure" option to cause ssh(1) to exit (with + a non-zero exit code) when requested port forwardings could not be + established + * extended sshd_config(5) "SubSystem" declarations to allow the + specification of command-line arguments +- removed obsoleted patches: autoconf-fix.patch + +------------------------------------------------------------------- +Tue Jul 25 13:40:10 CEST 2006 - schwab@suse.de + +- Fix syntax error in configure script. + +------------------------------------------------------------------- +Wed Jan 25 21:39:06 CET 2006 - mls@suse.de + +- converted neededforbuild to BuildRequires + +------------------------------------------------------------------- +Tue Jan 3 15:54:49 CET 2006 - postadal@suse.cz + +- updated to version 4.2p1 +- removed obsoleted patches: upstream_fixes.diff, gssapi-secfix.patch + +------------------------------------------------------------------- +Thu Sep 8 16:20:06 CEST 2005 - postadal@suse.cz + +- don't strip + +------------------------------------------------------------------- +Thu Aug 4 11:30:18 CEST 2005 - uli@suse.de + +- parallelize build + +------------------------------------------------------------------- +Fri Jun 10 16:24:22 CEST 2005 - postadal@suse.cz + +- updated to version 4.1p1 +- removed obsoleted patches: restore_terminal, pam-returnfromsession, + timing-attacks-fix, krb5ccname, gssapi-pam, logdenysource, + sendenv-fix, documentation-fix + +------------------------------------------------------------------- +Wed Jan 19 18:25:29 CET 2005 - postadal@suse.cz + +- renamed askpass-gnome package to openssh-askpass-gnome + +------------------------------------------------------------------- +Wed Jan 19 15:58:07 CET 2005 - postadal@suse.cz + +- splited spec file to decreas number of build dependencies + diff --git a/openssh-askpass-gnome.spec b/openssh-askpass-gnome.spec new file mode 100644 index 0000000..bf91659 --- /dev/null +++ b/openssh-askpass-gnome.spec @@ -0,0 +1,66 @@ +# +# spec file for package openssh-askpass-gnome +# +# Copyright (c) 2020 SUSE LLC +# +# All modifications and additions to the file contributed by third parties +# remain the property of their copyright owners, unless otherwise agreed +# upon. The license for this file, and modifications and additions to the +# file, is the same license as for the pristine package itself (unless the +# license for the pristine package is not an Open Source License, in which +# case the license is the MIT License). An "Open Source License" is a +# license that conforms to the Open Source Definition (Version 1.9) +# published by the Open Source Initiative. + +# Please submit bugfixes or comments via https://bugs.opensuse.org/ +# + + +%define _name openssh +Name: openssh-askpass-gnome +Version: 9.6p1 +Release: 0 +Summary: A GNOME-Based Passphrase Dialog for OpenSSH +License: BSD-2-Clause +Group: Productivity/Networking/SSH +URL: https://www.openssh.com/ +Source: https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/%{_name}-%{version}.tar.gz +Source42: https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/%{_name}-%{version}.tar.gz.asc +Requires: %{_name}-clients = %{version} +Supplements: packageand(openssh-clients:libgtk-3-0) +%if 0%{?suse_version} >= 1550 +BuildRequires: gtk3-devel +%else +BuildRequires: gtk2-devel +%endif + +%description +SSH (Secure Shell) is a program for logging into a remote machine and +for executing commands on a remote machine. This package contains a +GNOME-based passphrase dialog for OpenSSH. + +%prep +%autosetup -p1 -n %{_name}-%{version} + +%build +cd contrib +export CFLAGS="%{optflags}" +%if 0%{?suse_version} >= 1550 +%make_build gnome-ssh-askpass3 +%else +%make_build gnome-ssh-askpass2 +%endif + +%install +install -d -m 755 %{buildroot}%{_libexecdir}/ssh/ +%if 0%{?suse_version} >= 1550 +install contrib/gnome-ssh-askpass3 %{buildroot}%{_libexecdir}/ssh/gnome-ssh-askpass +%else +install contrib/gnome-ssh-askpass2 %{buildroot}%{_libexecdir}/ssh/gnome-ssh-askpass +%endif + +%files +%dir %{_libexecdir}/ssh +%attr(0755,root,root) %{_libexecdir}/ssh/gnome-ssh-askpass + +%changelog diff --git a/openssh-do-not-send-empty-message.patch b/openssh-do-not-send-empty-message.patch new file mode 100644 index 0000000..3e956fe --- /dev/null +++ b/openssh-do-not-send-empty-message.patch @@ -0,0 +1,19 @@ +--- openssh-8.4p1.orig/auth-pam.c 2020-09-27 09:25:01.000000000 +0200 ++++ openssh-8.4p1/auth-pam.c 2022-03-04 13:02:23.447712697 +0100 +@@ -638,10 +638,12 @@ + switch (PAM_MSG_MEMBER(msg, i, msg_style)) { + case PAM_ERROR_MSG: + case PAM_TEXT_INFO: +- if ((r = sshbuf_putf(loginmsg, "%s\n", +- PAM_MSG_MEMBER(msg, i, msg))) != 0) +- fatal("%s: buffer error: %s", +- __func__, ssh_err(r)); ++ if (strlen(PAM_MSG_MEMBER(msg, i, msg)) != 0) { ++ if ((r = sshbuf_putf(loginmsg, "%s\n", ++ PAM_MSG_MEMBER(msg, i, msg))) != 0) ++ fatal("%s: buffer error: %s", ++ __func__, ssh_err(r)); ++ } + reply[i].resp_retcode = PAM_SUCCESS; + break; + default: diff --git a/openssh-fips-ensure-approved-moduli.patch b/openssh-fips-ensure-approved-moduli.patch new file mode 100644 index 0000000..b51c1c2 --- /dev/null +++ b/openssh-fips-ensure-approved-moduli.patch @@ -0,0 +1,78 @@ +commit 15c95d6eb2e8bc549719578c9a16541015363360 +Author: Hans Petter Jansson +Date: Mon Oct 26 22:26:46 2020 +0100 + + Ensure DHGs are approved in FIPS mode using OpenSSL's DH_check_params() + +Index: openssh-8.8p1/dh.c +=================================================================== +--- openssh-8.8p1.orig/dh.c ++++ openssh-8.8p1/dh.c +@@ -155,6 +155,28 @@ parse_prime(int linenum, char *line, str + return 0; + } + ++static int ++dhg_is_approved(const struct dhgroup *dhg) ++{ ++ BIGNUM *g, *p; ++ DH *dh; ++ int dh_status; ++ int is_ok = 0; ++ ++ /* DH_set0_pqg() transfers ownership of the bignums, so we ++ * make temporary copies here for simplicity. */ ++ g = BN_dup(dhg->g); ++ p = BN_dup(dhg->p); ++ dh = dh_new_group(g, p); ++ ++ if (dh) { ++ is_ok = DH_check_params(dh, &dh_status); ++ } ++ ++ DH_free(dh); ++ return is_ok; ++} ++ + DH * + choose_dh(int min, int wantbits, int max) + { +@@ -173,12 +195,20 @@ choose_dh(int min, int wantbits, int max + linenum = 0; + best = bestcount = 0; + while (getline(&line, &linesize, f) != -1) { ++ int dhg_is_ok; ++ + linenum++; + if (!parse_prime(linenum, line, &dhg)) + continue; ++ ++ dhg_is_ok = dhg_is_approved(&dhg); ++ + BN_clear_free(dhg.g); + BN_clear_free(dhg.p); + ++ if (!dhg_is_ok) ++ continue; ++ + if (dhg.size > max || dhg.size < min) + continue; + +@@ -206,10 +236,16 @@ choose_dh(int min, int wantbits, int max + linenum = 0; + bestcount = 0; + while (getline(&line, &linesize, f) != -1) { ++ int dhg_is_ok; ++ + linenum++; + if (!parse_prime(linenum, line, &dhg)) + continue; +- if ((dhg.size > max || dhg.size < min) || ++ ++ dhg_is_ok = dhg_is_approved(&dhg); ++ ++ if (!dhg_is_ok || ++ (dhg.size > max || dhg.size < min) || + dhg.size != best || + bestcount++ != which) { + BN_clear_free(dhg.g); diff --git a/openssh-link-with-sk.patch b/openssh-link-with-sk.patch new file mode 100644 index 0000000..dd1bb6d --- /dev/null +++ b/openssh-link-with-sk.patch @@ -0,0 +1,15 @@ +Index: openssh-8.8p1/Makefile.in +=================================================================== +--- openssh-8.8p1.orig/Makefile.in ++++ openssh-8.8p1/Makefile.in +@@ -252,8 +252,8 @@ ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libss + 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 $(LIBS) + +-sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a $(SFTPSERVER_OBJS) +- $(LD) -o $@ $(SFTPSERVER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) ++sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-sk.o sk-usbhid.o $(SFTPSERVER_OBJS) ++ $(LD) -o $@ $(SFTPSERVER_OBJS) ssh-sk.o sk-usbhid.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) $(LIBFIDO2) + + sftp$(EXEEXT): $(LIBCOMPAT) libssh.a $(SFTP_OBJS) + $(LD) -o $@ $(SFTP_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(LIBEDIT) diff --git a/openssh-openssl-3.patch b/openssh-openssl-3.patch new file mode 100644 index 0000000..9ca6344 --- /dev/null +++ b/openssh-openssl-3.patch @@ -0,0 +1,125 @@ +--- + fips.c | 5 +++++ + kex.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 65 insertions(+), 1 deletion(-) + +--- a/fips.c ++++ b/fips.c +@@ -48,6 +48,11 @@ + + static int fips_state = -1; + ++#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) ++# define FIPS_mode() EVP_default_properties_is_fips_enabled(NULL) ++# define FIPS_mode_set(x) EVP_default_properties_enable_fips(NULL,x) ++#endif ++ + /* calculates HMAC of contents of a file given by filename using the hash + * algorithm specified by FIPS_HMAC_EVP in fips.h and placing the result into + * newly allacated memory - remember to free it when not needed anymore */ +--- a/kex.c ++++ b/kex.c +@@ -41,6 +41,9 @@ + #include + #include + #include ++# if (OPENSSL_VERSION_NUMBER >= 0x30000000L) ++# include ++# endif + #endif + + #include "ssh.h" +@@ -1191,14 +1194,61 @@ derive_key_via_openssl(struct ssh *ssh, + { + struct kex *kex = ssh->kex; + EVP_KDF_CTX *hashctx = NULL; +- const EVP_MD *md = NULL; + u_char *digest = NULL; + int r = SSH_ERR_LIBCRYPTO_ERROR; + ++# if (OPENSSL_VERSION_NUMBER >= 0x30000000L) ++ OSSL_PARAM params[6], *p = params; ++ char type = (char) id; ++ EVP_KDF *kdf = EVP_KDF_fetch (NULL, "SSHKDF", NULL); ++ if (!kdf) ++ goto out; ++ hashctx = EVP_KDF_CTX_new (kdf); ++# else ++ const EVP_MD *md = NULL; + hashctx = EVP_KDF_CTX_new_id (EVP_KDF_SSHKDF); ++# endif + if (!hashctx) + goto out; + ++# if (OPENSSL_VERSION_NUMBER >= 0x30000000L) ++ switch (kex->hash_alg) ++ { ++ case SSH_DIGEST_MD5: ++ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, ++ SN_md5, strlen(SN_md5)); ++ break; ++ case SSH_DIGEST_SHA1: ++ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, ++ SN_sha1, strlen(SN_sha1)); ++ break; ++ case SSH_DIGEST_SHA256: ++ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, ++ SN_sha256, strlen(SN_sha256)); ++ break; ++ case SSH_DIGEST_SHA384: ++ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, ++ SN_sha384, strlen(SN_sha384)); ++ break; ++ case SSH_DIGEST_SHA512: ++ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, ++ SN_sha512, strlen(SN_sha512)); ++ break; ++ default: ++ goto out; ++ } ++ ++ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, ++ sshbuf_ptr(shared_secret), sshbuf_len(shared_secret)); ++ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SSHKDF_XCGHASH, ++ hash, (size_t) hashlen); ++ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SSHKDF_SESSION_ID, ++ sshbuf_ptr(kex->session_id), (size_t) sshbuf_len(kex->session_id)); ++ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_SSHKDF_TYPE, ++ &type, sizeof(type)); ++ *p = OSSL_PARAM_construct_end(); ++ ++# else + md = get_openssl_md_for_hash_alg (kex->hash_alg); + if (!md) + goto out; +@@ -1215,6 +1265,7 @@ derive_key_via_openssl(struct ssh *ssh, + sshbuf_ptr(kex->session_id), + (size_t) sshbuf_len(kex->session_id)) != 1) + goto out; ++# endif + + digest = calloc (1, need); + if (!digest) { +@@ -1222,7 +1273,11 @@ derive_key_via_openssl(struct ssh *ssh, + goto out; + } + ++# if (OPENSSL_VERSION_NUMBER >= 0x30000000L) ++ if (EVP_KDF_derive (hashctx, digest, need, params) != 1) ++# else + if (EVP_KDF_derive (hashctx, digest, need) != 1) ++# endif + goto out; + + *keyp = digest; +@@ -1233,6 +1288,10 @@ derive_key_via_openssl(struct ssh *ssh, + if (hashctx) + EVP_KDF_CTX_free(hashctx); + ++# if (OPENSSL_VERSION_NUMBER >= 0x30000000L) ++ EVP_KDF_free(kdf); ++# endif ++ + if (digest) + free(digest); + diff --git a/openssh-reenable-dh-group14-sha1-default.patch b/openssh-reenable-dh-group14-sha1-default.patch new file mode 100644 index 0000000..8a2293a --- /dev/null +++ b/openssh-reenable-dh-group14-sha1-default.patch @@ -0,0 +1,41 @@ +Index: openssh-8.9p1/myproposal.h +=================================================================== +--- openssh-8.9p1.orig/myproposal.h ++++ openssh-8.9p1/myproposal.h +@@ -34,7 +34,8 @@ + "diffie-hellman-group-exchange-sha256," \ + "diffie-hellman-group16-sha512," \ + "diffie-hellman-group18-sha512," \ +- "diffie-hellman-group14-sha256" ++ "diffie-hellman-group14-sha256," \ ++ "diffie-hellman-group14-sha1" + + #define KEX_CLIENT_KEX KEX_SERVER_KEX + +Index: openssh-8.9p1/ssh_config.5 +=================================================================== +--- openssh-8.9p1.orig/ssh_config.5 ++++ openssh-8.9p1/ssh_config.5 +@@ -1228,7 +1228,8 @@ sntrup761x25519-sha512@openssh.com, + diffie-hellman-group-exchange-sha256, + diffie-hellman-group16-sha512, + diffie-hellman-group18-sha512, +-diffie-hellman-group14-sha256 ++diffie-hellman-group14-sha256, ++diffie-hellman-group14-sha1 + .Ed + .Pp + The list of available key exchange algorithms may also be obtained using +Index: openssh-8.9p1/sshd_config.5 +=================================================================== +--- openssh-8.9p1.orig/sshd_config.5 ++++ openssh-8.9p1/sshd_config.5 +@@ -996,7 +996,7 @@ ecdh-sha2-nistp256,ecdh-sha2-nistp384,ec + 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-sha256,diffie-hellman-group14-sha1 + .Ed + .Pp + The list of available key exchange algorithms may also be obtained using diff --git a/openssh-whitelist-syscalls.patch b/openssh-whitelist-syscalls.patch new file mode 100644 index 0000000..0ea17d1 --- /dev/null +++ b/openssh-whitelist-syscalls.patch @@ -0,0 +1,34 @@ +Index: openssh-8.8p1/sandbox-seccomp-filter.c +=================================================================== +--- openssh-8.8p1.orig/sandbox-seccomp-filter.c ++++ openssh-8.8p1/sandbox-seccomp-filter.c +@@ -201,6 +201,9 @@ static const struct sock_filter preauth_ + #ifdef __NR_close + SC_ALLOW(__NR_close), + #endif ++#ifdef __NR_close_range ++ SC_ALLOW(__NR_close_range), ++#endif + #ifdef __NR_exit + SC_ALLOW(__NR_exit), + #endif +@@ -213,6 +216,9 @@ static const struct sock_filter preauth_ + #ifdef __NR_futex_time64 + SC_FUTEX(__NR_futex_time64), + #endif ++#ifdef __NR_futex_time64 ++ SC_ALLOW(__NR_futex_time64), ++#endif + #ifdef __NR_geteuid + SC_ALLOW(__NR_geteuid), + #endif +@@ -293,6 +299,9 @@ static const struct sock_filter preauth_ + #endif + #ifdef __NR_pselect6_time64 + SC_ALLOW(__NR_pselect6_time64), ++#endif ++#ifdef __NR_pselect6_time64 ++ SC_ALLOW(__NR_pselect6_time64), + #endif + #ifdef __NR_read + SC_ALLOW(__NR_read), diff --git a/openssh.changes b/openssh.changes new file mode 100644 index 0000000..51c4223 --- /dev/null +++ b/openssh.changes @@ -0,0 +1,6027 @@ +------------------------------------------------------------------- +Sun Feb 25 18:26:23 UTC 2024 - Hans Petter Jansson + +- Update to openssh 9.6p1: + = Security + * ssh(1), sshd(8): implement protocol extensions to thwart the + so-called "Terrapin attack" discovered by Fabian Bäumer, Marcus + Brinkmann and Jörg Schwenk. This attack allows a MITM to effect a + limited break of the integrity of the early encrypted SSH transport + protocol by sending extra messages prior to the commencement of + encryption, and deleting an equal number of consecutive messages + immediately after encryption starts. A peer SSH client/server + would not be able to detect that messages were deleted. + * ssh-agent(1): when adding PKCS#11-hosted private keys while + specifying destination constraints, if the PKCS#11 token returned + multiple keys then only the first key had the constraints applied. + Use of regular private keys, FIDO tokens and unconstrained keys + are unaffected. + * ssh(1): if an invalid user or hostname that contained shell + metacharacters was passed to ssh(1), and a ProxyCommand, + LocalCommand directive or "match exec" predicate referenced the + user or hostname via %u, %h or similar expansion token, then + an attacker who could supply arbitrary user/hostnames to ssh(1) + could potentially perform command injection depending on what + quoting was present in the user-supplied ssh_config(5) directive. + + = Potentially incompatible changes + * ssh(1), sshd(8): the RFC4254 connection/channels protocol provides + a TCP-like window mechanism that limits the amount of data that + can be sent without acceptance from the peer. In cases where this + limit was exceeded by a non-conforming peer SSH implementation, + ssh(1)/sshd(8) previously discarded the extra data. From OpenSSH + 9.6, ssh(1)/sshd(8) will now terminate the connection if a peer + exceeds the window limit by more than a small grace factor. This + change should have no effect of SSH implementations that follow + the specification. + + = New features + * ssh(1): add a %j token that expands to the configured ProxyJump + hostname (or the empty string if this option is not being used) + that can be used in a number of ssh_config(5) keywords. bz3610 + * ssh(1): add ChannelTimeout support to the client, mirroring the + same option in the server and allowing ssh(1) to terminate + quiescent channels. + * ssh(1), sshd(8), ssh-add(1), ssh-keygen(1): add support for + reading ED25519 private keys in PEM PKCS8 format. Previously + only the OpenSSH private key format was supported. + * ssh(1), sshd(8): introduce a protocol extension to allow + renegotiation of acceptable signature algorithms for public key + authentication after the server has learned the username being + used for authentication. This allows varying sshd_config(5) + PubkeyAcceptedAlgorithms in a "Match user" block. + * ssh-add(1), ssh-agent(1): add an agent protocol extension to allow + specifying certificates when loading PKCS#11 keys. This allows the + use of certificates backed by PKCS#11 private keys in all OpenSSH + tools that support ssh-agent(1). Previously only ssh(1) supported + this use-case. + + = Bugfixes + * ssh(1): when deciding whether to enable the keystroke timing + obfuscation, enable it only if a channel with a TTY is active. + * ssh(1): switch mainloop from poll(3) to ppoll(3) and mask signals + before checking flags set in signal handler. Avoids potential + race condition between signaling ssh to exit and polling. bz3531 + * ssh(1): when connecting to a destination with both the + AddressFamily and CanonicalizeHostname directives in use, + the AddressFamily directive could be ignored. bz5326 + * sftp(1): correct handling of the limits@openssh.com option when + the server returned an unexpected message. + * A number of fixes to the PuTTY and Dropbear regress/integration + tests. + * ssh(1): release GSS OIDs only at end of authentication, avoiding + unnecessary init/cleanup cycles. bz2982 + * ssh_config(5): mention "none" is a valid argument to IdentityFile + in the manual. bz3080 + * scp(1): improved debugging for paths from the server rejected for + not matching the client's glob(3) pattern in old SCP/RCP protocol + mode. + * ssh-agent(1): refuse signing operations on destination-constrained + keys if a previous session-bind operation has failed. This may + prevent a fail-open situation in future if a user uses a mismatched + ssh(1) client and ssh-agent(1) where the client supports a key type + that the agent does not support. + +- Update to openssh 9.5p1: + = Potentially incompatible changes + * ssh-keygen(1): generate Ed25519 keys by default. Ed25519 public keys + are very convenient due to their small size. Ed25519 keys are + specified in RFC 8709 and OpenSSH has supported them since version 6.5 + (January 2014). + * sshd(8): the Subsystem directive now accurately preserves quoting of + subsystem commands and arguments. This may change behaviour for exotic + configurations, but the most common subsystem configuration + (sftp-server) is unlikely to be affected. + + = New features + * ssh(1): add keystroke timing obfuscation to the client. This attempts + to hide inter-keystroke timings by sending interactive traffic at + fixed intervals (default: every 20ms) when there is only a small + amount of data being sent. It also sends fake "chaff" keystrokes for + a random interval after the last real keystroke. These are + controlled by a new ssh_config ObscureKeystrokeTiming keyword. + * ssh(1), sshd(8): Introduce a transport-level ping facility. This adds + a pair of SSH transport protocol messages SSH2_MSG_PING/PONG to + implement a ping capability. These messages use numbers in the "local + extensions" number space and are advertised using a "ping@openssh.com" + ext-info message with a string version number of "0". + * sshd(8): allow override of Subsystem directives in sshd Match blocks. + + = Bugfixes + * scp(1): fix scp in SFTP mode recursive upload and download of + directories that contain symlinks to other directories. In scp mode, + the links would be followed, but in SFTP mode they were not. bz3611 + * ssh-keygen(1): handle cr+lf (instead of just cr) line endings in + sshsig signature files. + * ssh(1): interactive mode for ControlPersist sessions if they + originally requested a tty. + * sshd(8): make PerSourceMaxStartups first-match-wins + * sshd(8): limit artificial login delay to a reasonable maximum (5s) + and don't delay at all for the "none" authentication mechanism. + bz3602 + * sshd(8): Log errors in kex_exchange_identification() with level + verbose instead of error to reduce preauth log spam. All of those + get logged with a more generic error message by sshpkt_fatal(). + * sshd(8): correct math for ClientAliveInterval that caused the probes + to be sent less frequently than configured. + * ssh(1): fix regression in OpenSSH 9.4 (mux.c r1.99) that caused + multiplexed sessions to ignore SIGINT under some circumstances. + +- Update to openssh 9.4p1: + = Potentially incompatible changes + * This release removes support for older versions of libcrypto. + OpenSSH now requires LibreSSL >= 3.1.0 or OpenSSL >= 1.1.1. + Note that these versions are already deprecated by their upstream + vendors. + * ssh-agent(1): PKCS#11 modules must now be specified by their full + paths. Previously dlopen(3) could search for them in system + library directories. + + = New features + * ssh(1): allow forwarding Unix Domain sockets via ssh -W. + * ssh(1): add support for configuration tags to ssh(1). + This adds a ssh_config(5) "Tag" directive and corresponding + "Match tag" predicate that may be used to select blocks of + configuration similar to the pf.conf(5) keywords of the same + name. + * ssh(1): add a "match localnetwork" predicate. This allows matching + on the addresses of available network interfaces and may be used to + vary the effective client configuration based on network location. + * ssh(1), sshd(8), ssh-keygen(1): infrastructure support for KRL + extensions. This defines wire formats for optional KRL extensions + and implements parsing of the new submessages. No actual extensions + are supported at this point. + * sshd(8): AuthorizedPrincipalsCommand and AuthorizedKeysCommand now + accept two additional %-expansion sequences: %D which expands to + the routing domain of the connected session and %C which expands + to the addresses and port numbers for the source and destination + of the connection. + * ssh-keygen(1): increase the default work factor (rounds) for the + bcrypt KDF used to derive symmetric encryption keys for passphrase + protected key files by 50%. + + = Bugfixes + * ssh-agent(1): improve isolation between loaded PKCS#11 modules + by running separate ssh-pkcs11-helpers for each loaded provider. + * ssh(1): make -f (fork after authentication) work correctly with + multiplexed connections, including ControlPersist. bz3589 bz3589 + * ssh(1): make ConnectTimeout apply to multiplexing sockets and not + just to network connections. + * ssh-agent(1), ssh(1): improve defences against invalid PKCS#11 + modules being loaded by checking that the requested module + contains the required symbol before loading it. + * sshd(8): fix AuthorizedPrincipalsCommand when AuthorizedKeysCommand + appears before it in sshd_config. Since OpenSSH 8.7 the + AuthorizedPrincipalsCommand directive was incorrectly ignored in + this situation. bz3574 + * sshd(8), ssh(1), ssh-keygen(1): remove vestigal support for KRL + signatures When the KRL format was originally defined, it included + support for signing of KRL objects. However, the code to sign KRLs + and verify KRL signatues was never completed in OpenSSH. This + release removes the partially-implemented code to verify KRLs. + All OpenSSH tools now ignore KRL_SECTION_SIGNATURE sections in + KRL files. + * All: fix a number of memory leaks and unreachable/harmless integer + overflows. + * ssh-agent(1), ssh(1): don't truncate strings logged from PKCS#11 + modules; GHPR406 + * sshd(8), ssh(1): better validate CASignatureAlgorithms in + ssh_config and sshd_config. Previously this directive would accept + certificate algorithm names, but these were unusable in practice as + OpenSSH does not support CA chains. bz3577 + * ssh(1): make `ssh -Q CASignatureAlgorithms` only list signature + algorithms that are valid for CA signing. Previous behaviour was + to list all signing algorithms, including certificate algorithms. + * ssh-keyscan(1): gracefully handle systems where rlimits or the + maximum number of open files is larger than INT_MAX; bz3581 + * ssh-keygen(1): fix "no comment" not showing on when running + `ssh-keygen -l` on multiple keys where one has a comment and other + following keys do not. bz3580 + * scp(1), sftp(1): adjust ftruncate() logic to handle servers that + reorder requests. Previously, if the server reordered requests then + the resultant file would be erroneously truncated. + * ssh(1): don't incorrectly disable hostname canonicalization when + CanonicalizeHostname=yes and ProxyJump was expicitly set to + "none". bz3567 + * scp(1): when copying local->remote, check that the source file + exists before opening an SFTP connection to the server. Based on + GHPR#370 + +- Dropped patches: + * cb4ed12f.patch - implemented upstream. + * openssh-cve-2023-48795.patch - implemented upstream. + +- Rebased patches: + * openssh-6.6p1-selinux-contexts.patch + * openssh-7.7p1-fips.patch + * openssh-7.8p1-role-mls.patch + * openssh-8.0p1-gssapi-keyex.patch + +------------------------------------------------------------------- +Tue Dec 19 01:42:55 UTC 2023 - Hans Petter Jansson + +- Added openssh-cve-2023-48795.patch (bsc#1217950, CVE-2023-48795). + This mitigates a prefix truncation attack that could be used to + undermine channel security. + +------------------------------------------------------------------- +Fri Nov 3 10:44:14 UTC 2023 - Johannes Segitz + +- Enhanced SELinux functionality. Added + * openssh-7.8p1-role-mls.patch + Proper handling of MLS systems and basis for other SELinux + improvements + * openssh-6.6p1-privsep-selinux.patch + Properly set contexts during privilege separation + * openssh-6.6p1-keycat.patch + Add ssh-keycat command to allow retrival of authorized_keys + on MLS setups with polyinstantiation + * openssh-6.6.1p1-selinux-contexts.patch + Additional changes to set the proper context during privilege + separation + * openssh-7.6p1-cleanup-selinux.patch + Various changes and putting the pieces together + + For now we don't ship the ssh-keycat command, but we need the patch + for the other SELinux infrastructure + + This change fixes issues like bsc#1214788, where the ssh daemon + needs to act on behalf of a user and needs a proper context for this + +------------------------------------------------------------------- +Tue Oct 24 10:56:31 UTC 2023 - Dominique Leuenberger + +- Add cb4ed12f.patch: Fix build using zlib 1.3. The check expected + a version in the form a.b.c[.d], which no longer matches 1.3. + +------------------------------------------------------------------- +Wed Sep 27 06:28:57 UTC 2023 - Thorsten Kukuk + +- Disable SLP by default for Factory and ALP (bsc#1214884) + +------------------------------------------------------------------- +Fri Jul 21 02:48:58 UTC 2023 - Simon Lees + +- Update to openssh 9.3p2 (bsc#1213504, CVE-2023-38408): + Security + ======== + + Fix CVE-2023-38408 - a condition where specific libaries loaded via + ssh-agent(1)'s PKCS#11 support could be abused to achieve remote + code execution via a forwarded agent socket if the following + conditions are met: + + * Exploitation requires the presence of specific libraries on + the victim system. + * Remote exploitation requires that the agent was forwarded + to an attacker-controlled system. + + Exploitation can also be prevented by starting ssh-agent(1) with an + empty PKCS#11/FIDO allowlist (ssh-agent -P '') or by configuring + an allowlist that contains only specific provider libraries. + + This vulnerability was discovered and demonstrated to be exploitable + by the Qualys Security Advisory team. + + In addition to removing the main precondition for exploitation, + this release removes the ability for remote ssh-agent(1) clients + to load PKCS#11 modules by default (see below). + + Potentially-incompatible changes + -------------------------------- + + * ssh-agent(8): the agent will now refuse requests to load PKCS#11 + modules issued by remote clients by default. A flag has been added + to restore the previous behaviour "-Oallow-remote-pkcs11". + + Note that ssh-agent(8) depends on the SSH client to identify + requests that are remote. The OpenSSH >=8.9 ssh(1) client does + this, but forwarding access to an agent socket using other tools + may circumvent this restriction. + + +------------------------------------------------------------------- +Wed Jun 21 12:14:54 UTC 2023 - Thorsten Kukuk + +- Disable old lastlog, we use pam_lastlog2 +- openssh-8.4p1-pam_motd.patch: adjust to remove PrintLastLog + +------------------------------------------------------------------- +Thu Jun 15 07:05:38 UTC 2023 - Thorsten Kukuk + +- logind_set_tty.patch: tell systemd-logind our current TTY + +------------------------------------------------------------------- +Thu May 11 07:01:54 UTC 2023 - Antonio Larrosa + +- Update to openssh 9.3p1: + = Security + * ssh-add(1): when adding smartcard keys to ssh-agent(1) with the + per-hop destination constraints (ssh-add -h ...) added in + OpenSSH 8.9, a logic error prevented the constraints from being + communicated to the agent. This resulted in the keys being added + without constraints. The common cases of non-smartcard keys and + keys without destination constraints are unaffected. This + problem was reported by Luci Stanescu. + + * ssh(1): Portable OpenSSH provides an implementation of the + getrrsetbyname(3) function if the standard library does not + provide it, for use by the VerifyHostKeyDNS feature. A + specifically crafted DNS response could cause this function to + perform an out-of-bounds read of adjacent stack data, but this + condition does not appear to be exploitable beyond denial-of- + service to the ssh(1) client. + The getrrsetbyname(3) replacement is only included if the + system's standard library lacks this function and portable + OpenSSH was not compiled with the ldns library (--with-ldns). + getrrsetbyname(3) is only invoked if using VerifyHostKeyDNS to + fetch SSHFP records. This problem was found by the Coverity + static analyzer. + + = New features + * ssh-keygen(1), ssh-keyscan(1): accept -Ohashalg=sha1|sha256 + when outputting SSHFP fingerprints to allow algorithm + selection. bz3493 + * sshd(8): add a `sshd -G` option that parses and prints the + effective configuration without attempting to load private keys + and perform other checks. This allows usage of the option + before keys have been generated and for configuration + evaluation and verification by unprivileged users. + + = Bugfixes + * scp(1), sftp(1): fix progressmeter corruption on wide displays; + bz3534 + * ssh-add(1), ssh-keygen(1): use RSA/SHA256 when testing + usability of private keys as some systems are starting to + disable RSA/SHA1 in libcrypto. + * sftp-server(8): fix a memory leak. GHPR363 + * ssh(1), sshd(8), ssh-keyscan(1): remove vestigal protocol + compatibility code and simplify what's left. + * Fix a number of low-impact Coverity static analysis findings. + These include several reported via bz2687 + * ssh_config(5), sshd_config(5): mention that some options are + not first-match-wins. + * Rework logging for the regression tests. Regression tests will + now capture separate logs for each ssh and sshd invocation in + a test. + * ssh(1): make `ssh -Q CASignatureAlgorithms` work as the manpage + says it should; bz3532. + * ssh(1): ensure that there is a terminating newline when adding + a new entry to known_hosts; bz3529 + + = Portability + * sshd(8): harden Linux seccomp sandbox. Move to an allowlist of + mmap(2), madvise(2) and futex(2) flags, removing some + concerning kernel attack surface. + * sshd(8): improve Linux seccomp-bpf sandbox for older systems; + bz3537 + +- Update to openssh 9.2p1: + = Security + * sshd(8): fix a pre-authentication double-free memory fault + introduced in OpenSSH 9.1. This is not believed to be + exploitable, and it occurs in the unprivileged pre-auth process + that is subject to chroot(2) and is further sandboxed on most + major platforms. + * ssh(8): in OpenSSH releases after 8.7, the PermitRemoteOpen + option would ignore its first argument unless it was one of the + special keywords "any" or "none", causing the permission list + to fail open if only one permission was specified. bz3515 + * ssh(1): if the CanonicalizeHostname and + CanonicalizePermittedCNAMEs options were enabled, and the + system/libc resolver did not check that names in DNS responses + were valid, then use of these options could allow an attacker + with control of DNS to include invalid characters (possibly + including wildcards) in names added to known_hosts files when + they were updated. These names would still have to match the + CanonicalizePermittedCNAMEs allow-list, so practical + exploitation appears unlikely. + + = Potentially-incompatible changes + * ssh(1): add a new EnableEscapeCommandline ssh_config(5) option + that controls whether the client-side ~C escape sequence that + provides a command-line is available. Among other things, the + ~C command-line could be used to add additional port-forwards + at runtime. + This option defaults to "no", disabling the ~C command-line + that was previously enabled by default. Turning off the + command-line allows platforms that support sandboxing of the + ssh(1) client (currently only OpenBSD) to use a stricter + default sandbox policy. + + = New features + * sshd(8): add support for channel inactivity timeouts via a new + sshd_config(5) ChannelTimeout directive. This allows channels + that have not seen traffic in a configurable interval to be + automatically closed. Different timeouts may be applied to + session, X11, agent and TCP forwarding channels. + * sshd(8): add a sshd_config UnusedConnectionTimeout option to + terminate client connections that have no open channels for a + length of time. This complements the ChannelTimeout option + above. + * sshd(8): add a -V (version) option to sshd like the ssh client + has. + * ssh(1): add a "Host" line to the output of ssh -G showing the + original hostname argument. bz3343 + * scp(1), sftp(1): add a -X option to both scp(1) and sftp(1) to + allow control over some SFTP protocol parameters: the copy + buffer length and the number of in-flight requests, both of + which are used during upload/download. Previously these could + be controlled in sftp(1) only. This makes them available in + both SFTP protocol clients using the same option character + sequence. + * ssh-keyscan(1): allow scanning of complete CIDR address ranges, + e.g. "ssh-keyscan 192.168.0.0/24". If a CIDR range is passed, + then it will be expanded to all possible addresses in the range + including the all-0s and all-1s addresses. bz#976 + * ssh(1): support dynamic remote port forwarding in escape + command-line's -R processing. bz#3499 + + = Bugfixes + * ssh(1): when restoring non-blocking mode to stdio fds, restore + exactly the flags that ssh started with and don't just clobber + them with zero, as this could also remove the append flag from + the set. bz3523 + * ssh(1): avoid printf("%s", NULL) if using + UserKnownHostsFile=none and a hostkey in one of the system + known hosts file changes. + * scp(1): switch scp from using pipes to a socket-pair for + communication with its ssh sub-processes, matching how sftp(1) + operates. + * sshd(8): clear signal mask early in main(); sshd may have been + started with one or more signals masked (sigprocmask(2) is not + cleared on fork/exec) and this could interfere with various + things, e.g. the login grace timer. Execution environments that + fail to clear the signal mask before running sshd are clearly + broken, but apparently they do exist. + * ssh(1): warn if no host keys for hostbased auth can be loaded. + * sshd(8): Add server debugging for hostbased auth that is queued + and sent to the client after successful authentication, but + also logged to assist in diagnosis of HostbasedAuthentication + problems. bz3507 + * ssh(1): document use of the IdentityFile option as being usable + to list public keys as well as private keys. GHPR352 + * sshd(8): check for and disallow MaxStartups values less than or + equal to zero during config parsing, rather than failing later + at runtime. bz3489 + * ssh-keygen(1): fix parsing of hex cert expiry times specified + on the command-line when acting as a CA. + * scp(1): when scp(1) is using the SFTP protocol for transport + (the default), better match scp/rcp's handling of globs that + don't match the globbed characters but do match literally (e.g. + trying to transfer a file named "foo.[1]"). Previously scp(1) + in SFTP mode would not match these pathnames but legacy scp/rcp + mode would. bz3488 + * ssh-agent(1): document the "-O no-restrict-websafe" + command-line option. + * ssh(1): honour user's umask(2) if it is more restrictive then + the ssh default (022). + + = Portability + * sshd(8): allow writev(2) in the Linux seccomp sandbox. This + seems to be used by recent glibcs at least in some + configurations during error conditions. bz3512. + * sshd(8): simply handling of SSH_CONNECTION PAM env var, + removing global variable and checking the return value from + pam_putenv. bz3508 + * sshd(8): disable SANDBOX_SECCOMP_FILTER_DEBUG that was + mistakenly enabled during the OpenSSH 9.1 release cycle. + * misc: update autotools and regenerate the config files using + the latest autotools + * all: use -fzero-call-used-regs=used on clang 15 instead of + -fzero-call-used-reg=all, as some versions of clang 15 have + miscompile code when it was enabled. bz3475 + * sshd(8): defer PRNG seeding until after the initial + closefrom(2) call. PRNG seeding will initialize OpenSSL, and + some engine providers (e.g. Intel's QAT) will open descriptors + for their own use that closefrom(2) could clobber. bz3483 + * misc: in the poll(2)/ppoll(2) compatibility code, avoid + assuming the layout of fd_set. + * sftp-server(8), ssh-agent(1): fix ptrace(2) disabling on older + FreeBSD kernels. Some versions do not support using id 0 to + refer to the current PID for procctl, so try again with + getpid() explicitly before failing. + * configure.ac: fix -Wstrict-prototypes in configure test code. + Clang 16 now warns on this and legacy prototypes will be + removed in C23. GHPR355 + * configure.ac: fix setres*id checks to work with clang-16. glibc + has the prototypes for setresuid behind _GNU_SOURCE, and + clang 16 will error out on implicit function definitions. + bz3497 + +- Update to openssh 9.1p1: + = Security + * ssh-keyscan(1): fix a one-byte overflow in SSH- banner + processing. + Reported by Qualys + * ssh-keygen(1): double free() in error path of file hashing step + in signing/verify code; GHPR333 + * ssh-keysign(8): double-free in error path introduced in + openssh-8.9 + + = Potentially-incompatible changes + * The portable OpenSSH project now signs commits and release tags + using git's recent SSH signature support. The list of developer + signing keys is included in the repository as + .git_allowed_signers and is cross-signed using the PGP key that + is still used to sign release artifacts: + https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/RELEASE_KEY.asc + * ssh(1), sshd(8): SetEnv directives in ssh_config and + sshd_config are now first-match-wins to match other directives. + Previously if an environment variable was multiply specified + the last set value would have been used. bz3438 + * ssh-keygen(8): ssh-keygen -A (generate all default host key + types) will no longer generate DSA keys, as these are insecure + and have not been used by default for some years. + + = New features + * ssh(1), sshd(8): add a RequiredRSASize directive to set a + minimum RSA key length. Keys below this length will be ignored + for user authentication and for host authentication in sshd(8). + ssh(1) will terminate a connection if the server offers an RSA + key that falls below this limit, as the SSH protocol does not + include the ability to retry a failed key exchange. + * sftp-server(8): add a "users-groups-by-id@openssh.com" + extension request that allows the client to obtain user/group + names that correspond to a set of uids/gids. + * sftp(1): use "users-groups-by-id@openssh.com" sftp-server + extension (when available) to fill in user/group names for + directory listings. + * sftp-server(8): support the "home-directory" extension request + defined in draft-ietf-secsh-filexfer-extensions-00. This + overlaps a bit with the existing "expand-path@openssh.com", but + some other clients support it. + * ssh-keygen(1), sshd(8): allow certificate validity intervals, + sshsig verification times and authorized_keys expiry-time + options to accept dates in the UTC time zone in addition to the + default of interpreting them in the system time zone. YYYYMMDD + and YYMMDDHHMM[SS] dates/times will be interpreted as UTC if + suffixed with a 'Z' character. + Also allow certificate validity intervals to be specified in + raw seconds-since-epoch as hex value, e.g. -V 0x1234:0x4567890. + This is intended for use by regress tests and other tools that + call ssh-keygen as part of a CA workflow. bz3468 + * sftp(1): allow arguments to the sftp -D option, e.g. sftp -D + "/usr/libexec/sftp-server -el debug3" + * ssh-keygen(1): allow the existing -U (use agent) flag to work + with "-Y sign" operations, where it will be interpreted to + require that the private keys is hosted in an agent; bz3429 + + = Bugfixes + * ssh-keygen(1): implement the "verify-required" certificate + option. + This was already documented when support for user-verified FIDO + keys was added, but the ssh-keygen(1) code was missing. + * ssh-agent(1): hook up the restrict_websafe command-line flag; + previously the flag was accepted but never actually used. + * sftp(1): improve filename tab completions: never try to + complete names to non-existent commands, and better match the + completion type (local or remote filename) against the argument + position being completed. + * ssh-keygen(1), ssh(1), ssh-agent(1): several fixes to FIDO key + handling, especially relating to keys that request + user-verification. These should reduce the number of + unnecessary PIN prompts for keys that support intrinsic user + verification. GHPR302, GHPR329 + * ssh-keygen(1): when enrolling a FIDO resident key, check if a + credential with matching application and user ID strings + already exists and, if so, prompt the user for confirmation + before overwriting the credential. GHPR329 + * sshd(8): improve logging of errors when opening authorized_keys + files. bz2042 + * ssh(1): avoid multiplexing operations that could cause SIGPIPE + from causing the client to exit early. bz3454 + * ssh_config(5), sshd_config(5): clarify that the RekeyLimit + directive applies to both transmitted and received data. + GHPR328 + * ssh-keygen(1): avoid double fclose() in error path. + * sshd(8): log an error if pipe() fails while accepting a + connection. bz3447 + * ssh(1), ssh-keygen(1): fix possible NULL deref when built + without FIDO support. bz3443 + * ssh-keyscan(1): add missing *-sk types to ssh-keyscan manpage. + GHPR294. + * sshd(8): ensure that authentication passwords are cleared from + memory in error paths. GHPR286 + * ssh(1), ssh-agent(1): avoid possibility of notifier code + executing kill(-1). GHPR286 + * ssh_config(5): note that the ProxyJump directive also accepts + the same tokens as ProxyCommand. GHPR305. + * scp(1): do not not ftruncate(3) files early when in sftp mode. + The previous behaviour of unconditionally truncating the + destination file would cause "scp ~/foo localhost:foo" and the + reverse "scp localhost:foo ~/foo" to delete all the contents of + their destination. bz3431 + * ssh-keygen(1): improve error message when 'ssh-keygen -Y sign' + is unable to load a private key; bz3429 + * sftp(1), scp(1): when performing operations that glob(3) a + remote path, ensure that the implicit working directory used to + construct that path escapes glob(3) characters. This prevents + glob characters from being processed in places they shouldn't, + e.g. "cd /tmp/a*/", "get *.txt" should have the get operation + treat the path "/tmp/a*" literally and not attempt to expand + it. + * ssh(1), sshd(8): be stricter in which characters will be + accepted in specifying a mask length; allow only 0-9. GHPR278 + * ssh-keygen(1): avoid printing hash algorithm twice when dumping + a KRL + * ssh(1), sshd(8): continue running local I/O for open channels + during SSH transport rekeying. This should make ~-escapes work + in the client (e.g. to exit) if the connection happened to have + stalled during a rekey event. + * ssh(1), sshd(8): avoid potential poll() spin during rekeying + * Further hardening for sshbuf internals: disallow "reparenting" + a hierarchical sshbuf and zero the entire buffer if + reallocation fails. GHPR287 + + = Portability + * ssh(1), ssh-keygen(1), sshd(8): automatically enable the + built-in FIDO security key support if libfido2 is found and + usable, unless --without-security-key-builtin was requested. + * ssh(1), ssh-keygen(1), sshd(8): many fixes to make the WinHello + FIDO device usable on Cygwin. The windows://hello FIDO device + will be automatically used by default on this platform unless + requested otherwise, or when probing resident FIDO credentials + (an operation not currently supported by WinHello). + * Portable OpenSSH: remove workarounds for obsolete and + unsupported versions of OpenSSL libcrypto. In particular, this + release removes fallback support for OpenSSL that lacks AES-CTR + or AES-GCM. Those AES cipher modes were added to OpenSSL prior + to the minimum version currently supported by OpenSSH, so this + is not expected to impact any currently supported + configurations. + * sshd(8): fix SANDBOX_SECCOMP_FILTER_DEBUG on current + Linux/glibc + * All: resync and clean up internal CSPRNG code. + * scp(1), sftp(1), sftp-server(8): avoid linking these programs + with unnecessary libraries. They are no longer linked against + libz and libcrypto. This may be of benefit to space constrained + systems using any of those components in isolation. + * sshd(8): add AUDIT_ARCH_PPC to supported seccomp sandbox + architectures. + * configure: remove special casing of crypt(). configure will no + longer search for crypt() in libcrypto, as it was removed from + there years ago. configure will now only search libc and + libcrypt. + * configure: refuse to use OpenSSL 3.0.4 due to potential RCE in + its RSA implementation (CVE-2022-2274) on x86_64. + * All: request 1.1x API compatibility for OpenSSL >=3.x; GHPR322 + * ssh(1), ssh-keygen(1), sshd(8): fix a number of missing + includes required by the XMSS code on some platforms. + * sshd(8): cache timezone data in capsicum sandbox. + +- Update to openssh 9.0p1: + = Potentially-incompatible changes + * This release switches scp(1) from using the legacy scp/rcp + protocol to using the SFTP protocol by default. + Legacy scp/rcp performs wildcard expansion of remote filenames + (e.g. "scp host:* .") through the remote shell. This has the + side effect of requiring double quoting of shell + meta-characters in file names included on scp(1) command-lines, + otherwise they could be interpreted as shell commands on the + remote side. + This creates one area of potential incompatibility: scp(1) when + using the SFTP protocol no longer requires this finicky and + brittle quoting, and attempts to use it may cause transfers to + fail. We consider the removal of the need for double-quoting + shell characters in file names to be a benefit and do not + intend to introduce bug-compatibility for legacy scp/rcp in + scp(1) when using the SFTP protocol. + Another area of potential incompatibility relates to the use of + remote paths relative to other user's home directories, for + example - "scp host:~user/file /tmp". The SFTP protocol has no + native way to expand a ~user path. However, sftp-server(8) in + OpenSSH 8.7 and later support a protocol extension + "expand-path@openssh.com" to support this. + In case of incompatibility, the scp(1) client may be instructed + to use the legacy scp/rcp using the -O flag. + + = New features + * ssh(1), sshd(8): use the hybrid Streamlined NTRU Prime + x25519 + key exchange method by default + ("sntrup761x25519-sha512@openssh.com"). The NTRU algorithm is + believed to resist attacks enabled by future quantum computers + and is paired with the X25519 ECDH key exchange (the previous + default) as a backstop against any weaknesses in NTRU Prime + that may be discovered in the future. The combination ensures + that the hybrid exchange offers at least as good security as + the status quo. + We are making this change now (i.e. ahead of cryptographically- + relevant quantum computers) to prevent "capture now, decrypt + later" attacks where an adversary who can record and store SSH + session ciphertext would be able to decrypt it once a + sufficiently advanced quantum computer is available. + * sftp-server(8): support the "copy-data" extension to allow + server-side copying of files/data, following the design in + draft-ietf-secsh-filexfer-extensions-00. bz2948 + * sftp(1): add a "cp" command to allow the sftp client to perform + server-side file copies. + + = Bugfixes + * ssh(1), sshd(8): upstream: fix poll(2) spin when a channel's + output fd closes without data in the channel buffer. bz3405 and + bz3411 + * sshd(8): pack pollfd array in server listen/accept loop. Could + cause the server to hang/spin when MaxStartups > RLIMIT_NOFILE + * ssh-keygen(1): avoid NULL deref via the find-principals and + check-novalidate operations. bz3409 and GHPR307 respectively. + * scp(1): fix a memory leak in argument processing. bz3404 + * sshd(8): don't try to resolve ListenAddress directives in the + sshd re-exec path. They are unused after re-exec and parsing + errors (possible for example if the host's network + configuration changed) could prevent connections from being + accepted. + * sshd(8): when refusing a public key authentication request from + a client for using an unapproved or unsupported signature + algorithm include the algorithm name in the log message to make + debugging easier. + + = Portability + * sshd(8): refactor platform-specific locked account check, + fixing an incorrect free() on platforms with both libiaf and + shadow passwords (probably only Unixware) GHPR284, + * ssh(1), sshd(8): Fix possible integer underflow in + scan_scaled(3) parsing of K/M/G/etc quantities. bz#3401. + * sshd(8): provide killpg implementation (mostly for Tandem + NonStop) GHPR301. + * Check for missing ftruncate prototype. GHPR301 + * sshd(8): default to not using sandbox when cross compiling. On + most systems poll(2) does not work when the number of FDs is + reduced with setrlimit, so assume it doesn't when cross + compiling and we can't run the test. bz#3398. + * sshd(8): allow ppoll_time64 in seccomp sandbox. Should fix + sandbox violations on some (at least i386 and armhf) 32bit + Linux platforms. bz#3396. + * Improve detection of -fzero-call-used-regs=all support in + configure script. + +- Add patch that explicitly adds -lz in Makefile.in to some + binaries which need it: + * fix-missing-lz.patch +- Rebase patches: + * openssh-7.7p1-fips.patch + * openssh-7.7p1-fips_checks.patch + * openssh-7.7p1-ldap.patch + * openssh-7.7p1-pam_check_locks.patch + * openssh-7.7p1-seccomp_ipc_flock.patch + * openssh-7.7p1-sftp_print_diagnostic_messages.patch + * openssh-7.7p1-systemd-notify.patch + * openssh-8.0p1-gssapi-keyex.patch + * openssh-8.1p1-audit.patch + * openssh-8.1p1-ed25519-use-openssl-rng.patch + * openssh-8.4p1-vendordir.patch + * openssh-reenable-dh-group14-sha1-default.patch + * openssh-whitelist-syscalls.patch + * wtmpdb.patch +- Fix setting libexec dir in the LDAP patch. +- Fix build in Leap 15.x which doesn't use %{_distconfdir} + +------------------------------------------------------------------- +Fri May 5 15:18:20 UTC 2023 - Dominique Leuenberger + +- Add _multibuild to define 2nd spec file as additional flavor. + Eliminates the need for source package links in OBS. + +------------------------------------------------------------------- +Mon Apr 17 13:14:49 UTC 2023 - Thorsten Kukuk + +- wtmpdb.patch: add support for wtmpdb to sshd [jsc#PED-3144] + +------------------------------------------------------------------- +Mon Mar 27 08:39:38 UTC 2023 - Thorsten Kukuk + +- Rename sshd.pamd to sshd-sle.pamd and fix order of pam_keyinit +- Add new sshd.pamd including postlogin-* config files + +------------------------------------------------------------------- +Wed Feb 15 10:35:43 UTC 2023 - Thorsten Kukuk + +- Remove BuildRequires for libtirpc, we don't use it + +------------------------------------------------------------------- +Tue Feb 14 13:46:14 UTC 2023 - Thorsten Kukuk + +- Remove pam_lastlog from sshd PAM config. sshd is doing the same, + too, which leads to e.g. duplicate entries in wtmp [bsc#1208243] + +------------------------------------------------------------------- +Mon Dec 19 15:41:26 UTC 2022 - Otto Hollmann + +- Adapt OpenSSH to build with OpenSSL 3, use new KDF API (bsc#1205042) + Add openssh-openssl-3.patch + +------------------------------------------------------------------- +Thu Dec 15 16:35:33 UTC 2022 - Dirk Müller + +- limit to openssl < 3.0 as this version is not compatible (bsc#1205042) + next version update will fix it + +------------------------------------------------------------------- +Thu Nov 10 02:18:08 UTC 2022 - Hans Petter Jansson + +- Update openssh-8.1p1-audit.patch: Merge fix for race condition + (bsc#1115550, bsc#1174162). +- Add openssh-do-not-send-empty-message.patch, which prevents + superfluous newlines with empty MOTD files (bsc#1192439). + +------------------------------------------------------------------- +Mon Aug 8 07:36:55 UTC 2022 - Thorsten Kukuk + +- Use %_pam_vendordir + +------------------------------------------------------------------- +Wed Jul 6 12:15:29 UTC 2022 - Adam Majer + +- openssh-8.4p1-ssh_config_d.patch: admin overrides should take + priority (listed first) over package defaults + +------------------------------------------------------------------- +Mon Mar 28 15:00:52 UTC 2022 - Ludwig Nussel + +- read ssh and sshd config file also from /usr/etc +- add openssh-server-config-rootlogin subpackage that enabled PermitRootLogin + +------------------------------------------------------------------- +Mon Mar 7 18:00:09 UTC 2022 - Hans Petter Jansson + +- Version update to 8.9p1: + = Security + * sshd(8): fix an integer overflow in the user authentication path + that, in conjunction with other logic errors, could have yielded + unauthenticated access under difficult to exploit conditions. + + This situation is not exploitable because of independent checks in + the privilege separation monitor. Privilege separation has been + enabled by default in since openssh-3.2.2 (released in 2002) and + has been mandatory since openssh-7.5 (released in 2017). Moreover, + portable OpenSSH has used toolchain features available in most + modern compilers to abort on signed integer overflow since + openssh-6.5 (released in 2014). + + Thanks to Malcolm Stagg for finding and reporting this bug. + + = Potentially-incompatible changes + * sshd(8), portable OpenSSH only: this release removes in-built + support for MD5-hashed passwords. If you require these on your + system then we recommend linking against libxcrypt or similar. + * This release modifies the FIDO security key middleware interface + and increments SSH_SK_VERSION_MAJOR. + + = New features + * ssh(1), sshd(8), ssh-add(1), ssh-agent(1): add a system for + restricting forwarding and use of keys added to ssh-agent(1) + A detailed description of the feature is available at + https://www.openssh.com/agent-restrict.html and the protocol + extensions are documented in the PROTOCOL and PROTOCOL.agent + files in the source release. + * ssh(1), sshd(8): add the sntrup761x25519-sha512@openssh.com hybrid + ECDH/x25519 + Streamlined NTRU Prime post-quantum KEX to the + default KEXAlgorithms list (after the ECDH methods but before the + prime-group DH ones). The next release of OpenSSH is likely to + make this key exchange the default method. + * ssh-keygen(1): when downloading resident keys from a FIDO token, + pass back the user ID that was used when the key was created and + append it to the filename the key is written to (if it is not the + default). Avoids keys being clobbered if the user created multiple + resident keys with the same application string but different user + IDs. + * ssh-keygen(1), ssh(1), ssh-agent(1): better handling for FIDO keys + on tokens that provide user verification (UV) on the device itself, + including biometric keys, avoiding unnecessary PIN prompts. + * ssh-keygen(1): add "ssh-keygen -Y match-principals" operation to + perform matching of principals names against an allowed signers + file. To be used towards a TOFU model for SSH signatures in git. + * ssh-add(1), ssh-agent(1): allow pin-required FIDO keys to be added + to ssh-agent(1). $SSH_ASKPASS will be used to request the PIN at + authentication time. + * ssh-keygen(1): allow selection of hash at sshsig signing time + (either sha512 (default) or sha256). + * ssh(1), sshd(8): read network data directly to the packet input + buffer instead of indirectly via a small stack buffer. Provides a + modest performance improvement. + * ssh(1), sshd(8): read data directly to the channel input buffer, + providing a similar modest performance improvement. + * ssh(1): extend the PubkeyAuthentication configuration directive to + accept yes|no|unbound|host-bound to allow control over one of the + protocol extensions used to implement agent-restricted keys. + + = Bugfixes + * sshd(8): document that CASignatureAlgorithms, ExposeAuthInfo and + PubkeyAuthOptions can be used in a Match block. PR277. + * sshd(8): fix possible string truncation when constructing paths to + .rhosts/.shosts files with very long user home directory names. + * ssh-keysign(1): unbreak for KEX algorithms that use SHA384/512 + exchange hashes + * ssh(1): don't put the TTY into raw mode when SessionType=none, + avoids ^C being unable to kill such a session. bz3360 + * scp(1): fix some corner-case bugs in SFTP-mode handling of + ~-prefixed paths. + * ssh(1): unbreak hostbased auth using RSA keys. Allow ssh(1) to + select RSA keys when only RSA/SHA2 signature algorithms are + configured (this is the default case). Previously RSA keys were + not being considered in the default case. + * ssh-keysign(1): make ssh-keysign use the requested signature + algorithm and not the default for the key type. Part of unbreaking + hostbased auth for RSA/SHA2 keys. + * ssh(1): stricter UpdateHostkey signature verification logic on + the client- side. Require RSA/SHA2 signatures for RSA hostkeys + except when RSA/SHA1 was explicitly negotiated during initial + KEX; bz3375 + * ssh(1), sshd(8): fix signature algorithm selection logic for + UpdateHostkeys on the server side. The previous code tried to + prefer RSA/SHA2 for hostkey proofs of RSA keys, but missed some + cases. This will use RSA/SHA2 signatures for RSA keys if the + client proposed these algorithms in initial KEX. bz3375 + * All: convert all uses of select(2)/pselect(2) to poll(2)/ppoll(2). + This includes the mainloops in ssh(1), ssh-agent(1), ssh-agent(1) + and sftp-server(8), as well as the sshd(8) listen loop and all + other FD read/writability checks. On platforms with missing or + broken poll(2)/ppoll(2) syscalls a select(2)-based compat shim is + available. + * ssh-keygen(1): the "-Y find-principals" command was verifying key + validity when using ca certs but not with simple key lifetimes + within the allowed signers file. + * ssh-keygen(1): make sshsig verify-time argument parsing optional + * sshd(8): fix truncation in rhosts/shosts path construction. + * ssh(1), ssh-agent(1): avoid xmalloc(0) for PKCS#11 keyid for ECDSA + keys (we already did this for RSA keys). Avoids fatal errors for + PKCS#11 libraries that return empty keyid, e.g. Microchip ATECC608B + "cryptoauthlib"; bz#3364 + * ssh(1), ssh-agent(1): improve the testing of credentials against + inserted FIDO: ask the token whether a particular key belongs to + it in cases where the token supports on-token user-verification + (e.g. biometrics) rather than just assuming that it will accept it. + Will reduce spurious "Confirm user presence" notifications for key + handles that relate to FIDO keys that are not currently inserted in at + least some cases. bz3366 + * ssh(1), sshd(8): correct value for IPTOS_DSCP_LE. It needs to + allow for the preceding two ECN bits. bz#3373 + * ssh-keygen(1): add missing -O option to usage() for the "-Y sign" + option. + * ssh-keygen(1): fix a NULL deref when using the find-principals + function, when matching an allowed_signers line that contains a + namespace restriction, but no restriction specified on the + command-line + * ssh-agent(1): fix memleak in process_extension(); oss-fuzz + issue #42719 + * ssh(1): suppress "Connection to xxx closed" messages when LogLevel + is set to "error" or above. bz3378 + * ssh(1), sshd(8): use correct zlib flags when inflate(3)-ing + compressed packet data. bz3372 + * scp(1): when recursively transferring files in SFTP mode, create the + destination directory if it doesn't already exist to match scp(1) in + legacy RCP mode behaviour. + * scp(1): many improvements in error message consistency between scp(1) + in SFTP mode vs legacy RCP mode. + * sshd(8): fix potential race in SIGTERM handling PR289 + * ssh(1), ssh(8): since DSA keys are deprecated, move them to the + end of the default list of public keys so that they will be tried + last. PR295 + * ssh-keygen(1): allow 'ssh-keygen -Y find-principals' to match + wildcard principals in allowed_signers files + + = Portability + * ssh(1), sshd(8): don't trust closefrom(2) on Linux. glibc's + implementation does not work in a chroot when the kernel does not + have close_range(2). It tries to read from /proc/self/fd and when + that fails dies with an assertion of sorts. Instead, call + close_range(2) directly from our compat code and fall back if + that fails. bz#3349, + * OS X poll(2) is broken; use compat replacement. For character- + special devices like /dev/null, Darwin's poll(2) returns POLLNVAL + when polled with POLLIN. Apparently this is Apple bug 3710161 - + not public but a websearch will find other OSS projects + rediscovering it periodically since it was first identified in + 2005. + * Correct handling of exceptfds/POLLPRI in our select(2)-based + poll(2)/ppoll(2) compat implementation. + * Cygwin: correct checking of mbstowcs() return value. + * Add a basic SECURITY.md that refers people to the openssh.com + website. + * Enable additional compiler warnings and toolchain hardening flags, + including -Wbitwise-instead-of-logical, -Wmisleading-indentation, + -fzero-call-used-regs and -ftrivial-auto-var-init. + * HP/UX. Use compat getline(3) on HP-UX 10.x, where the libc version + is not reliable. + +- Rebased patches: + * openssh-7.7p1-ldap.patch + * openssh-8.0p1-gssapi-keyex.patch + * openssh-8.1p1-audit.patch + * openssh-8.4p1-vendordir.patch + * openssh-reenable-dh-group14-sha1-default.patch + +------------------------------------------------------------------- +Tue Sep 28 17:50:57 UTC 2021 - Hans Petter Jansson + +- Version update to 8.8p1: + = Security + * sshd(8) from OpenSSH 6.2 through 8.7 failed to correctly initialise + supplemental groups when executing an AuthorizedKeysCommand or + AuthorizedPrincipalsCommand, where a AuthorizedKeysCommandUser or + AuthorizedPrincipalsCommandUser directive has been set to run the + command as a different user. Instead these commands would inherit + the groups that sshd(8) was started with. + + Depending on system configuration, inherited groups may allow + AuthorizedKeysCommand/AuthorizedPrincipalsCommand helper programs to + gain unintended privilege. + + Neither AuthorizedKeysCommand nor AuthorizedPrincipalsCommand are + enabled by default in sshd_config(5). + + = Potentially-incompatible changes + * This release disables RSA signatures using the SHA-1 hash algorithm + by default. This change has been made as the SHA-1 hash algorithm is + cryptographically broken, and it is possible to create chosen-prefix + hash collisions for argv conversion. Multiple + backslashes were not being dequoted correctly and quoted space in + the middle of a string was being incorrectly split. GHPR223 + * ssh(1): return non-zero exit status when killed by signal; bz#3281 + * sftp-server(8): increase maximum SSH2_FXP_READ to match the maximum + packet size. Also handle zero-length reads that are not explicitly + banned by the spec. + +- Additional changes from 8.5p1 release: + = Security + * ssh-agent(1): fixed a double-free memory corruption that was + introduced in OpenSSH 8.2 . We treat all such memory faults as + potentially exploitable. This bug could be reached by an attacker + with access to the agent socket. + + = Potentially-incompatible changes + * ssh(1), sshd(8): this release changes the first-preference signature + algorithm from ECDSA to ED25519. + * ssh(1), sshd(8): set the TOS/DSCP specified in the configuration + for interactive use prior to TCP connect. The connection phase of + the SSH session is time-sensitive and often explicitly interactive. + The ultimate interactive/bulk TOS/DSCP will be set after + authentication completes. + * ssh(1), sshd(8): remove the pre-standardization cipher + rijndael-cbc@lysator.liu.se. It is an alias for aes256-cbc before + it was standardized in RFC4253 (2006), has been deprecated and + disabled by default since OpenSSH 7.2 (2016) and was only briefly + documented in ssh.1 in 2001. + * ssh(1), sshd(8): update/replace the experimental post-quantum + hybrid key exchange method based on Streamlined NTRU Prime coupled + with X25519. The previous sntrup4591761x25519-sha512@tinyssh.org + method is replaced with sntrup761x25519-sha512@openssh.com. + * ssh(1): disable CheckHostIP by default. It provides insignificant + benefits while making key rotation significantly more difficult, + especially for hosts behind IP-based load-balancers. + + = New features + * ssh(1): this release enables UpdateHostkeys by default subject to + some conservative preconditions: + - The key was matched in the UserKnownHostsFile (and not in the + GlobalKnownHostsFile). + - The same key does not exist under another name. + - A certificate host key is not in use. + - known_hosts contains no matching wildcard hostname pattern. + - VerifyHostKeyDNS is not enabled. + - The default UserKnownHostsFile is in use. + * ssh(1), sshd(8): add a new LogVerbose configuration directive for + that allows forcing maximum debug logging by file/function/line + pattern-lists. + * ssh(1): when prompting the user to accept a new hostkey, display + any other host names/addresses already associated with the key. + * ssh(1): allow UserKnownHostsFile=none to indicate that no + known_hosts file should be used to identify host keys. + * ssh(1): add a ssh_config KnownHostsCommand option that allows the + client to obtain known_hosts data from a command in addition to + the usual files. + * ssh(1): add a ssh_config PermitRemoteOpen option that allows the + client to restrict the destination when RemoteForward is used + with SOCKS. + * ssh(1): for FIDO keys, if a signature operation fails with a + "incorrect PIN" reason and no PIN was initially requested from the + user, then request a PIN and retry the operation. This supports + some biometric devices that fall back to requiring PIN when reading + of the biometric failed, and devices that require PINs for all + hosted credentials. + * sshd(8): implement client address-based rate-limiting via new + sshd_config(5) PerSourceMaxStartups and PerSourceNetBlockSize + directives that provide more fine-grained control on a per-origin + address basis than the global MaxStartups limit. + + = Bugfixes + * ssh(1): Prefix keyboard interactive prompts with "(user@host)" to + make it easier to determine which connection they are associated + with in cases like scp -3, ProxyJump, etc. bz#3224 + * sshd(8): fix sshd_config SetEnv directives located inside Match + blocks. GHPR201 + * ssh(1): when requesting a FIDO token touch on stderr, inform the + user once the touch has been recorded. + * ssh(1): prevent integer overflow when ridiculously large + ConnectTimeout values are specified, capping the effective value + (for most platforms) at 24 days. bz#3229 + * ssh(1): consider the ECDSA key subtype when ordering host key + algorithms in the client. + * ssh(1), sshd(8): rename the PubkeyAcceptedKeyTypes keyword to + PubkeyAcceptedAlgorithms. The previous name incorrectly suggested + that it control allowed key algorithms, when this option actually + specifies the signature algorithms that are accepted. The previous + name remains available as an alias. bz#3253 + * ssh(1), sshd(8): similarly, rename HostbasedKeyTypes (ssh) and + HostbasedAcceptedKeyTypes (sshd) to HostbasedAcceptedAlgorithms. + * sftp-server(8): add missing lsetstat@openssh.com documentation + and advertisement in the server's SSH2_FXP_VERSION hello packet. + * ssh(1), sshd(8): more strictly enforce KEX state-machine by + banning packet types once they are received. Fixes memleak caused + by duplicate SSH2_MSG_KEX_DH_GEX_REQUEST (oss-fuzz #30078). + * sftp(1): allow the full range of UIDs/GIDs for chown/chgrp on 32bit + platforms instead of being limited by LONG_MAX. bz#3206 + * Minor man page fixes (capitalization, commas, etc.) bz#3223 + * sftp(1): when doing an sftp recursive upload or download of a + read-only directory, ensure that the directory is created with + write and execute permissions in the interim so that the transfer + can actually complete, then set the directory permission as the + final step. bz#3222 + * ssh-keygen(1): document the -Z, check the validity of its argument + earlier and provide a better error message if it's not correct. + bz#2879 + * ssh(1): ignore comments at the end of config lines in ssh_config, + similar to what we already do for sshd_config. bz#2320 + * sshd_config(5): mention that DisableForwarding is valid in a + sshd_config Match block. bz3239 + * sftp(1): fix incorrect sorting of "ls -ltr" under some + circumstances. bz3248. + * ssh(1), sshd(8): fix potential integer truncation of (unlikely) + timeout values. bz#3250 + * ssh(1): make hostbased authentication send the signature algorithm + in its SSH2_MSG_USERAUTH_REQUEST packets instead of the key type. + This make HostbasedAcceptedAlgorithms do what it is supposed to - + filter on signature algorithm and not key type. + +- Rebased patches: + * openssh-7.7p1-IPv6_X_forwarding.patch + * openssh-7.7p1-X11_trusted_forwarding.patch + * openssh-7.7p1-X_forward_with_disabled_ipv6.patch + * openssh-7.7p1-cavstest-ctr.patch + * openssh-7.7p1-cavstest-kdf.patch + * openssh-7.7p1-disable_openssl_abi_check.patch + * openssh-7.7p1-eal3.patch + * openssh-7.7p1-enable_PAM_by_default.patch + * openssh-7.7p1-fips.patch + * openssh-7.7p1-fips_checks.patch + * openssh-7.7p1-host_ident.patch + * openssh-7.7p1-hostname_changes_when_forwarding_X.patch + * openssh-7.7p1-ldap.patch + * openssh-7.7p1-no_fork-no_pid_file.patch + * openssh-7.7p1-pam_check_locks.patch + * openssh-7.7p1-pts_names_formatting.patch + * openssh-7.7p1-remove_xauth_cookies_on_exit.patch + * openssh-7.7p1-seccomp_ipc_flock.patch + * openssh-7.7p1-seccomp_stat.patch + * openssh-7.7p1-send_locale.patch + * openssh-7.7p1-sftp_force_permissions.patch + * openssh-7.7p1-sftp_print_diagnostic_messages.patch + * openssh-7.7p1-systemd-notify.patch + * openssh-7.9p1-keygen-preserve-perms.patch + * openssh-7.9p1-revert-new-qos-defaults.patch + * openssh-8.0p1-gssapi-keyex.patch + * openssh-8.1p1-audit.patch + * openssh-8.1p1-seccomp-clock_gettime64.patch + * openssh-8.1p1-seccomp-clock_nanosleep.patch + * openssh-8.1p1-seccomp-clock_nanosleep_time64.patch + * openssh-8.1p1-use-openssl-kdf.patch + * openssh-8.4p1-vendordir.patch + * openssh-fips-ensure-approved-moduli.patch + * openssh-link-with-sk.patch + * openssh-reenable-dh-group14-sha1-default.patch + * openssh-whitelist-syscalls.patch + +- Removed openssh-fix-ssh-copy-id.patch (fixed upstream). +- openssh.keyring: rotated to new key from https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/RELEASE_KEY.asc + +------------------------------------------------------------------- +Thu Aug 19 10:07:10 UTC 2021 - Thorsten Kukuk + +- sshd-gen-keys-start: + - only source sysconfig file if it exists. + - create /etc/ssh if it does not exists. + Required for image based installation/updates. + +------------------------------------------------------------------- +Mon Jul 19 14:51:08 UTC 2021 - Cristian Rodríguez + +- The linux kernel has close_range(2) syscall which current glibc + uses to implement closefrom(3) which will be then used by openssh. + whitelist the new system call so closefrom does not fail or + fallback to iterating proc/self/fd (openssh-whitelist-syscalls.patch) + +------------------------------------------------------------------- +Wed Jun 23 18:32:20 UTC 2021 - Hans Petter Jansson + +- Don't move user-modified ssh_config and sshd_config files to + .rpmsave on upgrade. + +------------------------------------------------------------------- +Tue May 18 17:16:33 UTC 2021 - Thorsten Kukuk + +- Use pam_motd to unify motd message output [bsc#1185897] + (openssh-8.4p1-pam_motd.patch) + +------------------------------------------------------------------- +Thu Apr 22 12:02:55 UTC 2021 - Hans Petter Jansson + +- Change vendor configuration dir from /usr/share/ssh/ to + /usr/etc/ssh/. +- Remove upgrade enablement hack. This has been fixed in + systemd-rpm-macros (bsc#1180083). + +------------------------------------------------------------------- +Wed Feb 24 13:20:37 UTC 2021 - Thorsten Kukuk + +- Add support for vendor provided configuration files in + /usr/share/ssh/ (openssh-8.4p1-vendordir.patch) +- Move configuration files from /etc/ssh/ to /usr/share/ssh/ + +------------------------------------------------------------------- +Thu Feb 18 13:54:44 UTC 2021 - Johannes Segitz + +- Drop openssh-7.7p1-allow_root_password_login.patch to prevent login + as root via password by default (is also upstream default). Comment + indicates that this was a temporary meassure that we now had for + five years, time to get rid of it (bsc#1173067) + +------------------------------------------------------------------- +Mon Feb 15 10:01:33 UTC 2021 - Hans Petter Jansson + +- Add openssh-whitelist-syscalls.patch (bsc#1182232), fixing + failure to accept connections on 32-bit platforms with + glibc 2.33+. + +------------------------------------------------------------------- +Wed Jan 27 14:09:08 UTC 2021 - Thorsten Kukuk + +- Add support for /etc/ssh/ssh_config.d and /etc/ssh/sshd_config.d + (openssh-8.4p1-ssh_config_d.patch) + +------------------------------------------------------------------- +Sat Jan 23 18:28:19 UTC 2021 - Hans Petter Jansson + +- Add openssh-fix-ssh-copy-id.patch, which fixes breakage + introduced in 8.4p1 (bsc#1181311). + +------------------------------------------------------------------- +Fri Jan 22 21:06:42 UTC 2021 - Hans Petter Jansson + +- Improve robustness of sshd init detection when upgrading from + a pre-systemd distribution. + +------------------------------------------------------------------- +Fri Jan 22 03:30:59 UTC 2021 - Hans Petter Jansson + +- Add openssh-reenable-dh-group14-sha1-default.patch, which adds + diffie-hellman-group14-sha1 key exchange back to the default + list (bsc#1180958). This is needed for backwards compatibility + with older platforms. + +------------------------------------------------------------------- +Fri Jan 22 02:54:02 UTC 2021 - Hans Petter Jansson + +- Make sure sshd is enabled correctly when upgrading from a + pre-systemd distribution (bsc#1180083). + +------------------------------------------------------------------- +Mon Jan 18 11:04:41 UTC 2021 - Thorsten Kukuk + +- sysusers-sshd.conf: use sysusers.d configuration file to create + sshd user (avoid hard dependency on shadow). + +------------------------------------------------------------------- +Mon Jan 18 00:30:37 UTC 2021 - Dirk Müller + +- update to 8.4p1: + Security + ======== + * ssh-agent(1): restrict ssh-agent from signing web challenges for + FIDO/U2F keys. + * ssh-keygen(1): Enable FIDO 2.1 credProtect extension when generating + a FIDO resident key. + * ssh(1), ssh-keygen(1): support for FIDO keys that require a PIN for + each use. These keys may be generated using ssh-keygen using a new + "verify-required" option. When a PIN-required key is used, the user + will be prompted for a PIN to complete the signature operation. + New Features + ------------ + * sshd(8): authorized_keys now supports a new "verify-required" + option to require FIDO signatures assert that the token verified + that the user was present before making the signature. The FIDO + protocol supports multiple methods for user-verification, but + currently OpenSSH only supports PIN verification. + + * sshd(8), ssh-keygen(1): add support for verifying FIDO webauthn + signatures. Webauthn is a standard for using FIDO keys in web + browsers. These signatures are a slightly different format to plain + FIDO signatures and thus require explicit support. + + * ssh(1): allow some keywords to expand shell-style ${ENV} + environment variables. The supported keywords are CertificateFile, + ControlPath, IdentityAgent and IdentityFile, plus LocalForward and + RemoteForward when used for Unix domain socket paths. bz#3140 + + * ssh(1), ssh-agent(1): allow some additional control over the use of + ssh-askpass via a new $SSH_ASKPASS_REQUIRE environment variable, + including forcibly enabling and disabling its use. bz#69 + + * ssh(1): allow ssh_config(5)'s AddKeysToAgent keyword accept a time + limit for keys in addition to its current flag options. Time- + limited keys will automatically be removed from ssh-agent after + their expiry time has passed. + + * scp(1), sftp(1): allow the -A flag to explicitly enable agent + forwarding in scp and sftp. The default remains to not forward an + agent, even when ssh_config enables it. + + * ssh(1): add a '%k' TOKEN that expands to the effective HostKey of + the destination. This allows, e.g., keeping host keys in individual + files using "UserKnownHostsFile ~/.ssh/known_hosts.d/%k". bz#1654 + + * ssh(1): add %-TOKEN, environment variable and tilde expansion to + the UserKnownHostsFile directive, allowing the path to be + completed by the configuration (e.g. bz#1654) + + * ssh-keygen(1): allow "ssh-add -d -" to read keys to be deleted + from stdin. bz#3180 + + * sshd(8): improve logging for MaxStartups connection throttling. + sshd will now log when it starts and stops throttling and periodically + while in this state. bz#3055 + + Bugfixes + -------- + * ssh(1), ssh-keygen(1): better support for multiple attached FIDO + tokens. In cases where OpenSSH cannot unambiguously determine which + token to direct a request to, the user is now required to select a + token by touching it. In cases of operations that require a PIN to + be verified, this avoids sending the wrong PIN to the wrong token + and incrementing the token's PIN failure counter (tokens + effectively erase their keys after too many PIN failures). + * sshd(8): fix Include before Match in sshd_config; bz#3122 + * ssh(1): close stdin/out/error when forking after authentication + completes ("ssh -f ...") bz#3137 + * ssh(1), sshd(8): limit the amount of channel input data buffered, + avoiding peers that advertise large windows but are slow to read + from causing high memory consumption. + * ssh-agent(1): handle multiple requests sent in a single write() to + the agent. + * sshd(8): allow sshd_config longer than 256k + * sshd(8): avoid spurious "Unable to load host key" message when sshd + load a private key but no public counterpart + * ssh(1): prefer the default hostkey algorithm list whenever we have + a hostkey that matches its best-preference algorithm. + * sshd(1): when ordering the hostkey algorithms to request from a + server, prefer certificate types if the known_hosts files contain a key + marked as a @cert-authority; bz#3157 + * ssh(1): perform host key fingerprint comparisons for the "Are you + sure you want to continue connecting (yes/no/[fingerprint])?" + prompt with case sensitivity. + * sshd(8): ensure that address/masklen mismatches in sshd_config + yield fatal errors at daemon start time rather than later when + they are evaluated. + * ssh-keygen(1): ensure that certificate extensions are lexically + sorted. Previously if the user specified a custom extension then + the everything would be in order except the custom ones. bz#3198 + * ssh(1): also compare username when checking for JumpHost loops. + bz#3057 + * ssh-keygen(1): preserve group/world read permission on known_hosts + files across runs of "ssh-keygen -Rf /path". The old behaviour was + to remove all rights for group/other. bz#3146 + * ssh-keygen(1): Mention the [-a rounds] flag in the ssh-keygen + manual page and usage(). + * sshd(8): explicitly construct path to ~/.ssh/rc rather than + relying on it being relative to the current directory, so that it + can still be found if the shell startup changes its directory. + bz#3185 + * sshd(8): when redirecting sshd's log output to a file, undo this + redirection after the session child process is forked(). Fixes + missing log messages when using this feature under some + circumstances. + * sshd(8): start ClientAliveInterval bookkeeping before first pass + through select() loop; fixed theoretical case where busy sshd may + ignore timeouts from client. + * ssh(1): only reset the ServerAliveInterval check when we receive + traffic from the server and ignore traffic from a port forwarding + client, preventing a client from keeping a connection alive when + it should be terminated. bz#2265 + * ssh-keygen(1): avoid spurious error message when ssh-keygen + creates files outside ~/.ssh + * sftp-client(1): fix off-by-one error that caused sftp downloads to + make one more concurrent request that desired. This prevented using + sftp(1) in unpipelined request/response mode, which is useful when + debugging. bz#3054 + * ssh(1), sshd(8): handle EINTR in waitfd() and timeout_connect() + helpers. bz#3071 + * ssh(1), ssh-keygen(1): defer creation of ~/.ssh until we attempt to + write to it so we don't leave an empty .ssh directory when it's not + needed. bz#3156 + * ssh(1), sshd(8): fix multiplier when parsing time specifications + when handling seconds after other units. bz#3171 + +------------------------------------------------------------------- +Fri Jan 8 01:37:02 UTC 2021 - Hans Petter Jansson + +- Update openssh-8.1p1-audit.patch (bsc#1180501). This fixes + occasional crashes on connection termination caused by accessing + freed memory. + +------------------------------------------------------------------- +Fri Nov 27 11:36:56 UTC 2020 - Thorsten Kukuk + +- Support /usr/etc/pam.d + +------------------------------------------------------------------- +Wed Nov 11 20:05:27 UTC 2020 - Hans Petter Jansson + +- Fix build breakage caused by missing security key objects: + + Modify openssh-7.7p1-cavstest-ctr.patch. + + Modify openssh-7.7p1-cavstest-kdf.patch. + + Add openssh-link-with-sk.patch. + +------------------------------------------------------------------- +Wed Nov 11 18:27:55 UTC 2020 - Hans Petter Jansson + +- Add openssh-fips-ensure-approved-moduli.patch (bsc#1177939). + This ensures only approved DH parameters are used in FIPS mode. + +------------------------------------------------------------------- +Wed Nov 11 18:27:54 UTC 2020 - Hans Petter Jansson + +- Add openssh-8.1p1-ed25519-use-openssl-rng.patch (bsc#1173799). + This uses OpenSSL's RAND_bytes() directly instead of the internal + ChaCha20-based implementation to obtain random bytes for Ed25519 + curve computations. This is required for FIPS compliance. + +------------------------------------------------------------------- +Thu Oct 8 21:38:27 UTC 2020 - Hans Petter Jansson + +- Work around %service_add_post disabling sshd on upgrade with + package name change (bsc#1177039). + +------------------------------------------------------------------- +Fri Sep 25 13:40:51 UTC 2020 - Dominique Leuenberger + +- Fix fillup-template usage: + + %post server needs to reference ssh (not sshd), which matches + the sysconfig.ssh file name the package ships. + + %post client does not need any fillup_ calls, as there is no + client-relevant sysconfig file present. The naming of the + sysconfig file (ssh instead of sshd) is unfortunate. + +------------------------------------------------------------------- +Fri Sep 25 10:59:50 UTC 2020 - Franck Bui + +- Use of DISABLE_RESTART_ON_UPDATE is deprecated. + + Replace it with %service_del_postun_without_restart + +------------------------------------------------------------------- +Thu Sep 17 20:41:39 UTC 2020 - Jan Engelhardt + +- Move some Requires to the right subpackage. +- Avoid ">&" bashism in %post. +- Upgrade some old specfile constructs/macros and drop unnecessary + %{?systemd_*}. +- Trim descriptions and straighten out the grammar. + +------------------------------------------------------------------- +Thu Sep 10 21:38:30 UTC 2020 - Hans Petter Jansson + +- Split openssh package into openssh, openssh-common, + openssh-server and openssh-clients. This allows for the ssh + clients to be installed without the server component + (bsc#1176434). + +------------------------------------------------------------------- +Fri Jun 5 00:36:08 UTC 2020 - Hans Petter Jansson + +- Version update to 8.3p1: + = Potentially-incompatible changes + * sftp(1): reject an argument of "-1" in the same way as ssh(1) and + scp(1) do instead of accepting and silently ignoring it. + + = New features + * sshd(8): make IgnoreRhosts a tri-state option: "yes" to ignore + rhosts/shosts, "no" allow rhosts/shosts or (new) "shosts-only" + to allow .shosts files but not .rhosts. + * sshd(8): allow the IgnoreRhosts directive to appear anywhere in a + sshd_config, not just before any Match blocks. + * ssh(1): add %TOKEN percent expansion for the LocalFoward and + RemoteForward keywords when used for Unix domain socket forwarding. + * all: allow loading public keys from the unencrypted envelope of a + private key file if no corresponding public key file is present. + * ssh(1), sshd(8): prefer to use chacha20 from libcrypto where + possible instead of the (slower) portable C implementation included + in OpenSSH. + * ssh-keygen(1): add ability to dump the contents of a binary key + revocation list via "ssh-keygen -lQf /path". + +- Additional changes from 8.2p1 release: + = Potentially-incompatible changes + * ssh(1), sshd(8), ssh-keygen(1): this release removes the "ssh-rsa" + (RSA/SHA1) algorithm from those accepted for certificate signatures + (i.e. the client and server CASignatureAlgorithms option) and will + use the rsa-sha2-512 signature algorithm by default when the + ssh-keygen(1) CA signs new certificates. + * ssh(1), sshd(8): this release removes diffie-hellman-group14-sha1 + from the default key exchange proposal for both the client and + server. + * ssh-keygen(1): the command-line options related to the generation + and screening of safe prime numbers used by the + diffie-hellman-group-exchange-* key exchange algorithms have + changed. Most options have been folded under the -O flag. + * sshd(8): the sshd listener process title visible to ps(1) has + changed to include information about the number of connections that + are currently attempting authentication and the limits configured + by MaxStartups. + * ssh-sk-helper(8): this is a new binary. It is used by the FIDO/U2F + support to provide address-space isolation for token middleware + libraries (including the internal one). It needs to be installed + in the expected path, typically under /usr/libexec or similar. + + = New features + * This release adds support for FIDO/U2F hardware authenticators to + OpenSSH. U2F/FIDO are open standards for inexpensive two-factor + authentication hardware that are widely used for website + authentication. In OpenSSH FIDO devices are supported by new public + key types "ecdsa-sk" and "ed25519-sk", along with corresponding + certificate types. + * sshd(8): add an Include sshd_config keyword that allows including + additional configuration files via glob(3) patterns. + * ssh(1)/sshd(8): make the LE (low effort) DSCP code point available + via the IPQoS directive. + * ssh(1): when AddKeysToAgent=yes is set and the key contains no + comment, add the key to the agent with the key's path as the + comment. + * ssh-keygen(1), ssh-agent(1): expose PKCS#11 key labels and X.509 + subjects as key comments, rather than simply listing the PKCS#11 + provider library path. + * ssh-keygen(1): allow PEM export of DSA and ECDSA keys. + * ssh(1), sshd(8): make zlib compile-time optional, available via the + Makefile.inc ZLIB flag on OpenBSD or via the --with-zlib configure + option for OpenSSH portable. + * sshd(8): when clients get denied by MaxStartups, send a + notification prior to the SSH2 protocol banner according to + RFC4253 section 4.2. + * ssh(1), ssh-agent(1): when invoking the $SSH_ASKPASS prompt + program, pass a hint to the program to describe the type of + desired prompt. The possible values are "confirm" (indicating + that a yes/no confirmation dialog with no text entry should be + shown), "none" (to indicate an informational message only), or + blank for the original ssh-askpass behaviour of requesting a + password/phrase. + * ssh(1): allow forwarding a different agent socket to the path + specified by $SSH_AUTH_SOCK, by extending the existing ForwardAgent + option to accepting an explicit path or the name of an environment + variable in addition to yes/no. + * ssh-keygen(1): add a new signature operations "find-principals" to + look up the principal associated with a signature from an allowed- + signers file. + * sshd(8): expose the number of currently-authenticating connections + along with the MaxStartups limit in the process title visible to + "ps". + +- Rebased patches: + * openssh-7.7p1-cavstest-ctr.patch + * openssh-7.7p1-cavstest-kdf.patch + * openssh-7.7p1-fips.patch + * openssh-7.7p1-fips_checks.patch + * openssh-7.7p1-ldap.patch + * openssh-7.7p1-no_fork-no_pid_file.patch + * openssh-7.7p1-sftp_print_diagnostic_messages.patch + * openssh-8.0p1-gssapi-keyex.patch + * openssh-8.1p1-audit.patch + * openssh-8.1p1-seccomp-clock_nanosleep.patch + +- Removed openssh-7.7p1-seed-prng.patch (bsc#1165158). + +------------------------------------------------------------------- +Sun May 31 11:25:07 UTC 2020 - Andreas Stieger + +- add upstream signing key to actually verify source signature + +------------------------------------------------------------------- +Fri Feb 28 16:15:06 UTC 2020 - Ludwig Nussel + +- Don't recommend xauth to avoid pulling in X. + +------------------------------------------------------------------- +Tue Feb 18 14:47:36 UTC 2020 - Fabian Vogt + +- Add patches to fix the sandbox blocking glibc on 32bit platforms + (boo#1164061): + * openssh-8.1p1-seccomp-clock_nanosleep_time64.patch + * openssh-8.1p1-seccomp-clock_gettime64.patch + +------------------------------------------------------------------- +Tue Feb 11 02:20:32 UTC 2020 - Hans Petter Jansson + +- Add openssh-8.1p1-use-openssl-kdf.patch (jsc#SLE-9443). This + performs key derivation using OpenSSL's SSHKDF facility, which + allows OpenSSH to benefit from the former's FIPS certification + status. + +------------------------------------------------------------------- +Thu Nov 21 04:49:22 UTC 2019 - Hans Petter Jansson + +- Make sure ssh-keygen runs if SSHD_AUTO_KEYGEN variable is unset + or contains an unrecognized value (bsc#1157176). + +------------------------------------------------------------------- +Fri Nov 8 18:05:37 UTC 2019 - Cristian Rodríguez + +- Add openssh-8.1p1-seccomp-clock_nanosleep.patch, allow clock_nanosleep + glibc master implements multiple functions using that syscall making + the privsep sandbox kill the preauth process. + +------------------------------------------------------------------- +Thu Oct 17 06:23:58 UTC 2019 - Hans Petter Jansson + +- Update openssh-7.7p1-audit.patch to fix crash (bsc#1152730). Fix + by Enzo Matsumiya (ematsumiya@suse.com). This was integrated in + a separate code stream merged with the Oct. 10 update; the patch + was also rebased and renamed to openssh-8.1p1-audit.patch. + +------------------------------------------------------------------- +Mon Oct 14 23:58:39 UTC 2019 - Hans Petter Jansson + +- Add openssh-7.9p1-keygen-preserve-perms.patch (bsc#1150574). + This attempts to preserve the permissions of any existing + known_hosts file when modified by ssh-keygen (for instance, + with -R). +- Added openssh-7.9p1-revert-new-qos-defaults.patch, which reverts + an upstream commit that caused compatibility issues with other + software (bsc#1136402). + +------------------------------------------------------------------- +Mon Oct 14 23:56:42 UTC 2019 - Hans Petter Jansson + +- Run 'ssh-keygen -A' on startup only if SSHD_AUTO_KEYGEN="yes" + in /etc/sysconfig/ssh. This is set to "yes" by default, but + can be changed by the system administrator (bsc#1139089). + +------------------------------------------------------------------- +Mon Oct 14 23:50:04 UTC 2019 - Hans Petter Jansson + +- Add openssh-7.9p1-keygen-preserve-perms.patch (bsc#1150574). + This attempts to preserve the permissions of any existing + known_hosts file when modified by ssh-keygen (for instance, + with -R). + +------------------------------------------------------------------- +Thu Oct 10 00:41:18 UTC 2019 - Hans Petter Jansson + +- Version update to 8.1p1: + * ssh-keygen(1): when acting as a CA and 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 versions prior to 7.2 unless the default is + overridden (using "ssh-keygen -t ssh-rsa -s ..."). + * ssh(1): Allow %n to be expanded in ProxyCommand strings + * ssh(1), sshd(8): Allow prepending a list of algorithms to the + default set by starting the list with the '^' character, E.g. + "HostKeyAlgorithms ^ssh-ed25519" + * ssh-keygen(1): add an experimental lightweight signature and + verification ability. Signatures may be made using regular ssh keys + held on disk or stored in a ssh-agent and verified against an + authorized_keys-like list of allowed keys. Signatures embed a + namespace that prevents confusion and attacks between different + usage domains (e.g. files vs email). + * ssh-keygen(1): print key comment when extracting public key from a + private key. + * ssh-keygen(1): accept the verbose flag when searching for host keys + in known hosts (i.e. "ssh-keygen -vF host") to print the matching + host's random-art signature too. + * All: support PKCS8 as an optional format for storage of 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 insecure + key derivation function than PEM's. + +- Additional changes from 8.0p1 release: + * scp(1): Add "-T" flag to disable client-side filtering of + server file list. + * sshd(8): Remove support for obsolete "host/port" syntax. + * ssh(1), ssh-agent(1), ssh-add(1): Add support for ECDSA keys in + PKCS#11 tokens. + * ssh(1), sshd(8): Add experimental quantum-computing resistant + key exchange method, based on a combination of Streamlined NTRU + Prime 4591^761 and X25519. + * ssh-keygen(1): Increase the default RSA key size to 3072 bits, + following NIST Special Publication 800-57's guidance for a + 128-bit equivalent symmetric security level. + * ssh(1): Allow "PKCS11Provider=none" to override later instances of + the PKCS11Provider directive in ssh_config, + * sshd(8): Add a log message for situations where a connection is + dropped for attempting to run a command but a sshd_config + ForceCommand=internal-sftp restriction is in effect. + * ssh(1): When prompting whether to record a new host key, accept + the key fingerprint as a synonym for "yes". This allows the user + to paste a fingerprint obtained out of band at the prompt and + have the client do the comparison for you. + * ssh-keygen(1): When signing multiple certificates on a single + command-line invocation, allow automatically incrementing the + certificate serial number. + * scp(1), sftp(1): Accept -J option as an alias to ProxyJump on + the scp and sftp command-lines. + * ssh-agent(1), ssh-pkcs11-helper(8), ssh-add(1): Accept "-v" + command-line flags to increase the verbosity of output; pass + verbose flags though to subprocesses, such as ssh-pkcs11-helper + started from ssh-agent. + * ssh-add(1): Add a "-T" option to allowing testing whether keys in + an agent are usable by performing a signature and a verification. + * sftp-server(8): Add a "lsetstat@openssh.com" protocol extension + that replicates the functionality of the existing SSH2_FXP_SETSTAT + operation but does not follow symlinks. + * sftp(1): Add "-h" flag to chown/chgrp/chmod commands to request + they do not follow symlinks. + * sshd(8): Expose $SSH_CONNECTION in the PAM environment. This makes + the connection 4-tuple available to PAM modules that wish to use + it in decision-making. + * sshd(8): Add a ssh_config "Match final" predicate Matches in same + pass as "Match canonical" but doesn't require hostname + canonicalisation be enabled. + * sftp(1): Support a prefix of '@' to suppress echo of sftp batch + commands. + * ssh-keygen(1): When printing certificate contents using + "ssh-keygen -Lf /path/certificate", include the algorithm that + the CA used to sign the cert. + +- Rebased patches: + * openssh-7.7p1-IPv6_X_forwarding.patch + * openssh-7.7p1-X_forward_with_disabled_ipv6.patch + * openssh-7.7p1-cavstest-ctr.patch + * openssh-7.7p1-cavstest-kdf.patch + * openssh-7.7p1-disable_openssl_abi_check.patch + * openssh-7.7p1-fips.patch + * openssh-7.7p1-fips_checks.patch + * openssh-7.7p1-hostname_changes_when_forwarding_X.patch + * openssh-7.7p1-ldap.patch + * openssh-7.7p1-seed-prng.patch + * openssh-7.7p1-sftp_force_permissions.patch + * openssh-7.7p1-sftp_print_diagnostic_messages.patch + * openssh-8.0p1-gssapi-keyex.patch (formerly + openssh-7.7p1-gssapi_key_exchange.patch) + * openssh-8.1p1-audit.patch (formerly openssh-7.7p1-audit.patch) + +- Removed patches (integrated upstream): + * 0001-upstream-Fix-two-race-conditions-in-sshd-relating-to.patch + * openssh-7.7p1-seccomp_ioctl_s390_EP11.patch + * openssh-7.9p1-CVE-2018-20685.patch + * openssh-7.9p1-brace-expansion.patch + * openssh-CVE-2019-6109-force-progressmeter-update.patch + * openssh-CVE-2019-6109-sanitize-scp-filenames.patch + * openssh-CVE-2019-6111-scp-client-wildcard.patch + +- Removed patches (obsolete): + * openssh-openssl-1_0_0-compatibility.patch + +------------------------------------------------------------------- +Mon Aug 19 11:24:36 CEST 2019 - kukuk@suse.de + +- don't install SuSEfirewall2 service on Factory, since SuSEfirewall2 + has been replaced by firewalld, see [1]. + + [1]: https://lists.opensuse.org/opensuse-factory/2019-01/msg00490.html + +------------------------------------------------------------------- +Mon Jul 22 16:55:25 UTC 2019 - Fabian Vogt + +- ssh-askpass: Try a fallback if the other option is not available + +------------------------------------------------------------------- +Fri May 31 11:14:42 UTC 2019 - Vítězslav Čížek + +- Fix a crash with GSSAPI key exchange (bsc#1136104) + * modify openssh-7.7p1-gssapi_key_exchange.patch + +------------------------------------------------------------------- +Thu Mar 28 12:55:13 UTC 2019 - Vítězslav Čížek + +- Fix a double free() in the KDF CAVS testing tool (bsc#1065237) + * modify openssh-7.7p1-cavstest-kdf.patch + +------------------------------------------------------------------- +Tue Mar 12 15:16:20 UTC 2019 - Vítězslav Čížek + +- Minor clean-up of the fips patches, modified + openssh-7.7p1-fips.patch + openssh-7.7p1-fips_checks.patch + +------------------------------------------------------------------- +Mon Mar 11 15:06:17 UTC 2019 - Vítězslav Čížek + +- Fix two race conditions in sshd relating to SIGHUP (bsc#1119183) + * 0001-upstream-Fix-two-race-conditions-in-sshd-relating-to.patch + +------------------------------------------------------------------- +Thu Feb 28 19:20:58 UTC 2019 - Vítězslav Čížek + +- Correctly filter out non-compliant algorithms when in FIPS mode + (bsc#1126397) + * A hunk was applied to a wrong place due to a patch fuzz when + the fips patch was being ported to openssh 7.9p1 +- update openssh-7.7p1-fips.patch + +------------------------------------------------------------------- +Wed Feb 27 12:29:05 UTC 2019 - Vítězslav Čížek + +- Remove the "KexDHMin" config keyword (bsc#1127180) + It used to allow lowering of the minimal allowed DH group size, + which was increased to 2048 by upstream in the light of the Logjam + attack. + The code was broken since the upgrade to 7.6p1, but nobody noticed. + As apparently no one needs the functionality any more, let's drop + the patch. + It's still possible to use the fixed 1024-bit diffie-hellman-group1-sha1 + key exchange method when working with legacy systems. +- drop openssh-7.7p1-disable_short_DH_parameters.patch +- updated patches: + openssh-7.7p1-fips.patch + openssh-7.7p1-fips_checks.patch + openssh-7.7p1-gssapi_key_exchange.patch + +------------------------------------------------------------------- +Mon Feb 18 10:01:45 UTC 2019 - Pedro Monreal Gonzalez + +- Handle brace expansion in scp when checking that filenames sent + by the server side match what the client requested [bsc#1125687] + * openssh-7.9p1-brace-expansion.patch + +------------------------------------------------------------------- +Thu Feb 14 15:27:53 UTC 2019 - Pedro Monreal Gonzalez + +- Updated security fixes: + * [bsc#1121816, CVE-2019-6109] Sanitize scp filenames via snmprintf + and have progressmeter force an update at the beginning and end + of each transfer. Added patches: + - openssh-CVE-2019-6109-sanitize-scp-filenames.patch + - openssh-CVE-2019-6109-force-progressmeter-update.patch + * [bsc#1121821, CVE-2019-6111] Check in scp client that filenames + sent during remote->local directory copies satisfy the wildcard + specified by the user. Added patch: + - openssh-CVE-2019-6111-scp-client-wildcard.patch + * Removed openssh-7.9p1-scp-name-validator.patch + +------------------------------------------------------------------- +Thu Feb 14 10:29:20 UTC 2019 - Tomáš Chvátal + +- Change the askpass wrapper to not use x11 interface: + * by default we use the -gnome UI (which is gtk3 only, no gnome dep) + * if desktop is KDE/LxQt we use ksshaskpass + +------------------------------------------------------------------- +Mon Jan 28 10:34:53 UTC 2019 - Pedro Monreal Gonzalez + +- Remove old conditionals + +------------------------------------------------------------------- +Fri Jan 25 12:42:54 UTC 2019 - Pedro Monreal Gonzalez + +- Move ssh-ldap* man pages into openssh-helpers [bsc#1051531] + +------------------------------------------------------------------- +Thu Jan 24 15:51:19 UTC 2019 - Pedro Monreal Gonzalez + +- Allow root login by default [bsc#1118114, bsc#1121196] + * Added/updated previous patch openssh-7.7p1-allow_root_password_login.patch + * Mention the change in README.SUSE + +------------------------------------------------------------------- +Thu Jan 24 12:21:40 UTC 2019 - Pedro Monreal Gonzalez + +- Added SLE conditionals in the spec files: + * Keep gtk2-devel in openssh-askpass-gnome in SLE + * Keep krb5-mini-devel in SLE +- Removed obsolete configure options: + * SSH protocol 1 --with-ssh1 + * Smart card --with-opensc +- Cleaned spec file with spec-cleaner + +------------------------------------------------------------------- +Wed Jan 16 14:11:29 UTC 2019 - Pedro Monreal Gonzalez + +- Security fix: + * [bsc#1121816, CVE-2019-6109] scp client spoofing via object name + * [bsc#1121818, CVE-2019-6110] scp client spoofing via stderr + * [bsc#1121821, CVE-2019-6111] scp client missing received object + name validation + * Added patch openssh-7.9p1-scp-name-validator.patch + +------------------------------------------------------------------- +Fri Jan 11 15:09:04 UTC 2019 - Pedro Monreal Gonzalez + +- Security fix: [bsc#1121571, CVE-2018-20685] + * The scp client allows remote SSH servers to bypass intended + access restrictions + * Added patch openssh-7.9p1-CVE-2018-20685.patch + +------------------------------------------------------------------- +Thu Jan 3 11:44:45 UTC 2019 - Pedro Monreal Gonzalez + +- Added compatibility with SuSEfirewall2 [bsc#1118044] + +------------------------------------------------------------------- +Tue Dec 11 11:56:43 UTC 2018 - Pedro Monreal Gonzalez + +- Update the firewall rules in Tumbleweed + +------------------------------------------------------------------- +Mon Nov 26 11:07:42 UTC 2018 - Vítězslav Čížek + +- Fix build with openssl < 1.1.0 + * add openssh-openssl-1_0_0-compatibility.patch + +------------------------------------------------------------------- +Wed Oct 31 00:27:41 UTC 2018 - Cristian Rodríguez + +- openssh-7.7p1-audit.patch: fix sshd fatal error in + mm_answer_keyverify: buffer error: incomplete message [bnc#1114008] + +------------------------------------------------------------------- +Mon Oct 22 08:51:30 UTC 2018 - Pedro Monreal Gonzalez + +- Version update to 7.9p1 + * ssh(1), sshd(8): the setting of the new CASignatureAlgorithms + option (see below) bans the use of DSA keys as certificate + authorities. + * sshd(8): the authentication success/failure log message has + changed format slightly. It now includes the certificate + fingerprint (previously it included only key ID and CA key + fingerprint). + * ssh(1), sshd(8): allow most port numbers to be specified using + service names from getservbyname(3) (typically /etc/services). + * sshd(8): support signalling sessions via the SSH protocol. + A limited subset of signals is supported and only for login or + command sessions (i.e. not subsystems) that were not subject to + a forced command via authorized_keys or sshd_config. bz#1424 + * ssh(1): support "ssh -Q sig" to list supported signature options. + Also "ssh -Q help" to show the full set of supported queries. + * ssh(1), sshd(8): add a CASignatureAlgorithms option for the + client and server configs to allow control over which signature + formats are allowed for CAs to sign certificates. For example, + this allows banning CAs that sign certificates using the RSA-SHA1 + signature algorithm. + * sshd(8), ssh-keygen(1): allow key revocation lists (KRLs) to + revoke keys specified by SHA256 hash. + * ssh-keygen(1): allow creation of key revocation lists directly + from base64-encoded SHA256 fingerprints. This supports revoking + keys using only the information contained in sshd(8) + authentication log messages. + +- Removed obsolete configuration option --with-tcp-wrappers, and + --with-opensc for s390 and s390x. + +- Removed patch merged upstream + * openssh-7.7p1-openssl_1.1.0.patch + +- Refreshed patches + * openssh-7.7p1-audit.patch + * openssh-7.7p1-disable_short_DH_parameters.patch + * openssh-7.7p1-fips.patch + * openssh-7.7p1-gssapi_key_exchange.patch + * openssh-7.7p1-seccomp_ipc_flock.patch + * openssh-7.7p1-cavstest-ctr.patch + * openssh-7.7p1-ldap.patch + +------------------------------------------------------------------- +Fri Oct 19 13:22:10 UTC 2018 - Tomáš Chvátal + +- Mention upstream bugs on multiple local patches +- Adjust service to not spam restart and reload only on fails + +------------------------------------------------------------------- +Fri Oct 19 13:11:34 UTC 2018 - Tomáš Chvátal + +- Update openssh-7.7p1-sftp_force_permissions.patch from the + upstream bug, and mention the bug in the spec + +------------------------------------------------------------------- +Fri Oct 19 08:36:52 UTC 2018 - Tomáš Chvátal + +- Drop patch openssh-7.7p1-allow_root_password_login.patch + * There is no reason to set less secure default value, if + users need the behaviour they can still set it up themselves +- Drop patch openssh-7.7p1-blocksigalrm.patch + * We had a bug way in past about this but it was never reproduced + or even confirmed in the ticket, thus rather drop the patch + +------------------------------------------------------------------- +Wed Oct 17 09:22:36 UTC 2018 - Tomáš Chvátal + +- Disable ssh1 protocol support as neither RH or Debian enable + this protocol by default anymore either. + +------------------------------------------------------------------- +Wed Oct 17 08:42:12 UTC 2018 - Tomáš Chvátal + +- Remove the mention of the SLE12 in the README.SUSE +- Install firewall rules only when really needed ( + +- Version update to 7.8p1: + * For most details see release notes file + * ssh-keygen(1): write OpenSSH format private keys by default + instead of using OpenSSL's PEM format +- Rebase patches to apply on 7.8p1 release: + * openssh-7.7p1-fips.patch + * openssh-7.7p1-cavstest-kdf.patch + * openssh-7.7p1-fips_checks.patch + * openssh-7.7p1-gssapi_key_exchange.patch + * openssh-7.7p1-audit.patch + * openssh-7.7p1-openssl_1.1.0.patch + * openssh-7.7p1-ldap.patch + * openssh-7.7p1-IPv6_X_forwarding.patch + * openssh-7.7p1-sftp_print_diagnostic_messages.patch + * openssh-7.7p1-disable_short_DH_parameters.patch + * openssh-7.7p1-hostname_changes_when_forwarding_X.patch + * openssh-7.7p1-pam_check_locks.patch + * openssh-7.7p1-seed-prng.patch + * openssh-7.7p1-systemd-notify.patch + * openssh-7.7p1-X11_trusted_forwarding.patch +- Dropped patches: + * openssh-7.7p1-lastlog.patch + * openssh-7.7p1-blocksigalrm.patch +- Do not use env in script cavs_driver-ssh.pl +- Added pam_keyinit to pam configuration file [bsc#1081947] + +------------------------------------------------------------------- +Tue Oct 9 11:01:40 UTC 2018 - Tomáš Chvátal + +- Format with spec-cleaner +- Reduce conditionals to support SLE12+ only +- Split out bundled patches to be normal patches applied over + the package (use -p1 for patches): + * openssh-7.7p1-allow_root_password_login.patch + * openssh-7.7p1-X11_trusted_forwarding.patch + * openssh-7.7p1-lastlog.patch + * openssh-7.7p1-enable_PAM_by_default.patch + * openssh-7.7p1-eal3.patch + * openssh-7.7p1-blocksigalrm.patch + * openssh-7.7p1-send_locale.patch + * openssh-7.7p1-hostname_changes_when_forwarding_X.patch + * openssh-7.7p1-remove_xauth_cookies_on_exit.patch + * openssh-7.7p1-pts_names_formatting.patch + * openssh-7.7p1-pam_check_locks.patch + * openssh-7.7p1-disable_short_DH_parameters.patch + * openssh-7.7p1-seccomp_getuid.patch + * openssh-7.7p1-seccomp_geteuid.patch + * openssh-7.7p1-seccomp_stat.patch + * openssh-7.7p1-seccomp_ipc_flock.patch + * openssh-7.7p1-seccomp_ioctl_s390_EP11.patch + * openssh-7.7p1-fips.patch + * openssh-7.7p1-cavstest-ctr.patch + * openssh-7.7p1-cavstest-kdf.patch + * openssh-7.7p1-fips_checks.patch + * openssh-7.7p1-seed-prng.patch + * openssh-7.7p1-systemd-notify.patch + * openssh-7.7p1-gssapi_key_exchange.patch + * openssh-7.7p1-audit.patch + * openssh-7.7p1-openssl_1.1.0.patch + * openssh-7.7p1-disable_openssl_abi_check.patch + * openssh-7.7p1-no_fork-no_pid_file.patch + * openssh-7.7p1-host_ident.patch + * openssh-7.7p1-sftp_force_permissions.patch + * openssh-7.7p1-X_forward_with_disabled_ipv6.patch + * openssh-7.7p1-ldap.patch + * openssh-7.7p1-IPv6_X_forwarding.patch + * openssh-7.7p1-sftp_print_diagnostic_messages.patch + +------------------------------------------------------------------- +Tue Sep 18 09:22:23 UTC 2018 - schwab@suse.de + +- seccomp_filter sandbox is not supported on ppc + +------------------------------------------------------------------- +Mon Aug 27 09:26:15 UTC 2018 - tchvatal@suse.com + +- Depend explicitly on zlib-devel, previously pulled in by openssl + +------------------------------------------------------------------- +Mon Jun 25 20:30:16 UTC 2018 - astieger@suse.com + +- BuildRequire pkgconfig(krb5) instead of krb5-mini-devel to ensure + zypper si can pick a resolvable provider. Build cycle remains + solved via project config pulling in -mini. (bsc#1099044) + +------------------------------------------------------------------- +Mon May 21 15:19:03 UTC 2018 - pcerny@suse.com + +- Upgrade to 7.7p1 (bsc#1094068) + Most important changes (more details below): + * Drop compatibility support for pre-2001 SSH implementations + * sshd(1) does not load DSA keys by default + Distilled upstream log: + ---- Potentially-incompatible changes + * ssh(1)/sshd(8): Drop compatibility support for some very old + SSH implementations, including ssh.com <=2.* and OpenSSH <= + 3.*. These versions were all released in or before 2001 and + predate the final SSH RFCs. The support in question isn't + necessary for RFC-compliant SSH implementations. + ---- New Features + * experimental support for PQC XMSS keys (Extended Hash-Based + Signatures), not compiled in by default. + * sshd(8): Add a "rdomain" criteria for the sshd_config Match + keyword to allow conditional configuration that depends on + which routing domain a connection was received on (currently + supported on OpenBSD and Linux). + * sshd_config(5): Add an optional rdomain qualifier to the + ListenAddress directive to allow listening on different + routing domains. This is supported only on OpenBSD and Linux + at present. + * sshd_config(5): Add RDomain directive to allow the + authenticated session to be placed in an explicit routing + domain. This is only supported on OpenBSD at present. + * sshd(8): Add "expiry-time" option for authorized_keys files + to allow for expiring keys. + * ssh(1): Add a BindInterface option to allow binding the + outgoing connection to an interface's address (basically a + more usable BindAddress) + * ssh(1): Expose device allocated for tun/tap forwarding via a + new %T expansion for LocalCommand. This allows LocalCommand + to be %used to prepare the interface. + * sshd(8): Expose the device allocated for tun/tap forwarding + via a new SSH_TUNNEL environment variable. This allows + automatic setup of the interface and surrounding network + configuration automatically on the server. + * ssh(1)/scp(1)/sftp(1): Add URI support to ssh, sftp and scp, + e.g. ssh://user@host or sftp://user@host/path. Additional + connection parameters that use deporecated MD5 are not + implemented. + * ssh-keygen(1): Allow certificate validity intervals that + specify only a start or stop time (instead of both or + neither). + * sftp(1): Allow "cd" and "lcd" commands with no explicit path + argument. lcd will change to the local user's home directory + as usual. cd will change to the starting directory for + session (because the protocol offers no way to obtain the + remote user's home directory). bz#2760 + * sshd(8): When doing a config test with sshd -T, only require + the attributes that are actually used in Match criteria + rather than (an incomplete list of) all criteria. + ---- Bugfixes + * ssh(1)/sshd(8): More strictly check signature types during + key exchange against what was negotiated. Prevents downgrade + of RSA signatures made with SHA-256/512 to SHA-1. + * sshd(8): Fix support for client that advertise a protocol + version of "1.99" (indicating that they are prepared to + accept both SSHv1 and SSHv2). This was broken in OpenSSH 7.6 + during the removal of SSHv1 support. bz#2810 + * ssh(1): Warn when the agent returns a ssh-rsa (SHA1) + signature when a rsa-sha2-256/512 signature was requested. + This condition is possible when an old or non-OpenSSH agent + is in use. bz#2799 + * ssh-agent(1): Fix regression introduced in 7.6 that caused + ssh-agent to fatally exit if presented an invalid signature + request message. + * sshd_config(5): Accept yes/no flag options + case-insensitively, as has been the case in ssh_config(5) for + a long time. bz#2664 + * ssh(1): Improve error reporting for failures during + connection. Under some circumstances misleading errors were + being shown. bz#2814 + * ssh-keyscan(1): Add -D option to allow printing of results + directly in SSHFP format. bz#2821 + * regress tests: fix PuTTY interop test broken in last + release's SSHv1 removal. bz#2823 + * ssh(1): Compatibility fix for some servers that erroneously + drop the connection when the IUTF8 (RFC8160) option is sent. + * scp(1): Disable RemoteCommand and RequestTTY in the ssh + session started by scp (sftp was already doing this.) + * ssh-keygen(1): Refuse to create a certificate with an + unusable number of principals. + * ssh-keygen(1): Fatally exit if ssh-keygen is unable to write + all the public key during key generation. Previously it would + silently ignore errors writing the comment and terminating + newline. + * ssh(1): Do not modify hostname arguments that are addresses + by automatically forcing them to lower-case. Instead + canonicalise them to resolve ambiguities (e.g. ::0001 => ::1) + before they are matched against known_hosts. bz#2763 + * ssh(1): Don't accept junk after "yes" or "no" responses to + hostkey prompts. bz#2803 + * sftp(1): Have sftp print a warning about shell cleanliness + when decoding the first packet fails, which is usually caused + by shells polluting stdout of non-interactive startups. + bz#2800 + * ssh(1)/sshd(8): Switch timers in packet code from using + wall-clock time to monotonic time, allowing the packet layer + to better function over a clock step and avoiding possible + integer overflows during steps. + * Numerous manual page fixes and improvements. + +------------------------------------------------------------------- +Wed May 2 08:14:41 UTC 2018 - dimstar@opensuse.org + +- Use TIRPC on suse_version >= 1500: sunrpc is deprecated and + should be replaced by TIRPC. + +------------------------------------------------------------------- +Mon Apr 30 15:11:31 UTC 2018 - pcerny@suse.com + +- additional rebased patches (bsc#1080779) + * auditing support + * LDAP integration + * various distribution tweaks from SLE12 + (X forwarding over IPv6, sftp forced permissions + and verbose batch mode) + +------------------------------------------------------------------- +Wed Apr 4 13:19:30 CEST 2018 - kukuk@suse.de + +- Use %license instead of %doc [bsc#1082318] + +------------------------------------------------------------------- +Mon Feb 12 22:55:01 UTC 2018 - pcerny@suse.com + +- add OpenSSL 1.0 to 1.1 shim to remove dependency on old OpenSSL + (update tracker: bsc#1080779) + +------------------------------------------------------------------- +Wed Jan 31 13:31:41 UTC 2018 - pcerny@suse.com + +- Add missing crypto hardware enablement patches for IBM mainframes + (FATE#323902) + +------------------------------------------------------------------- +Wed Jan 24 21:42:35 UTC 2018 - pcerny@suse.com + +- add missing part of systemd integration (unit type) + +------------------------------------------------------------------- +Tue Jan 16 13:04:01 UTC 2018 - dimstar@opensuse.org + +- BuildRequire pkgconfig(libsystemd) instead of systemd-devel: + allow the scheduler to pick systemd-mini flavors to get build + going. + +------------------------------------------------------------------- +Fri Jan 12 12:38:09 UTC 2018 - pcerny@suse.com + +- Replace forgotten references to /var/adm/fillup-templates + with new %_fillupdir macro (boo#1069468) +- tighten configuration access rights + +------------------------------------------------------------------- +Fri Jan 12 00:38:37 CET 2018 - pcerny@suse.com + +- Update to vanilla 7.6p1 + Most important changes (more details below): + * complete removal of the ancient SSHv1 protocol + * sshd(8) cannot run without privilege separation + * removal of suport for arcfourm blowfish and CAST ciphers + and RIPE-MD160 HMAC + * refuse RSA keys shorter than 1024 bits + Distilled upstream log: +- OpenSSH 7.3 + ---- Security + * sshd(8): Mitigate a potential denial-of-service attack + against the system's crypt(3) function via sshd(8). An + attacker could send very long passwords that would cause + excessive CPU use in crypt(3). sshd(8) now refuses to accept + password authentication requests of length greater than 1024 + characters. Independently reported by Tomas Kuthan (Oracle), + Andres Rojas and Javier Nieto. + * sshd(8): Mitigate timing differences in password + authentication that could be used to discern valid from + invalid account names when long passwords were sent and + particular password hashing algorithms are in use on the + server. CVE-2016-6210, reported by EddieEzra.Harari at + verint.com + * ssh(1), sshd(8): Fix observable timing weakness in the CBC + padding oracle countermeasures. Reported by Jean Paul + Degabriele, Kenny Paterson, Torben Hansen and Martin + Albrecht. Note that CBC ciphers are disabled by default and + only included for legacy compatibility. + * ssh(1), sshd(8): Improve operation ordering of MAC + verification for Encrypt-then-MAC (EtM) mode transport MAC + algorithms to verify the MAC before decrypting any + ciphertext. This removes the possibility of timing + differences leaking facts about the plaintext, though no such + leakage has been observed. Reported by Jean Paul Degabriele, + Kenny Paterson, Torben Hansen and Martin Albrecht. + * sshd(8): (portable only) Ignore PAM environment vars when + UseLogin=yes. If PAM is configured to read user-specified + environment variables and UseLogin=yes in sshd_config, then a + hostile local user may attack /bin/login via LD_PRELOAD or + similar environment variables set via PAM. CVE-2015-8325, + found by Shayan Sadigh. + ---- New Features + * ssh(1): Add a ProxyJump option and corresponding -J + command-line flag to allow simplified indirection through a + one or more SSH bastions or "jump hosts". + * ssh(1): Add an IdentityAgent option to allow specifying + specific agent sockets instead of accepting one from the + environment. + * ssh(1): Allow ExitOnForwardFailure and ClearAllForwardings to + be optionally overridden when using ssh -W. bz#2577 + * ssh(1), sshd(8): Implement support for the IUTF8 terminal + mode as per draft-sgtatham-secsh-iutf8-00. + * ssh(1), sshd(8): Add support for additional fixed + Diffie-Hellman 2K, 4K and 8K groups from + draft-ietf-curdle-ssh-kex-sha2-03. + * ssh-keygen(1), ssh(1), sshd(8): support SHA256 and SHA512 RSA + signatures in certificates; + * ssh(1): Add an Include directive for ssh_config(5) files. + * ssh(1): Permit UTF-8 characters in pre-authentication banners + sent from the server. bz#2058 + ---- Bugfixes + * ssh(1), sshd(8): Reduce the syslog level of some relatively + common protocol events from LOG_CRIT. bz#2585 + * sshd(8): Refuse AuthenticationMethods="" in configurations + and accept AuthenticationMethods=any for the default + behaviour of not requiring multiple authentication. bz#2398 + * sshd(8): Remove obsolete and misleading "POSSIBLE BREAK-IN + ATTEMPT!" message when forward and reverse DNS don't match. + bz#2585 + * ssh(1): Close ControlPersist background process stderr except + in debug mode or when logging to syslog. bz#1988 + * misc: Make PROTOCOL description for + direct-streamlocal@openssh.com channel open messages match + deployed code. bz#2529 + * ssh(1): Deduplicate LocalForward and RemoteForward entries to + fix failures when both ExitOnForwardFailure and hostname + canonicalisation are enabled. bz#2562 + * sshd(8): Remove fallback from moduli to obsolete "primes" + file that was deprecated in 2001. bz#2559. + * sshd_config(5): Correct description of UseDNS: it affects ssh + hostname processing for authorized_keys, not known_hosts; + bz#2554 + * ssh(1): Fix authentication using lone certificate keys in an + agent without corresponding private keys on the filesystem. + bz#2550 + * sshd(8): Send ClientAliveInterval pings when a time-based + RekeyLimit is set; previously keepalive packets were not + being sent. bz#2252 + ---- Portability + * ssh(1), sshd(8): Fix compilation by automatically disabling + ciphers not supported by OpenSSL. bz#2466 + * misc: Fix compilation failures on some versions of AIX's + compiler related to the definition of the VA_COPY macro. + bz#2589 + * sshd(8): Whitelist more architectures to enable the + seccomp-bpf sandbox. bz#2590 + * ssh-agent(1), sftp-server(8): Disable process tracing on + Solaris using setpflags(__PROC_PROTECT, ...). bz#2584 + * sshd(8): On Solaris, don't call Solaris setproject() with + UsePAM=yes it's PAM's responsibility. bz#2425 +- OpenSSH 7.4 + ---- Potentially-incompatible changes + * ssh(1): Remove 3des-cbc from the client's default proposal. + 64-bit block ciphers are not safe in 2016 and we don't want + to wait until attacks like SWEET32 are extended to SSH. As + 3des-cbc was the only mandatory cipher in the SSH RFCs, this + may cause problems connecting to older devices using the + default configuration, but it's highly likely that such + devices already need explicit configuration for key exchange + and hostkey algorithms already anyway. + * sshd(8): Remove support for pre-authentication compression. + Doing compression early in the protocol probably seemed + reasonable in the 1990s, but today it's clearly a bad idea in + terms of both cryptography (cf. multiple compression oracle + attacks in TLS) and attack surface. Pre-auth compression + support has been disabled by default for >10 years. Support + remains in the client. + * ssh-agent will refuse to load PKCS#11 modules outside a + whitelist of trusted paths by default. The path whitelist may + be specified at run-time. + * sshd(8): When a forced-command appears in both a certificate + and an authorized keys/principals command= restriction, sshd + will now refuse to accept the certificate unless they are + identical. The previous (documented) behaviour of having the + certificate forced-command override the other could be a bit + confusing and error-prone. + * sshd(8): Remove the UseLogin configuration directive and + support for having /bin/login manage login sessions. + ---- Security + * ssh-agent(1): Will now refuse to load PKCS#11 modules from + paths outside a trusted whitelist (run-time configurable). + Requests to load modules could be passed via agent forwarding + and an attacker could attempt to load a hostile PKCS#11 + module across the forwarded agent channel: PKCS#11 modules + are shared libraries, so this would result in code execution + on the system running the ssh-agent if the attacker has + control of the forwarded agent-socket (on the host running + the sshd server) and the ability to write to the filesystem + of the host running ssh-agent (usually the host running the + ssh client). Reported by Jann Horn of Project Zero. + * sshd(8): When privilege separation is disabled, forwarded + Unix- domain sockets would be created by sshd(8) with the + privileges of 'root' instead of the authenticated user. This + release refuses Unix-domain socket forwarding when privilege + separation is disabled (Privilege separation has been enabled + by default for 14 years). Reported by Jann Horn of Project + Zero. + * sshd(8): Avoid theoretical leak of host private key material + to privilege-separated child processes via realloc() when + reading keys. No such leak was observed in practice for + normal-sized keys, nor does a leak to the child processes + directly expose key material to unprivileged users. Reported + by Jann Horn of Project Zero. + * sshd(8): The shared memory manager used by pre-authentication + compression support had a bounds checks that could be elided + by some optimising compilers. Additionally, this memory + manager was incorrectly accessible when pre-authentication + compression was disabled. This could potentially allow + attacks against the privileged monitor process from the + sandboxed privilege-separation process (a compromise of the + latter would be required first). This release removes + support for pre-authentication compression from sshd(8). + Reported by Guido Vranken using the Stack unstable + optimisation identification tool + (http://css.csail.mit.edu/stack/) + * sshd(8): Fix denial-of-service condition where an attacker + who sends multiple KEXINIT messages may consume up to 128MB + per connection. Reported by Shi Lei of Gear Team, Qihoo 360. + * sshd(8): Validate address ranges for AllowUser and DenyUsers + directives at configuration load time and refuse to accept + invalid ones. It was previously possible to specify invalid + CIDR address ranges (e.g. user@127.1.2.3/55) and these would + always match, possibly resulting in granting access where it + was not intended. Reported by Laurence Parry. + ---- New Features + * ssh(1): Add a proxy multiplexing mode to ssh(1) inspired by + the version in PuTTY by Simon Tatham. This allows a + multiplexing client to communicate with the master process + using a subset of the SSH packet and channels protocol over a + Unix-domain socket, with the main process acting as a proxy + that translates channel IDs, etc. This allows multiplexing + mode to run on systems that lack file- descriptor passing + (used by current multiplexing code) and potentially, in + conjunction with Unix-domain socket forwarding, with the + client and multiplexing master process on different machines. + Multiplexing proxy mode may be invoked using "ssh -O proxy + ..." + * sshd(8): Add a sshd_config DisableForwarding option that + disables X11, agent, TCP, tunnel and Unix domain socket + forwarding, as well as anything else we might implement in + the future. Like the 'restrict' authorized_keys flag, this is + intended to be a simple and future-proof way of restricting + an account. + * sshd(8), ssh(1): Support the "curve25519-sha256" key exchange + method. This is identical to the currently-supported method + named "curve25519-sha256@libssh.org". + * sshd(8): Improve handling of SIGHUP by checking to see if + sshd is already daemonised at startup and skipping the call + to daemon(3) if it is. This ensures that a SIGHUP restart of + sshd(8) will retain the same process-ID as the initial + execution. sshd(8) will also now unlink the PidFile prior to + SIGHUP restart and re-create it after a successful restart, + rather than leaving a stale file in the case of a + configuration error. bz#2641 + * sshd(8): Allow ClientAliveInterval and ClientAliveCountMax + directives to appear in sshd_config Match blocks. + * sshd(8): Add %-escapes to AuthorizedPrincipalsCommand to + match those supported by AuthorizedKeysCommand (key, key + type, fingerprint, etc.) and a few more to provide access to + the contents of the certificate being offered. + * Added regression tests for string matching, address matching + and string sanitisation functions. + * Improved the key exchange fuzzer harness. + ---- Bugfixes + * ssh(1): Allow IdentityFile to successfully load and use + certificates that have no corresponding bare public key. + bz#2617 certificate id_rsa-cert.pub (and no id_rsa.pub). + * ssh(1): Fix public key authentication when multiple + authentication is in use and publickey is not just the first + method attempted. bz#2642 + * regress: Allow the PuTTY interop tests to run unattended. + bz#2639 + * ssh-agent(1), ssh(1): improve reporting when attempting to + load keys from PKCS#11 tokens with fewer useless log messages + and more detail in debug messages. bz#2610 + * ssh(1): When tearing down ControlMaster connections, don't + pollute stderr when LogLevel=quiet. + * sftp(1): On ^Z wait for underlying ssh(1) to suspend before + suspending sftp(1) to ensure that ssh(1) restores the + terminal mode correctly if suspended during a password + prompt. + * ssh(1): Avoid busy-wait when ssh(1) is suspended during a + password prompt. + * ssh(1), sshd(8): Correctly report errors during sending of + ext- info messages. + * sshd(8): fix NULL-deref crash if sshd(8) received an out-of- + sequence NEWKEYS message. + * sshd(8): Correct list of supported signature algorithms sent + in the server-sig-algs extension. bz#2547 + * sshd(8): Fix sending ext_info message if privsep is disabled. + * sshd(8): more strictly enforce the expected ordering of + privilege separation monitor calls used for authentication + and allow them only when their respective authentication + methods are enabled in the configuration + * sshd(8): Fix uninitialised optlen in getsockopt() call; + harmless on Unix/BSD but potentially crashy on Cygwin. + * Fix false positive reports caused by explicit_bzero(3) not + being recognised as a memory initialiser when compiled with + -fsanitize-memory. + * sshd_config(5): Use 2001:db8::/32, the official IPv6 subnet + for configuration examples. + ---- Portability + * On environments configured with Turkish locales, fall back to + the C/POSIX locale to avoid errors in configuration parsing + caused by that locale's unique handling of the letters 'i' + and 'I'. bz#2643 + * sftp-server(8), ssh-agent(1): Deny ptrace on OS X using + ptrace(PT_DENY_ATTACH, ..) + * ssh(1), sshd(8): Unbreak AES-CTR ciphers on old (~0.9.8) + OpenSSL. + * Fix compilation for libcrypto compiled without RIPEMD160 + support. + * contrib: Add a gnome-ssh-askpass3 with GTK+3 support. bz#2640 + * sshd(8): Improve PRNG reseeding across privilege separation + and force libcrypto to obtain a high-quality seed before + chroot or sandboxing. + * All: Explicitly test for broken strnvis. NetBSD added an + strnvis and unfortunately made it incompatible with the + existing one in OpenBSD and Linux's libbsd (the former having + existed for over ten years). Try to detect this mess, and + assume the only safe option if we're cross compiling. +- OpenSSH 7.5 + ---- Potentially-incompatible changes + * This release deprecates the sshd_config + UsePrivilegeSeparation option, thereby making privilege + separation mandatory. Privilege separation has been on by + default for almost 15 years and sandboxing has been on by + default for almost the last five. + * The format of several log messages emitted by the packet code + has changed to include additional information about the user + and their authentication state. Software that monitors + ssh/sshd logs may need to account for these changes. For + example: + Connection closed by user x 1.1.1.1 port 1234 [preauth] + Connection closed by authenticating user x 10.1.1.1 port 1234 + [preauth] Connection closed by invalid user x 1.1.1.1 port + 1234 [preauth] + Affected messages include connection closure, timeout, remote + disconnection, negotiation failure and some other fatal + messages generated by the packet code. + * [Portable OpenSSH only] This version removes support for + building against OpenSSL versions prior to 1.0.1. OpenSSL + stopped supporting versions prior to 1.0.1 over 12 months ago + (i.e. they no longer receive fixes for security bugs). + ---- Security + * ssh(1), sshd(8): Fix weakness in CBC padding oracle + countermeasures that allowed a variant of the attack fixed in + OpenSSH 7.3 to proceed. Note that the OpenSSH client + disables CBC ciphers by default, sshd offers them as + lowest-preference options and will remove them by default + entriely in the next release. Reported by Jean Paul + Degabriele, Kenny Paterson, Martin Albrecht and Torben Hansen + of Royal Holloway, University of London. + * sftp-client(1): [portable OpenSSH only] On Cygwin, a client + making a recursive file transfer could be maniuplated by a + hostile server to perform a path-traversal attack. creating + or modifying files outside of the intended target directory. + Reported by Jann Horn of Google Project Zero. + ---- New Features + * ssh(1), sshd(8): Support "=-" syntax to easily remove methods + from algorithm lists, e.g. Ciphers=-*cbc. bz#2671 + ---- Bugfixes + * sshd(1): Fix NULL dereference crash when key exchange start + messages are sent out of sequence. + * ssh(1), sshd(8): Allow form-feed characters to appear in + configuration files. + * sshd(8): Fix regression in OpenSSH 7.4 support for the + server-sig-algs extension, where SHA2 RSA signature methods + were not being correctly advertised. bz#2680 + * ssh(1), ssh-keygen(1): Fix a number of case-sensitivity bugs + in known_hosts processing. bz#2591 bz#2685 + * ssh(1): Allow ssh to use certificates accompanied by a + private key file but no corresponding plain *.pub public key. + bz#2617 + * ssh(1): When updating hostkeys using the UpdateHostKeys + option, accept RSA keys if HostkeyAlgorithms contains any RSA + keytype. Previously, ssh could ignore RSA keys when only the + ssh-rsa-sha2-* methods were enabled in HostkeyAlgorithms and + not the old ssh-rsa method. bz#2650 + * ssh(1): Detect and report excessively long configuration file + lines. bz#2651 + * Merge a number of fixes found by Coverity and reported via + Redhat and FreeBSD. Includes fixes for some memory and file + descriptor leaks in error paths. bz#2687 + * ssh-keyscan(1): Correctly hash hosts with a port number. + bz#2692 + * ssh(1), sshd(8): When logging long messages to stderr, don't + truncate "\r\n" if the length of the message exceeds the + buffer. bz#2688 + * ssh(1): Fully quote [host]:port in generated ProxyJump/-J + command- line; avoid confusion over IPv6 addresses and shells + that treat square bracket characters specially. + * ssh-keygen(1): Fix corruption of known_hosts when running + "ssh-keygen -H" on a known_hosts containing already-hashed + entries. + * Fix various fallout and sharp edges caused by removing SSH + protocol 1 support from the server, including the server + banner string being incorrectly terminated with only \n + (instead of \r\n), confusing error messages from ssh-keyscan + bz#2583 and a segfault in sshd if protocol v.1 was enabled + for the client and sshd_config contained references to legacy + keys bz#2686. + * ssh(1), sshd(8): Free fd_set on connection timeout. bz#2683 + * sshd(8): Fix Unix domain socket forwarding for root + (regression in OpenSSH 7.4). + * sftp(1): Fix division by zero crash in "df" output when + server returns zero total filesystem blocks/inodes. + * ssh(1), ssh-add(1), ssh-keygen(1), sshd(8): Translate OpenSSL + errors encountered during key loading to more meaningful + error codes. bz#2522 bz#2523 + * ssh-keygen(1): Sanitise escape sequences in key comments sent + to printf but preserve valid UTF-8 when the locale supports + it; bz#2520 + * ssh(1), sshd(8): Return reason for port forwarding failures + where feasible rather than always "administratively + prohibited". bz#2674 + * sshd(8): Fix deadlock when AuthorizedKeysCommand or + AuthorizedPrincipalsCommand produces a lot of output and a + key is matched early. bz#2655 + * Regression tests: several reliability fixes. bz#2654 bz#2658 + bz#2659 + * ssh(1): Fix typo in ~C error message for bad port forward + cancellation. bz#2672 + * ssh(1): Show a useful error message when included config + files can't be opened; bz#2653 + * sshd(8): Make sshd set GSSAPIStrictAcceptorCheck=yes as the + manual page (previously incorrectly) advertised. bz#2637 + * sshd_config(5): Repair accidentally-deleted mention of %k + token in AuthorizedKeysCommand; bz#2656 + * sshd(8): Remove vestiges of previously removed LOGIN_PROGRAM; + bz#2665 + * ssh-agent(1): Relax PKCS#11 whitelist to include libexec and + common 32-bit compatibility library directories. + * sftp-client(1): Fix non-exploitable integer overflow in + SSH2_FXP_NAME response handling. + * ssh-agent(1): Fix regression in 7.4 of deleting + PKCS#11-hosted keys. It was not possible to delete them + except by specifying their full physical path. bz#2682 + ---- Portability + * sshd(8): Avoid sandbox errors for Linux S390 systems using an + ICA crypto coprocessor. + * sshd(8): Fix non-exploitable weakness in seccomp-bpf sandbox + arg inspection. + * ssh(1): Fix X11 forwarding on OSX where X11 was being started + by launchd. bz#2341 + * ssh-keygen(1), ssh(1), sftp(1): Fix output truncation for + various that contain non-printable characters where the + codeset in use is ASCII. + * build: Fix builds that attempt to link a kerberised libldns. + bz#2603 + * build: Fix compilation problems caused by unconditionally + defining _XOPEN_SOURCE in wide character detection. + * sshd(8): Fix sandbox violations for clock_gettime VSDO + syscall fallback on some Linux/X32 kernels. bz#2142 +- OpenSSH 7.6 + ---- Potentially-incompatible changes + This release includes a number of changes that may affect + existing configurations: + * ssh(1): delete SSH protocol version 1 support, associated + configuration options and documentation. + * ssh(1)/sshd(8): remove support for the hmac-ripemd160 MAC. + * ssh(1)/sshd(8): remove support for the arcfour, blowfish and + CAST ciphers. + * Refuse RSA keys <1024 bits in length and improve reporting + for keys that do not meet this requirement. + * ssh(1): do not offer CBC ciphers by default. + ---- Security + * sftp-server(8): in read-only mode, sftp-server was + incorrectly permitting creation of zero-length files. + Reported by Michal Zalewski. + ---- New Features + * ssh(1): add RemoteCommand option to specify a command in the + ssh config file instead of giving it on the client's command + line. This allows the configuration file to specify the + command that will be executed on the remote host. + * sshd(8): add ExposeAuthInfo option that enables writing + details of the authentication methods used (including public + keys where applicable) to a file that is exposed via a + $SSH_USER_AUTH environment variable in the subsequent + session. + * ssh(1): add support for reverse dynamic forwarding. In this + mode, ssh will act as a SOCKS4/5 proxy and forward + connections to destinations requested by the remote SOCKS + client. This mode is requested using extended syntax for the + -R and RemoteForward options and, because it is implemented + solely at the client, does not require the server be updated + to be supported. + * sshd(8): allow LogLevel directive in sshd_config Match + blocks; bz#2717 + * ssh-keygen(1): allow inclusion of arbitrary string or flag + certificate extensions and critical options. + * ssh-keygen(1): allow ssh-keygen to use a key held in + ssh-agent as a CA when signing certificates. bz#2377 + * ssh(1)/sshd(8): allow IPQoS=none in ssh/sshd to not set an + explicit ToS/DSCP value and just use the operating system + default. + * ssh-add(1): added -q option to make ssh-add quiet on success. + * ssh(1): expand the StrictHostKeyChecking option with two new + settings. The first "accept-new" will automatically accept + hitherto-unseen keys but will refuse connections for changed + or invalid hostkeys. This is a safer subset of the current + behaviour of StrictHostKeyChecking=no. The second setting + "off", is a synonym for the current behaviour of + StrictHostKeyChecking=no: accept new host keys, and continue + connection for hosts with incorrect hostkeys. A future + release will change the meaning of StrictHostKeyChecking=no + to the behaviour of "accept-new". bz#2400 + * ssh(1): add SyslogFacility option to ssh(1) matching the + equivalent option in sshd(8). bz#2705 + ---- Bugfixes + * ssh(1): use HostKeyAlias if specified instead of hostname for + matching host certificate principal names; bz#2728 + * sftp(1): implement sorting for globbed ls; bz#2649 + * ssh(1): add a user@host prefix to client's "Permission + denied" messages, useful in particular when using "stacked" + connections (e.g. ssh -J) where it's not clear which host is + denying. bz#2720 + * ssh(1): accept unknown EXT_INFO extension values that contain + \0 characters. These are legal, but would previously cause + fatal connection errors if received. + * ssh(1)/sshd(8): repair compression statistics printed at + connection exit + * sftp(1): print '?' instead of incorrect link count (that the + protocol doesn't provide) for remote listings. bz#2710 + * ssh(1): return failure rather than fatal() for more cases + during session multiplexing negotiations. Causes the session + to fall back to a non-mux connection if they occur. bz#2707 + * ssh(1): mention that the server may send debug messages to + explain public key authentication problems under some + circumstances; bz#2709 + * Translate OpenSSL error codes to better report incorrect + passphrase errors when loading private keys; bz#2699 + * sshd(8): adjust compatibility patterns for WinSCP to + correctly identify versions that implement only the legacy DH + group exchange scheme. bz#2748 + * ssh(1): print the "Killed by signal 1" message only at + LogLevel verbose so that it is not shown at the default + level; prevents it from appearing during ssh -J and + equivalent ProxyCommand configs. bz#1906, bz#2744 + * ssh-keygen(1): when generating all hostkeys (ssh-keygen -A), + clobber existing keys if they exist but are zero length. + zero-length keys could previously be made if ssh-keygen + failed or was interrupted part way through generating them. + bz#2561 + * ssh(1): fix pledge(2) violation in the escape sequence "~&" + used to place the current session in the background. + * ssh-keyscan(1): avoid double-close() on file descriptors; + bz#2734 + * sshd(8): avoid reliance on shared use of pointers shared + between monitor and child sshd processes. bz#2704 + * sshd_config(8): document available AuthenticationMethods; + bz#2453 + * ssh(1): avoid truncation in some login prompts; bz#2768 + * sshd(8): Fix various compilations failures, inc bz#2767 + * ssh(1): make "--" before the hostname terminate argument + processing after the hostname too. + * ssh-keygen(1): switch from aes256-cbc to aes256-ctr for + encrypting new-style private keys. Fixes problems related to + private key handling for no-OpenSSL builds. bz#2754 + * ssh(1): warn and do not attempt to use keys when the public + and private halves do not match. bz#2737 + * sftp(1): don't print verbose error message when ssh + disconnects from under sftp. bz#2750 + * sshd(8): fix keepalive scheduling problem: activity on a + forwarded port from preventing the keepalive from being sent; + bz#2756 + * sshd(8): when started without root privileges, don't require + the privilege separation user or path to exist. Makes running + the regression tests easier without touching the filesystem. + * Make integrity.sh regression tests more robust against + timeouts. bz#2658 + * ssh(1)/sshd(8): correctness fix for channels implementation: + accept channel IDs greater than 0x7FFFFFFF. + ---- Portability + * sshd(9): drop two more privileges in the Solaris sandbox: + PRIV_DAX_ACCESS and PRIV_SYS_IB_INFO; bz#2723 + * sshd(8): expose list of completed authentication methods to + PAM via the SSH_AUTH_INFO_0 PAM environment variable. bz#2408 + * ssh(1)/sshd(8): fix several problems in the tun/tap + forwarding code, mostly to do with host/network byte order + confusion. bz#2735 + * Add --with-cflags-after and --with-ldflags-after configure + flags to allow setting CFLAGS/LDFLAGS after configure has + completed. These are useful for setting sanitiser/fuzzing + options that may interfere with configure's operation. + * sshd(8): avoid Linux seccomp violations on ppc64le over the + socketcall syscall. + * Fix use of ldns when using ldns-config; bz#2697 + * configure: set cache variables when cross-compiling. The + cross- compiling fallback message was saying it assumed the + test passed, but it wasn't actually set the cache variables + and this would cause later tests to fail. + * Add clang libFuzzer harnesses for public key parsing and + signature verification. +- packaging: + * moving patches into a separate archive + * first round of rebased patches: + [-X11_trusted_forwarding] + [-allow_root_password_login] + [-blocksigalrm] + [-cavstest-ctr] + [-cavstest-kdf] + [-disable_short_DH_parameters] + [-eal3] + [-enable_PAM_by_default] + [-fips] + [-fips_checks] + [-gssapi_key_exchange] + [-hostname_changes_when_forwarding_X] + [-lastlog] + [-missing_headers] + [-pam_check_locks] + [-pts_names_formatting] + [-remove_xauth_cookies_on_exit] + [-seccomp_geteuid] + [-seccomp_getuid] + [-seccomp_stat] + [-seed-prng] + [-send_locale] + [-systemd-notify] + * not rebased (obsoleted) patches (so far): + [-additional_seccomp_archs] + [-allow_DSS_by_default] + [-default_protocol] + [-dont_use_pthreads_in_PAM] + [-eal3_obsolete] + [-gssapimitm] + [-saveargv-fix] + * obviously removing all standalone patch files: + [openssh-7.2p2-allow_root_password_login.patch] + [openssh-7.2p2-allow_DSS_by_default.patch] + [openssh-7.2p2-X11_trusted_forwarding.patch] + [openssh-7.2p2-lastlog.patch] + [openssh-7.2p2-enable_PAM_by_default.patch] + [openssh-7.2p2-dont_use_pthreads_in_PAM.patch] + [openssh-7.2p2-eal3.patch] + [openssh-7.2p2-blocksigalrm.patch] + [openssh-7.2p2-send_locale.patch] + [openssh-7.2p2-hostname_changes_when_forwarding_X.patch] + [openssh-7.2p2-remove_xauth_cookies_on_exit.patch] + [openssh-7.2p2-pts_names_formatting.patch] + [openssh-7.2p2-pam_check_locks.patch] + [openssh-7.2p2-disable_short_DH_parameters.patch] + [openssh-7.2p2-seccomp_getuid.patch] + [openssh-7.2p2-seccomp_geteuid.patch] + [openssh-7.2p2-seccomp_stat.patch] + [openssh-7.2p2-additional_seccomp_archs.patch] + [openssh-7.2p2-fips.patch] + [openssh-7.2p2-cavstest-ctr.patch] + [openssh-7.2p2-cavstest-kdf.patch] + [openssh-7.2p2-seed-prng.patch] + [openssh-7.2p2-gssapi_key_exchange.patch] + [openssh-7.2p2-audit.patch] + [openssh-7.2p2-audit_fixes.patch] + [openssh-7.2p2-audit_seed_prng.patch] + [openssh-7.2p2-login_options.patch] + [openssh-7.2p2-disable_openssl_abi_check.patch] + [openssh-7.2p2-no_fork-no_pid_file.patch] + [openssh-7.2p2-host_ident.patch] + [openssh-7.2p2-sftp_homechroot.patch] + [openssh-7.2p2-sftp_force_permissions.patch] + [openssh-7.2p2-X_forward_with_disabled_ipv6.patch] + [openssh-7.2p2-ldap.patch] + [openssh-7.2p2-IPv6_X_forwarding.patch] + [openssh-7.2p2-ignore_PAM_with_UseLogin.patch] + [openssh-7.2p2-prevent_timing_user_enumeration.patch] + [openssh-7.2p2-limit_password_length.patch] + [openssh-7.2p2-keep_slogin.patch] + [openssh-7.2p2-kex_resource_depletion.patch] + [openssh-7.2p2-verify_CIDR_address_ranges.patch] + [openssh-7.2p2-restrict_pkcs11-modules.patch] + [openssh-7.2p2-prevent_private_key_leakage.patch] + [openssh-7.2p2-secure_unix_sockets_forwarding.patch] + [openssh-7.2p2-ssh_case_insensitive_host_matching.patch] + [openssh-7.2p2-disable_preauth_compression.patch] + [openssh-7.2p2-s390_hw_crypto_syscalls.patch] + [openssh-7.2p2-s390_OpenSSL-ibmpkcs11_syscalls.patch] + +------------------------------------------------------------------- +Thu Nov 23 13:38:52 UTC 2017 - rbrown@suse.com + +- Replace references to /var/adm/fillup-templates with new + %_fillupdir macro (boo#1069468) + +------------------------------------------------------------------- +Wed Oct 25 15:09:06 UTC 2017 - jsegitz@suse.com + +- sshd_config is has now permissions 0600 in secure mode + +------------------------------------------------------------------- +Mon May 15 20:47:29 UTC 2017 - pcerny@suse.com + +- Fix preauth seccomp separation on mainframes (bsc#1016709) + [openssh-7.2p2-s390_hw_crypto_syscalls.patch] + [openssh-7.2p2-s390_OpenSSL-ibmpkcs11_syscalls.patch] +- enable case-insensitive hostname matching (bsc#1017099) + [openssh-7.2p2-ssh_case_insensitive_host_matching.patch] +- add CAVS tests + [openssh-7.2p2-cavstest-ctr.patch] + [openssh-7.2p2-cavstest-kdf.patch] +- Adding missing pieces for user matching (bsc#1021626) +- Properly verify CIDR masks in configuration + (bsc#1005893) + [openssh-7.2p2-verify_CIDR_address_ranges.patch] +- Remove pre-auth compression support from the server to prevent + possible cryptographic attacks. + (CVE-2016-10012, bsc#1016370) + [openssh-7.2p2-disable_preauth_compression.patch] +- limit directories for loading PKCS11 modules + (CVE-2016-10009, bsc#1016366) + [openssh-7.2p2-restrict_pkcs11-modules.patch] +- Prevent possible leaks of host private keys to low-privilege + process handling authentication + (CVE-2016-10011, bsc#1016369) + [openssh-7.2p2-prevent_private_key_leakage.patch] +- Do not allow unix socket forwarding when running without + privilege separation + (CVE-2016-10010, bsc#1016368) + [openssh-7.2p2-secure_unix_sockets_forwarding.patch] +- prevent resource depletion during key exchange + (bsc#1005480, CVE-2016-8858) + [openssh-7.2p2-kex_resource_depletion.patch] +- fix suggested command for removing conflicting server keys from + the known_hosts file (bsc#1006221) +- enable geteuid{,32} syscalls on mainframes, since it may be + called from libica/ibmica on machines with hardware crypto + accelerator (bsc#1004258) + [openssh-7.2p2-seccomp_geteuid.patch] +- fix regression of (bsc#823710) + [openssh-7.2p2-audit_fixes.patch] +- add slogin (removed upstreams) + [openssh-7.2p2-keep_slogin.patch] +- require OpenSSL < 1.1 where that one is a default + +------------------------------------------------------------------- +Wed Feb 22 19:31:08 UTC 2017 - crrodriguez@opensuse.org + +- sshd.service: Set TasksMax=infinity, as there should be + no limit on the amount of tasks sshd can run. + +------------------------------------------------------------------- +Thu Sep 29 23:27:49 UTC 2016 - pcerny@suse.com + +- remaining patches that were still missing + since the update to 7.2p2 (FATE#319675): +- allow X forwarding over IPv4 when IPv6 sockets is not available + [openssh-7.2p2-X_forward_with_disabled_ipv6.patch] +- do not write PID file when not daemonizing + [openssh-7.2p2-no_fork-no_pid_file.patch] +- use correct options when invoking login + [openssh-7.2p2-login_options.patch] +- helper application for retrieving users' public keys from + an LDAP server + [openssh-7.2p2-ldap.patch] +- allow forcing permissions over sftp + [openssh-7.2p2-sftp_force_permissions.patch] +- do not perform run-time checks for OpenSSL API/ABI change + [openssh-7.2p2-disable_openssl_abi_check.patch] +- suggest commands for cleaning known hosts file + [openssh-7.2p2-host_ident.patch] +- sftp home chroot patch + [openssh-7.2p2-sftp_homechroot.patch] +- ssh sessions auditing + [openssh-7.2p2-audit.patch] +- enable seccomp sandbox on additional architectures + [openssh-7.2p2-additional_seccomp_archs.patch] +- fix forwarding with IPv6 addresses in DISPLAY (bnc#847710) + [openssh-7.2p2-IPv6_X_forwarding.patch] +- ignore PAM environment when using login + (bsc#975865, CVE-2015-8325) + [openssh-7.2p2-ignore_PAM_with_UseLogin.patch] +- limit accepted password length (prevents possible DoS) + (bsc#992533, CVE-2016-6515) + [openssh-7.2p2-limit_password_length.patch] +- Prevent user enumeration through the timing of password + processing (bsc#989363, CVE-2016-6210) + [openssh-7.2p2-prevent_timing_user_enumeration.patch] +- Add auditing for PRNG re-seeding + [openssh-7.2p2-audit_seed_prng.patch] + +------------------------------------------------------------------- +Fri Sep 16 12:45:11 UTC 2016 - pcerny@suse.com + +- FIPS compatibility (no selfchecks, only crypto restrictions) + [openssh-7.2p2-fips.patch] +- PRNG re-seeding + [openssh-7.2p2-seed-prng.patch] +- preliminary version of GSSAPI KEX + [openssh-7.2p2-gssapi_key_exchange.patch] + +------------------------------------------------------------------- +Mon Jul 25 13:46:06 UTC 2016 - meissner@suse.com + +- added gpg signature + +------------------------------------------------------------------- +Tue Jun 7 16:52:45 UTC 2016 - pcerny@suse.com + +- enable support for SSHv1 protocol and discourage its usage + (bsc#983307) +- enable DSA by default for backward compatibility and discourage + its usage (bsc#983784) + [openssh-7.2p2-allow_DSS_by_default.patch] + +------------------------------------------------------------------- +Mon May 30 00:30:16 UTC 2016 - pcerny@suse.com + +- enable trusted X11 forwarding by default + [openssh-7.2p2-X11_trusted_forwarding.patch] +- set UID for lastlog properly + [openssh-7.2p2-lastlog.patch] +- enable use of PAM by default + [openssh-7.2p2-enable_PAM_by_default.patch] +- copy command line arguments properly + [openssh-7.2p2-saveargv-fix.patch] +- do not use pthreads in PAM code + [openssh-7.2p2-dont_use_pthreads_in_PAM.patch] +- fix paths in documentation + [openssh-7.2p2-eal3.patch] +- prevent race consitions triggered by SIGALRM + [openssh-7.2p2-blocksigalrm.patch] +- do send and accept locale environment variables by default + [openssh-7.2p2-send_locale.patch] +- handle hostnames changes during X forwarding + [openssh-7.2p2-hostname_changes_when_forwarding_X.patch] +- try to remove xauth cookies on exit + [openssh-7.2p2-remove_xauth_cookies_on_exit.patch] +- properly format pts names for ?tmp? log files + [openssh-7.2p2-pts_names_formatting.patch] +- check locked accounts when using PAM + [openssh-7.2p2-pam_check_locks.patch] +- chenge default PermitRootLogin to 'yes' to prevent unwanted + surprises on updates from older versions. + See README.SUSE for details + [openssh-7.2p2-allow_root_password_login.patch] +- Disable DH parameters under 2048 bits by default and allow + lowering the limit back to the RFC 4419 specified minimum + through an option (bsc#932483, bsc#948902) + [openssh-7.2p2-disable_short_DH_parameters.patch] +- Add getuid() and stat() syscalls to the seccomp filter + (bsc#912436) + [openssh-7.2p2-seccomp_getuid.patch, + openssh-7.2p2-seccomp_stat.patch] + +------------------------------------------------------------------- +Fri May 27 23:27:51 UTC 2016 - pcerny@suse.com + +- upgrade to 7.2p2 + upstream package without any SUSE patches + Distilled upstream log: +- OpenSSH 6.7 + Potentially-incompatible changes: + * sshd(8): The default set of ciphers and MACs has been + altered to remove unsafe algorithms. In particular, CBC + ciphers and arcfour* are disabled by default. + The full set of algorithms remains available if configured + explicitly via the Ciphers and MACs sshd_config options. + * sshd(8): Support for tcpwrappers/libwrap has been removed. + * OpenSSH 6.5 and 6.6 have a bug that causes ~0.2% of + connections using the curve25519-sha256@libssh.org KEX + exchange method to fail when connecting with something that + implements the specification correctly. OpenSSH 6.7 disables + this KEX method when speaking to one of the affected + versions. + New Features: + * ssh(1), sshd(8): Add support for Unix domain socket + forwarding. A remote TCP port may be forwarded to a local + Unix domain socket and vice versa or both ends may be a Unix + domain socket. + * ssh(1), ssh-keygen(1): Add support for SSHFP DNS records for + ED25519 key types. + * sftp(1): Allow resumption of interrupted uploads. + * ssh(1): When rekeying, skip file/DNS lookups of the hostkey + if it is the same as the one sent during initial key exchange + * sshd(8): Allow explicit ::1 and 127.0.0.1 forwarding bind + addresses when GatewayPorts=no; allows client to choose + address family + * sshd(8): Add a sshd_config PermitUserRC option to control + whether ~/.ssh/rc is executed, mirroring the no-user-rc + authorized_keys option + * ssh(1): Add a %C escape sequence for LocalCommand and + ControlPath that expands to a unique identifer based on a + hash of the tuple of (local host, remote user, hostname, + port). Helps avoid exceeding miserly pathname limits for Unix + domain sockets in multiplexing control paths + * sshd(8): Make the "Too many authentication failures" message + include the user, source address, port and protocol in a + format similar to the authentication success / failure + messages + Bugfixes: + * sshd(8): Fix remote forwarding with the same listen port but + different listen address. + * ssh(1): Fix inverted test that caused PKCS#11 keys that were + explicitly listed in ssh_config or on the commandline not to + be preferred. + * ssh-keygen(1): Fix bug in KRL generation: multiple + consecutive revoked certificate serial number ranges could be + serialised to an invalid format. Readers of a broken KRL + caused by this bug will fail closed, so no + should-have-been-revoked key will be accepted. + * ssh(1): Reflect stdio-forward ("ssh -W host:port ...") + failures in exit status. Previously we were always returning 0 + * ssh(1), ssh-keygen(1): Make Ed25519 keys' title fit properly + in the randomart border + * ssh-agent(1): Only cleanup agent socket in the main agent + process and not in any subprocesses it may have started (e.g. + forked askpass). Fixes agent sockets being zapped when + askpass processes fatal() + * ssh-add(1): Make stdout line-buffered; saves partial output + getting lost when ssh-add fatal()s part-way through (e.g. + when listing keys from an agent that supports key types that + ssh-add doesn't) + * ssh-keygen(1): When hashing or removing hosts, don't choke on + @revoked markers and don't remove @cert-authority markers + * ssh(1): Don't fatal when hostname canonicalisation fails and + a ProxyCommand is in use; continue and allow the ProxyCommand + to connect anyway (e.g. to a host with a name outside the DNS + behind a bastion) + * scp(1): When copying local->remote fails during read, don't + send uninitialised heap to the remote end. + * sftp(1): Fix fatal "el_insertstr failed" errors when + tab-completing filenames with a single quote char somewhere + in the string + * ssh-keyscan(1): Scan for Ed25519 keys by default. + * ssh(1): When using VerifyHostKeyDNS with a DNSSEC resolver, + down-convert any certificate keys to plain keys and attempt + SSHFP resolution. Prevents a server from skipping SSHFP + lookup and forcing a new-hostkey dialog by offering only + certificate keys. +- OpenSSH 6.8 + Potentially-incompatible changes: + * sshd(8): UseDNS now defaults to 'no'. Configurations that + match against the client host name (via sshd_config or + authorized_keys) may need to re-enable it or convert to + matching against addresses. + New Features: + * Add FingerprintHash option to ssh(1) and sshd(8), and + equivalent command-line flags to the other tools to control + algorithm used for key fingerprints. The default changes from + MD5 to SHA256 and format from hex to base64. + Fingerprints now have the hash algorithm prepended. An + example of the new format: + SHA256:mVPwvezndPv/ARoIadVY98vAC0g+P/5633yTC4d/wXE Please + note that visual host keys will also be different. + * ssh(1), sshd(8): Experimental host key rotation support. Add + a protocol extension for a server to inform a client of all + its available host keys after authentication has completed. + The client may record the keys in known_hosts, allowing it to + upgrade to better host key algorithms and a server to + gracefully rotate its keys. + The client side of this is controlled by a UpdateHostkeys + config option (default off). + * ssh(1): Add a ssh_config HostbasedKeyType option to control + which host public key types are tried during host-based + authentication. + * ssh(1), sshd(8): fix connection-killing host key mismatch + errors when sshd offers multiple ECDSA keys of different + lengths. + * ssh(1): when host name canonicalisation is enabled, try to + parse host names as addresses before looking them up for + canonicalisation. fixes bz#2074 and avoiding needless DNS + lookups in some cases. + * ssh-keygen(1), sshd(8): Key Revocation Lists (KRLs) no longer + require OpenSSH to be compiled with OpenSSL support. + * ssh(1), ssh-keysign(8): Make ed25519 keys work for host based + authentication. + * sshd(8): SSH protocol v.1 workaround for the Meyer, et al, + Bleichenbacher Side Channel Attack. Fake up a bignum key + before RSA decryption. + * sshd(8): Remember which public keys have been used for + authentication and refuse to accept previously-used keys. + This allows AuthenticationMethods=publickey,publickey to + require that users authenticate using two _different_ public + keys. + * sshd(8): add sshd_config HostbasedAcceptedKeyTypes and + PubkeyAcceptedKeyTypes options to allow sshd to control what + public key types will be accepted. Currently defaults to all. + * sshd(8): Don't count partial authentication success as a + failure against MaxAuthTries. + * ssh(1): Add RevokedHostKeys option for the client to allow + text-file or KRL-based revocation of host keys. + * ssh-keygen(1), sshd(8): Permit KRLs that revoke certificates + by serial number or key ID without scoping to a particular + CA. + * ssh(1): Add a "Match canonical" criteria that allows + ssh_config Match blocks to trigger only in the second config + pass. + * ssh(1): Add a -G option to ssh that causes it to parse its + configuration and dump the result to stdout, similar to + "sshd -T". + * ssh(1): Allow Match criteria to be negated. + E.g. "Match !host". + * The regression test suite has been extended to cover more + OpenSSH features. The unit tests have been expanded and now + cover key exchange. + Bugfixes: + * ssh-keyscan(1): ssh-keyscan has been made much more robust + again servers that hang or violate the SSH protocol. + * ssh(1), ssh-keygen(1): Fix regression: Key path names were + being lost as comment fields. + * ssh(1): Allow ssh_config Port options set in the second + config parse phase to be applied (they were being ignored). + * ssh(1): Tweak config re-parsing with host canonicalisation - make + the second pass through the config files always run when host name + canonicalisation is enabled (and not whenever the host name + changes) + * ssh(1): Fix passing of wildcard forward bind addresses when + connection multiplexing is in use + * ssh-keygen(1): Fix broken private key conversion from + non-OpenSSH formats. + * ssh-keygen(1): Fix KRL generation bug when multiple CAs are + in use. + * Various fixes to manual pages +- OpenSSH 6.9 + Security: + * ssh(1): when forwarding X11 connections with + ForwardX11Trusted=no, connections made after + ForwardX11Timeout expired could be permitted and no longer + subject to XSECURITY restrictions because of an ineffective + timeout check in ssh(1) coupled with "fail open" behaviour in + the X11 server when clients attempted connections with + expired credentials. This problem was reported by Jann Horn. + * ssh-agent(1): fix weakness of agent locking (ssh-add -x) to + password guessing by implementing an increasing failure + delay, storing a salted hash of the password rather than the + password itself and using a timing-safe comparison function + for verifying unlock attempts. This problem was reported by + Ryan Castellucci. + New Features: + * ssh(1), sshd(8): promote chacha20-poly1305@openssh.com to be + the default cipher + * sshd(8): support admin-specified arguments to + AuthorizedKeysCommand + * sshd(8): add AuthorizedPrincipalsCommand that allows + retrieving authorized principals information from a + subprocess rather than a file. + * ssh(1), ssh-add(1): support PKCS#11 devices with external PIN + entry devices + * sshd(8): allow GSSAPI host credential check to be relaxed for + multihomed hosts via GSSAPIStrictAcceptorCheck option + * ssh-keygen(1): support "ssh-keygen -lF hostname" to search + known_hosts and print key hashes rather than full keys. + * ssh-agent(1): add -D flag to leave ssh-agent in foreground + without enabling debug mode + Bugfixes: + * ssh(1), sshd(8): deprecate legacy + SSH2_MSG_KEX_DH_GEX_REQUEST_OLD message and do not try to use + it against some 3rd-party SSH implementations that use it + (older PuTTY, WinSCP). + * Many fixes for problems caused by compile-time deactivation + of SSH1 support (including bz#2369) + * ssh(1), sshd(8): cap DH-GEX group size at 4Kbits for Cisco + implementations as some would fail when attempting to use + group sizes >4K + * ssh(1): fix out-of-bound read in EscapeChar configuration + option parsing + * sshd(8): fix application of PermitTunnel, LoginGraceTime, + AuthenticationMethods and StreamLocalBindMask options in + Match blocks + * ssh(1), sshd(8): improve disconnection message on TCP reset; + bz#2257 + * ssh(1): remove failed remote forwards established by + muliplexing from the list of active forwards + * sshd(8): make parsing of authorized_keys "environment=" + options independent of PermitUserEnv being enabled + * sshd(8): fix post-auth crash with permitopen=none + * ssh(1), ssh-add(1), ssh-keygen(1): allow new-format private + keys to be encrypted with AEAD ciphers + * ssh(1): allow ListenAddress, Port and AddressFamily + configuration options to appear in any order + * sshd(8): check for and reject missing arguments for + VersionAddendum and ForceCommand + * ssh(1), sshd(8): don't treat unknown certificate extensions + as fatal + * ssh-keygen(1): make stdout and stderr output consistent + * ssh(1): mention missing DISPLAY environment in debug log when + X11 forwarding requested + * sshd(8): correctly record login when UseLogin is set + * sshd(8): Add some missing options to sshd -T output and fix + output of VersionAddendum and HostCertificate. bz#2346 + * Document and improve consistency of options that accept a + "none" argument" TrustedUserCAKeys, RevokedKeys (bz#2382), + AuthorizedPrincipalsFile (bz#2288) + * ssh(1): include remote username in debug output + * sshd(8): avoid compatibility problem with some versions of + Tera Term, which would crash when they received the hostkeys + notification message (hostkeys-00@openssh.com) + * sshd(8): mention ssh-keygen -E as useful when comparing + legacy MD5 host key fingerprints + * ssh(1): clarify pseudo-terminal request behaviour and use + make manual language consistent + * ssh(1): document that the TERM environment variable is not + subject to SendEnv and AcceptEnv +- OpenSSH 7.0: + This focuses primarily on deprecating weak, legacy and/or + unsafe cryptography. + Security: + * sshd(8): OpenSSH 6.8 and 6.9 incorrectly set TTYs to be + world- writable. Local attackers may be able to write + arbitrary messages to logged-in users, including terminal + escape sequences. Reported by Nikolay Edigaryev. + * sshd(8): Portable OpenSSH only: Fixed a privilege separation + weakness related to PAM support. Attackers who could + successfully compromise the pre-authentication process for + remote code execution and who had valid credentials on the + host could impersonate other users. Reported by Moritz + Jodeit. + * sshd(8): Portable OpenSSH only: Fixed a use-after-free bug + related to PAM support that was reachable by attackers who + could compromise the pre-authentication process for remote + code execution. Also reported by Moritz Jodeit. + * sshd(8): fix circumvention of MaxAuthTries using keyboard- + interactive authentication. By specifying a long, repeating + keyboard-interactive "devices" string, an attacker could + request the same authentication method be tried thousands of + times in a single pass. The LoginGraceTime timeout in sshd(8) + and any authentication failure delays implemented by the + authentication mechanism itself were still applied. Found by + Kingcope. + Potentially-incompatible Changes: + * Support for the legacy SSH version 1 protocol is disabled by + default at compile time. + * Support for the 1024-bit diffie-hellman-group1-sha1 key + exchange is disabled by default at run-time. It may be + re-enabled using the instructions in README.legacy or + http://www.openssh.com/legacy.html + * Support for ssh-dss, ssh-dss-cert-* host and user keys is + disabled by default at run-time. These may be re-enabled + using the instructions at http://www.openssh.com/legacy.html + * Support for the legacy v00 cert format has been removed. + * The default for the sshd_config(5) PermitRootLogin option has + changed from "yes" to "prohibit-password". + * PermitRootLogin=without-password/prohibit-password now bans + all interactive authentication methods, allowing only + public-key, hostbased and GSSAPI authentication (previously + it permitted keyboard-interactive and password-less + authentication if those were enabled). + New Features: + * ssh_config(5): add PubkeyAcceptedKeyTypes option to control + which public key types are available for user authentication. + * sshd_config(5): add HostKeyAlgorithms option to control which + public key types are offered for host authentications. + * ssh(1), sshd(8): extend Ciphers, MACs, KexAlgorithms, + HostKeyAlgorithms, PubkeyAcceptedKeyTypes and + HostbasedKeyTypes options to allow appending to the default + set of algorithms instead of replacing it. Options may now be + prefixed with a '+' to append to the default, e.g. + "HostKeyAlgorithms=+ssh-dss". + * sshd_config(5): PermitRootLogin now accepts an argument of + 'prohibit-password' as a less-ambiguous synonym of 'without- + password'. + Bugfixes: + * ssh(1), sshd(8): add compatability workarounds for Cisco and + more PuTTY versions. + * Fix some omissions and errors in the PROTOCOL and + PROTOCOL.mux documentation relating to Unix domain socket + forwarding + * ssh(1): Improve the ssh(1) manual page to include a better + description of Unix domain socket forwarding + * ssh(1), ssh-agent(1): skip uninitialised PKCS#11 slots, + fixing failures to load keys when they are present. + * ssh(1), ssh-agent(1): do not ignore PKCS#11 hosted keys that + wth empty CKA_ID + * sshd(8): clarify documentation for UseDNS option +- OpenSSH 7.1: + Security: + * sshd(8): OpenSSH 7.0 contained a logic error in + PermitRootLogin= prohibit-password/without-password that + could, depending on compile-time configuration, permit + password authentication to root while preventing other forms + of authentication. This problem was reported by Mantas + Mikulenas. + Bugfixes: + * ssh(1), sshd(8): add compatability workarounds for FuTTY + * ssh(1), sshd(8): refine compatability workarounds for WinSCP + * Fix a number of memory faults (double-free, free of + uninitialised memory, etc) in ssh(1) and ssh-keygen(1). + Reported by Mateusz Kocielski. +- OpenSSH 7.1p2: + * SECURITY: ssh(1): The OpenSSH client code between 5.4 and 7.1 + contains experimential support for resuming SSH-connections + (roaming). + The matching server code has never been shipped, but the + client code was enabled by default and could be tricked by a + malicious server into leaking client memory to the server, + including private client user keys. + The authentication of the server host key prevents + exploitation by a man-in-the-middle, so this information leak + is restricted to connections to malicious or compromised + servers. + MITIGATION: For OpenSSH >= 5.4 the vulnerable code in the + client can be completely disabled by adding 'UseRoaming no' + to the gobal ssh_config(5) file, or to user configuration in + ~/.ssh/config, or by passing -oUseRoaming=no on the command + line. + PATCH: See below for a patch to disable this feature + (Disabling Roaming in the Source Code). + This problem was reported by the Qualys Security Advisory + team. + * SECURITY: Eliminate the fallback from untrusted + X11-forwarding to trusted forwarding for cases when the X + server disables the SECURITY extension. Reported by Thomas + Hoger. + * SECURITY: Fix an out of-bound read access in the packet + handling code. Reported by Ben Hawkes. + * PROTOCOL: Correctly interpret the 'first_kex_follows' option + during the intial key exchange. Reported by Matt Johnston. + * Further use of explicit_bzero has been added in various + buffer handling code paths to guard against compilers + aggressively doing dead-store removal. + Potentially-incompatible changes: + * This release disables a number of legacy cryptographic + algorithms by default in ssh: + + Several ciphers blowfish-cbc, cast128-cbc, all arcfour + variants and the rijndael-cbc aliases for AES. + + MD5-based and truncated HMAC algorithms. +- OpenSSH 7.2: + Security: + * ssh(1), sshd(8): remove unfinished and unused roaming code + (was already forcibly disabled in OpenSSH 7.1p2). + * ssh(1): eliminate fallback from untrusted X11 forwarding to + trusted forwarding when the X server disables the SECURITY + extension. + * ssh(1), sshd(8): increase the minimum modulus size supported + for diffie-hellman-group-exchange to 2048 bits. + * sshd(8): pre-auth sandboxing is now enabled by default + (previous releases enabled it for new installations via + sshd_config). + New Features: + * all: add support for RSA signatures using SHA-256/512 hash + algorithms based on draft-rsa-dsa-sha2-256-03.txt and + draft-ssh-ext-info-04.txt. + * ssh(1): Add an AddKeysToAgent client option which can be set + to 'yes', 'no', 'ask', or 'confirm', and defaults to 'no'. + When enabled, a private key that is used during + authentication will be added to ssh-agent if it is running + (with confirmation enabled if set to 'confirm'). + * sshd(8): add a new authorized_keys option "restrict" that + includes all current and future key restrictions + (no-*-forwarding, etc.). Also add permissive versions of the + existing restrictions, e.g. "no-pty" -> "pty". This + simplifies the task of setting up restricted keys and ensures + they are maximally-restricted, regardless of any permissions + we might implement in the future. + * ssh(1): add ssh_config CertificateFile option to explicitly + list certificates. bz#2436 + * ssh-keygen(1): allow ssh-keygen to change the key comment for + all supported formats. + * ssh-keygen(1): allow fingerprinting from standard input, e.g. + "ssh-keygen -lf -" + * ssh-keygen(1): allow fingerprinting multiple public keys in a + file, e.g. "ssh-keygen -lf ~/.ssh/authorized_keys" bz#1319 + * sshd(8): support "none" as an argument for sshd_config + Foreground and ChrootDirectory. Useful inside Match blocks to + override a global default. bz#2486 + * ssh-keygen(1): support multiple certificates (one per line) + and reading from standard input (using "-f -") for + "ssh-keygen -L" + * ssh-keyscan(1): add "ssh-keyscan -c ..." flag to allow + fetching certificates instead of plain keys. + * ssh(1): better handle anchored FQDNs (e.g. 'cvs.openbsd.org') + in hostname canonicalisation - treat them as already + canonical and remove the trailing '.' before matching + ssh_config. + Bugfixes: + * sftp(1): existing destination directories should not + terminate recursive uploads (regression in openssh 6.8) + * ssh(1), sshd(8): correctly send back SSH2_MSG_UNIMPLEMENTED + replies to unexpected messages during key exchange. + * ssh(1): refuse attempts to set ConnectionAttempts=0, which + does not make sense and would cause ssh to print an + uninitialised stack variable. + * ssh(1): fix errors when attempting to connect to scoped IPv6 + addresses with hostname canonicalisation enabled. + * sshd_config(5): list a couple more options usable in Match + blocks. + * sshd(8): fix "PubkeyAcceptedKeyTypes +..." inside a Match + block. + * ssh(1): expand tilde characters in filenames passed to -i + options before checking whether or not the identity file + exists. Avoids confusion for cases where shell doesn't expand + (e.g. "-i ~/file" vs. "-i~/file"). + * ssh(1): do not prepend "exec" to the shell command run by + "Match exec" in a config file, which could cause some + commands to fail in certain environments. + * ssh-keyscan(1): fix output for multiple hosts/addrs on one + line when host hashing or a non standard port is in use + * sshd(8): skip "Could not chdir to home directory" message + when ChrootDirectory is active. + * ssh(1): include PubkeyAcceptedKeyTypes in ssh -G config dump. + * sshd(8): avoid changing TunnelForwarding device flags if they + are already what is needed; makes it possible to use tun/tap + networking as non-root user if device permissions and + interface flags are pre-established + * ssh(1), sshd(8): RekeyLimits could be exceeded by one packet. + * ssh(1): fix multiplexing master failure to notice client + exit. + * ssh(1), ssh-agent(1): avoid fatal() for PKCS11 tokens that + present empty key IDs. + * sshd(8): avoid printf of NULL argument. + * ssh(1), sshd(8): allow RekeyLimits larger than 4GB. + * ssh-keygen(1): sshd(8): fix several bugs in (unused) KRL + signature support. + * ssh(1), sshd(8): fix connections with peers that use the key + exchange guess feature of the protocol. + * sshd(8): include remote port number in log messages. + * ssh(1): don't try to load SSHv1 private key when compiled + without SSHv1 support. + * ssh-agent(1), ssh(1): fix incorrect error messages during key + loading and signing errors. + * ssh-keygen(1): don't leave empty temporary files when + performing known_hosts file edits when known_hosts doesn't + exist. + * sshd(8): correct packet format for tcpip-forward replies for + requests that don't allocate a port + * ssh(1), sshd(8): fix possible hang on closed output. + * ssh(1): expand %i in ControlPath to UID. + * ssh(1), sshd(8): fix return type of openssh_RSA_verify. + * ssh(1), sshd(8): fix some option parsing memory leaks. + * ssh(1): add a some debug output before DNS resolution; it's a + place where ssh could previously silently stall in cases of + unresponsive DNS servers. + * ssh(1): remove spurious newline in visual hostkey. + * ssh(1): fix printing (ssh -G ...) of HostKeyAlgorithms=+... + * ssh(1): fix expansion of HostkeyAlgorithms=+... + Documentation: + * ssh_config(5), sshd_config(5): update default algorithm lists + to match current reality. + * ssh(1): mention -Q key-plain and -Q key-cert query options. + * sshd_config(8): more clearly describe what + AuthorizedKeysFile=none does. + * ssh_config(5): better document ExitOnForwardFailure. + * sshd(5): mention internal DH-GEX fallback groups in manual. + * sshd_config(5): better description for MaxSessions option. + Portability: + * sshd(8): fix multiple authentication using S/Key. +- OpenSSH 7.2p2: + Security: + * sshd(8): sanitise X11 authentication credentials to avoid + xauth command injection when X11Forwarding is enabled. + (removing patches from previous version: + * CVE-2016-0777_CVE-2016-0778.patch + * openssh-6.6p1-X11-forwarding.patch + * openssh-6.6p1-X_forward_with_disabled_ipv6.patch + * openssh-6.6p1-audit1-remove_duplicit_audit.patch + * openssh-6.6p1-audit2-better_audit_of_user_actions.patch + * openssh-6.6p1-audit3-key_auth_usage-fips.patch + * openssh-6.6p1-audit3-key_auth_usage.patch + * openssh-6.6p1-audit4-kex_results-fips.patch + * openssh-6.6p1-audit4-kex_results.patch + * openssh-6.6p1-audit5-session_key_destruction.patch + * openssh-6.6p1-audit6-server_key_destruction.patch + * openssh-6.6p1-audit7-libaudit_compat.patch + * openssh-6.6p1-audit8-libaudit_dns_timeouts.patch + * openssh-6.6p1-blocksigalrm.patch + * openssh-6.6p1-curve25519-6.6.1p1.patch + * openssh-6.6p1-default-protocol.patch + * openssh-6.6p1-disable-openssl-abi-check.patch + * openssh-6.6p1-eal3.patch + * openssh-6.6p1-fingerprint_hash.patch + * openssh-6.6p1-fips-checks.patch + * openssh-6.6p1-fips.patch + * openssh-6.6p1-gssapi_key_exchange.patch + * openssh-6.6p1-gssapimitm.patch + * openssh-6.6p1-host_ident.patch + * openssh-6.6p1-key-converter.patch + * openssh-6.6p1-lastlog.patch + * openssh-6.6p1-ldap.patch + * openssh-6.6p1-login_options.patch + * openssh-6.6p1-no_fork-no_pid_file.patch + * openssh-6.6p1-pam-check-locks.patch + * openssh-6.6p1-pam-fix2.patch + * openssh-6.6p1-pam-fix3.patch + * openssh-6.6p1-pts.patch + * openssh-6.6p1-saveargv-fix.patch + * openssh-6.6p1-seccomp_getuid.patch + * openssh-6.6p1-seccomp_stat.patch + * openssh-6.6p1-seed-prng.patch + * openssh-6.6p1-send_locale.patch + * openssh-6.6p1-sftp_force_permissions.patch + * openssh-6.6p1-sftp_homechroot.patch + * openssh-6.6p1-xauth.patch + * openssh-6.6p1-xauthlocalhostname.patch) + +------------------------------------------------------------------- +Fri Apr 29 15:56:38 UTC 2016 - pcerny@suse.com + +- update seccomp sandbox that broke after OpenSSL update + (bsc#912436, bsc#977812) + [openssh-6.6p1-seccomp_stat.patch] + +------------------------------------------------------------------- +Wed Apr 6 11:42:35 UTC 2016 - kukuk@suse.com + +- openssh-6.6p1-ldap.patch: replace TRUE/FALSE with 1/0, since + this defines did come via an indirect header inclusion and are + not everywhere defined. + +------------------------------------------------------------------- +Thu Jan 14 15:35:55 UTC 2016 - astieger@suse.com + +- CVE-2016-0777, bsc#961642, CVE-2016-0778, bsc#961645 + Add CVE-2016-0777_CVE-2016-0778.patch to disable the roaming code + to prevent information leak and buffer overflow + +------------------------------------------------------------------- +Mon Jan 12 10:35:12 UTC 2015 - meissner@suse.com + +- gpg signature and keyring added. + pub 3200R/6D920D30 2013-12-10 [expires: 2021-01-01] + uid Damien Miller + sub 3200R/672A1105 2013-12-10 [expires: 2021-01-01] + +------------------------------------------------------------------- +Sat Dec 27 23:45:00 UTC 2014 - Led + +- fix bashisms in sshd.init script + +------------------------------------------------------------------- +Wed Oct 8 10:12:40 UTC 2014 - werner@suse.de + +- Ensure that ssh can use the ssh support of the gpg-agent (boo#899647) + +------------------------------------------------------------------- +Mon Jul 21 15:58:09 UTC 2014 - p.drouand@gmail.com + +- Do not depend on insserv if the package build with systemd support; + it's useless + +------------------------------------------------------------------- +Sat May 17 22:31:29 UTC 2014 - crrodriguez@opensuse.org + +- Remove tcpwrappers support now, This feature was removed + in upstream code at the end of April and the underlying + libraries are abandonware. + See: http://comments.gmane.org/gmane.linux.suse.general/348119 + +------------------------------------------------------------------- +Thu Apr 24 01:33:45 UTC 2014 - pcerny@suse.com + +- curve25519 key exchange fix (-curve25519-6.6.1p1.patch) +- patch re-ordering (-audit3-key_auth_usage-fips.patch, + -audit4-kex_results-fips.patch) + +------------------------------------------------------------------- +Tue Apr 15 09:26:16 UTC 2014 - rhafer@suse.com + +- Remove uneeded dependency on the OpenLDAP server (openldap2) + from openssh-helpers. openssh-helpers just depends on the + openldap client libraries, which will be auto-generated by rpm. + +------------------------------------------------------------------- +Fri Apr 11 21:50:51 UTC 2014 - pcerny@suse.com + +- update to 6.6p1 + Security: + * sshd(8): when using environment passing with a sshd_config(5) + AcceptEnv pattern with a wildcard. OpenSSH prior to 6.6 could + be tricked into accepting any enviornment variable that + contains the characters before the wildcard character. + Features since 6.5p1: + * ssh(1), sshd(8): removal of the J-PAKE authentication code, + which was experimental, never enabled and has been + unmaintained for some time. + * ssh(1): skip 'exec' clauses other clauses predicates failed + to match while processing Match blocks. + * ssh(1): if hostname canonicalisation is enabled and results + in the destination hostname being changed, then re-parse + ssh_config(5) files using the new destination hostname. This + gives 'Host' and 'Match' directives that use the expanded + hostname a chance to be applied. + Bugfixes: + * ssh(1): avoid spurious "getsockname failed: Bad file + descriptor" in ssh -W. bz#2200, debian#738692 + * sshd(8): allow the shutdown(2) syscall in seccomp-bpf and + systrace sandbox modes, as it is reachable if the connection + is terminated during the pre-auth phase. + * ssh(1), sshd(8): fix unsigned overflow that in SSH protocol 1 + bignum parsing. Minimum key length checks render this bug + unexploitable to compromise SSH 1 sessions. + * sshd_config(5): clarify behaviour of a keyword that appears + in multiple matching Match blocks. bz#2184 + * ssh(1): avoid unnecessary hostname lookups when + canonicalisation is disabled. bz#2205 + * sshd(8): avoid sandbox violation crashes in GSSAPI code by + caching the supported list of GSSAPI mechanism OIDs before + entering the sandbox. bz#2107 + * ssh(1): fix possible crashes in SOCKS4 parsing caused by + assumption that the SOCKS username is nul-terminated. + * ssh(1): fix regression for UsePrivilegedPort=yes when + BindAddress is not specified. + * ssh(1), sshd(8): fix memory leak in ECDSA signature + verification. + * ssh(1): fix matching of 'Host' directives in ssh_config(5) + files to be case-insensitive again (regression in 6.5). +- FIPS checks in sftp-server + +------------------------------------------------------------------- +Mon Mar 31 01:22:21 UTC 2014 - pcerny@suse.com + +- FIPS checks during ssh client and daemon startup + (-fips-checks.patch) + +------------------------------------------------------------------- +Tue Mar 25 10:07:18 UTC 2014 - idonmez@suse.com + +- Update openssh-6.5p1-audit4-kex_results.patch to ensure that + we don't pass a NULL string to buffer_put_cstring. This happens + when you have "Ciphers chacha20-poly1305@openssh.com" directive. + +------------------------------------------------------------------- +Mon Mar 17 02:21:13 UTC 2014 - pcerny@suse.com + +- re-enabling the GSSAPI Key Exchange patch + +------------------------------------------------------------------- +Fri Feb 28 12:59:27 UTC 2014 - pcerny@suse.com + +- re-enabling FIPS-enablement patch +- enable X11 forwarding when IPv6 is present but disabled on server + (bnc#712683, FATE#31503; -X_forward_with_disabled_ipv6.patch) + +------------------------------------------------------------------- +Tue Feb 18 12:56:31 UTC 2014 - pcerny@suse.com + +- openssh-6.5p1-seccomp_getuid.patch: re-enabling the seccomp sandbox + (allowing use of the getuid syscall) (bnc#864171) + +------------------------------------------------------------------- +Wed Feb 12 01:24:16 UTC 2014 - pcerny@suse.com + +- Update to 6.5p1 + Features since 6.4p1: + * ssh(1), sshd(8): support for key exchange using ECDH in + Daniel Bernstein's Curve25519; default when both the client + and server support it. + * ssh(1), sshd(8): support for Ed25519 as a public key type fo + rboth server and client. Ed25519 is an EC signature offering + better security than ECDSA and DSA and good performance. + * Add a new private key format that uses a bcrypt KDF to better + protect keys at rest. Used unconditionally for Ed25519 keys, + on demand for other key types via the -o ssh-keygen(1) + option. Intended to become default in the near future. + Details documented in PROTOCOL.key. + * ssh(1), sshd(8): new transport cipher + "chacha20-poly1305@openssh.com" combining Daniel Bernstein's + ChaCha20 stream cipher and Poly1305 MAC to build an + authenticated encryption mode. Details documented + PROTOCOL.chacha20poly1305. + * ssh(1), sshd(8): refuse RSA keys from old proprietary clients + and servers that use the obsolete RSA+MD5 signature scheme. + It will still be possible to connect with these + clients/servers but only DSA keys will be accepted, and + OpenSSH will refuse connection entirely in a future release. + * ssh(1), sshd(8): refuse old proprietary clients and servers + that use a weaker key exchange hash calculation. + * ssh(1): increase the size of the Diffie-Hellman groups + requested for each symmetric key size. New values from NIST + Special Publication 800-57 with the upper limit specified by + RFC4419. + * ssh(1), ssh-agent(1): support pkcs#11 tokens that only + provide X.509 certs instead of raw public keys (requested as + bz#1908). + * ssh(1): new ssh_config(5) "Match" keyword that allows + conditional configuration to be applied by matching on + hostname, user and result of arbitrary commands. + * ssh(1): support for client-side hostname canonicalisation + using a set of DNS suffixes and rules in ssh_config(5). This + allows unqualified names to be canonicalised to + fully-qualified domain names to eliminate ambiguity when + looking up keys in known_hosts or checking host certificate + names. + * sftp-server(8): ability to whitelist and/or blacklist sftp + protocol requests by name. + * sftp-server(8): sftp "fsync@openssh.com" to support calling + fsync(2) on an open file handle. + * sshd(8): ssh_config(5) PermitTTY to disallow TTY allocation, + mirroring the longstanding no-pty authorized_keys option. + * ssh(1): ssh_config ProxyUseFDPass option that supports the + use of ProxyCommands that establish a connection and then + pass a connected file descriptor back to ssh(1). This allows + the ProxyCommand to exit rather than staying around to + transfer data. + Bugfixes since 6.4p1: + * ssh(1), sshd(8): fix potential stack exhaustion caused by + nested certificates. + * ssh(1): bz#1211: make BindAddress work with + UsePrivilegedPort. + * sftp(1): bz#2137: fix the progress meter for resumed + transfer. + * ssh-add(1): bz#2187: do not request smartcard PIN when + removing keys from ssh-agent. + * sshd(8): bz#2139: fix re-exec fallback when original sshd + binary cannot be executed. + * ssh-keygen(1): make relative-specified certificate expiry + times relative to current time and not the validity start + time. + * sshd(8): bz#2161: fix AuthorizedKeysCommand inside a Match + block. + * sftp(1): bz#2129: symlinking a file would incorrectly + canonicalise the target path. + * ssh-agent(1): bz#2175: fix a use-after-free in the PKCS#11 + agent helper executable. + * sshd(8): improve logging of sessions to include the user + name, remote host and port, the session type (shell, command, + etc.) and allocated TTY (if any). + * sshd(8): bz#1297: tell the client (via a debug message) when + their preferred listen address has been overridden by the + server's GatewayPorts setting. + * sshd(8): bz#2162: include report port in bad protocol banner + message. + * sftp(1): bz#2163: fix memory leak in error path in + do_readdir(). + * sftp(1): bz#2171: don't leak file descriptor on error. + * sshd(8): include the local address and port in "Connection + from ..." message (only shown at loglevel>=verbose). +- systemd systems + * create sysconfig file on systemd systems as well, yet do not + require it at run-time (bnc#862600) + * symlink rcsshd to /usr/bin/service +- rename "-forcepermissions" patch to "-sftp_force_permissions" +- disable key converter - ssh-keygen is able to do the same + +------------------------------------------------------------------- +Tue Feb 11 07:42:09 UTC 2014 - meissner@suse.com + +- add a rcsshd symlink to /usr/sbin/service + +------------------------------------------------------------------- +Wed Feb 5 08:38:11 UTC 2014 - idonmez@suse.com + +- Add openssh-6.2p1-forcepermissions.patch to implement a force + permissions mode (fate#312774). The patch is based on + http://marc.info/?l=openssh-unix-dev&m=128896838930893 + +------------------------------------------------------------------- +Fri Jan 24 15:13:09 UTC 2014 - pcerny@suse.com + +- Update to 6.4p1 + Features since 6.2p2: + * ssh-agent(1) support in sshd(8); allows encrypted hostkeys, or + hostkeys on smartcards. + * ssh(1)/sshd(8): allow optional time-based rekeying via a + second argument to the existing RekeyLimit option. RekeyLimit + is now supported in sshd_config as well as on the client. + * sshd(8): standardise logging of information during user + authentication. + * The presented key/cert and the remote username (if available) + is now logged in the authentication success/failure message on + the same log line as the local username, remote host/port and + protocol in use. Certificates contents and the key + fingerprint of the signing CA are logged too. + * ssh(1) ability to query what cryptographic algorithms are + supported in the binary. + * ssh(1): ProxyCommand=- for cases where stdin and stdout + already point to the proxy. + * ssh(1): allow IdentityFile=none + * ssh(1)/sshd(8): -E option to append debugging logs to a + specified file instead of stderr or syslog. + * sftp(1): support resuming partial downloads with the "reget" + command and on the sftp commandline or on the "get" + commandline with the "-a" (append) option. + * ssh(1): "IgnoreUnknown" configuration option to selectively + suppress errors arising from unknown configuration directives. + * sshd(8): support for submethods to be appended to required + authentication methods listed via AuthenticationMethods. + Bugfixes since 6.2p2: + * sshd(8): fix refusal to accept certificate if a key of a + different type to the CA key appeared in authorized_keys + before the CA key. + * ssh(1)/ssh-agent(1)/sshd(8): Use a monotonic time source for + timers so that things like keepalives and rekeying will work + properly over clock steps. + * sftp(1): update progressmeter when data is acknowledged, not + when it's sent. bz#2108 + * ssh(1)/ssh-keygen(1): improve error messages when the current + user does not exist in /etc/passwd; bz#2125 + * ssh(1): reset the order in which public keys are tried after + partial authentication success. + * ssh-agent(1): clean up socket files after SIGINT when in debug + mode; bz#2120 + * ssh(1) and others: avoid confusing error messages in the case + of broken system resolver configurations; bz#2122 + * ssh(1): set TCP nodelay for connections started with -N; + bz#2124 + * ssh(1): correct manual for permission requirements on + ~/.ssh/config; bz#2078 + * ssh(1): fix ControlPersist timeout not triggering in cases + where TCP connections have hung. bz#1917 + * ssh(1): properly deatch a ControlPersist master from its + controlling terminal. + * sftp(1): avoid crashes in libedit when it has been compiled + with multi- byte character support. bz#1990 + * sshd(8): when running sshd -D, close stderr unless we have + explicitly requested logging to stderr. bz#1976, + * ssh(1): fix incomplete bzero; bz#2100 + * sshd(8): log and error and exit if ChrootDirectory is + specified and running without root privileges. + * Many improvements to the regression test suite. In particular + log files are now saved from ssh and sshd after failures. + * Fix a number of memory leaks. bz#1967 bz#2096 and others + * sshd(8): fix public key authentication when a :style is + appended to the requested username. + * ssh(1): do not fatally exit when attempting to cleanup + multiplexing- created channels that are incompletely opened. + bz#2079 + * sshd(8): fix a memory corruption problem triggered during + rekeying when an AES-GCM cipher is selected + * Fix unaligned accesses in umac.c for strict-alignment + architectures. bz#2101 + * Fix broken incorrect commandline reporting errors. bz#1448 + * Only include SHA256 and ECC-based key exchange methods if + libcrypto has the required support. + * Fix crash in SOCKS5 dynamic forwarding code on + strict-alignment architectures. + - FIPS and GSSKEX patched disabled for now + +------------------------------------------------------------------- +Fri Oct 4 17:50:32 UTC 2013 - pcerny@suse.com + +- fix server crashes when using AES-GCM +- removed superfluous build dependency on X + +------------------------------------------------------------------- +Thu Sep 19 02:02:56 UTC 2013 - pcerny@suse.com + +- spec file and patch cleanup + * key converter is now in the -key-converter.patch + * openssh-nodaemon-nopid.patch is -no_fork-no_pid_file.patch + * openssh-nocrazyabicheck.patch is + -disable-openssl-abi-check.patch + * removing obsolete -engines.diff patch +- patches from SLE11 + * use auditing infrastructure extending upstream hooks + (-auditX-*.patch) instead of the single old patch + (-audit.patch) + * FIPS enablement (currently disabled) + (-fingerprint_hash.patch, -fips.patch) + * GSSAPI key exchange + (bnc#784689, fate#313068, -gssapi_key_exchange.patch) + * SysV init script update - 'stop' now terminates all sshd + processes and closes all connections, 'soft-stop' only + terminates the listener process (keeps active sessions intact) + (fate#314243) + * helper application for retrieving users' public keys from + an LDAP server (bnc#683733, fate#302144, -ldap.patch) + - subpackage openssh-akc-ldap + * several bugfixes: + - login invocation + (bnc#833605, -login_options.patch) + - disable locked accounts when using PAM + (bnc#708678, fate#312033, -pam-check-locks.patch) + - fix wtmp handling + (bnc#18024, -lastlog.patch) +- init script is moved into documentation for openSUSE 12.3+ + (as it confused systemd) + +------------------------------------------------------------------- +Tue Sep 10 21:15:59 UTC 2013 - crrodriguez@opensuse.org + +- fix the logic in openssh-nodaemon-nopid.patch which is broken + and pid_file therefore still being created. + +------------------------------------------------------------------- +Sat Aug 3 17:57:06 UTC 2013 - crrodriguez@opensuse.org + +- Update to version 6.2p2 +* ssh(1)/sshd(8): Added support for AES-GCM authenticated encryption +* ssh(1)/sshd(8): Added support for encrypt-then-mac (EtM) MAC modes +* ssh(1)/sshd(8): Added support for the UMAC-128 MAC +* sshd(8): Added support for multiple required authentication +* sshd(8)/ssh-keygen(1): Added support for Key Revocation Lists +* ssh(1): When SSH protocol 2 only is selected (the default), ssh(1) + now immediately sends its SSH protocol banner to the server without + waiting to receive the server's banner, saving time when connecting. +* dozens of other changes, see http://www.openssh.org/txt/release-6.2 + +------------------------------------------------------------------- +Mon Jul 1 18:54:31 UTC 2013 - coolo@suse.com + +- avoid the build cycle between curl, krb5, libssh2_org and openssh + by using krb5-mini-devel + +------------------------------------------------------------------- +Wed Jun 19 09:50:25 UTC 2013 - speilicke@suse.com + +- Recommend xauth, X11-forwarding won't work if it is not installed + +------------------------------------------------------------------- +Sun Apr 14 19:02:32 UTC 2013 - crrodriguez@opensuse.org + +- sshd.service: Do not order after syslog.target, it is + not required or recommended and that target does not even exist + anymore. + +------------------------------------------------------------------- +Tue Jan 8 10:16:45 UTC 2013 - dmueller@suse.com + +- use ssh-keygen(1) default keylengths in generating the host key + instead of hardcoding it + +------------------------------------------------------------------- +Tue Nov 13 10:26:37 UTC 2012 - meissner@suse.com + +- Updated to 6.1p1, a bugfix release + Features: + * sshd(8): This release turns on pre-auth sandboxing sshd by default for + new installs, by setting UsePrivilegeSeparation=sandbox in sshd_config. + * ssh-keygen(1): Add options to specify starting line number and number of + lines to process when screening moduli candidates, allowing processing + of different parts of a candidate moduli file in parallel + * sshd(8): The Match directive now supports matching on the local (listen) + address and port upon which the incoming connection was received via + LocalAddress and LocalPort clauses. + * sshd(8): Extend sshd_config Match directive to allow setting AcceptEnv + and {Allow,Deny}{Users,Groups} + * Add support for RFC6594 SSHFP DNS records for ECDSA key types. bz#1978 + * ssh-keygen(1): Allow conversion of RSA1 keys to public PEM and PKCS8 + * sshd(8): Allow the sshd_config PermitOpen directive to accept "none" as + an argument to refuse all port-forwarding requests. + * sshd(8): Support "none" as an argument for AuthorizedPrincipalsFile + * ssh-keyscan(1): Look for ECDSA keys by default. bz#1971 + * sshd(8): Add "VersionAddendum" to sshd_config to allow server operators + to append some arbitrary text to the server SSH protocol banner. + Bugfixes: + * ssh(1)/sshd(8): Don't spin in accept() in situations of file + descriptor exhaustion. Instead back off for a while. + * ssh(1)/sshd(8): Remove hmac-sha2-256-96 and hmac-sha2-512-96 MACs as + they were removed from the specification. bz#2023, + * sshd(8): Handle long comments in config files better. bz#2025 + * ssh(1): Delay setting tty_flag so RequestTTY options are correctly + picked up. bz#1995 + * sshd(8): Fix handling of /etc/nologin incorrectly being applied to root + on platforms that use login_cap. + Portable OpenSSH: + * sshd(8): Allow sshd pre-auth sandboxing to fall-back to the rlimit + sandbox from the Linux SECCOMP filter sandbox when the latter is + not available in the kernel. + * ssh(1): Fix NULL dereference when built with LDNS and using DNSSEC to + retrieve a CNAME SSHFP record. + * Fix cross-compilation problems related to pkg-config. bz#1996 + +------------------------------------------------------------------- +Tue Nov 13 10:26:16 CET 2012 - kukuk@suse.de + +- Fix groupadd arguments +- Add LSB tag to sshd init script + +------------------------------------------------------------------- +Fri Oct 26 15:01:21 UTC 2012 - coolo@suse.com + +- explicit buildrequire groff, needed for man pages + +------------------------------------------------------------------- +Tue Oct 16 12:29:36 UTC 2012 - coolo@suse.com + +- buildrequire systemd through pkgconfig to break cycle + +------------------------------------------------------------------- +Wed Aug 15 19:25:08 UTC 2012 - crrodriguez@opensuse.org + +- When not daemonizing, such is used with systemd, no not + create a PID file + +------------------------------------------------------------------- +Mon Jun 18 11:34:51 UTC 2012 - coolo@suse.com + +- do not buildrequire xorg-x11, the askpass is an extra package + and should build from a different package + +------------------------------------------------------------------- +Tue May 29 07:14:36 UTC 2012 - meissner@suse.com + +- use correct download url and tarball format. + +------------------------------------------------------------------- +Tue May 29 06:52:13 UTC 2012 - crrodriguez@opensuse.org + +- Update to version 6.0, large list of changes, seen + http://www.openssh.org/txt/release-6.0 for detail. + +------------------------------------------------------------------- +Thu May 10 20:50:33 UTC 2012 - crrodriguez@opensuse.org + +- By default openSSH checks at *runtime* if the openssl + API version matches with the running library, that might + be good if you are compiling SSH yourself but it is a totally + insane way to check for binary/source compatibility in a distribution. + +------------------------------------------------------------------- +Mon Feb 20 08:29:17 UTC 2012 - meissner@suse.com + +- include X11 app default dir + +------------------------------------------------------------------- +Fri Dec 23 08:27:08 UTC 2011 - brian@aljex.com + +- Fix building for OS 11.0, 10.3, 10.2 +* Don't require selinux on OS 11.0 or lower + +------------------------------------------------------------------- +Fri Dec 23 06:34:28 UTC 2011 - brian@aljex.com + +- Fix building for OS 11.2 and 11.1 +- Cleanup remove remaining litteral /etc/init.d 's + +------------------------------------------------------------------- +Wed Dec 21 10:38:59 UTC 2011 - coolo@suse.com + +- add autoconf as buildrequire to avoid implicit dependency + +------------------------------------------------------------------- +Tue Nov 29 19:48:29 UTC 2011 - crrodriguez@opensuse.org + +- Add systemd startup units + +------------------------------------------------------------------- +Sat Oct 29 22:41:55 UTC 2011 - pcerny@suse.com + +- finalising libexecdir change (bnc#726712) + +------------------------------------------------------------------- +Wed Oct 19 00:32:20 UTC 2011 - pcerny@suse.com + +- Update to 5.9p1 + * sandboxing privsep child through rlimit + +------------------------------------------------------------------- +Fri Sep 16 09:43:47 UTC 2011 - jengelh@medozas.de + +- Avoid overriding libexecdir with %_lib (bnc#712025) +- Clean up the specfile by request of Minh Ngo, details entail: +* remove norootforbuild comments, redundant %clean section +* run spec-beautifier over it +- Add PIEFLAGS to compilation of askpass; fails otherwise + +------------------------------------------------------------------- +Mon Aug 29 23:47:58 UTC 2011 - crrodriguez@opensuse.org + +- Update to verison 5.8p2 +* Fixed vuln in systems without dev/random, we arenot affected +* Fixes problems building with selinux enabled +- Fix build with as-needed and no-add-needed + +------------------------------------------------------------------- +Sat Aug 13 20:46:17 UTC 2011 - crrodriguez@opensuse.org + +- Enable libedit/autocompletion support in sftp + +------------------------------------------------------------------- +Tue May 10 15:08:17 UTC 2011 - meissner@novell.com + +- Change default keysizes of rsa and dsa from 1024 to 2048 + to match ssh-keygen manpage recommendations. + +------------------------------------------------------------------- +Fri Feb 4 11:19:25 UTC 2011 - lchiquitto@novell.com + +- Update to 5.8p1 + * Fix vulnerability in legacy certificate signing introduced in + OpenSSH-5.6 and found by Mateusz Kocielski. + * Fix compilation failure when enableing SELinux support. + * Do not attempt to call SELinux functions when SELinux is + disabled. +- Remove patch that is now upstream: + * openssh-5.7p1-selinux.diff + +------------------------------------------------------------------- +Thu Feb 3 16:42:01 UTC 2011 - pcerny@novell.com + +- specfile/patches cleanup + +------------------------------------------------------------------- +Mon Jan 24 11:24:59 UTC 2011 - lchiquitto@novell.com + +- Update to 5.7p1 + * Implement Elliptic Curve Cryptography modes for key exchange (ECDH) + and host/user keys (ECDSA) as specified by RFC5656. + * sftp(1)/sftp-server(8): add a protocol extension to support a hard + link operation. + * scp(1): Add a new -3 option to scp: Copies between two remote hosts + are transferred through the local host. + * ssh(1): automatically order the hostkeys requested by the client + based on which hostkeys are already recorded in known_hosts. + * ssh(1)/sshd(8): add a new IPQoS option to specify arbitrary + TOS/DSCP/QoS values instead of hardcoding lowdelay/throughput. + * sftp(1): the sftp client is now significantly faster at performing + directory listings, using OpenBSD glob(3) extensions to preserve + the results of stat(3) operations performed in the course of its + execution rather than performing expensive round trips to fetch + them again afterwards. + * ssh(1): "atomically" create the listening mux socket by binding it on + a temporary name and then linking it into position after listen() has + succeeded. + * ssh(1)/sshd(8): add a KexAlgorithms knob to the client and server + configuration to allow selection of which key exchange methods are + used by ssh(1) and sshd(8) and their order of preference. + * sftp(1)/scp(1): factor out bandwidth limiting code from scp(1) into + a generic bandwidth limiter that can be attached using the atomicio + callback mechanism and use it to add a bandwidth limit option to + sftp(1). + * Support building against openssl-1.0.0a. + * Bug fixes. +- Remove patches that are now upstream: + * openssh-5.6p1-tmpdir.diff + * openssh-linux-new-oomkill.patch +- Add upstream patch to fix build with SELinux enabled. + +------------------------------------------------------------------- +Wed Jan 12 13:37:38 CET 2011 - sbrabec@suse.cz + +- Removed relics of no more implemented opensc support. + +------------------------------------------------------------------- +Thu Nov 18 12:20:59 UTC 2010 - lnussel@suse.de + +- add pam_lastlog to show failed login attempts +- remove permissions handling, no special handling needed + +------------------------------------------------------------------- +Tue Nov 16 14:45:14 UTC 2010 - cristian.rodriguez@opensuse.org + +- Use upstream oom_adj is deprecated patch + +------------------------------------------------------------------- +Tue Nov 2 13:25:19 UTC 2010 - coolo@novell.com + +- remove the code trying to patch X11 paths - which was broken + for a very long time and was useless anyway as the Makefiles + do this correctly themselves + +------------------------------------------------------------------- +Sun Oct 31 12:37:02 UTC 2010 - jengelh@medozas.de + +- Use %_smp_mflags + +------------------------------------------------------------------- +Thu Oct 14 16:00:19 UTC 2010 - crrodriguez@opensuse.org + +- Fix warning "oom_adj is deprecated use oom_score_adj instead" + +------------------------------------------------------------------- +Mon Sep 13 14:47:10 CEST 2010 - anicka@suse.cz + +- actualize README.SuSE (bnc#638893) + +------------------------------------------------------------------- +Tue Aug 24 15:43:08 CEST 2010 - anicka@suse.cz + +- update to 5.6p1 + * Added a ControlPersist option to ssh_config(5) that automatically + starts a background ssh(1) multiplex master when connecting. + * Hostbased authentication may now use certificate host keys. + * ssh-keygen(1) now supports signing certificate using a CA key that + has been stored in a PKCS#11 token. + * ssh(1) will now log the hostname and address that we connected to at + LogLevel=verbose after authentication is successful to mitigate + "phishing" attacks by servers with trusted keys that accept + authentication silently and automatically before presenting fake + password/passphrase prompts. + * Expand %h to the hostname in ssh_config Hostname options. + * Allow ssh-keygen(1) to import (-i) and export (-e) of PEM and PKCS#8 + keys in addition to RFC4716 (SSH.COM) encodings via a new -m option + * sshd(8) will now queue debug messages for bad ownership or + permissions on the user's keyfiles encountered during authentication + and will send them after authentication has successfully completed. + * ssh(1) connection multiplexing now supports remote forwarding with + dynamic port allocation and can report the allocated port back to + the user + * sshd(8) now supports indirection in matching of principal names + listed in certificates. + * sshd(8) now has a new AuthorizedPrincipalsFile option to specify a + file containing a list of names that may be accepted in place of the + username when authorizing a certificate trusted via the + sshd_config(5) TrustedCAKeys option. + * Additional sshd_config(5) options are now valid inside Match blocks + * Revised the format of certificate keys. + * bugfixes +- removed -forward patch (SSH_MAX_FORWARDS_PER_DIRECTION not hard-coded + any more), removed memory leak fix (fixed in upstream) + +------------------------------------------------------------------- +Fri Aug 20 13:00:43 CEST 2010 - anicka@suse.cz + +- hint user how to remove offending keys (bnc#625552) + +------------------------------------------------------------------- +Thu Jul 22 17:58:09 CEST 2010 - anicka@suse.cz + +- update to 5.5p1 + +------------------------------------------------------------------- +Tue Jul 20 17:19:24 CEST 2010 - anicka@suse.cz + +- update to 5.5p1 + * Allow ChrootDirectory to work in SELinux platforms. + * bugfixes + +------------------------------------------------------------------- +Wed Jun 30 16:01:30 CEST 2010 - meissner@suse.de + +- Disable visual hostkey support again, after discussion on + its usefulness. + +------------------------------------------------------------------- +Mon May 17 18:11:33 UTC 2010 - cristian.rodriguez@opensuse.org + +- Hardware crypto is supported and patched but never + enabled, need to use --with-ssl-engine explicitely + +------------------------------------------------------------------- +Fri May 14 16:03:17 CEST 2010 - anicka@suse.cz + +- fixed memory leak in sftp (bnc#604274) + +------------------------------------------------------------------- +Fri Apr 23 12:01:50 CEST 2010 - anicka@suse.cz + +- honour /etc/nologin (bnc#530885) + +------------------------------------------------------------------- +Thu Mar 25 11:00:00 CET 2010 - meissner@suse.de + +- Enable VisualHostKey (ascii art of the hostkey fingerprint) and + HashHostKeys (hardening measure to make them unusable for worms/malicious + users for further host hopping). + +------------------------------------------------------------------- +Tue Mar 23 18:57:07 CET 2010 - anicka@suse.cz + +- update to 5.4p1 + * After a transition period of about 10 years, this release disables + SSH protocol 1 by default. Clients and servers that need to use the + legacy protocol must explicitly enable it in ssh_config / sshd_config + or on the command-line. + * Remove the libsectok/OpenSC-based smartcard code and add support for + PKCS#11 tokens. This support is automatically enabled on all + platforms that support dlopen(3) and was inspired by patches written + by Alon Bar-Lev. Details in the ssh(1) and ssh-add(1) manpages. + * Add support for certificate authentication of users and hosts using a + new, minimal OpenSSH certificate format (not X.509). Certificates + contain a public key, identity information and some validity + constraints and are signed with a standard SSH public key using + ssh-keygen(1). CA keys may be marked as trusted in authorized_keys + or via a TrustedUserCAKeys option in sshd_config(5) (for user + authentication), or in known_hosts (for host authentication). + Documentation for certificate support may be found in ssh-keygen(1), + sshd(8) and ssh(1) and a description of the protocol extensions in + PROTOCOL.certkeys. + * Added a 'netcat mode' to ssh(1): "ssh -W host:port ..." This connects + stdio on the client to a single port forward on the server. This + allows, for example, using ssh as a ProxyCommand to route connections + via intermediate servers. bz#1618 + * Add the ability to revoke keys in sshd(8) and ssh(1). User keys may + be revoked using a new sshd_config(5) option "RevokedKeys". Host keys + are revoked through known_hosts (details in the sshd(8) man page). + Revoked keys cannot be used for user or host authentication and will + trigger a warning if used. + * Rewrite the ssh(1) multiplexing support to support non-blocking + operation of the mux master, improve the resilience of the master to + malformed messages sent to it by the slave and add support for + requesting port- forwardings via the multiplex protocol. The new + stdio-to-local forward mode ("ssh -W host:port ...") is also + supported. The revised multiplexing protocol is documented in the + file PROTOCOL.mux in the source distribution. + * Add a 'read-only' mode to sftp-server(8) that disables open in write + mode and all other fs-modifying protocol methods. bz#430 + * Allow setting an explicit umask on the sftp-server(8) commandline to + override whatever default the user has. bz#1229 + * Many improvements to the sftp(1) client, many of which were + implemented by Carlos Silva through the Google Summer of Code + program: + - Support the "-h" (human-readable units) flag for ls + - Implement tab-completion of commands, local and remote filenames + - Support most of scp(1)'s commandline arguments in sftp(1), as a + first step towards making sftp(1) a drop-in replacement for scp(1). + Note that the rarely-used "-P sftp_server_path" option has been + moved to "-D sftp_server_path" to make way for "-P port" to match + scp(1). + - Add recursive transfer support for get/put and on the commandline + * New RSA keys will be generated with a public exponent of RSA_F4 == + (2**16)+1 == 65537 instead of the previous value 35. + * Passphrase-protected SSH protocol 2 private keys are now protected + with AES-128 instead of 3DES. This applied to newly-generated keys + as well as keys that are reencrypted (e.g. by changing their + passphrase). +- cleanup in patches + +------------------------------------------------------------------- +Tue Mar 2 09:09:18 UTC 2010 - coolo@novell.com + +- do not use paths at all, but prereq packages + +------------------------------------------------------------------- +Sat Feb 27 20:35:01 UTC 2010 - aj@suse.de + +- Use complete path for groupadd and useradd in pre section. + +------------------------------------------------------------------- +Tue Feb 23 15:45:06 CET 2010 - anicka@suse.cz + +- audit patch: add fix for bnc#545271 + +------------------------------------------------------------------- +Mon Feb 22 17:15:22 CET 2010 - anicka@suse.cz + +- do not fix uid/gid anymore (bnc#536564) + +------------------------------------------------------------------- +Tue Dec 15 11:04:00 CET 2009 - jengelh@medozas.de + +- select large PIE for SPARC, it is required to avoid + "relocation truncated to fit: R_SPARC_GOT13 against symbol xyz + defined in COMMON section in sshd.o" + +------------------------------------------------------------------- +Mon Sep 21 14:40:51 CEST 2009 - anicka@suse.cz + +- add new version of homechroot patch (added documentation, added + check for nodev and nosuid) +- remove Provides and Obsoletes ssh + +------------------------------------------------------------------- +Thu Aug 20 16:54:08 CEST 2009 - anicka@suse.cz + +- make sftp in chroot users life easier (ie. bnc#518238), + many thanks jchadima@redhat.com for a patch + +------------------------------------------------------------------- +Sun Jul 12 21:43:21 CEST 2009 - coolo@novell.com + +- readd $SSHD_BIN so that sshd starts at all + +------------------------------------------------------------------- +Tue Jul 7 15:06:58 CEST 2009 - llunak@novell.com + +- Added a hook for ksshaskpass + +------------------------------------------------------------------- +Sun Jul 5 12:17:40 CEST 2009 - dmueller@novell.com + +- readd -f to startproc and remove -p instead to + ensure that sshd is started even though old instances + are still running (e.e. being logged in from remote) + +------------------------------------------------------------------- +Fri Jun 19 10:35:46 CEST 2009 - coolo@novell.com + +- disable as-needed for this package as it fails to build with it + +------------------------------------------------------------------- +Tue May 26 11:56:20 CEST 2009 - anicka@suse.cz + +- disable -f in startproc to calm the warning (bnc#506831) + +------------------------------------------------------------------- +Thu Apr 23 09:44:07 CEST 2009 - lnussel@suse.de + +- do not enable sshd by default + +------------------------------------------------------------------- +Mon Feb 23 17:27:45 CET 2009 - anicka@suse.cz + +- update to 5.2p1 + * This release changes the default cipher order to prefer the AES CTR + modes and the revised "arcfour256" mode to CBC mode ciphers that are + susceptible to CPNI-957037 "Plaintext Recovery Attack Against SSH". + * This release also adds countermeasures to mitigate CPNI-957037-style + attacks against the SSH protocol's use of CBC-mode ciphers. Upon + detection of an invalid packet length or Message Authentication + Code, ssh/sshd will continue reading up to the maximum supported + packet length rather than immediately terminating the connection. + This eliminates most of the known differences in behaviour that + leaked information about the plaintext of injected data which formed + the basis of this attack. We believe that these attacks are rendered + infeasible by these changes. + * Added a -y option to ssh(1) to force logging to syslog rather than + stderr, which is useful when running daemonised (ssh -f) + * The sshd_config(5) ForceCommand directive now accepts commandline + arguments for the internal-sftp server. + * The ssh(1) ~C escape commandline now support runtime creation of + dynamic (-D) port forwards. + * Support the SOCKS4A protocol in ssh(1) dynamic (-D) forwards. + (bz#1482) + * Support remote port forwarding with a listen port of '0'. This + informs the server that it should dynamically allocate a listen + port and report it back to the client. (bz#1003) + * sshd(8) now supports setting PermitEmptyPasswords and + AllowAgentForwarding in Match blocks + * Repair a ssh(1) crash introduced in openssh-5.1 when the client is + sent a zero-length banner (bz#1496) + * Due to interoperability problems with certain + broken SSH implementations, the eow@openssh.com and + no-more-sessions@openssh.com protocol extensions are now only sent + to peers that identify themselves as OpenSSH. + * Make ssh(1) send the correct channel number for + SSH2_MSG_CHANNEL_SUCCESS and SSH2_MSG_CHANNEL_FAILURE messages to + avoid triggering 'Non-public channel' error messages on sshd(8) in + openssh-5.1. + * Avoid printing 'Non-public channel' warnings in sshd(8), since the + ssh(1) has sent incorrect channel numbers since ~2004 (this reverts + a behaviour introduced in openssh-5.1). + * Avoid double-free in ssh(1) ~C escape -L handler (bz#1539) + * Correct fail-on-error behaviour in sftp(1) batchmode for remote + stat operations. (bz#1541) + * Disable nonfunctional ssh(1) ~C escape handler in multiplex slave + connections. (bz#1543) + * Avoid hang in ssh(1) when attempting to connect to a server that + has MaxSessions=0 set. + * Multiple fixes to sshd(8) configuration test (-T) mode + * Several core and portable OpenSSH bugs fixed: 1380, 1412, 1418, + 1419, 1421, 1490, 1491, 1492, 1514, 1515, 1518, 1520, 1538, 1540 + * Many manual page improvements. + +------------------------------------------------------------------- +Mon Dec 1 15:43:14 CET 2008 - anicka@suse.cz + +- respect SSH_MAX_FORWARDS_PER_DIRECTION (bnc#448775) + +------------------------------------------------------------------- +Mon Nov 10 16:01:27 CET 2008 - anicka@suse.cz + +- fix printing banner (bnc#443380) + +------------------------------------------------------------------- +Fri Oct 24 16:24:34 CEST 2008 - anicka@suse.cz + +- call pam functions in the right order (bnc#438292) +- mention default forwarding of locale settings in + README.SuSE (bnc#434799) + +------------------------------------------------------------------- +Tue Sep 9 17:55:29 CEST 2008 - anicka@suse.cz + +- remove pam_resmgr from sshd.pamd (bnc#422619) + +------------------------------------------------------------------- +Sun Aug 24 08:26:05 CEST 2008 - coolo@suse.de + +- fix fillup macro usage + +------------------------------------------------------------------- +Fri Aug 22 11:51:12 CEST 2008 - prusnak@suse.cz + +- enabled SELinux support [Fate#303662] + +------------------------------------------------------------------- +Tue Jul 22 20:39:29 CEST 2008 - anicka@suse.cz + +- update to 5.1p1 + * sshd(8): Avoid X11 man-in-the-middle attack on HP/UX (and possibly + other platforms) when X11UseLocalhost=no + * Introduce experimental SSH Fingerprint ASCII Visualisation to ssh(1) + and ssh-keygen(1). Visual fingerprinnt display is controlled by a new + ssh_config(5) option "VisualHostKey". + * sshd_config(5) now supports CIDR address/masklen matching in "Match + address" blocks, with a fallback to classic wildcard matching. + * sshd(8) now supports CIDR matching in ~/.ssh/authorized_keys + from="..." restrictions, also with a fallback to classic wildcard + matching. + * Added an extended test mode (-T) to sshd(8) to request that it write + its effective configuration to stdout and exit. Extended test mode + also supports the specification of connection parameters (username, + source address and hostname) to test the application of + sshd_config(5) Match rules. + * ssh(1) now prints the number of bytes transferred and the overall + connection throughput for SSH protocol 2 sessions when in verbose + mode (previously these statistics were displayed for protocol 1 + connections only). + * sftp-server(8) now supports extension methods statvfs@openssh.com and + fstatvfs@openssh.com that implement statvfs(2)-like operations. + * sftp(1) now has a "df" command to the sftp client that uses the + statvfs@openssh.com to produce a df(1)-like display of filesystem + space and inode utilisation (requires statvfs@openssh.com support on + the server) + * Added a MaxSessions option to sshd_config(5) to allow control of the + number of multiplexed sessions supported over a single TCP connection. + This allows increasing the number of allowed sessions above the + previous default of 10, disabling connection multiplexing + (MaxSessions=1) or disallowing login/shell/subsystem sessions + entirely (MaxSessions=0). + * Added a no-more-sessions@openssh.com global request extension that is + sent from ssh(1) to sshd(8) when the client knows that it will never + request another session (i.e. when session multiplexing is disabled). + This allows a server to disallow further session requests and + terminate the session in cases where the client has been hijacked. + * ssh-keygen(1) now supports the use of the -l option in combination + with -F to search for a host in ~/.ssh/known_hosts and display its + fingerprint. + * ssh-keyscan(1) now defaults to "rsa" (protocol 2) keys, instead of + "rsa1". + * Added an AllowAgentForwarding option to sshd_config(8) to control + whether authentication agent forwarding is permitted. Note that this + is a loose control, as a client may install their own unofficial + forwarder. + * ssh(1) and sshd(8): avoid unnecessary malloc/copy/free when receiving + network data, resulting in a ~10% speedup + * ssh(1) and sshd(8) will now try additional addresses when connecting + to a port forward destination whose DNS name resolves to more than + one address. The previous behaviour was to try the only first address + and give up if that failed. (bz#383) + * ssh(1) and sshd(8) now support signalling that channels are + half-closed for writing, through a channel protocol extension + notification "eow@openssh.com". This allows propagation of closed + file descriptors, so that commands such as: + "ssh -2 localhost od /bin/ls | true" + do not send unnecessary data over the wire. (bz#85) + * sshd(8): increased the default size of ssh protocol 1 ephemeral keys + from 768 to 1024 bits. + * When ssh(1) has been requested to fork after authentication + ("ssh -f") with ExitOnForwardFailure enabled, delay the fork until + after replies for any -R forwards have been seen. Allows for robust + detection of -R forward failure when using -f. (bz#92) + * "Match group" blocks in sshd_config(5) now support negation of + groups. E.g. "Match group staff,!guests" (bz#1315) + * sftp(1) and sftp-server(8) now allow chmod-like operations to set + set[ug]id/sticky bits. (bz#1310) + * The MaxAuthTries option is now permitted in sshd_config(5) match + blocks. + * Multiplexed ssh(1) sessions now support a subset of the ~ escapes + that are available to a primary connection. (bz#1331) + * ssh(1) connection multiplexing will now fall back to creating a new + connection in most error cases. (bz#1439 bz#1329) + * Added some basic interoperability tests against Twisted Conch. + * Documented OpenSSH's extensions to and deviations from the published + SSH protocols (the PROTOCOL file in the distribution) + * Documented OpenSSH's ssh-agent protocol (PROTOCOL.agent). + * bugfixes +- remove gssapi_krb5-fix patch + +------------------------------------------------------------------- +Fri Apr 18 17:53:30 CEST 2008 - werner@suse.de + +- Handle pts slave lines like utemper + +------------------------------------------------------------------- +Wed Apr 9 14:37:57 CEST 2008 - anicka@suse.cz + +- update to 5.0p1 + * CVE-2008-1483: Avoid possible hijacking of X11-forwarded + connections by refusing to listen on a port unless all address + families bind successfully. +- remove CVE-2008-1483 patch + +------------------------------------------------------------------- +Wed Apr 2 14:57:26 CEST 2008 - anicka@suse.cz + +- update to 4.9p1 + * Disable execution of ~/.ssh/rc for sessions where a command has been + forced by the sshd_config ForceCommand directive. Users who had + write access to this file could use it to execute abritrary commands. + This behaviour was documented, but was an unsafe default and an extra + hassle for administrators. + * Added chroot(2) support for sshd(8), controlled by a new option + "ChrootDirectory". Please refer to sshd_config(5) for details, and + please use this feature carefully. (bz#177 bz#1352) + * Linked sftp-server(8) into sshd(8). The internal sftp server is + used when the command "internal-sftp" is specified in a Subsystem + or ForceCommand declaration. When used with ChrootDirectory, the + internal sftp server requires no special configuration of files + inside the chroot environment. Please refer to sshd_config(5) for + more information. + * Added a "no-user-rc" option for authorized_keys to disable execution + of ~/.ssh/rc + * Added a protocol extension method "posix-rename@openssh.com" for + sftp-server(8) to perform POSIX atomic rename() operations. + (bz#1400) + * Removed the fixed limit of 100 file handles in sftp-server(8). The + server will now dynamically allocate handles up to the number of + available file descriptors. (bz#1397) + * ssh(8) will now skip generation of SSH protocol 1 ephemeral server + keys when in inetd mode and protocol 2 connections are negotiated. + This speeds up protocol 2 connections to inetd-mode servers that + also allow Protocol 1 (bz#440) + * Accept the PermitRootLogin directive in a sshd_config(5) Match + block. Allows for, e.g. permitting root only from the local + network. + * Reworked sftp(1) argument splitting and escaping to be more + internally consistent (i.e. between sftp commands) and more + consistent with sh(1). Please note that this will change the + interpretation of some quoted strings, especially those with + embedded backslash escape sequences. (bz#778) + * Support "Banner=none" in sshd_config(5) to disable sending of a + pre-login banner (e.g. in a Match block). + * ssh(1) ProxyCommands are now executed with $SHELL rather than + /bin/sh. + * ssh(1)'s ConnectTimeout option is now applied to both the TCP + connection and the SSH banner exchange (previously it just covered + the TCP connection). This allows callers of ssh(1) to better detect + and deal with stuck servers that accept a TCP connection but don't + progress the protocol, and also makes ConnectTimeout useful for + connections via a ProxyCommand. + * Many new regression tests, including interop tests against PuTTY's + plink. + * Support BSM auditing on Mac OS X + * bugfixes +- remove addrlist, pam_session_close, strict-aliasing-fix patches + (not needed anymore) + +------------------------------------------------------------------- +Tue Mar 25 11:10:14 CET 2008 - anicka@suse.cz + +- fix CVE-2008-1483 (bnc#373527) + +------------------------------------------------------------------- +Fri Jan 4 11:11:52 CET 2008 - anicka@suse.cz + +- fix privileges of a firewall definition file [#351193] + +------------------------------------------------------------------- +Sat Dec 15 00:10:13 CET 2007 - anicka@suse.cz + +- add patch calling pam with root privileges [#334559] +- drop pwname-home patch [#104773] + +------------------------------------------------------------------- +Fri Dec 7 22:28:40 CET 2007 - anicka@suse.cz + +- fix race condition in xauth patch + +------------------------------------------------------------------- +Wed Dec 5 10:45:36 CET 2007 - anicka@suse.cz + +- update to 4.7p1 + * Add "-K" flag for ssh to set GSSAPIAuthentication=yes and + GSSAPIDelegateCredentials=yes. This is symmetric with -k + * make scp try to skip FIFOs rather than blocking when nothing is + listening. + * increase default channel windows + * put the MAC list into a display + * many bugfixes + +------------------------------------------------------------------- +Mon Oct 8 16:34:06 CEST 2007 - anicka@suse.cz + +- block SIGALRM only during calling syslog() [#331032] + +------------------------------------------------------------------- +Thu Sep 13 15:50:39 CEST 2007 - nadvornik@suse.cz + +- fixed checking of an untrusted cookie, CVE-2007-4752 [#308521] + +------------------------------------------------------------------- +Tue Aug 28 18:25:57 CEST 2007 - anicka@suse.cz + +- fix blocksigalrm patch to set old signal mask after + writing the log in every case [#304819] + +------------------------------------------------------------------- +Tue Aug 21 04:51:45 CEST 2007 - anicka@suse.cz + +- avoid generating ssh keys when a non-standard location + is configured [#281228] + +------------------------------------------------------------------- +Wed Jul 25 16:18:50 CEST 2007 - anicka@suse.cz + +- fixed typo in sshd.fw [#293764] + +------------------------------------------------------------------- +Mon Mar 19 19:14:26 CET 2007 - nadvornik@suse.cz + +- fixed default for ChallengeResponseAuthentication [#255374] + +------------------------------------------------------------------- +Mon Mar 12 10:56:31 CET 2007 - anicka@suse.cz + +- update to 4.6p1 + * sshd now allows the enabling and disabling of authentication + methods on a per user, group, host and network basis via the + Match directive in sshd_config. + * Allow multiple forwarding options to work when specified in a + PermitOpen directive + * Clear SIGALRM when restarting due to SIGHUP. Prevents stray + signal from taking down sshd if a connection was pending at + the time SIGHUP was received + * hang on exit" when background processes are running at the + time of exit on a ttyful/login session + * some more bugfixes + +------------------------------------------------------------------- +Mon Mar 5 11:03:41 CET 2007 - anicka@suse.cz + +- fix path for firewall definition + +------------------------------------------------------------------- +Thu Mar 1 15:14:23 CET 2007 - anicka@suse.cz + +- add support for Linux audit (FATE #120269) + +------------------------------------------------------------------- +Wed Feb 21 11:21:48 CET 2007 - anicka@suse.cz + +- add firewall definition [#246921], FATE #300687, + source: sshd.fw + +------------------------------------------------------------------- +Sat Jan 6 12:30:16 CET 2007 - anicka@suse.cz + +- disable SSHv1 protocol in default configuration [#231808] + +------------------------------------------------------------------- +Tue Dec 12 14:41:45 CET 2006 - anicka@suse.cz + +- update to 4.5p1 + * Use privsep_pw if we have it, but only require it if we + absolutely need it. + * Correctly check for bad signatures in the monitor, otherwise + the monitor and the unpriv process can get out of sync. + * Clear errno before calling the strtol functions. + * exit instead of doing a blocking tcp send if we detect + a client/server timeout, since the tcp sendqueue might + be already full (of alive requests) + * include signal.h, errno.h, sys/in.h + * some more bugfixes + +------------------------------------------------------------------- +Wed Nov 22 13:42:32 CET 2006 - anicka@suse.cz + +- fixed README.SuSE [#223025] + +------------------------------------------------------------------- +Thu Nov 9 13:59:35 CET 2006 - anicka@suse.cz + +- backport security fixes from openssh 4.5 (#219115) + +------------------------------------------------------------------- +Tue Nov 7 13:43:44 CET 2006 - ro@suse.de + +- fix manpage permissions + +------------------------------------------------------------------- +Tue Oct 31 14:04:52 CET 2006 - anicka@suse.cz + +- fix gssapi_krb5-fix patch [#215615] +- fix xauth patch + +------------------------------------------------------------------- +Tue Oct 10 16:07:11 CEST 2006 - postadal@suse.cz + +- fixed building openssh from src.rpm [#176528] (gssapi_krb5-fix.patch) + +------------------------------------------------------------------- +Tue Oct 3 14:44:08 CEST 2006 - postadal@suse.cz + +- updated to version 4.4p1 [#208662] + * fixed pre-authentication DoS, that would cause sshd(8) to spin + until the login grace time expired + * fixed unsafe signal hander, which was vulnerable to a race condition + that could be exploited to perform a pre-authentication DoS + * fixed a GSSAPI authentication abort that could be used to determine + the validity of usernames on some platforms + * implemented conditional configuration in sshd_config(5) using the + "Match" directive + * added support for Diffie-Hellman group exchange key agreement with a + final hash of SHA256 + * added a "ForceCommand", "PermitOpen" directive to sshd_config(5) + * added optional logging of transactions to sftp-server(8) + * ssh(1) will now record port numbers for hosts stored in + ~/.ssh/authorized_keys when a non-standard port has been requested + * added an "ExitOnForwardFailure" option to cause ssh(1) to exit (with + a non-zero exit code) when requested port forwardings could not be + established + * extended sshd_config(5) "SubSystem" declarations to allow the + specification of command-line arguments +- removed obsoleted patches: autoconf-fix.patch, dos-fix.patch +- fixed gcc issues (gcc-fix.patch) + +------------------------------------------------------------------- +Wed Sep 20 17:34:54 CEST 2006 - postadal@suse.cz + +- fixed DoS by CRC compensation attack detector [#206917] (dos-fix.patch) +- fixed client NULL deref on protocol error +- cosmetic fix in init script [#203826] + +------------------------------------------------------------------- +Fri Sep 1 14:14:52 CEST 2006 - kukuk@suse.de + +- sshd.pamd: Add pam_loginuid, move pam_nologin to a better position + +------------------------------------------------------------------- +Fri Aug 25 15:37:46 CEST 2006 - postadal@suse.cz + +- fixed path for xauth [#198676] + +------------------------------------------------------------------- +Thu Aug 3 15:07:41 CEST 2006 - postadal@suse.cz + +- fixed build with X11R7 + +------------------------------------------------------------------- +Thu Jul 20 17:25:27 CEST 2006 - postadal@suse.cz + +- updated to version 4.3p2 + * experimental support for tunneling network packets via tun(4) +- removed obsoleted patches: pam-error.patch, CVE-2006-0225.patch, + scp.patch, sigalarm.patch + +------------------------------------------------------------------- +Mon Feb 13 12:54:28 CET 2006 - postadal@suse.cz + +- upstream fixes + - fixed "scp a b c", when c is not directory (scp.patch) + - eliminate some code duplicated in privsep and non-privsep paths, and + explicitly clear SIGALRM handler (sigalarm.patch) + +------------------------------------------------------------------- +Fri Feb 3 19:02:49 CET 2006 - postadal@suse.cz + +- fixed local arbitrary command execution vulnerability [#143435] + (CVE-2006-0225.patch) + +------------------------------------------------------------------- +Thu Feb 2 13:19:41 CET 2006 - postadal@suse.cz + +- fixed xauth.diff for disabled UsePrivilegeSeparation mode [#145809] +- build on s390 without Smart card support (opensc) [#147383] + +------------------------------------------------------------------- +Mon Jan 30 16:25:01 CET 2006 - postadal@suse.cz + +- fixed patch xauth.diff [#145809] +- fixed comments [#142989] + +------------------------------------------------------------------- +Wed Jan 25 21:39:06 CET 2006 - mls@suse.de + +- converted neededforbuild to BuildRequires + +------------------------------------------------------------------- +Mon Jan 16 18:05:44 CET 2006 - meissner@suse.de + +- added -fstack-protector. + +------------------------------------------------------------------- +Tue Jan 3 15:46:33 CET 2006 - postadal@suse.cz + +- updated to version 4.2p1 +- removed obsoleted patches: upstream_fixes.diff, gssapi-secfix.patch + +------------------------------------------------------------------- +Tue Nov 15 17:51:07 CET 2005 - postadal@suse.cz + +- do not delegate GSSAPI credentials to log in with a different method + than GSSAPI [#128928] (CAN-2005-2798, gssapi-secfix.patch) + +------------------------------------------------------------------- +Sun Oct 23 10:40:24 CEST 2005 - postadal@suse.cz + +- fixed PAM to send authentication failing mesaage to client [#130043] + (pam-error.patch) + +------------------------------------------------------------------- +Wed Sep 14 16:58:14 CEST 2005 - postadal@suse.cz + +- fixed uninitialized variable in patch xauth.diff [#98815] + +------------------------------------------------------------------- +Thu Sep 8 15:56:37 CEST 2005 - postadal@suse.cz + +- don't strip + +------------------------------------------------------------------- +Mon Sep 5 20:04:04 CEST 2005 - postadal@suse.cz + +- added patch xauth.diff prevent from polluting xauthority file [#98815] + +------------------------------------------------------------------- +Mon Aug 22 18:12:20 CEST 2005 - postadal@suse.cz + +- fixed problem when multiple accounts have same UID [#104773] + (pwname-home.diff) +- added fixes from upstream (upstream_fixes.diff) + +------------------------------------------------------------------- +Thu Aug 18 17:50:46 CEST 2005 - postadal@suse.cz + +- added patch tmpdir.diff for using $TMPDIR by ssh-agent [#95731] + +------------------------------------------------------------------- +Thu Aug 4 11:29:38 CEST 2005 - uli@suse.de + +- parallelize build + +------------------------------------------------------------------- +Mon Aug 1 17:48:02 CEST 2005 - postadal@suse.cz + +- added patch resolving problems with hostname changes [#98627] + (xauthlocalhostname.diff) + +------------------------------------------------------------------- +Wed Jun 22 18:42:57 CEST 2005 - kukuk@suse.de + +- Compile/link with -fpie/-pie + +------------------------------------------------------------------- +Wed Jun 15 17:41:24 CEST 2005 - meissner@suse.de + +- build x11-ask-pass with RPM_OPT_FLAGS. + +------------------------------------------------------------------- +Fri Jun 10 16:18:25 CEST 2005 - postadal@suse.cz + +- updated to version 4.1p1 +- removed obsoleted patches: restore_terminal, pam-returnfromsession, + timing-attacks-fix, krb5ccname, gssapi-pam, logdenysource, + sendenv-fix, documentation-fix + +------------------------------------------------------------------- +Thu Mar 10 10:36:42 CET 2005 - postadal@suse.cz + +- fixed SendEnv config parsing bug +- documented timeout on untrusted x11 forwarding sessions (openssh#849) +- mentioned ForwardX11Trusted in ssh.1 (openssh#987) + +------------------------------------------------------------------- +Thu Mar 3 13:29:13 CET 2005 - postadal@suse.cz + +- enabled accepting and sending locale environment variables in protocol 2 + [#65747, #50091] + +------------------------------------------------------------------- +Thu Feb 24 16:33:54 CET 2005 - postadal@suse.cz + +- added patches from cvs: gssapi-pam (openssh#918), + krb5ccname (openssh#445), logdenysource (openssh#909) + +------------------------------------------------------------------- +Thu Feb 3 13:29:23 CET 2005 - postadal@suse.cz + +- fixed keyboard-interactive/pam/Kerberos leaks info about user existence + [#48329] (openssh#971, CAN-2003-0190) + +------------------------------------------------------------------- +Wed Jan 19 15:58:07 CET 2005 - postadal@suse.cz + +- splited spec file to decreas number of build dependencies +- fixed restoring terminal setting after Ctrl+C during password prompt in scp/sftp [#43309] +- allowed users to see output from failing PAM session modules (openssh #890, + pam-returnfromsession.patch) + +------------------------------------------------------------------- +Mon Nov 8 17:17:45 CET 2004 - kukuk@suse.de + +- Use common-* PAM config files for sshd PAM configuration + +------------------------------------------------------------------- +Mon Oct 25 15:14:49 CEST 2004 - postadal@suse.cz + +- switched heimdal-* to kerberos-devel-packages in #needforbuild + +------------------------------------------------------------------- +Fri Sep 3 15:03:01 CEST 2004 - ro@suse.de + +- fix lib64 issue + +------------------------------------------------------------------- +Tue Aug 31 16:03:54 CEST 2004 - postadal@suse.cz + +- updated to version 3.9p1 + +- removed obsoleted patches: scp-fix.diff and window_change-fix.diff + +------------------------------------------------------------------- +Thu Aug 26 15:40:53 CEST 2004 - postadal@suse.cz + +- added openssh-askpass-gnome subpackage +- added ssh-askpass script for choosing askpass depending on windowmanager + (by Robert Love ) +- build with Smart card support (opensc) [#44289] + +------------------------------------------------------------------- +Tue Aug 17 15:52:20 CEST 2004 - postadal@suse.cz + +- removed old implementation of "Update Messages" [#36059] + +------------------------------------------------------------------- +Thu Aug 12 16:36:53 CEST 2004 - postadal@suse.cz + +- updated to version 3.8p1 + +- removed obsoleted patches: sftp-progress-fix and pam-fix4 + +------------------------------------------------------------------- +Mon Jun 28 16:56:23 CEST 2004 - meissner@suse.de + +- block sigalarm during syslog output or we might deadlock + on recursively entering syslog(). (LTC#9523, SUSE#42354) + +------------------------------------------------------------------- +Wed May 26 15:27:32 CEST 2004 - postadal@suse.cz + +- fixed commented default value for GSSAPI + +------------------------------------------------------------------- +Thu May 20 21:23:27 CEST 2004 - mludvig@suse.cz + +- Load drivers for available hardware crypto accelerators. + +------------------------------------------------------------------- +Fri Apr 30 15:03:39 CEST 2004 - postadal@suse.cz + +- updated README.kerberos (GSSAPICleanupCreds renamed to GSSAPICleanupCredentials) + +------------------------------------------------------------------- +Mon Apr 19 14:41:01 CEST 2004 - postadal@suse.cz + +- updated README.SuSE (GSSAPICleanupCreds renamed to GSSAPICleanupCredentials) + [#39010] + +------------------------------------------------------------------- +Fri Mar 26 17:24:45 CET 2004 - postadal@suse.cz + +- fixed sshd(8) and sshd_config(5) man pages (EAL3) +- fixed spelling errors in README.SuSE [#37086] + +------------------------------------------------------------------- +Thu Mar 25 14:50:50 CET 2004 - postadal@suse.cz + +- fixed change window request [#33177] + +------------------------------------------------------------------- +Mon Mar 22 15:19:15 CET 2004 - postadal@suse.cz + +- updated README.SuSE +- removed %verify from /usr/bin/ssh in specfile + +------------------------------------------------------------------- +Thu Mar 18 15:48:52 CET 2004 - postadal@suse.cz + +- fixed previous fix of security bug in scp [#35443] (CAN-2004-0175) + (was too restrictive) +- fixed permission of /usr/bin/ssh + +------------------------------------------------------------------- +Mon Mar 15 17:56:06 CET 2004 - postadal@suse.cz + +- fixed comments in sshd_config and ssh_config + +------------------------------------------------------------------- +Mon Mar 15 17:25:08 CET 2004 - postadal@suse.cz + +- enabled privilege separation mode (new version fixes a lot of problematic PAM + calling [#30328]) +- fixed security bug in scp [#35443] (CAN-2004-0175) +- reverted to old behaviour of ForwardingX11 [#35836] + (set ForwardX11Trusted to 'yes' by default) +- updated README.SuSE +- fixed pam code (pam-fix4.diff, backported from openssh-SNAP-20040311) + +------------------------------------------------------------------- +Fri Mar 05 13:10:55 CET 2004 - postadal@suse.cz + +- updated README.SuSE (Remote x11 clients are now untrusted by default) [#35368] +- added gssapimitm patch (support for old GSSAPI) + +------------------------------------------------------------------- +Mon Mar 01 18:13:37 CET 2004 - postadal@suse.cz + +- updated to version 3.8p1 + * The "gssapi" support has been replaced with the "gssapi-with-mic" + to fix possible MITM attacks. These two versions are not compatible. + +- removed obsoleted patches: krb5.patch, dns-lookups.patch, pam-fix.diff, + pam-end-fix.diff +- used process forking instead pthreads + (developers fixed bugs in pam calling and they recommended to don't use threads) + +------------------------------------------------------------------- +Tue Feb 24 11:37:17 CET 2004 - postadal@suse.cz + +- fixed the problem with save_argv in sshd.c re-apeared again in version 3.7.1p2 + (it caused bad behaviour after receiving SIGHUP - used by reload of init script) + [#34845] + +------------------------------------------------------------------- +Wed Feb 18 18:06:20 CET 2004 - kukuk@suse.de + +- Real strict-aliasing patch + +------------------------------------------------------------------- +Wed Feb 18 16:04:17 CET 2004 - postadal@suse.cz + +- fixed strict-aliasing patch [#34551] + +------------------------------------------------------------------- +Sat Feb 14 00:20:09 CET 2004 - adrian@suse.de + +- provide SLP registration file /etc/slp.reg.d/ssh.reg + +------------------------------------------------------------------- +Tue Feb 03 15:18:36 CET 2004 - postadal@suse.cz + +- used patch from pam-end-fix.diff [#33132] +- fixed instalation openssh without documentation [#33937] +- fixed auth-pam.c which breaks strict aliasing + +------------------------------------------------------------------- +Mon Jan 19 13:19:32 CET 2004 - meissner@suse.de + +- Added a ; to ssh-key-converter.c to fix gcc 3.4 build. + +------------------------------------------------------------------- +Fri Jan 16 12:57:41 CET 2004 - kukuk@suse.de + +- Add pam-devel to neededforbuild + +------------------------------------------------------------------- +Thu Nov 06 10:14:31 CET 2003 - postadal@suse.cz + +- added /usr/bin/slogin explicitly to %file list [#32921] + +------------------------------------------------------------------- +Sun Nov 2 21:10:35 CET 2003 - adrian@suse.de + +- add %run_permissions to fix build + +------------------------------------------------------------------- +Tue Oct 14 12:23:36 CEST 2003 - postadal@suse.cz + +- reverted value UsePAM to "yes" and set PasswordAuthentication to "no" + in file /etc/ssh/sshd_config (the version 3.7.1p2 disabled PAM support + by default) [#31749] + +------------------------------------------------------------------- +Tue Sep 23 15:02:00 CEST 2003 - draht@suse.de + +- New version 3.7.1p2; signature from 86FF9C48 Damien Miller + verified for source tarball. Bugs fixed with this version: + #31637 (CAN-2003-0786, CAN-2003-0786). Briefly: + 1) SSH1 PAM challenge response auth ignored the result of the + authentication (with privsep off) + 2) The PAM conversation function trashed the stack, by referring + to the **resp parameter as an array of pointers rather than + as a pointer to an array of struct pam_responses. + At least security bug 1) is exploitable. + +------------------------------------------------------------------- +Fri Sep 19 19:56:01 CEST 2003 - postadal@suse.cz + +- use pthreads instead process forking (it needs by pam modules) +- fixed bug in calling pam_setcred [#31025] + (pam-fix.diff - string "FILE:" added to begin of KRB5CCNAME) +- updated README.SuSE +- reverted ChallengeResponseAuthentication option to default value yes + (necessary for pam authentication) [#31432] + +------------------------------------------------------------------- +Thu Sep 18 18:34:33 CEST 2003 - postadal@suse.cz + +- updated to version 3.7.1p1 (with security patches) +- removed obsoleted patches: chauthtok.patch, krb-include-fix.diff, + gssapi-fix.diff, saveargv-fix.diff, gssapi-20030430.diff, racecondition-fix +- updated README.kerberos + +------------------------------------------------------------------- +Tue Sep 16 16:57:02 CEST 2003 - postadal@suse.cz + +- fixed race condition in allocating memory [#31025] (CAN-2003-0693) + +------------------------------------------------------------------- +Mon Sep 15 11:52:20 CEST 2003 - postadal@suse.cz + +- disabled privilege separation, which caused some problems [#30328] + (updated README.SuSE) + +------------------------------------------------------------------- +Thu Sep 04 11:59:39 CEST 2003 - postadal@suse.cz + +- fixed bug in x11-ssh-askpass dialog [#25846] (askpass-fix.diff is workaround for gcc bug) + +------------------------------------------------------------------- +Fri Aug 29 11:39:40 CEST 2003 - kukuk@suse.de + +- Call useradd -r for system account [Bug #29611] + +------------------------------------------------------------------- +Mon Aug 25 10:40:37 CEST 2003 - postadal@suse.cz + +- use new stop_on_removal/restart_on_upate macros +- fixed lib64 problem in /etc/ssh/sshd_config [#28766] + +------------------------------------------------------------------- +Tue Aug 19 11:21:33 CEST 2003 - mmj@suse.de + +- Add sysconfig metadata [#28943] + +------------------------------------------------------------------- +Fri Aug 1 01:57:08 CEST 2003 - ro@suse.de + +- add e2fsprogs-devel to neededforbuild + +------------------------------------------------------------------- +Thu Jul 24 19:47:14 CEST 2003 - postadal@suse.cz + +- updated to version 3.6.1p2 +- added the new version of patch for GSSAPI (gssapi-20030430.diff), + the older one was removed (gssapi.patch) +- added README.kerberos to filelist + +------------------------------------------------------------------- +Tue Jun 3 00:41:08 CEST 2003 - mmj@suse.de + +- Remove files we don't package + +------------------------------------------------------------------- +Wed Apr 02 15:03:44 CEST 2003 - postadal@suse.cz + +- fixed bad behaviour after receiving SIGHUP (this bug caused not working reload of init script) + +------------------------------------------------------------------- +Tue Mar 18 14:25:08 CET 2003 - postadal@suse.cz + +- added $remote_fs to init.d script (needed if /usr is on remote fs [#25577]) + +------------------------------------------------------------------- +Thu Mar 13 17:02:52 CET 2003 - postadal@suse.cz + +- fixed segfault while using GSSAPI for authentication when connecting to localhost (took care about error value of ssh_gssapi_import_name() in function ssh_gssapi_client_ctx()) + +------------------------------------------------------------------- +Mon Mar 10 09:28:31 CET 2003 - kukuk@suse.de + +- Remove extra "/" from pid file path. + +------------------------------------------------------------------- +Mon Mar 03 16:49:24 CET 2003 - postadal@suse.cz + +- modified init.d script (now checking sshd.init.pid instead of port 22) [#24263] + +------------------------------------------------------------------- +Mon Mar 3 16:05:24 CET 2003 - okir@suse.de + +- added comment to /etc/pam.d/ssh on how to enable + support for resmgr (#24363). + +------------------------------------------------------------------- +Fri Feb 21 18:52:05 CET 2003 - postadal@suse.cz + +- added ssh-copy-id shell script [#23745] + +------------------------------------------------------------------- +Fri Feb 14 13:42:14 CET 2003 - postadal@suse.cz + +- given back gssapi and dns-lookups patches + +------------------------------------------------------------------- +Wed Jan 22 23:05:35 CET 2003 - postadal@suse.cz + +- updated to version 3.5p1 +- removed obsolete patches: owl-mm, forced-commands-only, krb +- added patch krb5 (for heimdal) +- temporarily removed gssapi patch and dns-lookups (needs rewriting) +- fix sysconfig metadata + +------------------------------------------------------------------- +Thu Dec 5 10:52:41 CET 2002 - okir@suse.de + +- avoid Kerberos DNS lookups in the default config (#20395) +- added README.kerberos + +------------------------------------------------------------------- +Thu Sep 19 11:00:46 CEST 2002 - postadal@suse.cz + +- added info about changes in the new version of openssh + to README.SuSE [#19757] + +------------------------------------------------------------------- +Mon Sep 2 10:39:24 CEST 2002 - okir@suse.de + +- privsep directory now /var/lib/empty, which is provided by + filesystem package (#17556) + +------------------------------------------------------------------- +Wed Aug 28 05:48:16 CEST 2002 - nashif@suse.de + +- Added insserv & co to PreReq + +------------------------------------------------------------------- +Mon Aug 26 11:57:20 CEST 2002 - okir@suse.de + +- applied patch that adds GSSAPI support in protocol version 2 (#18239) + +------------------------------------------------------------------- +Thu Aug 22 14:09:43 CEST 2002 - postadal@suse.cz + +- added the patch to fix malfunction of PermitRootLogin seted to + forced-commands-only [#17149] + +------------------------------------------------------------------- +Fri Aug 9 14:41:30 CEST 2002 - okir@suse.de + +- syslog now reports kerberos auth method when logging in via + kerberos (#17469) + +------------------------------------------------------------------- +Tue Jul 23 04:34:10 PDT 2002 - okir@suse.de + +- enabled kerberos support +- added patch to support kerberos 5 authentication in privsep mode. +- added missing section 5 manpages +- added missing ssh-keysign to files list (new for privsep) + +------------------------------------------------------------------- +Mon Jul 22 14:16:54 CEST 2002 - okir@suse.de + +- fixed handling of expired passwords in privsep mode + +------------------------------------------------------------------- +Tue Jul 9 13:48:52 CEST 2002 - mmj@suse.de + +- Don't source rc.config + +------------------------------------------------------------------- +Wed Jul 3 01:01:24 CEST 2002 - draht@suse.de + +- ssh-keygen must be told to explicitly create type rsa1 keys + in the start script. + +------------------------------------------------------------------- +Tue Jul 2 12:03:58 CEST 2002 - ro@suse.de + +- useradd/groupadd in preinstall to standardize + +------------------------------------------------------------------- +Sat Jun 29 10:33:18 CEST 2002 - ro@suse.de + +- updated patch from solar: zero out bytes for no longer used pages + in mmap-fallback solution + +------------------------------------------------------------------- +Thu Jun 27 18:07:37 CEST 2002 - ro@suse.de + +- updated owl-fallback.diff from solar + +------------------------------------------------------------------- +Thu Jun 27 17:04:16 CEST 2002 - ro@suse.de + +- update to 3.4p1 + o privilege separation support + o overflow fix from ISS +- unsplit openssh-server and openssh-client + +------------------------------------------------------------------- +Tue Jun 18 12:12:41 CEST 2002 - mmj@suse.de + +- Update to 3.2.3p1 which fixed following compared to 3.2.2p1 + o a defect in the BSD_AUTH access control handling for + o login/tty problems on Solaris (bug #245) + o build problems on Cygwin systems + +- Split the package to openssh, openssh-server, openssh-client and + openssh-askpass + +------------------------------------------------------------------- +Sun May 19 16:15:03 CEST 2002 - mmj@suse.de + +- Updated to 3.2.2p which includes security and several bugfixes. + +------------------------------------------------------------------- +Fri Mar 15 12:05:21 CET 2002 - ro@suse.de + +- added "Obsoletes: ssh" + +------------------------------------------------------------------- +Tue Mar 5 17:15:30 MET 2002 - draht@suse.de + +- security fix for bug in channels.c (channelbug.dif) + +------------------------------------------------------------------- +Fri Mar 1 15:40:59 CET 2002 - bk@suse.de + +- fix ssh-agent example to use eval `ssh-agent -s` and a typo. +- add sentence on use of ssh-agent with startx + +------------------------------------------------------------------- +Tue Feb 26 12:31:21 CET 2002 - bk@suse.de + +- update README.SuSE to improve documentation on protocol version + +------------------------------------------------------------------- +Wed Feb 13 13:15:41 CET 2002 - cihlar@suse.cz + +- rewritten addrlist patch - "0.0.0.0" is removed from list + after "::" is successful [#8951] + +------------------------------------------------------------------- +Mon Feb 11 15:17:32 CET 2002 - cihlar@suse.cz + +- added info about the change of the default protocol version + to README.SuSE + +------------------------------------------------------------------- +Thu Feb 7 12:42:53 CET 2002 - cihlar@suse.cz + +- removed addrlist patch which fixed bug [#8951] as it breaks + functionality on machines with kernel without IPv6 support, + bug reopened, new solution will be find +- switched to default protocol version 2 +- added ssh-keyconvert (thanks Olaf Kirch ) +- removed static linking against libcrypto, as crypt() was removed + from it [#5333] + +------------------------------------------------------------------- +Tue Jan 22 15:43:33 CET 2002 - kukuk@suse.de + +- Add pam_nologin to account management (else it will not be + called if user does not do password authentification) + +------------------------------------------------------------------- +Tue Jan 15 15:49:07 CET 2002 - egmont@suselinux.hu + +- removed colon from shutdown message + +------------------------------------------------------------------- +Thu Jan 10 09:27:50 CET 2002 - cihlar@suse.cz + +- use %{_lib} + +------------------------------------------------------------------- +Thu Dec 13 01:01:36 CET 2001 - ro@suse.de + +- moved rc.config.d -> sysconfig + +------------------------------------------------------------------- +Mon Dec 10 14:07:21 CET 2001 - cihlar@suse.cz + +- removed START_SSHD + +------------------------------------------------------------------- +Fri Dec 7 11:26:22 CET 2001 - cihlar@suse.cz + +- update to version 3.0.2p1: + * CheckMail option in sshd_config is deprecated + * X11 cookies are now stored in $HOME + * fixed a vulnerability in the UseLogin option + * /etc/ssh_known_hosts2 and ~/.ssh/known_hosts2 are obsolete, + /etc/ssh_known_hosts and ~/.ssh/known_hosts can be used + * several minor fixes +- update x11-ssh-askpass to version 1.2.4.1: + * fixed Imakefile.in +- fixed bug in adresses "::" and "0.0.0.0" [#8951] + +------------------------------------------------------------------- +Fri Oct 5 07:34:11 CEST 2001 - cihlar@suse.cz + +- update to version 2.9.9p2 +- removed obsolete clientloop and command patches +- uncommented "HostKey /etc/ssh/ssh_host_rsa_key" in sshd_config +- added German translation of e-mail to sysadmin +- init script fixed to work when more listening sshd runs +- added /bin/netstat to requires + +------------------------------------------------------------------- +Mon Sep 24 14:25:58 CEST 2001 - cihlar@suse.cz + +- fixed security problem with sftp & bypassing + keypair auth restrictions - patch based on CVS +- fixed status part of init script - it returned + running even if there were only sshd of connections + and no listening sshd [#11220] +- fixed stop part of init script - when there was no + /var/run/sshd.pid, all sshd were killed + +------------------------------------------------------------------- +Thu Sep 6 14:31:15 CEST 2001 - nadvornik@suse.cz + +- added patch for correct buffer flushing from CVS [bug #6450] + +------------------------------------------------------------------- +Fri Jul 27 09:05:24 CEST 2001 - cihlar@suse.cz + +- update x11-ssh-askpass to version 1.2.2 + +------------------------------------------------------------------- +Thu Jul 26 10:55:16 CEST 2001 - cihlar@suse.cz + +- update to version 2.9p2 +- removed obsolete "cookies" patch + +------------------------------------------------------------------- +Mon Jun 11 11:21:22 CEST 2001 - cihlar@suse.cz + +- fixed to compile with new xmkmf + +------------------------------------------------------------------- +Thu Jun 7 09:42:23 CEST 2001 - cihlar@suse.cz + +- fixed security bug when any file "cookies" could + be removed by anybody + +------------------------------------------------------------------- +Tue Jun 5 12:49:50 CEST 2001 - bjacke@suse.de + +- generate rsa host key in init script + +------------------------------------------------------------------- +Tue Jun 5 07:59:41 CEST 2001 - cihlar@suse.cz + +- removed complete path from PAM modules + +------------------------------------------------------------------- +Thu May 3 09:36:17 CEST 2001 - cihlar@suse.cz + +- update to version 2.9p1 +- removed obsolete --with-openssl +- removed obsolete man patch + +------------------------------------------------------------------- +Mon Apr 30 07:50:23 CEST 2001 - cihlar@suse.cz + +- enable PAM support + +------------------------------------------------------------------- +Fri Apr 13 11:50:26 CEST 2001 - ro@suse.de + +- fixed specfile for extra README.SuSE + +------------------------------------------------------------------- +Fri Apr 13 08:03:45 CEST 2001 - cihlar@suse.cz + +- fixed init script by new skeleton + +------------------------------------------------------------------- +Thu Mar 22 14:56:50 CET 2001 - cihlar@suse.cz + +- update to version 2.5.2p2 + +------------------------------------------------------------------- +Wed Mar 14 14:12:38 CET 2001 - cihlar@suse.cz + +- fixed ssh man page + +------------------------------------------------------------------- +Mon Mar 12 07:56:37 CET 2001 - cihlar@suse.cz + +- update to version 2.5.1p2 +- added xf86 to neededforbuild + +------------------------------------------------------------------- +Fri Mar 9 15:16:59 CET 2001 - schwab@suse.de + +- Fix missing crypt declaration. + +------------------------------------------------------------------- +Fri Feb 23 08:57:55 CET 2001 - cihlar@suse.cz + +- update to version 2.5.1p1 +- update x11-ssh-askpass to version 1.2.0 + +------------------------------------------------------------------- +Tue Feb 20 11:27:20 CET 2001 - cihlar@suse.cz + +- modified README.SuSE [#4365] +- fixed start script to agree with skeleton +- fixed start script so "stop" kills only sshd + listening for connections +- compiled with --with-openssl +- "ListenAddress 0.0.0.0" in sshd_config commented out - + listen on both ipv4 and ipv6 +- fixed var/adm/notify/messages/openssh_update [#6406] + +------------------------------------------------------------------- +Thu Jan 25 15:02:01 CET 2001 - smid@suse.cz + +- startup script fixed [#5559] + +------------------------------------------------------------------- +Tue Jan 16 09:40:50 CET 2001 - nadvornik@suse.cz + +- libcrypto linked static [#5333] + +------------------------------------------------------------------- +Thu Jan 11 13:41:48 CET 2001 - cihlar@suse.cz + +- uncomment sftp-server part in sshd_config +- added /usr/X11R6/lib/X11/app-defaults/SshAskpass to %files + +------------------------------------------------------------------- +Thu Jan 11 12:37:10 CET 2001 - cihlar@suse.cz + +- fixed %files [#5230] +- fixed installation of x11-ssh-askpass to BuildRoot +- added man pages of x11-ssh-askpass + +------------------------------------------------------------------- +Wed Jan 10 11:54:42 CET 2001 - smid@suse.cz + +- notice about how to enable ipv6 added to mail +- for administrator [#5297] + +------------------------------------------------------------------- +Wed Dec 13 10:43:25 CET 2000 - smid@suse.cz + +- default ipv6 listennig disabled (problems with libc2.2) [#4588] + +------------------------------------------------------------------- +Tue Dec 5 14:03:35 CET 2000 - smid@suse.cz + +- notify message changed + +------------------------------------------------------------------- +Mon Dec 4 21:45:35 CET 2000 - lmuelle@suse.de + +- fixed provides/ conflicts to ssh + +------------------------------------------------------------------- +Thu Nov 30 16:03:34 CET 2000 - smid@suse.cz + +- path to ssh-askpass fixed +- stop in %preun removed +- new init style + +------------------------------------------------------------------- +Sun Nov 26 23:53:53 CET 2000 - schwab@suse.de + +- Restore rcsshd link. + +------------------------------------------------------------------- +Sun Nov 26 15:34:12 CET 2000 - kukuk@suse.de + +- Add openssl-devel to neededforbuild + +------------------------------------------------------------------- +Mon Nov 20 16:11:34 CET 2000 - smid@suse.cz + +- New version 2.3.0 + +------------------------------------------------------------------- +Wed Sep 6 12:52:06 CEST 2000 - smid@suse.cz + +- remove --with-ipv4-default option + +------------------------------------------------------------------- +Wed Jul 5 19:04:28 CEST 2000 - garloff@suse.de + +- ... and tell the sysadmin and user more about what they can do + about it (schwab). + +------------------------------------------------------------------- +Wed Jul 5 00:55:37 CEST 2000 - garloff@suse.de + +- Inform the user (admin) about the fact that the default behaviour + with respect to X11-forwarding has been changed to be disabled. + +------------------------------------------------------------------- +Wed Jun 28 13:11:08 CEST 2000 - smid@suse.cz + +- warning that generating DSA key can an take a long time. + (bugzilla 3015) +- writing to wtmp and lastlog fixed (bugzilla 3024) +- reading config file (parameter Protocol) fixed + +------------------------------------------------------------------- +Fri Jun 16 10:42:52 CEST 2000 - garloff@suse.de + +- Added generation of ssh_host_dsa_key + +------------------------------------------------------------------- +Tue Jun 13 08:32:19 MEST 2000 - nadvornik@suse.cz + +- update to 2.1.1p1 + +------------------------------------------------------------------- +Thu Jun 8 10:10:55 MEST 2000 - cihlar@suse.cz + +- uncommented %clean + +------------------------------------------------------------------- +Fri May 5 13:08:15 CEST 2000 - smid@suse.cz + +- buildroot added +- upgrade to 1.2.3 + +------------------------------------------------------------------- +Tue Mar 21 09:50:57 CET 2000 - kukuk@suse.de + +- Update to 1.2.2p1 + +------------------------------------------------------------------- +Mon Mar 6 12:03:49 CET 2000 - kukuk@suse.de + +- Fix the diff. + +------------------------------------------------------------------- +Sun Mar 5 18:22:07 CET 2000 - kukuk@suse.de + +- Add a README.SuSE with a short description how to use ssh-add + +------------------------------------------------------------------- +Tue Feb 29 21:03:50 CET 2000 - schwab@suse.de + +- Update config.{guess,sub}. + +------------------------------------------------------------------- +Fri Feb 25 11:01:24 CET 2000 - kukuk@suse.de + +- Fix need for build, add group tag. + +------------------------------------------------------------------- +Wed Feb 2 09:23:13 CET 2000 - kukuk@suse.de + +- Change new defaults back to old one + +------------------------------------------------------------------- +Sun Jan 30 12:51:49 CET 2000 - kukuk@suse.de + +- Add x11-ssh-askpass to filelist + +------------------------------------------------------------------- +Fri Jan 28 18:03:50 CET 2000 - kukuk@suse.de + +- Update to OpenSSH 1.2.2 +- Add x11-ssh-askpass-1.0 + +------------------------------------------------------------------- +Tue Jan 25 15:57:09 CET 2000 - kukuk@suse.de + +- Add reload and status to /sbin/init.d/sshd [Bug 1747] + +------------------------------------------------------------------- +Thu Jan 20 17:26:02 CET 2000 - kukuk@suse.de + +- Update to 1.2.1pre27 with IPv6 support + +------------------------------------------------------------------- +Fri Dec 31 21:18:10 CET 1999 - kukuk@suse.de + +- Initial version diff --git a/openssh.keyring b/openssh.keyring new file mode 100644 index 0000000..f174408 --- /dev/null +++ b/openssh.keyring @@ -0,0 +1,353 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQGiBDqa5pwRBADJSEyXXsgXiyytN93prDPTPmrueRP9lQQfgaQvCvqK0bN0AF1Z +Vxxk9wlSXQp3+Qw5+qqsN5ovzsn39r9pqGslfCqQn9ACTmsn42+VCyW4hdwUGSBS +5myh65ZJTK1ufWCZFssxQ0EiALagu4DlH6Z2O7tFDnJNagF55vlnK0uMQwCg/8RU +QYDmisEHjkarAapPaupxjhkD/j9riCVasWPYJwAuhiQWAKxGRwp/ZyTaWCSERUBR +4Dg9QxpuwHKIT8BeDA3hJa/9Yxu5jec2NVKbtVSZvRkgUfRNOkrcH2eiY8Iz6est +J64dGWuGMKQW0GEqW+OXpRTTPJZ0mgPmU16qDzLPdx6F3BAk2LG+TTwlKUPuGqOt +6u2EA/4+1CBYZ8mXq9GJnLRBPAoYwSJJzbQnMm9Jat/yg9N6nigSIiFyG8ixh167 +gGGKfzvpjY7DeJzDI0Cub+tRova8gFg+T15AcPMST5v7v6O/ug9aYWERZ0zjUhRH +ybtYLYhUUbdYM29PwGBNfZhGIOYwfFE9UpPS5LeXHs28oVLlH4jcBCARAgCcBQJS +ppQ+lR0BVGhpcyBrZXkgaGFzIGJlZW4gc3VwZXJzZWRlZCBieSBrZXkgSUQgNkQ5 +MjBEMzAKS2V5IGZpbmdlcnByaW50ID0gNTlDMiAxMThFIEQyMDYgRDkyNyBFNjY3 +ICBFQkUzIEQzRTUgRjU2QiA2RDkyIDBEMzAKUGxlYXNlIHVwZGF0ZSB0byB0aGlz +IG5ldyBrZXkuAAoJEM6OywOG/5xIWdMAoJZA/6ls+J6YIpVDFHkb4/8fl0w4AJ90 +K3I7hssc7QuWHfPlq3EozRtjIbQuRGFtaWVuIE1pbGxlciAoUGVyc29uYWwgS2V5 +KSA8ZGptQG1pbmRyb3Qub3JnPohXBBMRAgAXBQI6muacBQsHCgMEAxUDAgMWAgEC +F4AACgkQzo7LA4b/nEiDMgCZAUzKq241h5GTJxC0guS6ht9i9ZsAoL/oXCmFsofA +RehZF6AakIdasvS9iEYEExECAAYFAj77h64ACgkQmD+U6HbiLS3r4ACfclqiFP6E +TBkTbjqC328yXlT2rlEAnR6Wv3SNayY4jOgfxCMxi61S2CkAiQGsBBABAgAGBQJS +ppEIAAoJENPl9Wttkg0wMMsMf0tC6QkZnCkTiEVSar2Bd0gJWRCZOGgWwYnXVXif +5UaQhRgfXyXDxADWi76UYl4v8UFrH9yODXhZM0hoNbt6T98stHmw3dIvrYfhRgQ0 +83p/N7II3i1iDJDUZ9PA8n4c5BWXirOUXPxtp23WgsEqG5DaN3CGo99YZO8aB3AH +hWd8xvGGDOKOMpAPQekgG/CZw3pcdaSOsZvOEOnbk/VuI2DVjTu/hX0PmRKkfeVf +aafi6bcDkm8Vs7Sw4TIrNmGJTKIDhwXSrFlDfs/CmZJUxzP/S7W+dZ4kvESDSWia +wmxQFMIxRqgHeLiRHYXCL5Fg+WYFv+EMj/ta5PVot86/iWfrj0MRKZFCpRfDjqTv +t0G0ziOW9kTFK8TpxBacJR7n4whM6SNf6L9onHn7xqx2r0J8TLcua9hTvapuNPdL +y1cxAKMZO8q10AMGkYd03qLlHxtgKXBeWkV/UYAc1zArv4JFdWTraLbIHmi8jpvE +NM3qcNWuNVyiTi4Kxum+CFd8V7b4X/6yBLRD/U6/dMUy4LiIVwQTEQIAFwUCOprm +nAULBwoDBAMVAwIDFgIBAheAAAoJEM6OywOG/5xIgzIAnjRm47SkL5RQ9lDvVdm5 +SmNw0HX0AKC+AssIfepBFkPIFBSLcNoSWiTkzrkCDQQ6mubUEAgA8/15wnMpXvYZ +sYMp7a9+WUCSsfYOn7QcNe/CUsDNzuyTThqd/fBIeEPa5BKeTR9alXnBvedxbnnU +/SAF6q/KY6ebXajGAnGisvmidEsNc1Q9lTmN4e0sn1NuaXGIhxGtYK3yj1aFpudy +MFhlVbarheXYpgHu+fg9Gl8lQjr9BM/cICUeh+vZaeP3A9hsjWhmq8GPRy7xxb1z +jWNqpvxleTo8jlDuNYJkOKcl0IfoKHBRR6zNAM73iLMIDaSdMTVl1/IlxrK92Ar6 +puyaCFPSSsQ1fvem8Qy303SqaC2Cm+vFnbZgMpbIqOfomX1rXTm/16ZNmMeS3Wnc +vf/p95unLwAFEQgAq76FUm3dDEdBVl/mwWdDY0nDQaN5D0kgp0Oo0R6JJM+ea/jB +3u3asQid6Zru2kTpdn4LoOsKG/u/ql3ypHv03U+sLgm+AnRUurT4D632FfosKtjQ +fwWrXjxoO2elAC2lC0NJvNwwhFSyTZ43phHSKLkoXpYpAADu0AyjK+7wIx/J9M8D +KcETF57wjOs2JUvYtZDpvC1QE5NFsooaUBkmk7pHT4ypRu7CsDLttLLCvQxlaT4L +pU2e6x6l5eI7mPC0No+HTzWj6ClhvCbgVQrMn9g+hjVvez3ykEpMxXmbG1QeEkUK +1U3IYAUmKMUVVt3y5P8nN0wuQG4ehqY+Is2sFIhGBBgRAgAGBQI6mubUAAoJEM6O +ywOG/5xIH7YAnRyGVA1QFg0WubIkovAKLPiIsgIAAJ9NsBjpdVqP2CfkWPnOijef +E5gDxJkBogQ3R/zyEQQAsWguKhytuM/8IwqKRSQBPaHRTyVMjsvLr7uUIoW2qf0V +VDVxuSXy4K/k43Q/ssw2nDipUkS74vMgGzgUQk4BI0LkoPSIVoXo+v65KCSbrMNY +m7lGGN7ZkFg5zWDfdVFiN5P/tUg91UfmCI71zp78SltyBM+FLPJhBYE0dvkHDjMA +oN744XCDTRMARJLK8DH1O3eTkE+1A/9brypK8VFX1+J3jfZmz7nD2St9+6/rkcM+ +P8V7bHHttSVLswhTZ8bMZv5aJjsyyPrnFFLmlPddaQDND1fVFevrHOTbSnMjt8lK +Ksh4z+FFCQTB8wtpXbs2xHjny1Oy8kwiCnYCtDr3fOYnoqFkCMwT2ulbcKGZ3L6k +neUGSvWOhAQArqhDaGwsZfkvzirG9vo/PFBwdeKNj/tDOE+1SQasDT0L3gd/tfmZ +LBCed2yQ7axppQlQRIcNL24+GHefTY5Y92T7GLVIg2cK5JUtMKMmgWj3szyXi5Oc +QKxQdhmBgsWutyJj6SlAHSDrjFhVabIeJKuyuZzxhyvmSzzjBsugsayIUQQgEQIA +CQUCOprFaAIdAQASCRCiuYn1EbV0jwdlR1BHAAEB6xwAn3FxEH2wPVFlzVKf09Sh +uwEfspiYAKCkKEhT4qVjGQ2D4cwgtoZ03pQgELQlRGFtaWVuIE1pbGxlciA8ZG1p +bGxlckBpbG9naWMuY29tLmF1PohfBBMRAgAXBQI6JFsGBQsHCgMEAxUDAgMWAgEC +F4AAEgkQormJ9RG1dI8HZUdQRwABAU4BAKCFIZWrqfMjc8zKhnfoTSEAt/ojUwCf +eqkKspOp6Uqq1tlr1oyYmN5P5Y6IRgQQEQIABgUCODCW/wAKCRB9nsJ2HENBrF/D +AJ48befkKUUGogX4tPfIAzbu+auUPwCgp41iiMRqeqgWbsG1ujpDnVQRp/y0H0Rh +bWllbiBNaWxsZXIgPGRqbUBtaW5kcm90Lm9yZz6IXwQTEQIAFwUCOiRbLwULBwoD +BAMVAwIDFgIBAheAABIJEKK5ifURtXSPB2VHUEcAAQG/QQCcD+0bmcV5aYRb8JQ9 +Q+DeKi2fqfwAoJ0g1TDjN+ZpKAaOI95waVgGjYAhiEYEEBECAAYFAjgwlwgACgkQ +fZ7CdhxDQazdMwCcCWb+3Ehg/wK6nrIebHYlDBwcYLAAoMXIboTxrdRh71R3/4Pd +zTR9g2vQtCVEYW1pZW4gTWlsbGVyIDxkbWlsbGVyQHZpdG5ldC5jb20uc2c+iF8E +ExECABcFAjokWy8FCwcKAwQDFQMCAxYCAQIXgAASCRCiuYn1EbV0jwdlR1BHAAEB +9qQAnAzpzF24V7K84PQTKQ0V5a1EiGmBAKDIg1wPX7ZSRDHBrAaLKpEirnj1MIhG +BBARAgAGBQI4MJcIAAoJEH2ewnYcQ0GsnfYAmwZq27x3h0EV0t+0i3j7dClD5eMX +AJwP4AvyuGuyz3qGOYxXG/1RuhqoubkBDQQ3R/0CEAQA35tSeji8z1JVaQApKuEK +VhZAm2zaZLFiAusKqS+/RXUhIFTI7Du/dJTPODm3pLQEnF4evo3qgokSP5rf5Y++ +JPUfkS6NTons29mnCVyWPl8+3yJaTPbX708e+r5ZWuN30c9dl8Br7mHzJrsTRumT +9qSVPUklzv77JOAxBGTEhAcAAwUD/0MelpnyrZNVFja/xObo/OL4r6mwwO0pyK1Q +qE8AuGO37Ug0WO6QNxgFLKR8l+9sod6q4KAEBxhA0DiVrJFNkTuza6HR5i22Y4ei +VNbPC8IqRuF6o4KC3zejZgpPpApqrO0mMmo7GXcBpkpCS8vzJ09EvfExbALB0Jku +GQn7SImsiEkEKBECAAkFAjqaxBECHQEACgkQormJ9RG1dI9+GwCfTEqyOILSu5Nz +DhcUrqpknPlXX/YAoI/vfDq8kQG0QldbtWsC+MWQH9zsiFQEGBECAAwFAjdH/QIF +CQLH6gAAEgkQormJ9RG1dI8HZUdQRwABAfKmAJ9EMdNbg94wSQrHb8oKVAKfjFZt +TACgusXeU8duOaTgSb89XrAGCTb3THu5AQ0EOiRfFRQEAOelb5M0Hjb87WcPiIy2 +UAsxOwDno7H7vR9WLfpfKjPwk7Xoa05qyThF2L96keXZZAm54yapyeXhNPGquFyq +YMOwxX+aQyUr13uH3KTkAaDKMkC5jAAkcZwTk+tENsB/StqyqbH5/KVOoCfxEFFA +MVgTbXQnEGpqUL+WGz4Ay6IPAAUXBAChhg+rFXcsAMne7QK2816p64Lm44BB46n6 +WdZoST84rOq0ZNd+fYSqfRcaPJHHjO4lAEH+1dgQjpqxkEveodKPsixoLQdHd76s +SRDcX15IhWG+OBNCD4k6Y1DLLYhPE5bUToQYm8kPhVS3yuMLuNhtDntNQURfQL7B +JxQM0A8/b4hJBCgRAgAJBQI6msQVAh0BAAoJEKK5ifURtXSP1O8AnA3CcDJd1ZUD +2Kr86Q9DSuimSMuAAKCX77M6fadIiy415K3vIfadl/nsq4hOBBgRAgAGBQI6JF8V +ABIJEKK5ifURtXSPB2VHUEcAAQHXmQCdEbOoH3DE+L9keE5ODJ7j6CvHPRgAoJZm +54r/EPzKnu9gTsI0J+7oIh7emQGiBDqa3UERBACPhKenaTumEld5L06d5z4yl4AC +f+VsVD98Im0slZfKTcqMb3Y9Vzq4CduOVb6p4M9yX2bjxCk2mtmg5iunPuteGmVb +YSNcd7yjm9giqe6EnxXkxXmCP/AVA0kB09XYcsjmMFbRFahXo3xpdExAjyU6JVxC +/61kX8h4oYxjtWw/BwCgzf2qjNPEXshE0lwpoGwcwxk5cnUEAILKVk6G+rcususo +b2AiPjzcQnCZYNzoHpNOSkwInV/MqN6Pb1reKcJQ44RFyh6+fsdeNM2+7ifF+5DS +ZB13+5fhmtNtryIeMgfH0nYVu7YllPEmSmPOdERpjibxXbxEjWM8n4qKBe7iYVHW +tB+j9O6HyAB36mHcorYIs9NvHl76A/9kl+eBT4i2/jjPQQ4V4rrYXl7M5EWxpgMS +yUwzqM/YPZZCXJTqzv6FxUUc7LprdOEIbzQOyJqugKqHzQCekii7bcyAwu1NrV/z +amTherN+l0UqIArjWVh0IVagpXptGooVq7snoef8W/KzZQRVC1rcEQ3zV3TD3IQZ +mjx8ZgWCqbQuRGFtaWVuIE1pbGxlciAoUGVyc29uYWwgS2V5KSA8ZGptQG1pbmRy +b3Qub3JnPohfBBMRAgAXBQI6mt1BBQsHCgMEAxUDAgMWAgECF4AAEgkQqBmi2Gke ++NoHZUdQRwABAVy9AJ9RqC+W+xZCok3gcEZMiHy1lboyvgCeMSO/ld6brLcz4o8/ +OMMwNne2IZeJAawEEAECAAYFAlKmjbQACgkQ0+X1a22SDTCk7wx/TLjgpMrFa/tg +k+/boARaFlsAJ/4OgyiY6314YbTyqatq1RVwWHTln1QJn8zXWpHUi9scfboxFYqz +vKT1g6TXAkg1fu5muiBCTMVVCuawXEDr0iVxfsFoCDjLKecMUxqwfj9gL3kitkbj +Ga7YcZnUcAOoLOWxsXNs5QZmKl/+E26iKGAB1sy/wMU40KjrOEg12fvIoDemeGfV +gPdeChkhpDkm7upB32UvzDbZsKO7eHxoBYW1sRJy04Tyl/hwXnNCfqYJ42BuITrk +EOSDr35MTYuLzC5l5l1uQXiCaJZxLGiM+ngkT76dkVQ4OcCgojuDih8aeT+TkM7H +YkCoVje/6Z45wNzsG1lTxE9AKTBzpi0ZKGv5/WVSQ1anuC56bgdfD9jjMrhsVwWf +mICN8zrOtYLcOJV6sUa+hZy8edEqZRkt93b8r0F2XDEVYId80debcFWExuil2TDO +Z0nfkgxRDq+wtwem51rrRc3gLH1UR/NWsSmC2Mvj7jSDGeA+gIbRFNE6+a2YG1aj +fxNdMBZ/OrkBDQQ6mt1DEAQAp/JyP+Brxt7T5vTTJSUMWSjOC+aBNZNFFHbG9KW3 +x8qoE7d/SYLGIqHXscGQ0a6gzoe01DFiDovtipM6g/FarCPjRVMN72SEju2pv7hl +Gr/fcyHhKOYwcxaCVFOQetlnKq4zVrJvc0OZD/nsbRCH2ze3T5xtSQ7IlJ/rDUf/ +2JsAAwYD/2h2esQEPQy8MRpFhcBZ8Z3iVaAZ0LSgvoap8RKBSmzS9QHYgk/U4N9k +W6BFQBfmG02aGMLN+WHy8oMMNVEaJxkQvXU7evd2vPIk9mW8JSeqAGa7dmZRjVkK +PBDy79eSoM/Z8Gb1TFnKJ9ju+s+pqdi0bJPsDty+yA+96MFOy5epiE4EGBECAAYF +Ajqa3UMAEgkQqBmi2Gke+NoHZUdQRwABAVDHAJ40H81xz0kVSd6/NVHLDEd7+98X +tACfZmBzmbxbQ1dhnKg3hxACZvKwMKuZAZ0EUqaCBQEMgJQ2qbhw2Hu10RvBo2Fu +fCouIekgt5dPqx10YjRK3Pmh8HW68geb2RdgbldRTCVznLCMhmbYl64qqt3/rADP +mVotqAUDqTzoRnPO4ETdvkXFJDgQ3grldkQmjrXEBIQXvPWZAKKqgDr8XjTuG3uc +2iJUT3mQ6aomW/hypukLDefx/ZVb6ZVQfoxhFlWtgAL02cla/bit6bZ+OAWE1PX9 +vHjgbsf1tUmovuEwQZr7FhAEjdhP+6US70diYsVV6JmbWAHV4pdbuNLhy0uXm4+v +FrIDkNf+o0HbKqBVWUgoXBSbyAY8Y86ew0qjTEGx4TsTQX8p4alpPlpL3IWA+b0D +rnYnH196ViBvR70im3eXGuI9DCAX9zEsa4/9YRs3l+lYWe5XRWKSW6y5UjZ7wYck +ZTltAPkCXO9a7hK/qgE5wMJptJzJ1jsjE8GT9cFYIX1AMhraprfYxz11hzwScmzM +95UIdfmEbbeiYNGZ0sYvAfsX4K4G8LEAoLKZm0mXkOFGaeF3NGD137RUbiEsXs7T +oA0AEQEAAbQfRGFtaWVuIE1pbGxlciA8ZGptQG1pbmRyb3Qub3JnPokBzQQTAQIA +JwIbAwUJDUfrsQIeAQIXgAUCUqaMnAQLCQgHBhUKCQgLAgUWAgMBAAAKCRDT5fVr +bZINMHZMDH0TWjM8kpQZYk9l5+qxKvwqw7oOndC4+vDZnCCjZB94JP67M0DkAoIM +gBpgSlVtCy+7iwPLx0BbX4cQ0LFWsxdYb5IfjWVx0B0jiKjQ8YdVAOXjZHmNfd72 +l+NgJAAtW/kENd10rrTnifLESa51DcgIUJhchypBsDWd+PdSTTqMaG4z30Hb9qRv +EKgVKJRf24cNko1gAalTv8UIX3EJkXgp31PC/LLXuMMiDuSbf9DgnL75U/wXK8Tk +mMF0tFBIHNIb0YKO/1/IpZbtLRsxjgPdIoq38mbVdyEQyClGvh4GmAKzevE7WFeP +Oqbe173u7Lr+rwK4lS26kmw8pz1aHj6iBRmJ8LS1rtSvFmnzJlNG89JTFiuW8PMz +fZUMtDcVfpjaLhU2jjw9IkwD4E9THsNNxkohe3jnvOwsPiMXixF3A6T9AX8ZcKQf +YYDIodYI9cg576MheCK5qNypmb1wBaMveGJ1KiEp95+8qTOyDvmYOaOG8C0Odwhu +YiYk2Nch7Y9BTiJj1WrmLS+VpUqAGApKiEYEEBECAAYFAlKmi98ACgkQzo7LA4b/ +nEid/wCfQDsw+t8kjPZ7rjdURXgBfd0734gAn0w6xCIHgueq1Nxz00Ewd/1UsTjo +iQIcBBABAgAGBQJTFsNwAAoJEOX6rNyYiqSg3ZwQAKMYW9GCRVKwd8fxBIovohsD +oYOK/psUp8f8/IK1+aW9EsYcgnzpd8YuOcEa9PWd7/U+70/2fx4qyIkcJ/ofKP9U +zButogqdW1b4VISDP0t5cO9+DE4nSKod0hQdjJNM3611mr6lIhw2D56BdIzWuJl5 +eCSDnyQQd6iDt5j3wELnBJt8YnYC4TytJFzg9R7iFfkONKJZWpZlgj+ChSuMVMjM +qa9l6+mYZKy4FU2mZks4EvLiWYnGQAHPjU9h+KWgoIbTXLv3Rc+NYlgXErECpZaG +B89oiEIHqH7Na4e+gtxML2/RgoLgWEsMPJBnv6AnuX8cVX1EqGJT5AzmHVmWlJHq +pSXw8g7yIRjtHZ9UKJOIamtHhDfcLpI8lSGwb0quyF/OwBcpbyWkFdOhHfTV+6Vj +tLwHbiPDJIEVkCfcyItW9s9l78U42zqyXFsgUNcjrvR09OMf0eXREVRGgo0O6glY +XRwUDFG/StCsKYFDUz2IEe4a9MjzGCSB0bUR5nKFVxomSNNQVw6Qo7oeGfXtyEG/ +/KzhkDHsVWKU6qKSTK5fumQIUJHGJCCiQa6a0/6BXdoC/IVPbFgM/MHwAj030hyY +gb525l0BVD9+NEYs4Z7ZXkrdEHSIj2bTaDV2WywIYXcbxwovJlQT+gxeBxMoMJf9 +zzAY5iVBn985M85NNXvpiEYEEBEIAAYFAlLp6B4ACgkQyYKAx4/0+mkA8QCdFdv8 +9LNkAe1WK2gpjdW4mxXVCsUAmwf9+GFVwx69yKTXwcrvv29glD1WiQIcBBABAgAG +BQJTFqe/AAoJEEu0T4MGAI+Frd8P/0NxkhUMOo7PVWKAYEA15JQ6mvfhUkNI8MCl +PP2r0oDm3hf/sDdhi7P1pI/Wqlc/XAVQLZDtJZfZFvU4q0eF3Zs9uX3jvZjOGGQo +vVTnioQIV1JxHTriucFbkUEaMqdaQiFFAlb09qIbQaClKrbSa1d8oP+G8A7NIKxq +wwQMDk0I1UKus2QN4p0cBEuFdntlbkwwnyse7WrZS/7KcNGiHeFk8B/D63Vy2ISS +yORmeBTkA7r8qs4GAB+qrNTs+xsEQTC7Dx4Nz2FtgEmpXOifE0Txc3n761aAfNao +8bYukIbbF7Sw2ZvfwnEXikiL3m4uYFPcLsGfT3KFSKra69Vrm/DdZVGODJwALqo1 +CpPdV69qpq/e6q6SKTdJrc6YKeFZMyjHRFT4IhVG7KvUAjQkt0RcG17JinOlJ26F +MH9nosU2RlVJuESUJH9xzMgWugF5Uj6jQlm5h/PWKNEtX/PjFCFjkacffWzRGOEg +1mqB8B6O7UttATbt4mNV/BMZFGqNH0Jq64RM0n3Q5TaIhUIW/0jsES1TKrJ96W+M +m/JiBd6tTXjAlk7B+m9eI7fEA7y6dugm0Qpw1+C4aIopQayaguPf/hicQqRr/ggu +tKsO+vhJ9ie6cB1Zdc+BNGCrmpPrALmMbKmgw7i9ZI1iWE0pijX8kiBJoZaTb4Rq +PT8tKiYLiQIcBBABAgAGBQJTF2LJAAoJENaX3zJH9H8fPQMP/0MRl17h9QMdSRvU +T0Hy/cVCUwNs4hWhjA5k+eWKZe3LxOjnZEEA7S0Oi07cyOlKH7qNg8xA42KM3NPD +tEM8U6CvkdJ7Bctr1OOMUIdLq4485BDsPccoVc5J8MRf+4BFQodd8B8jekTv/rfn +/eXie3M12pjiy8ZryeBFod/3C/VLCQwMG4eMzga6+anuc66U6zteEnG0QyS4uckJ +iAlcxYqLK3Sm6WB/FlR8LmSPPAEl9xH5W8gSrAGZRg9w5tOVnOOsDWU3yfBxzi8X +ZnMRc7+22XOuzkQlQDDRM/r8L5aM6rGjLTRUpbv3JU11gf0+5yUAqrWD+KumgyGd +cxWnfEHRQZA7jV3eEXpoE2mKOiZ3zaA0gZRmG745+E+MS964jTOdEy3ZEITuSCOt +aPjiySebYSpxhuoqdA5sIgC/qLfigTEDQiY4LnrTxZp1uQGhcbzBKEAScLK6mFHj +MTnTFm9hChnD8UmjfBFpHNhvvXS6h+ZdpgLuG2XEv3DtLs8N/E7uh0zN38lupX5M +r9GC3EOrTXte/TWGQVlXU4j60J2FiUk38ORryyDMd3LS5bjTqaERkqd+uw7utuM7 +dTU8cohcMgM+vw6l3fNg8+I31Mpy9N6QLS26qP0b+uYKZpX5UG2H9j+ekrZ7ReBr +LB4s2VIDHBoc6qRbXTI7I6Sf/Ez9iQIcBBABAgAGBQJTF5i3AAoJECPNT7oMAX3y +AaoP/jSWlN++0Sms0WgN67JHDZhXpU+uiumaKS2VXXakIeAKu8kra6KIqmTadmm1 +zSJ83yhr6q3TjnCaOMLcSCEaCeizeMHeUbLPiM1zlcXH3jqpZxIPJ2lZTsySeAEA +QwT30NIjySlOX5Ba/ZknQ8iiqqkZM1PBxqYIcjN8ijOY59L4NQnTsdn0m6pAe1m1 +6zD3sGljVvJeQuvoyaqxnOEQhzfnYjziFIkTbRKh0bk2jq3GjpYKjm0H0yDzr1xc +G5R31DZb+n5tWDKDYUX+PtDh8ypgzobTBQ1JTl7e2qeu/EpbFccRqsu1S9kJyC3j +yYzpk2Bf8mfsfH6Z+FUR8AEKW67vBQQFRIV0H4WCBazI2k1/ibNoaLqKJNDh0j3p +89XAdlXdie8Cr+kd0XQJ/ExqaBPpTiVWGFeEVxo9cC18zFv8N8ZvOnEBwJZ77uai +KYAjNUEfE8W7RX0bZgkIS5gXcuFRgLDcHqWEhFTasSObmNx8rrbmkZUnyuctCFu3 +iYAAOvpBZNEXXnwU5S//G19gjfNlLQSBcCn6A4fJo1szPhC9VD9suf21FkZYZ2dG +T1U1CYmw46wsb6ZyG8hd56fD3VkMF6fs123NuCmKJwdv4dCAtKXeizm3KwuqfiIt +Pr+CZlF7fgBSvxSllErP3fRio6w6ueu/2nMdxq/+VqSSfi0jiQIcBBABAgAGBQJT +GxrFAAoJEGXrljbwLFcEA1wQALFhneSP944km15LMqr4AGOaStxSWv+Fr3NcDv/L +XOZ9olMHGZIrAV2yl6hW0vPOiQXJGM2+t1H5Q2gbktPt/F5LD/lR8cxMOCfDbVA5 +nUzi52mY7J6rv15AmJNzlxOrUsOxGIp2AuBFI+NLcmzW1vA4VN8oY22zePYSsAyA +NODpYLwzmLvWh/n6Gkb9Dcr5d5M6clPJlvyCjT3HOkmLCPBTv/I4lm004pLW+pep +wfmHi1XoXDXLChrBU0caV63+KdIKaSkZafGhhdOSeMT2ti6squ+9VBm6g207ZaU4 +6wzATdVfCJkhAPk8HMi/853vqXPhl06VFi3KYrL6tsSie0X6vNlMfkQ1obdh2KHV +tqSFhO+0pwjLQ6Ei5X0MIYk2M8XFUIV1RPmQ4RdvfbMuJpyXLBxTY2ItB70ZHvEm +XOTYLYAhAH+UvSODocIP24I/mdyPbiTxgpYVa8pMFw70aA/1zPWftZCYWe0l98im +cUW2YPknLl3bxOV+CI4g5XFW/84qxS1Ty228vIK7GmnZx2AMyaSA0w84d9wQnxJc +rNSS1M3uYvHLICEr4HWP+lTj8wFd3kd0URnB8Ybc7zsy/Rroy/KPKArhbCHb9O+w ++KuC5f1Bu4uZc/o2Zckp5zfKI7xtUbW914PB9hbo+TXkTBre9nZkSQjODL6wPLIa +nYFviQIcBBABAgAGBQJTH7siAAoJEPTXp5Fd6nib42oP/0RJLp8X945IPFd1AMoM +Q23cy74qBAvh+c+k2pFEPrU+W9nJ2w3Mqwn8ja9MDewUjSq9ZLZxlTz+M8idYpoN +46VtZLCxpaLXH3Uv8T++Vwdi143UMPipJqf50mWqqciDsl9LbQZR2XolfzM9WTVU +Vt9ynNVZG+ij4tbeobViZrifY07dfR8y0TZ2LF7mah5lnDAAwSVEUOg/YX7jIgxS +fP9oD5buD2SYH/4rZFzkN3fCZQiV4uwCMIJl+fDR/adBvOaZrUVnM661vmGcsgOq +qRUE+hSZ/ih8Jsox65UAfPHdx/SEptBFgoyIpdxR4NPxpgeHZbNnstJ1R/cyKmww +hMgF11WUJbm1RN1vDPwAZNAcSzDAZhnOmtOsPtiLXDMNm7dufgYWFFxjZUxo87+W +eHgWG8ACki+AuYJgjW0gXMghVdkVQJYcLxcbZBPcHu2eUJLI83QhVQxUg5IjdOGv +OS3SuMhtDYx04zEdGB3FSVRwfyIqImjEbyXnMAT0RDhFoWvrhAy/jGsrH4tO9hg5 +1AS4EJ2pwdYme7yCA0h2s1ZG+WHF4lTJ21fvx4H352Ah5tckpmmbpJbB+ZBz+uWv +rYmQP/W+06kP1axNmjSDcMID7rqoITn7emPJYLpc4vszoGxxl3yFbWM7IL8kLT2P +QC1FMP5L9SY95T3L9xciMnFTiEYEEBECAAYFAlMkhq8ACgkQi9gubzC5S1zAmwCg +gBsG5xTQsPG3Ro8GpItuIJBGmZsAoJMRnRC62mQKL700dHk49IFL7sH6iQEcBBAB +AgAGBQJUmgqLAAoJEF+OLmRrT7LQnV0H+gMxUdmn+eZUN+6fyAf1TMHifp3qvqdK +05sL2NIY4rz7GgYbb3L7wH45w+ztuE6pmdg4JwCGijp3V8quyICbvU94YTbu/n7E +3r5U9H4JXUuW99GtML6v0Jnmp7AthmsMVwTFoMj8fzszRTjh0LWxbMIP/BXbr91t +hf0A9L2OBFeHCXtpr8JnTK4lkDtwRw5PKZHQPUlP07R2Ki6pva96ePgtGnpnL8n9 +Zlwvg5mCSsQOQv8R7+7GcmGqSWOEcUB67GF4AVsGMqEj/9BRYsdjWozE7oq60FwG +rg+HEaTO7To3EKWI31pZU+u3WgGE7cH82/YgtCQdgKYzDAT9AQFADRCJAhwEEAEC +AAYFAlS3/EIACgkQni8RbMiXM6uvYBAAoDMezX0JkRWg7GlsHJyF9mneaUMmhLiJ ++yO8Jd9JkJcSsDvy56X0mszyqL3e/mcrSow71fGeAnJbKcTsdMX8T7JpWL26LApb +PxiO/wo1vGczwJ+bBMDQAGIQgY9OinCL8OEw1C1saM6rLIa3z9vySBmbQA30TXdG +kRBQETcHGZfDAe7BdzBgqBK+ZlCwoCUoiprP+kidiumZ88cQmmR0LFyB72GDeT2q +H0E1WOlKRhm0hwqB+Tc7E/wvX3YlufA65azQDjeSC7skDGljHxIl+ze2DSED8p99 +1bbjE5MESIySX7VdJHpp6mJ/Syh0wdiOKBn5Ff8+DxmymtzyBHGYzdYWs/UOVRIw +VSgjn+BJVpbRPqtlhpAC6PLSots7Mm6f194qJv9SDLfi/HDrKP62PG7p6zYM+zjD +j5FQBdBdMWK84/fTUT9iQsnCkmrSeaXzIlTRCBH1OUByeIbUaxcngZzGwSzsF4S3 +fOhYpnsaHW/uBzYRvgui4W2bzcoUui0QU87gGEXg5jnJtUhCtVgD3jvVov+pIQCO +eMMUTSTWzg7w/7uPY8B4+tXf95J7vSJcjYnjr+yM21DrIwjhKbzjmcvsk13FR7tZ +5f7R9vTuO0CJewIXuCJ0NLaahn/s+8V9RXoNa3TA+R+ZW/KFR/awXrq7SOJ2SbTV +JQk037siPOaJAhwEEAECAAYFAlS3/GQACgkQxfSDrd7oY4DKLA/+Kncf9t8FLms1 +fo1cflBb9UGgG6YceRx2+O3VZXiCqJSsHFj1Ywk+MyH44mD/JDM/YTKazT8mpnny +2/lDEzFdfbryZdA0p3pyrFp+8sx4pzKNPZxOubAOqefZ1k/SoTbTa35f3V+L926O +zIl2ZdU4WOysa13RhoRvUKjekWl94J0jECcBlkBiOI7uL64Rz4WG4VYhXJGV/LRz +OBot27Umh0sCmb3i24b9FmOu8tvAwf//zlh97ykEH1nLiVz+QU054nmbqVACp2W/ +02Z6cnfWqoLsQIg2Y+6oeCrjCldzlHcOjvE6VwXJpAde7mZfQCw66G9ndEs8Xoa7 +I4D06uGoewKVMJKU5AaFT4Wf69KXDI9YBRSuyZbww+rxESAB9HGfR3O8quDgsmV3 +BKsNRJT7rOPm+Z+UoHS12alJmVcuv+ioh1GpmeWoKiRgjlJOQcXy/TIvTMvGb8oF +ZN9MEMCZ09x3JoYTiXvx6phrxpW82DLXPqCD7mEHR3/u9898VRWMrSP1WKpNeeyC +6Wf8Urz1ySinr/wMbafrQu0Z0nycFFbUXLRO8MwJupt0/S0kA0c2WVzlZwYrbWZ4 +XGIxl6G9i+G1D5USOKbLC/bXnZlLERiQbD/85UHpt37s0T2K48lGUhSjCxclGyG7 +UpFf+mzEYbQcNMTkjr1RVURd/DtLeXeJAhwEEAECAAYFAlS3/vcACgkQMn7oMPR2 +HNgGtxAAiQy29MXY+Ljs3V4ZSE9kuhpV9jruyvNQD3y+vGa2fYXvwZbzqvDQIo/N +TRR+hZngz6Qo7i8NUYfzIp/GHI3nqoZll9idWdWjeg+ioD08XzmoTnTJwJAPTOVp +2WREzTyRc/FZCD8vW51iFV0xpWZA8a+/Foc1q/P9B/zvBx5UQfYCjMCcKpR3Xkuh +oRh6vdxSi9M+QuyATk1mXoniOQKhIvAzLTH2DSoAudI3V4E3GSc1NruGt35WDfvP +cwvcXk7iI4outPfyrG9mEIkiZDukB6MrKG3VKegD0fFIFouQ/eoodWKICY0S3QaP +HRL3rTOtCNtVEEaVDoaT6jDUvsfOpXreev1UriH24cawD4HmMaOs0p9e+FDTkvJx +OLErDBvODG/4Pfqai7BFaLrElnjQ6vI1e42fd+XQJlZPbDqjZkk3PD1DGNeWxXfe +VbQVK3O4G7z9Puj/YTcNyygVxwJPuZQrYX7mSjfetG7J/ZjoSSBKqJSzCyCb529o +sf2cS5JV/U5e+LQCrq+6i6fXWuUGsTu4ceJpskPahjCvcYVWMtbtBf7XhseJk97k +g/Qg01zLg8ff4np1nDCExSd8ak7DPEPOOnbedTNtmUpzaQJ1hAEsIHH23scuJMOZ +WdBHXB8j0l+w7Ssd/Up0+WR6KhYc+7D+U+mRlupXcvtXBgxzeK2JAhwEEAEIAAYF +AlS4CCsACgkQpLsVjWJqnRcPzg//R1PXrcHYVGO5tMkCpd2EdTEN2KsixMzbQAeW +C0LCvCgwuNZz5vXRrO8AIf9d5GvGx1xxr7w/aQHdA3fTwQH4VYz5Diya0OgXDWew +u0+P7AhHJbBTFxikPbX7Pe5J9ri2h9W2QGlNg9xZraF86yjdTOavrDYuc+Ly2OD1 +Ln4xGr1x0LbVLCS9Th8v7rzQMjVpZQghpVUBcZ0Jgk2NFTu4ODMpC40CM7iVX4Nc +gzPecBTGRO0UJkU9L1ta/DjTh+TWWSif0gQJB396zeX7P9d9vOXbfYwYwVgvNc5x +rt71agaL6RIRiSR0nVOUu5w7M+rtqw2Goc6rVWk97GaMBxq0hCZvunr2SA5IsGDM +rFlfLb93/a4up+Tcw+4SeKwoLyRIYMcenPRxjsyYni4bVG9W34uwahQe5It875hT +ZWdZob/0uHYpEWOH2w+qzmQUtTsquD+W78J3H3SiojLiPHlsRbAk4nr0SN+EX5R3 ++YW7jLRrVhrfvr+vYobH1664P7b1LX2Yi2u7ktZcWKVxLr6vZqNVXgdhgQmNyAOX +VhJurUc7EryV1tnt+EYRj0ruTdi0Je0fE6cNabrkKTnMUHTUbrpJDxJcq0q34SP+ +nnqaHmdtfDvuFVMlAynQrfD7nJOY/fm+l6FY9UvNJCvid71afBV9DdbPtivn0oP9 +L63+pSCJAhwEEwECAAYFAlS3/okACgkQxodfNUHO/eAexBAAl+zTx7FFagVHNlDe +tN31ErMvImw1oDVyoTAKCJbVK4YOT0AEL/GRM6nbQb2HAW26iWw0tehoKCJjw9uJ +y0m+1o/psE0nRl97sfZX5VCuFiAaRCyboEu49+KUSoCAQnkOc+r2vEPEvO0pNgZU +hUsRIwPRP67aDIfb61T9CSwZXmAkukDTuDq+sTGJ0fUpT59aM398O7BBqVnXZoTa +LHkXAd1sXGbWXNy7vNVXuHEAvebeQDzmAiiTp/RLxlUNrp4nB6bcAK5wn7kaAPJj +jREXeVk4lEGuUE1QpfdtvSAQ+8Qd47A700z4g7XFwHfXN0kX5JmeScVjrghkOCA5 +sjM9P6uxgCb54iSGnCrNJf57LddvSrI4UNAvFrYHVkek5VvC48xeUME/ldUT+eQv +1Xs2CJwtX9mxQg8hvuGDr03PP1LfKoxVvAZcJ4iJ+gxD+q7KHae127X0FCbzxrz5 +JQtTXep9UO5L9YskX9jKFH2+t+BrLEpxo6EQ2UsY5zmR3FFpvXu8Dryc28nI7MFl +uvNj+HPwNlvGt4/jLDxNUr1/qfny4nmH+F0GwJSbvvOysngGZ2R4XtyBOE7MvxEg +jsspXuLqm1TRyQCidUUOreramtPUUMQ8kbH66T75GAEnD862nlArSTZ76rbTGJ/4 +JN+Tb0gCoT3+8rsFFLIbjbi+SBCJAc8EEwECACkFAlKmggUCGwMFCQ1H67EHCwkI +BwMCAQYVCAIJCgsEFgIDAQIeAQIXgAAKCRDT5fVrbZINMHp/DH911etPzwZZetcw +8cKb7UY4UHFHQJ8rQIF91mY1PHpX/fh0VG+kXizlHEZxHpwXHXbJWUevYovymo8D +hbHB/VKV4kSQLMOR/jVtnbFRRhpkzzGSZhypd85NRODfxqqyFd5M6CPH8+vRikLs +QbJTV1OxLUhtlm4/3+W4O+h7pl8Q5pFw8HQRESPFrOeugU7z5nB6h3q0XdE+/2kD +Rf0G2eF+oLrvTBvi16u6ftGYc2Qqzbr4W5D3beWn+9eEvVJrxIb7ZR2iQGn19rV+ +92qB87bADM9yddmiAD0fP0ITDz7DOKxTAw7uMr0pfHaN27C1GCv7duqoHdM8BxR6 +oSxg/Jm0rsCE52uA1t5EbvFwfWJZ/wSiqv03BUlRTnawlQi0W/fFM3wgq2myWDa7 +aU+U+bRUBgt00qb5vtXDeBhS1wFLpKlyrlALsq5g6DStrjKT54pYQfaVnXUjxzxx +u20yI55QygiKhg7foFNgw6vTPwfo2OSid2XQDm3Hjjee4kSovrtn9jL5h27V0HcY +YED6vLNauQGdBFKmggUBDIDU53B+nBcpyH47TRbUWxBIxwSNqEaajzhZOugz+qNN +3tiyV3fTQ8y/fCRCfZZ2HJNxr8SaRbR9VMZJiztne/lKk9/SmthKOZ+7xaVejPrg +Cl1eoYeOP0oB6rY65S1avChuCJATNTgfGXP3hf/rkGAbmTs5PITcnpuBFwzAkKAK +TCMrznBtsGQYf4mj2j9nD1M9zNBwTsGYZiSQs0BdvDuiYoE4vhnrD2xdOjP1SdDQ +QH2zhO8BscYpf3LY8RCNk37CTNHcNq9YHuqXy8dkhGaykCwMAm8NPWh+w227wwHz +AlzG9lqhnuP3BQtimdo1jH3HESGBsH2jWYFxix0OPfHPmOuC2r9yl2AYLpuD5rAN +z/KVDWY2CUp9jw/2EUiEgA1mKWeYCWTkZKhZyU//r2b67fgoqgdThhzcjWk81wvo +3KLRuHyYep71Z50p+h3tjjIzVLbR9dpLi+ssiUqDFuwOlaJauTSW1XTe7ILt6oN7 +efPMZb/YYtMePnGwDb4fAa0+ibmabOO9Xk8U2lLtr3QlABEBAAGJAbUEGAECAA8F +AlKmggUCGwwFCQ1H67EACgkQ0+X1a22SDTARJwx/ZCMNabddrAnE0DymqrGsV5MS +j4YRLOdVFNR6mutQV3UYfDfepoC+ouLFn7Hxyv7UaP98l3l6IhUl9EthteULyy7w +lleeB9fRWG4xxShv8VOKR+lyhiRHOuJSwkQHf86aOUuMaCdCbkbP1NXWK3IXdvOg +eRHyy9YQoorM2ggQ8ctTfLtupKQ6uOdjdtl91VGHrXxduNXbw0y6hmxXwTik65Cj +L7ezkiOYh/+aRKIUTdUnB1o96bbdSxdq0Vv96gL8CGLSIJ3/yKgXCL6gdPY+e30e +vNUXoTyAFU7e8qjpQmANOv1C3bs1zp4cvQ7mPnSKez2hv/cOg4Lc/kDTzOGX7Djr +rIYS/n4Sz+6xQCz/ieDiSwjcNMsr1iCPvSXmgG4wVh3dvkoZV8AiUZzmbAg4gbjV +gsjNlOsa465PKaPAJ0L1xRknpHYK/9XHSG1nSGoN3JoM7Qij04b9bazZPvXrS1j2 +JzgzAEIV6bPAUQsgEggc1j+f/CybFAaQjc6Pzomk5VWBHmVdZH4GsZwGORITKJkC +DQRf7mYNARAAz2vrsO3Cz8vYpaXvc5tN9uloHBpeMl7Fb5A5U4XB36ux3JE03mxI +WgpVaCtKgwPAwaOprywMBee3jJh2xBIuv3cy1JSB/zCl12erUEQhSqk8wc4SWou/ +h9ecl5L0b3255lbayeTWJaaz2EjVzezbiROqeHTXkd8Agrjbr6IzcdycOZiVK8SL +jdpCN8A9VzqjD7FLsQ+i4MN9sE+V7QjUASnTEPBgvVhrEX10xQTagoyF2230XlcY +SKv2rLpgk7J2LzjFWrNZ/m2AriMMg1jQGKijYMHV1f5PQ/DSye/9QTUPLwHziRZe +k7A3pZGTjv4bq1Tywc8d0VmvE56IfVIsn1cYhYq4mBm2IeWTO+IcxVjAS2ufN8RU +u8MnFnFHohzKVB6Q7Cg4HhiUgmNn6xnRE59NxuTd30OcTDxQ0SNgJjSRfMMq8nl0 +upQCDH5ksrVSCUPB95GLeO2WtSgMOBsefeZcQU3y0QyxRkBX1sB1H84u9vF25FZH +HzMJmd+PhWW+V8n00wnr8zpUdvmBzIGz3C91Y0DjJxewmfYvgoBD80cSF9SJQ5Hw +vk1M/125sfUBN1rBvh08ON3mMvfxds4deT8Gtc8N74ggWYRGgJUkYvTEc8Ho0FGW +kg/VTNeRTEY7tIzVm2XojWMvdK1733sf1b3mEV3NTyqYuDnnxjoDa0cAEQEAAbQf +RGFtaWVuIE1pbGxlciA8ZGptQG1pbmRyb3Qub3JnPokCTgQTAQgAOBYhBHFouYOB +Wl7vWaSt/So/QU5zYGC6BQJf7mYNAhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheA +AAoJECo/QU5zYGC6kI4P/AxEYU8XTuZHYzAim7sHRr+Z1HnknrgN9mGL3HuCy8H8 +cdOZkQLnHSOmYjGfOKRNTzWibr36Cd4ERCXP+blDCtkrFw1QLoLRICZ5nJCcFSr5 +CanrU87wUwCQ0xfkkPl8iF8j1dorIDZOetAKumn87wKYnNphGQifPZF5GS0NS+Xp +7vmg+R+abTTCSTnxFNPwiQJwRm/lXO+A4bCHcuPL/X1vfVEYOARS+n3l29gpnHUo +roiWKC/F+HRvr6o4dIAml+jMq6xBMB6j9yYsyzNrq96GMxXDLvPCUkEad96+gR2v +RJJvFMUMa9tzc4C9n/Ks8t5s7um63l3eSYlHuVL6adI9SlVLbzyudBr7P+mU3r0z +xvYozTzPALwgohs4bYiWqdtE9y+qLsJrg5zM1g5gFJWAFWNhXkfB10NeoYN0L8Iy +RZMaBq4154fg99eaQBETzh1qoyAE1wZ5DFzzGMn0Z5gqyYd6pTxYol+6UIFvkuIb +hvzo7AnEQb9CMzCceJcPaSDoWJn8MXibgcR8zQ+bJL9BoOwevTuPBRRg4dW6IOBD +EqBjzZysSI7ET36R99WsBq0kxtPjmrbo5G66DkrwDBps7sggRg2Y23tgmrOssDVs +zN+erC+80XClDTBz8myB3y6d4VU+dWG4n0ZDGJE+w6YNZN/2pCKESlgU8e5K5qUt +iQHDBBABCAAdFiEEWcIRjtIG2SfmZ+vj0+X1a22SDTAFAl/uZjAACgkQ0+X1a22S +DTC/XwyAkFkZcqk56SuA4a4Q1PZydNNkQMKMJME2Kt5L8GB07jQPiTUoCDCEKW7v +SV5Vxl94HLQs0Wt4G+UhEmI74ZzKU0FZfF+Smnw9PQ/chVdXVAeekeBxQgDP++Mp +Lur34YveVeQkIBlQ8fbxrvd3RVI6LJ8DSxTUZ+MT34DgTs6+ryJkyA62mcSy5QL2 +ZMH82uZ/1KRN6P2YOUV7UmvWPta5kZ+ocfSoTcYCx/Ms4XOx6g6DbfDZ5AkRfY7c +qUXwJEA5bEooZXxMIVX3cN6O8CVjhl0lzNyeppoCmsuHBg1/YErsLbyphKzIuY0E +8Ng5nSKKefZA3+2OlwvRNN4FPVXcf618s+LkMPdedRxuxOj5Lg0m8I33t//4U8xJ +CjgItN27+C8C+3uAb+oG0JP592z+zweVVjbqgfKKQ0XWJBV8YrdQ7CC65WTBkSKK +Fk9uVDjfftrsWkkyWttGk1As9yAvPbupZ2swoMEcQLAhyaTLmBYrgIW6g6OMhCHv +k4BIGUZ0EQmzi11G5Bu7OEKN2/KIlLkCDQRf7mYNARAA2iZs8bBisxr5aQE1gTVX +wvgtnIOjQ6aDOh9bminaAQtg+ntvNFi6HUzSvB0XTjAw8sH2Bz38CkczuDfd4YfZ +OzAJRJTG58NAubAMDjJ3yHrfP/uXn+KVEUdDYv+wTbbA4cPztMLhNxNJwgPKjVLj +9FGkdYLCe+xTD3POiwMOtazpW4udynNCcQ1P+DIPzHuOisJ1AkYqDrShclEUcitO +44/+8JzhiKH9HxwomOLku7lwjF1nEyvVC6zJXlxqXImbeFFRbKLlItcbrVD1SJWB +F6EstFgSCFcjG0+KN86LRABfp9804OjHiSBiDOTT0W4W5icDnKOzj+ZlsdSdSIcw +AnLz7nsgobgjUaRPos013ddcMDFSIS+SNtAE/si4JHdLGUVCKH5RgHyWMjK2MQGx +3LCaHPVT/Ei0uLdSbKtpLpSsYsNokliw84Czd6sUjjR/IhHjJ7ryD4eJSyXt7vuZ +6e9twyJumcPJvWw3feFjGqGKmhwpw6viKkYEqDSkS7IJRqdS8My1PMm38Ew61WaS +YYehueH1yO//Wtlo2hYfFh4N4Hcu9E6NeJBNEc20gz6tTkkybuIuCsZdRr9MEZgc +EEwH+Mf386Lp+/VqfpmykUaT4XATkzhSHiFFx3y1jD/gClN4zATmS9s21df8Nooc +qWTJjOjLmKn9nevp4Jrf5NEAEQEAAYkCNgQYAQgAIBYhBHFouYOBWl7vWaSt/So/ +QU5zYGC6BQJf7mYNAhsMAAoJECo/QU5zYGC6a/oQAKjogHiQqRKLsaRj5yipy52i +s8vXjsDdhv29GTFV/0aLrPcFx5NkHPf5mQsN/k1fYfwHaq2uwGuL/YB6Ra6eZBOP +/xd0i7JpULrSPTDBWEgqF5UzuabQJY8oYK8RdA5RS6Tc4Q38L9f9RbHYPGvRgDeb +ZngMVOUQOD0s4EkAYwofOOE/a5S+Ty+12o7t+BTFucjgF/RiogO38HyeUepKiJFU +vuSRcluIvHaooLvDMvfmZT/nZhZsqAa3nT780Og9aopI36tmUuZSR1fJ5jYgj5dU +3JA11HWaiwbZiVXEnNDh/WPrzM8k+KGf/dxymLuCbROc+wwjhqiWGn7cKJcVLHzS +CO0rPVaJvrliTui0ytRLQ5F3A8+nsq84lbHXDZWnYMcGVF0iluQksbQkc9VPunRI +VA3UfPt7O/rK8LkZlJttKPZL042IC7vrPFZIHDbYl5OEQwohO55v/0MgtaDzc/Pk +7mnVkcLyvaL1yl8FWe+fKY4Jk8SUCygwxCCjtCv7TWYaNGepelQonwRWxCyf+xUa +nErOxgAHhLfgrzFW31qU2nrd2Ubbtj6jXwtJNMeP1ZCBL5BgcUpypYUh9DyxsjdS +mjhmFk4UXBCppf5Po/1qSpr5KPmwuWTd0KGCEnosU9RSpJtE78phxqkKaB8A3HmR +ePJgyS4h2BL0NgQRIRVW +=OOF9 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/openssh.spec b/openssh.spec new file mode 100644 index 0000000..72ddb17 --- /dev/null +++ b/openssh.spec @@ -0,0 +1,571 @@ +# +# spec file for package openssh +# +# Copyright (c) 2020 SUSE LLC +# +# All modifications and additions to the file contributed by third parties +# remain the property of their copyright owners, unless otherwise agreed +# upon. The license for this file, and modifications and additions to the +# file, is the same license as for the pristine package itself (unless the +# license for the pristine package is not an Open Source License, in which +# case the license is the MIT License). An "Open Source License" is a +# license that conforms to the Open Source Definition (Version 1.9) +# published by the Open Source Initiative. + +# Please submit bugfixes or comments via https://bugs.opensuse.org/ +# + +%define sandbox_seccomp 0 +%ifnarch ppc +%define sandbox_seccomp 1 +%endif +%define _fwdir %{_sysconfdir}/sysconfig/SuSEfirewall2.d +%define _fwdefdir %{_fwdir}/services +%define _appdefdir %( grep "configdirspec=" $( which xmkmf ) | sed -r 's,^[^=]+=.*-I(.*)/config.*$,\\1/app-defaults,' ) +%define CHECKSUM_SUFFIX .hmac +%define CHECKSUM_HMAC_KEY "HMAC_KEY:OpenSSH-FIPS@SLE" +%bcond_without ldap + +%if 0%{?suse_version} >= 1550 +%bcond_without wtmpdb +%else +%bcond_with wtmpdb +%endif + +#Compat macro for new _fillupdir macro introduced in Nov 2017 +%if ! %{defined _fillupdir} + %define _fillupdir %{_localstatedir}/adm/fillup-templates +%endif +Name: openssh +Version: 9.6p1 +Release: 0 +Summary: Secure Shell Client and Server (Remote Login Program) +License: BSD-2-Clause AND MIT +Group: Productivity/Networking/SSH +URL: https://www.openssh.com/ +Source0: https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz +Source1: https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc +Source2: sshd.pamd +Source3: README.SUSE +Source4: README.kerberos +Source5: ssh.reg +Source6: ssh-askpass +Source7: sshd.fw +Source8: sysconfig.ssh +Source9: sshd-gen-keys-start +Source10: sshd.service +Source11: README.FIPS +Source12: cavs_driver-ssh.pl +Source13: https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/RELEASE_KEY.asc#/openssh.keyring +Source14: sysusers-sshd.conf +Source15: sshd-sle.pamd +Patch1: openssh-7.7p1-X11_trusted_forwarding.patch +Patch3: openssh-7.7p1-enable_PAM_by_default.patch +Patch4: openssh-7.7p1-eal3.patch +Patch6: openssh-7.7p1-send_locale.patch +Patch7: openssh-7.7p1-hostname_changes_when_forwarding_X.patch +Patch8: openssh-7.7p1-remove_xauth_cookies_on_exit.patch +Patch9: openssh-7.7p1-pts_names_formatting.patch +Patch10: openssh-7.7p1-pam_check_locks.patch +# https://bugzilla.mindrot.org/show_bug.cgi?id=2752 +Patch14: openssh-7.7p1-seccomp_stat.patch +# https://bugzilla.mindrot.org/show_bug.cgi?id=2752 +Patch15: openssh-7.7p1-seccomp_ipc_flock.patch +# https://bugzilla.mindrot.org/show_bug.cgi?id=2752 +# Local FIPS patchset +Patch17: openssh-7.7p1-fips.patch +# Local cavs patchset +Patch18: openssh-7.7p1-cavstest-ctr.patch +# Local cavs patchset +Patch19: openssh-7.7p1-cavstest-kdf.patch +# Local FIPS patchset +Patch20: openssh-7.7p1-fips_checks.patch +# https://bugzilla.mindrot.org/show_bug.cgi?id=2641 +Patch22: openssh-7.7p1-systemd-notify.patch +Patch23: openssh-8.0p1-gssapi-keyex.patch +# https://bugzilla.mindrot.org/show_bug.cgi?id=1402 +Patch24: openssh-8.1p1-audit.patch +# Local patch to disable runtime abi SSL checks, quite pointless for us +Patch26: openssh-7.7p1-disable_openssl_abi_check.patch +# https://bugzilla.mindrot.org/show_bug.cgi?id=2641 +Patch27: openssh-7.7p1-no_fork-no_pid_file.patch +Patch28: openssh-7.7p1-host_ident.patch +# https://bugzilla.mindrot.org/show_bug.cgi?id=1844 +Patch29: openssh-7.7p1-sftp_force_permissions.patch +# https://bugzilla.mindrot.org/show_bug.cgi?id=2143 +Patch30: openssh-7.7p1-X_forward_with_disabled_ipv6.patch +Patch31: openssh-7.7p1-ldap.patch +# https://bugzilla.mindrot.org/show_bug.cgi?id=2213 +Patch32: openssh-7.7p1-IPv6_X_forwarding.patch +Patch33: openssh-7.7p1-sftp_print_diagnostic_messages.patch +Patch34: openssh-7.9p1-keygen-preserve-perms.patch +Patch35: openssh-7.9p1-revert-new-qos-defaults.patch +Patch36: openssh-8.1p1-seccomp-clock_nanosleep.patch +Patch37: openssh-8.1p1-seccomp-clock_nanosleep_time64.patch +Patch38: openssh-8.1p1-seccomp-clock_gettime64.patch +Patch39: openssh-8.1p1-use-openssl-kdf.patch +Patch40: openssh-8.1p1-ed25519-use-openssl-rng.patch +Patch41: openssh-fips-ensure-approved-moduli.patch +Patch42: openssh-link-with-sk.patch +Patch43: openssh-reenable-dh-group14-sha1-default.patch +Patch45: openssh-8.4p1-ssh_config_d.patch +Patch46: openssh-whitelist-syscalls.patch +Patch47: openssh-8.4p1-vendordir.patch +Patch48: openssh-8.4p1-pam_motd.patch +Patch49: openssh-do-not-send-empty-message.patch +Patch50: openssh-openssl-3.patch +Patch51: wtmpdb.patch +Patch52: logind_set_tty.patch +Patch100: fix-missing-lz.patch +Patch102: openssh-7.8p1-role-mls.patch +Patch103: openssh-6.6p1-privsep-selinux.patch +Patch104: openssh-6.6p1-keycat.patch +Patch105: openssh-6.6.1p1-selinux-contexts.patch +Patch106: openssh-7.6p1-cleanup-selinux.patch +BuildRequires: audit-devel +BuildRequires: automake +BuildRequires: groff +BuildRequires: libedit-devel +BuildRequires: libselinux-devel +%if %{with ldap} +BuildRequires: openldap2-devel +%endif +BuildRequires: openssl-devel +BuildRequires: pam-devel +BuildRequires: pkgconfig +BuildRequires: zlib-devel +BuildRequires: pkgconfig(libfido2) >= 1.2.0 +BuildRequires: pkgconfig(libsystemd) +BuildRequires: sysuser-shadow +BuildRequires: sysuser-tools +Requires: %{name}-clients = %{version}-%{release} +Requires: %{name}-server = %{version}-%{release} +%if 0%{?suse_version} >= 1550 +BuildRequires: pkgconfig(krb5) +%else +BuildRequires: krb5-mini-devel +%endif +%if %{with wtmpdb} +BuildRequires: pkgconfig(libwtmpdb) +%endif +Requires(pre): findutils +Requires(pre): grep + +%description +SSH (Secure Shell) is a program for logging into and executing commands +on a remote machine. It replaces rsh (rlogin and rsh) and +provides secure encrypted communication between two untrusted +hosts over an insecure network. + +xorg-x11 (X Window System) connections and arbitrary TCP/IP ports can +also be forwarded over the secure channel. + +This is a dummy package that pulls in both the client and server +components. + +%package common +Summary: SSH (Secure Shell) common files +Group: Productivity/Networking/SSH +Conflicts: nonfreessh +Conflicts: %{name}-fips < %{version}-%{release} +Conflicts: %{name}-fips > %{version}-%{release} + +%description common +SSH (Secure Shell) is a program for logging into and executing commands +on a remote machine. It replaces rsh (rlogin and rsh) and +provides secure encrypted communication between two untrusted +hosts over an insecure network. + +xorg-x11 (X Window System) connections and arbitrary TCP/IP ports can +also be forwarded over the secure channel. + +This package contains common files for the Secure Shell server and +clients. + +%package server +Summary: SSH (Secure Shell) server +Group: Productivity/Networking/SSH +Requires: %{name}-common = %{version}-%{release} +Recommends: audit +Requires(pre): findutils +Requires(pre): grep +Requires(post): %fillup_prereq +Requires(post): permissions +Provides: openssh:%{_sbindir}/sshd +%sysusers_requires + +%description server +SSH (Secure Shell) is a program for logging into and executing commands +on a remote machine. It replaces rsh (rlogin and rsh) and +provides secure encrypted communication between two untrusted +hosts over an insecure network. + +xorg-x11 (X Window System) connections and arbitrary TCP/IP ports can +also be forwarded over the secure channel. + +This package contains the Secure Shell daemon, which allows clients to +securely connect to your server. + +%package server-config-rootlogin +Summary: Config to permit root logins to sshd +Group: Productivity/Networking/SSH +Requires: %{name}-server = %{version}-%{release} + +%description server-config-rootlogin +The openssh-server package by default disallows password based +root logins. This package provides a config that does. It's useful +to temporarily have a password based login to be able to use +ssh-copy-id(1). + +%package clients +Summary: SSH (Secure Shell) client applications +Group: Productivity/Networking/SSH +Requires: %{name}-common = %{version}-%{release} +Provides: openssh:%{_bindir}/ssh + +%description clients +SSH (Secure Shell) is a program for logging into and executing commands +on a remote machine. It replaces rsh (rlogin and rsh) and +provides secure encrypted communication between two untrusted +hosts over an insecure network. + +xorg-x11 (X Window System) connections and arbitrary TCP/IP ports can +also be forwarded over the secure channel. + +This package contains clients for making secure connections to Secure +Shell servers. + +%if %{with ldap} +%package helpers +Summary: OpenSSH AuthorizedKeysCommand helpers +Group: Productivity/Networking/SSH +Requires: %{name}-common = %{version}-%{release} + +%description helpers +SSH (Secure Shell) is a program for logging into and executing commands +on a remote machine. It replaces rsh (rlogin and rsh) and +provides secure encrypted communication between two untrusted +hosts over an insecure network. + +xorg-x11 (X Window System) connections and arbitrary TCP/IP ports can +also be forwarded over the secure channel. + +This package contains helper applications for OpenSSH which retrieve +keys from various sources. +%endif + +%package fips +Summary: OpenSSH FIPS crypto module HMACs +Group: Productivity/Networking/SSH +Requires: %{name}-common = %{version}-%{release} +Conflicts: %{name}-common < %{version}-%{release} +Conflicts: %{name}-common > %{version}-%{release} +Obsoletes: %{name}-hmac + +%description fips +This package contains hashes that, together with the main openssh packages, +form the FIPS certifiable crypto module. + +%package cavs +Summary: OpenSSH FIPS crypto module CAVS tests +Group: Productivity/Networking/SSH +Requires: %{name}-common = %{version}-%{release} + +%description cavs +This package contains the FIPS-140 CAVS (Cryptographic Algorithm +Validation Program/Suite) related tests of OpenSSH. + +%prep +%setup -q +cp %{SOURCE3} %{SOURCE4} %{SOURCE11} . + +%autopatch -p1 + +# set libexec dir in the LDAP patch +sed -i.libexec 's,@LIBEXECDIR@,%{_libexecdir}/ssh,' \ + $( grep -Rl @LIBEXECDIR@ \ + $( grep "^+++" %{PATCH31} | sed -r 's@^.+/([^/\t ]+).*$@\1@' ) + ) + +%build +autoreconf -fiv +%ifarch s390 s390x %{sparc} +PIEFLAGS="-fPIE" +%else +PIEFLAGS="-fpie" +%endif +CFLAGS="%{optflags} $PIEFLAGS -fstack-protector" +CXXFLAGS="%{optflags} $PIEFLAGS -fstack-protector" +LDFLAGS="-pie -Wl,--as-needed" +#CPPFLAGS="%%{optflags} -DUSE_INTERNAL_B64" +export LDFLAGS CFLAGS CXXFLAGS CPPFLAGS +%configure \ + --sysconfdir=%{_sysconfdir}/ssh \ + --libexecdir=%{_libexecdir}/ssh \ + --with-selinux \ + --with-pid-dir=/run \ + --with-systemd \ + --with-ssl-engine \ + --with-pam \ + --with-kerberos5=%{_prefix} \ + --with-privsep-path=%{_localstatedir}/lib/empty \ +%if %{sandbox_seccomp} + --with-sandbox=seccomp_filter \ +%else + --with-sandbox=rlimit \ +%endif + --disable-strip \ + --with-audit=linux \ +%if %{with ldap} + --with-ldap \ +%endif + --with-xauth=%{_bindir}/xauth \ + --with-libedit \ +%if %{with wtmpdb} + --with-wtmpdb \ +%endif +%if 0%{?suse_version} >= 1550 + --disable-lastlog \ + --with-logind \ +%endif + --with-security-key-builtin \ + --target=%{_target_cpu}-suse-linux + +%make_build +%sysusers_generate_pre %{SOURCE14} sshd sshd.conf + +%install +%make_install +%if %{defined _distconfdir} +install -d -m 755 %{buildroot}%{_pam_vendordir} +install -m 644 %{SOURCE2} %{buildroot}%{_pam_vendordir}/sshd +%else +# SLE has no distconfdir, so use sle PAM config +install -d -m 755 %{buildroot}%{_sysconfdir}/pam.d +install -m 644 %{SOURCE15} %{buildroot}%{_sysconfdir}/pam.d/sshd +%endif +install -d -m 755 %{buildroot}%{_localstatedir}/lib/sshd +install -d -m 755 %{buildroot}%{_sysconfdir}/ssh/ssh_config.d +install -d -m 755 %{buildroot}%{_sysconfdir}/ssh/sshd_config.d +%if 0%{?suse_version} < 1600 +install -d -m 755 %{buildroot}%{_sysconfdir}/slp.reg.d/ +install -m 644 %{SOURCE5} %{buildroot}%{_sysconfdir}/slp.reg.d/ +%endif +install -D -m 0644 %{SOURCE10} %{buildroot}%{_unitdir}/sshd.service +ln -s service %{buildroot}%{_sbindir}/rcsshd +install -d -m 755 %{buildroot}%{_fillupdir} +install -m 644 %{SOURCE8} %{buildroot}%{_fillupdir} +# install shell script to automate the process of adding your public key to a remote machine +install -m 755 contrib/ssh-copy-id %{buildroot}%{_bindir} +install -m 644 contrib/ssh-copy-id.1 %{buildroot}%{_mandir}/man1 +sed -i -e s@%{_prefix}/libexec@%{_libexecdir}@g %{buildroot}%{_sysconfdir}/ssh/sshd_config + +echo "PermitRootLogin yes" > %{buildroot}%{_sysconfdir}/ssh/sshd_config.d/50-permit-root-login.conf + +# Move /etc to /usr/etc/ssh +%if %{defined _distconfdir} +mkdir -p %{buildroot}%{_distconfdir}/ssh/ssh{,d}_config.d +mv %{buildroot}%{_sysconfdir}/ssh/moduli %{buildroot}%{_distconfdir}/ssh/ +mv %{buildroot}%{_sysconfdir}/ssh/ssh_config %{buildroot}%{_distconfdir}/ssh/ +mv %{buildroot}%{_sysconfdir}/ssh/sshd_config %{buildroot}%{_distconfdir}/ssh/ +mv %{buildroot}%{_sysconfdir}/ssh/sshd_config.d/50-permit-root-login.conf %{buildroot}%{_distconfdir}/ssh/sshd_config.d/50-permit-root-login.conf +%endif + +%if 0%{?suse_version} < 1550 +# install firewall definitions +mkdir -p %{buildroot}%{_fwdefdir} +install -m 644 %{SOURCE7} %{buildroot}%{_fwdefdir}/sshd +%endif + +# askpass wrapper +sed -e "s,@LIBEXECDIR@,%{_libexecdir},g" < %{SOURCE6} > %{buildroot}%{_libexecdir}/ssh/ssh-askpass +sed -e "s,@LIBEXECDIR@,%{_libexecdir},g" < %{SOURCE12} > %{buildroot}%{_libexecdir}/ssh/cavs_driver-ssh.pl +rm -f %{buildroot}%{_datadir}/Ssh.bin +# sshd keys generator wrapper +install -D -m 0755 %{SOURCE9} %{buildroot}%{_sbindir}/sshd-gen-keys-start + +# Install sysusers.d config for sshd user +mkdir -p %{buildroot}%{_sysusersdir} +install -m 644 %{SOURCE14} %{buildroot}%{_sysusersdir}/sshd.conf + +rm %{buildroot}/usr/libexec/ssh/ssh-keycat +#rm -r %{buildroot}/usr/lib/debug/.build-id + +# the hmac hashes - taken from openssl +# +# re-define the __os_install_post macro: the macro strips +# the binaries and thereby invalidates any hashes created earlier. +# +# this shows up earlier because otherwise the %%expand of +# the macro is too late. +%{expand:%%global __os_install_post {%__os_install_post +for b in \ + %{_bindir}/ssh \ + %{_sbindir}/sshd \ + %{_libexecdir}/ssh/sftp-server \ + ; do + openssl dgst -sha256 -binary -hmac %{CHECKSUM_HMAC_KEY} < %{buildroot}$b > %{buildroot}$b%{CHECKSUM_SUFFIX} +done + +}} + +%pre server -f sshd.pre +%if %{defined _distconfdir} +# Prepare for migration to /usr/etc. +test -f /etc/pam.d/sshd.rpmsave && mv -v /etc/pam.d/sshd.rpmsave /etc/pam.d/sshd.rpmsave.old ||: +test -f /etc/ssh/sshd_config.rpmsave && mv -v /etc/ssh/sshd_config.rpmsave /etc/ssh/sshd_config.rpmsave.old ||: +%endif + +%service_add_pre sshd.service + +%post server +%{fillup_only -n ssh} +%service_add_post sshd.service + +%preun server +%service_del_preun sshd.service + +%postun server +# The openssh-fips trigger script for openssh will normally restart sshd once +# it gets installed, so only restart the service here if openssh-fips is not +# present. +if rpm -q openssh-fips >/dev/null 2>/dev/null; then +%service_del_postun_without_restart sshd.service +else +%service_del_postun sshd.service +fi + +%if %{defined _distconfdir} +%posttrans server +# Migration to /usr/etc. +test -f /etc/pam.d/sshd.rpmsave && mv -v /etc/pam.d/sshd.rpmsave /etc/pam.d/sshd ||: +test -f /etc/ssh/sshd_config.rpmsave && mv -v /etc/ssh/sshd_config.rpmsave /etc/ssh/sshd_config ||: +%endif + +%if %{defined _distconfdir} +%pre clients +# Prepare for migration to /usr/etc. +test -f /etc/ssh/ssh_config.rpmsave && mv -v /etc/ssh/ssh_config.rpmsave /etc/ssh/ssh_config.rpmsave.old ||: +%endif + +%if %{defined _distconfdir} +%posttrans clients +# Migration to /usr/etc. +test -f /etc/ssh/ssh_config.rpmsave && mv -v /etc/ssh/ssh_config.rpmsave /etc/ssh/ssh_config ||: +%endif + +%triggerin -n openssh-fips -- %{name} = %{version}-%{release} +%restart_on_update sshd + +%files +# openssh is an empty package that depends on -clients and -server, +# resulting in a clean upgrade path from prior to the split even when +# recommends are disabled. + +%files common +%license LICENCE +%doc README.SUSE README.kerberos README.FIPS ChangeLog OVERVIEW README TODO CREDITS +%attr(0755,root,root) %dir %{_sysconfdir}/ssh +%if %{defined _distconfdir} +%attr(0755,root,root) %dir %{_distconfdir}/ssh +%attr(0600,root,root) %{_distconfdir}/ssh/moduli +%attr(0755,root,root) %dir %{_distconfdir}/ssh/ssh_config.d +%else +%attr(0755,root,root) %dir %{_sysconfdir}/ssh +%attr(0600,root,root) %{_sysconfdir}/ssh/moduli +%attr(0755,root,root) %dir %{_sysconfdir}/ssh/ssh_config.d +%endif +%attr(0444,root,root) %{_mandir}/man1/ssh-keygen.1* +%attr(0444,root,root) %{_mandir}/man5/moduli.5* +%attr(0755,root,root) %{_bindir}/ssh-keygen* + +%files server +%attr(0755,root,root) %{_sbindir}/sshd +%attr(0755,root,root) %{_sbindir}/rcsshd +%attr(0755,root,root) %{_sbindir}/sshd-gen-keys-start +%dir %attr(0755,root,root) %{_localstatedir}/lib/sshd +%dir %attr(0755,root,root) %{_sysconfdir}/ssh/sshd_config.d +%if %{defined _distconfdir} +%attr(0755,root,root) %dir %{_distconfdir}/ssh +%attr(0755,root,root) %dir %{_distconfdir}/ssh/sshd_config.d +%attr(0640,root,root) %{_distconfdir}/ssh/sshd_config +%attr(0644,root,root) %{_pam_vendordir}/sshd +%else +%attr(0640,root,root) %{_sysconfdir}/ssh/sshd_config +%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/pam.d/sshd +%endif +%attr(0644,root,root) %{_unitdir}/sshd.service +%attr(0644,root,root) %{_sysusersdir}/sshd.conf +%attr(0444,root,root) %{_mandir}/man5/sshd_config* +%attr(0444,root,root) %{_mandir}/man8/sftp-server.8* +%attr(0444,root,root) %{_mandir}/man8/sshd.8* +%attr(0755,root,root) %{_libexecdir}/ssh/sftp-server +%if 0%{?suse_version} < 1600 +%dir %{_sysconfdir}/slp.reg.d +%config %{_sysconfdir}/slp.reg.d/ssh.reg +%endif +%{_fillupdir}/sysconfig.ssh +%if 0%{?suse_version} < 1550 +%dir %{_fwdir} +%dir %{_fwdefdir} +%config %{_fwdefdir}/sshd +%endif + +%files server-config-rootlogin +%if %{defined _distconfdir} +%{_distconfdir}/ssh/sshd_config.d/50-permit-root-login.conf +%else +%{_sysconfdir}/ssh/sshd_config.d/50-permit-root-login.conf +%endif + +%files clients +%dir %attr(0755,root,root) %{_sysconfdir}/ssh/ssh_config.d +%if %{defined _distconfdir} +%attr(0644,root,root) %{_distconfdir}/ssh/ssh_config +%else +%attr(0644,root,root) %{_sysconfdir}/ssh/ssh_config +%endif +%attr(0755,root,root) %{_bindir}/ssh +%attr(0755,root,root) %{_bindir}/scp* +%attr(0755,root,root) %{_bindir}/sftp* +%attr(0755,root,root) %{_bindir}/ssh-add* +%attr(0755,root,root) %{_bindir}/ssh-agent* +%attr(0755,root,root) %{_bindir}/ssh-copy-id* +%attr(0755,root,root) %{_bindir}/ssh-keyscan* +%attr(0755,root,root) %dir %{_libexecdir}/ssh +%attr(0755,root,root) %{_libexecdir}/ssh/ssh-askpass* +%attr(0755,root,root) %{_libexecdir}/ssh/ssh-keysign* +%attr(0755,root,root) %{_libexecdir}/ssh/ssh-pkcs11-helper* +%attr(0755,root,root) %{_libexecdir}/ssh/ssh-sk-helper* +%attr(0444,root,root) %{_mandir}/man1/scp.1* +%attr(0444,root,root) %{_mandir}/man1/sftp.1* +%attr(0444,root,root) %{_mandir}/man1/ssh-add.1* +%attr(0444,root,root) %{_mandir}/man1/ssh-agent.1* +%attr(0444,root,root) %{_mandir}/man1/ssh-keyscan.1* +%attr(0444,root,root) %{_mandir}/man1/ssh.1* +%attr(0444,root,root) %{_mandir}/man1/ssh-copy-id.1* +%attr(0444,root,root) %{_mandir}/man5/ssh_config.5* +%attr(0444,root,root) %{_mandir}/man8/ssh-pkcs11-helper.8* +%attr(0444,root,root) %{_mandir}/man8/ssh-sk-helper.8* +%attr(0444,root,root) %{_mandir}/man8/ssh-keysign.8* + +%if %{with ldap} +%files helpers +%attr(0755,root,root) %dir %{_sysconfdir}/ssh +%verify(not mode) %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ssh/ldap.conf +%attr(0755,root,root) %dir %{_libexecdir}/ssh +%attr(0755,root,root) %{_libexecdir}/ssh/ssh-ldap* +%attr(0444,root,root) %{_mandir}/man5/ssh-ldap* +%attr(0444,root,root) %{_mandir}/man8/ssh-ldap* +%doc HOWTO.ldap-keys openssh-lpk-openldap.schema openssh-lpk-sun.schema +%endif + +%files fips +%attr(0444,root,root) %{_bindir}/ssh%{CHECKSUM_SUFFIX} +%attr(0444,root,root) %{_sbindir}/sshd%{CHECKSUM_SUFFIX} +%attr(0444,root,root) %{_libexecdir}/ssh/sftp-server%{CHECKSUM_SUFFIX} + +%files cavs +%attr(0755,root,root) %{_libexecdir}/ssh/cavs* + +%changelog diff --git a/ssh-askpass b/ssh-askpass new file mode 100644 index 0000000..230122f --- /dev/null +++ b/ssh-askpass @@ -0,0 +1,26 @@ +#!/bin/bash + +SESSION= + +if [ -n "$KDE_FULL_SESSION" ] ; then + SESSION=kde +fi + +if [ "$DESKTOP_SESSION" = "lxqt" ]; then + SESSION=kde +fi + +GNOME_SSH_ASKPASS="@LIBEXECDIR@/ssh/gnome-ssh-askpass" +KDE_SSH_ASKPASS="@LIBEXECDIR@/ssh/ksshaskpass" + +case "$SESSION" in + kde) + [ -e $KDE_SSH_ASKPASS ] && exec $KDE_SSH_ASKPASS ${1+"$@"} + exec $GNOME_SSH_ASKPASS ${1+"$@"} + ;; + *) + [ -e $GNOME_SSH_ASKPASS ] && exec $GNOME_SSH_ASKPASS ${1+"$@"} + exec $KDE_SSH_ASKPASS ${1+"$@"} + ;; +esac + diff --git a/ssh.reg b/ssh.reg new file mode 100644 index 0000000..a567084 --- /dev/null +++ b/ssh.reg @@ -0,0 +1,18 @@ +############################################################################# +# +# OpenSLP registration file +# +# register SSH daemon +# +############################################################################# + +# Register the usual sshd, if it is running +service:ssh://$HOSTNAME:22,en,65535 +tcp-port=22 +description=Secure Shell Daemon + +# ssh can get used to copy files with konqueror using the fish:/ protocol +service:fish://$HOSTNAME:22,en,65535 +tcp-port=22 +description=KDE file transfer via SSH + diff --git a/sshd-gen-keys-start b/sshd-gen-keys-start new file mode 100644 index 0000000..abc10df --- /dev/null +++ b/sshd-gen-keys-start @@ -0,0 +1,9 @@ +#!/bin/sh + +test -f /etc/sysconfig/ssh && . /etc/sysconfig/ssh + +if [ "x$SSHD_AUTO_KEYGEN" != "xno" ]; then + echo "Checking for missing server keys in /etc/ssh" + test -d /etc/ssh || mkdir -p /etc/ssh + ssh-keygen -A +fi diff --git a/sshd-sle.pamd b/sshd-sle.pamd new file mode 100644 index 0000000..efe67cb --- /dev/null +++ b/sshd-sle.pamd @@ -0,0 +1,11 @@ +#%PAM-1.0 +auth requisite pam_nologin.so +auth include common-auth +account requisite pam_nologin.so +account include common-account +password include common-password +session required pam_loginuid.so +session optional pam_keyinit.so force revoke +session include common-session +session optional pam_motd.so + diff --git a/sshd.fw b/sshd.fw new file mode 100644 index 0000000..359304d --- /dev/null +++ b/sshd.fw @@ -0,0 +1,5 @@ +## Name: Secure Shell Server +## Description: Open ports for Secure Shell Server + +# space separated list of allowed TCP ports +TCP="ssh" diff --git a/sshd.pamd b/sshd.pamd new file mode 100644 index 0000000..323cf44 --- /dev/null +++ b/sshd.pamd @@ -0,0 +1,14 @@ +#%PAM-1.0 +auth requisite pam_nologin.so +auth substack common-auth +auth include postlogin-auth +account requisite pam_nologin.so +account substack common-account +account include postlogin-account +password substack common-password +password include postlogin-password +session required pam_loginuid.so +session optional pam_keyinit.so force revoke +session substack common-session +session include postlogin-session +session optional pam_motd.so diff --git a/sshd.service b/sshd.service new file mode 100644 index 0000000..783df8c --- /dev/null +++ b/sshd.service @@ -0,0 +1,18 @@ +[Unit] +Description=OpenSSH Daemon +After=network.target + +[Service] +Type=notify +EnvironmentFile=-/etc/sysconfig/ssh +ExecStartPre=/usr/sbin/sshd-gen-keys-start +ExecStartPre=/usr/sbin/sshd -t $SSHD_OPTS +ExecStart=/usr/sbin/sshd -D $SSHD_OPTS +ExecReload=/bin/kill -HUP $MAINPID +KillMode=process +Restart=on-failure +RestartPreventExitStatus=255 +TasksMax=infinity + +[Install] +WantedBy=multi-user.target diff --git a/sysconfig.ssh b/sysconfig.ssh new file mode 100644 index 0000000..248449b --- /dev/null +++ b/sysconfig.ssh @@ -0,0 +1,14 @@ +## Path: Network/Remote access/SSH +## Description: SSH server settings +## Type: string +## Default: "" +## ServiceRestart: sshd +# +# Options for sshd +# +SSHD_OPTS="" + +# +# Whether to run ssh-keygen -A +# +SSHD_AUTO_KEYGEN="yes" diff --git a/sysusers-sshd.conf b/sysusers-sshd.conf new file mode 100644 index 0000000..040c8ad --- /dev/null +++ b/sysusers-sshd.conf @@ -0,0 +1,2 @@ +# Type Name ID GECOS [HOME] +u sshd - "SSH daemon" /var/lib/sshd diff --git a/wtmpdb.patch b/wtmpdb.patch new file mode 100644 index 0000000..bf5bca9 --- /dev/null +++ b/wtmpdb.patch @@ -0,0 +1,185 @@ +diff -ur openssh-8.9p1.old/configure.ac openssh-8.9p1/configure.ac +--- openssh-8.9p1.old/configure.ac 2022-02-23 12:31:11.000000000 +0100 ++++ openssh-8.9p1/configure.ac 2023-04-17 14:52:21.499002203 +0200 +@@ -1703,6 +1703,49 @@ + fi ] + ) + ++# Check whether user wants wtmpdb support ++WTMPDB_MSG="no" ++AC_ARG_WITH([wtmpdb], ++ [ --with-wtmpdb[[=PATH]] Enable wtmpdb support for sshd], ++ [ if test "x$withval" != "xno" ; then ++ if test "x$withval" = "xyes" ; then ++ AC_PATH_TOOL([PKGCONFIG], [pkg-config], [no]) ++ if test "x$PKGCONFIG" != "xno"; then ++ AC_MSG_CHECKING([if $PKGCONFIG knows about wtmpdb]) ++ if "$PKGCONFIG" libwtmpdb; then ++ AC_MSG_RESULT([yes]) ++ use_pkgconfig_for_libwtmpdb=yes ++ else ++ AC_MSG_RESULT([no]) ++ fi ++ fi ++ else ++ CPPFLAGS="$CPPFLAGS -I${withval}/include" ++ if test -n "${rpath_opt}"; then ++ LDFLAGS="-L${withval}/lib ${rpath_opt}${withval}/lib ${LDFLAGS}" ++ else ++ LDFLAGS="-L${withval}/lib ${LDFLAGS}" ++ fi ++ fi ++ if test "x$use_pkgconfig_for_libwtmpdb" = "xyes"; then ++ LIBWTMPDB=`$PKGCONFIG --libs libwtmpdb` ++ CPPFLAGS="$CPPFLAGS `$PKGCONFIG --cflags libwtmpdb`" ++ else ++ LIBWTMPDB="-lwtmpdb" ++ fi ++ OTHERLIBS=`echo $LIBWTMPDB | sed 's/-lwtmpdb//'` ++ AC_CHECK_LIB([wtmpdb], [wtmpdb_login], ++ [ AC_DEFINE([USE_WTMPDB], [1], [Use libwtmpdb for sshd]) ++ WTMPDB_MSG="yes" ++ AC_SUBST([LIBWTMPDB]) ++ ], ++ [ AC_MSG_ERROR([libwtmpdb not found]) ], ++ [ $OTHERLIBS ] ++ ) ++ fi ] ++) ++ ++ + AUDIT_MODULE=none + AC_ARG_WITH([audit], + [ --with-audit=module Enable audit support (modules=debug,bsm,linux)], +diff -ur openssh-8.9p1.old/loginrec.c openssh-8.9p1/loginrec.c +--- openssh-8.9p1.old/loginrec.c 2022-02-23 12:31:11.000000000 +0100 ++++ openssh-8.9p1/loginrec.c 2023-04-18 10:05:04.311193333 +0200 +@@ -187,6 +187,10 @@ + # include + #endif + ++#ifdef USE_WTMPDB ++# include ++#endif ++ + /** + ** prototypes for helper functions in this file + **/ +@@ -207,6 +211,9 @@ + int wtmpx_write_entry(struct logininfo *li); + int lastlog_write_entry(struct logininfo *li); + int syslogin_write_entry(struct logininfo *li); ++#ifdef USE_WTMPDB ++int wtmpdb_write_entry(struct logininfo *li); ++#endif + + int getlast_entry(struct logininfo *li); + int lastlog_get_entry(struct logininfo *li); +@@ -467,6 +474,9 @@ + #ifdef USE_WTMPX + wtmpx_write_entry(li); + #endif ++#ifdef USE_WTMPDB ++ wtmpdb_write_entry(li); ++#endif + #ifdef CUSTOM_SYS_AUTH_RECORD_LOGIN + if (li->type == LTYPE_LOGIN && + !sys_auth_record_login(li->username,li->hostname,li->line, +@@ -1409,6 +1419,64 @@ + } + #endif /* USE_WTMPX */ + ++#ifdef USE_WTMPDB ++static int ++wtmpdb_perform_login(struct logininfo *li) ++{ ++ uint64_t login_time = li->tv_sec * ((uint64_t) 1000000ULL) + li->tv_usec; ++ const char *tty; ++ ++ if (strncmp(li->line, "/dev/", 5) == 0) ++ tty = &(li->line[5]); ++ else ++ tty = li->line; ++ ++ li->wtmpdb_id = wtmpdb_login(NULL, USER_PROCESS, li->username, ++ login_time, tty, li->hostname, 0, 0); ++ if (li->wtmpdb_id < 0) ++ return (0); ++ ++ return (1); ++} ++ ++ ++static int ++wtmpdb_perform_logout(struct logininfo *li) ++{ ++ uint64_t logout_time = li->tv_sec * ((uint64_t) 1000000ULL) + li->tv_usec; ++ ++ if (li->wtmpdb_id == 0) { ++ const char *tty; ++ ++ if (strncmp(li->line, "/dev/", 5) == 0) ++ tty = &(li->line[5]); ++ else ++ tty = li->line; ++ ++ li->wtmpdb_id = wtmpdb_get_id(NULL, tty, NULL); ++ } ++ wtmpdb_logout(NULL, li->wtmpdb_id, logout_time, NULL); ++ ++ return (1); ++} ++ ++ ++int ++wtmpdb_write_entry(struct logininfo *li) ++{ ++ switch(li->type) { ++ case LTYPE_LOGIN: ++ return (wtmpdb_perform_login(li)); ++ case LTYPE_LOGOUT: ++ return (wtmpdb_perform_logout(li)); ++ default: ++ logit("%s: invalid type field", __func__); ++ return (0); ++ } ++} ++#endif ++ ++ + /** + ** Low-level libutil login() functions + **/ +diff -ur openssh-8.9p1.old/loginrec.h openssh-8.9p1/loginrec.h +--- openssh-8.9p1.old/loginrec.h 2022-02-23 12:31:11.000000000 +0100 ++++ openssh-8.9p1/loginrec.h 2023-04-17 14:58:20.808850750 +0200 +@@ -79,6 +79,9 @@ + unsigned int tv_sec; + unsigned int tv_usec; + union login_netinfo hostaddr; /* caller's host address(es) */ ++#ifdef USE_WTMPDB ++ int64_t wtmpdb_id; /* ID for wtmpdb_logout */ ++#endif + }; /* struct logininfo */ + + /* +diff -ur openssh-8.9p1.old/Makefile.in openssh-8.9p1/Makefile.in +--- openssh-8.9p1.old/Makefile.in 2022-02-23 12:31:11.000000000 +0100 ++++ openssh-8.9p1/Makefile.in 2023-04-17 14:44:32.156538001 +0200 +@@ -55,6 +55,7 @@ + SSHDLIBS=@SSHDLIBS@ + LIBEDIT=@LIBEDIT@ + LIBFIDO2=@LIBFIDO2@ ++LIBWTMPDB=@LIBWTMPDB@ + AR=@AR@ + AWK=@AWK@ + RANLIB=@RANLIB@ +@@ -212,7 +213,7 @@ + $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(GSSLIBS) $(CHANNELLIBS) + + sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS) +- $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS) $(CHANNELLIBS) ++ $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS) $(CHANNELLIBS) $(LIBWTMPDB) + + scp$(EXEEXT): $(LIBCOMPAT) libssh.a $(SCP_OBJS) + $(LD) -o $@ $(SCP_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)