From 00e6e9d3e41fb1ae645c9bd868cac4e3339e1f3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Schr=C3=B6ter?= Date: Fri, 15 Mar 2024 15:48:53 +0100 Subject: [PATCH] Sync from SUSE:ALP:Source:Standard:1.0 openssh revision f793e41158efbf91a9de8e2e7a9a07fd --- 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-fips.patch | 173 +++-- openssh-7.8p1-role-mls.patch | 885 +++++++++++++++++++++++++ openssh-8.0p1-gssapi-keyex.patch | 449 +++++++------ openssh-8.4p1-pam_motd.patch | 8 +- openssh-9.3p2.tar.gz | 3 - openssh-9.3p2.tar.gz.asc | 16 - openssh-9.6p1.tar.gz | 3 + openssh-9.6p1.tar.gz.asc | 16 + openssh-askpass-gnome.changes | 7 + openssh-askpass-gnome.spec | 2 +- openssh-cve-2023-48795.patch | 399 ----------- openssh.changes | 267 +++++++- openssh.spec | 20 +- 18 files changed, 2729 insertions(+), 742 deletions(-) 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.8p1-role-mls.patch delete mode 100644 openssh-9.3p2.tar.gz delete mode 100644 openssh-9.3p2.tar.gz.asc create mode 100644 openssh-9.6p1.tar.gz create mode 100644 openssh-9.6p1.tar.gz.asc delete mode 100644 openssh-cve-2023-48795.patch diff --git a/logind_set_tty.patch b/logind_set_tty.patch new file mode 100644 index 0000000..2d3e888 --- /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..27bcb15 --- /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..bc3618d --- /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..753f1bf --- /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..5115946 --- /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-fips.patch b/openssh-7.7p1-fips.patch index 470e98f..189237e 100644 --- a/openssh-7.7p1-fips.patch +++ b/openssh-7.7p1-fips.patch @@ -3,11 +3,11 @@ FIPS 140-2 compliance. Perform selftests on start and use only FIPS approved algorithms. -Index: openssh-8.8p1/Makefile.in +Index: openssh-9.6p1/Makefile.in =================================================================== ---- openssh-8.8p1.orig/Makefile.in -+++ openssh-8.8p1/Makefile.in -@@ -113,6 +113,8 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ +--- openssh-9.6p1.orig/Makefile.in ++++ openssh-9.6p1/Makefile.in +@@ -115,6 +115,8 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ SKOBJS= ssh-sk-client.o @@ -16,32 +16,10 @@ Index: openssh-8.8p1/Makefile.in SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ sshconnect.o sshconnect2.o mux.o $(SKOBJS) -#Index: openssh-8.8p1/cipher-ctr.c -#=================================================================== -#--- openssh-8.8p1.orig/cipher-ctr.c -#+++ openssh-8.8p1/cipher-ctr.c -#@@ -27,6 +27,8 @@ -# #include "xmalloc.h" -# #include "log.h" -# -#+#include "fips.h" -#+ -# /* compatibility with old or broken OpenSSL versions */ -# #include "openbsd-compat/openssl-compat.h" -# -#@@ -139,6 +141,8 @@ evp_aes_128_ctr(void) -# #ifndef SSH_OLD_EVP -# aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | -# EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV; -#+ if (fips_mode()) -#+ aes_ctr.flags |= EVP_CIPH_FLAG_FIPS; -# #endif -# return (&aes_ctr); -# } -Index: openssh-8.8p1/cipher.c +Index: openssh-9.6p1/cipher.c =================================================================== ---- openssh-8.8p1.orig/cipher.c -+++ openssh-8.8p1/cipher.c +--- openssh-9.6p1.orig/cipher.c ++++ openssh-9.6p1/cipher.c @@ -51,6 +51,9 @@ #include "openbsd-compat/openssl-compat.h" @@ -61,7 +39,7 @@ Index: openssh-8.8p1/cipher.c #ifdef WITH_OPENSSL #ifndef OPENSSL_NO_DES { "3des-cbc", 8, 24, 0, 0, CFLAG_CBC, EVP_des_ede3_cbc }, -@@ -112,8 +115,52 @@ static const struct sshcipher ciphers[] +@@ -110,8 +113,52 @@ static const struct sshcipher ciphers[] { NULL, 0, 0, 0, 0, 0, NULL } }; @@ -114,7 +92,7 @@ Index: openssh-8.8p1/cipher.c /* Returns a comma-separated list of supported ciphers. */ char * cipher_alg_list(char sep, int auth_only) -@@ -122,7 +169,7 @@ 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; @@ -123,7 +101,7 @@ Index: openssh-8.8p1/cipher.c if ((c->flags & CFLAG_INTERNAL) != 0) continue; if (auth_only && c->auth_len == 0) -@@ -205,7 +252,7 @@ const struct sshcipher * +@@ -203,7 +250,7 @@ const struct sshcipher * cipher_by_name(const char *name) { const struct sshcipher *c; @@ -132,10 +110,10 @@ Index: openssh-8.8p1/cipher.c if (strcmp(c->name, name) == 0) return c; return NULL; -Index: openssh-8.8p1/fips.c +Index: openssh-9.6p1/fips.c =================================================================== --- /dev/null -+++ openssh-8.8p1/fips.c ++++ openssh-9.6p1/fips.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2012 Petr Cerny. All rights reserved. @@ -349,10 +327,10 @@ Index: openssh-8.8p1/fips.c + return dgst; +} + -Index: openssh-8.8p1/fips.h +Index: openssh-9.6p1/fips.h =================================================================== --- /dev/null -+++ openssh-8.8p1/fips.h ++++ openssh-9.6p1/fips.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2012 Petr Cerny. All rights reserved. @@ -398,10 +376,10 @@ Index: openssh-8.8p1/fips.h + +#endif + -Index: openssh-8.8p1/hmac.c +Index: openssh-9.6p1/hmac.c =================================================================== ---- openssh-8.8p1.orig/hmac.c -+++ openssh-8.8p1/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]; @@ -411,20 +389,20 @@ Index: openssh-8.8p1/hmac.c printf("ssh_hmac_start failed"); if (ssh_hmac_init(ctx, key, klen) < 0 || ssh_hmac_update(ctx, m, mlen) < 0 || -Index: openssh-8.8p1/kex.c +Index: openssh-9.6p1/kex.c =================================================================== ---- openssh-8.8p1.orig/kex.c -+++ openssh-8.8p1/kex.c -@@ -62,6 +62,8 @@ +--- 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 *); + static int kex_choose_conf(struct ssh *, uint32_t seq); static int kex_input_newkeys(int, u_int32_t, struct ssh *); -@@ -85,7 +87,7 @@ struct kexalg { +@@ -87,7 +89,7 @@ struct kexalg { int ec_nid; int hash_alg; }; @@ -433,7 +411,7 @@ Index: openssh-8.8p1/kex.c #ifdef WITH_OPENSSL { KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, { KEX_DH14_SHA1, KEX_DH_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, -@@ -118,6 +120,47 @@ static const struct kexalg kexalgs[] = { +@@ -120,6 +122,47 @@ static const struct kexalg kexalgs[] = { { NULL, 0, -1, -1}, }; @@ -481,7 +459,7 @@ Index: openssh-8.8p1/kex.c char * kex_alg_list(char sep) { -@@ -125,7 +168,7 @@ kex_alg_list(char sep) +@@ -127,7 +170,7 @@ kex_alg_list(char sep) size_t nlen, rlen = 0; const struct kexalg *k; @@ -490,7 +468,7 @@ Index: openssh-8.8p1/kex.c if (ret != NULL) ret[rlen++] = sep; nlen = strlen(k->name); -@@ -145,7 +188,7 @@ kex_alg_by_name(const char *name) +@@ -147,7 +190,7 @@ kex_alg_by_name(const char *name) { const struct kexalg *k; @@ -499,7 +477,7 @@ Index: openssh-8.8p1/kex.c if (strcmp(k->name, name) == 0) return k; } -@@ -165,7 +208,10 @@ kex_names_valid(const char *names) +@@ -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) { @@ -510,10 +488,10 @@ Index: openssh-8.8p1/kex.c free(s); return 0; } -Index: openssh-8.8p1/mac.c +Index: openssh-9.6p1/mac.c =================================================================== ---- openssh-8.8p1.orig/mac.c -+++ openssh-8.8p1/mac.c +--- openssh-9.6p1.orig/mac.c ++++ openssh-9.6p1/mac.c @@ -41,6 +41,9 @@ #include "openbsd-compat/openssl-compat.h" @@ -593,11 +571,11 @@ Index: openssh-8.8p1/mac.c if (strcmp(name, m->name) != 0) continue; if (mac != NULL) -Index: openssh-8.8p1/readconf.c +Index: openssh-9.6p1/readconf.c =================================================================== ---- openssh-8.8p1.orig/readconf.c -+++ openssh-8.8p1/readconf.c -@@ -68,6 +68,8 @@ +--- openssh-9.6p1.orig/readconf.c ++++ openssh-9.6p1/readconf.c +@@ -71,6 +71,8 @@ #include "myproposal.h" #include "digest.h" @@ -606,7 +584,7 @@ Index: openssh-8.8p1/readconf.c /* Format of the configuration file: # Configuration data is parsed as follows: -@@ -2307,6 +2309,23 @@ config_has_permitted_cnames(Options *opt +@@ -2478,6 +2480,23 @@ config_has_permitted_cnames(Options *opt return options->num_permitted_cnames > 0; } @@ -630,7 +608,7 @@ Index: openssh-8.8p1/readconf.c /* * 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 -@@ -2618,6 +2637,9 @@ fill_default_options(Options * 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; @@ -640,7 +618,7 @@ Index: openssh-8.8p1/readconf.c #ifdef ENABLE_SK_INTERNAL if (options->sk_provider == NULL) options->sk_provider = xstrdup("internal"); -@@ -2654,6 +2676,8 @@ fill_default_options(Options * options) +@@ -2840,6 +2862,8 @@ fill_default_options(Options * options) ASSEMBLE(ca_sign_algorithms, def_sig, all_sig); #undef ASSEMBLE @@ -649,23 +627,23 @@ Index: openssh-8.8p1/readconf.c #define CLEAR_ON_NONE(v) \ do { \ if (option_clear_or_none(v)) { \ -Index: openssh-8.8p1/readconf.h +Index: openssh-9.6p1/readconf.h =================================================================== ---- openssh-8.8p1.orig/readconf.h -+++ openssh-8.8p1/readconf.h -@@ -212,6 +212,7 @@ typedef struct { - #define SSH_STRICT_HOSTKEY_YES 2 - #define SSH_STRICT_HOSTKEY_ASK 3 +--- 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); -Index: openssh-8.8p1/servconf.c + const char *portstr, const char *user, const char *jump_host); +Index: openssh-9.6p1/servconf.c =================================================================== ---- openssh-8.8p1.orig/servconf.c -+++ openssh-8.8p1/servconf.c -@@ -70,6 +70,7 @@ +--- openssh-9.6p1.orig/servconf.c ++++ openssh-9.6p1/servconf.c +@@ -68,6 +68,7 @@ #include "auth.h" #include "myproposal.h" #include "digest.h" @@ -673,7 +651,7 @@ Index: openssh-8.8p1/servconf.c static void add_listen_addr(ServerOptions *, const char *, const char *, int); -@@ -205,6 +206,23 @@ option_clear_or_none(const char *o) +@@ -207,6 +208,23 @@ option_clear_or_none(const char *o) return o == NULL || strcasecmp(o, "none") == 0; } @@ -697,7 +675,7 @@ Index: openssh-8.8p1/servconf.c static void assemble_algorithms(ServerOptions *o) { -@@ -246,6 +264,8 @@ assemble_algorithms(ServerOptions *o) +@@ -248,6 +266,8 @@ assemble_algorithms(ServerOptions *o) free(def_kex); free(def_key); free(def_sig); @@ -706,7 +684,7 @@ Index: openssh-8.8p1/servconf.c } void -@@ -438,6 +458,8 @@ fill_default_server_options(ServerOption +@@ -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; @@ -715,20 +693,20 @@ Index: openssh-8.8p1/servconf.c if (options->disable_forwarding == -1) options->disable_forwarding = 0; if (options->expose_userauth_info == -1) -Index: openssh-8.8p1/ssh-keygen.c +Index: openssh-9.6p1/ssh-keygen.c =================================================================== ---- openssh-8.8p1.orig/ssh-keygen.c -+++ openssh-8.8p1/ssh-keygen.c -@@ -67,6 +67,8 @@ - #include "sk-api.h" /* XXX for SSH_SK_USER_PRESENCE_REQD; remove */ - #include "cipher.h" +--- 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 - # define DEFAULT_KEY_TYPE_NAME "rsa" - #else -@@ -1037,11 +1039,13 @@ do_fingerprint(struct passwd *pw) + #include + #include +@@ -1040,11 +1042,13 @@ do_fingerprint(struct passwd *pw) static void do_gen_all_hostkeys(struct passwd *pw) { @@ -744,8 +722,7 @@ Index: openssh-8.8p1/ssh-keygen.c #ifdef WITH_OPENSSL { "rsa", "RSA" ,_PATH_HOST_RSA_KEY_FILE }, #ifdef OPENSSL_HAS_ECC -# { "dsa", "DSA", _PATH_HOST_DSA_KEY_FILE }, -@@ -1056,6 +1060,17 @@ do_gen_all_hostkeys(struct passwd *pw) +@@ -1058,6 +1062,17 @@ do_gen_all_hostkeys(struct passwd *pw) { NULL, NULL, NULL } }; @@ -763,7 +740,7 @@ Index: openssh-8.8p1/ssh-keygen.c u_int32_t bits = 0; int first = 0; struct stat st; -@@ -1063,6 +1078,12 @@ do_gen_all_hostkeys(struct passwd *pw) +@@ -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; @@ -776,7 +753,7 @@ Index: openssh-8.8p1/ssh-keygen.c for (i = 0; key_types[i].key_type; i++) { public = private = NULL; prv_tmp = pub_tmp = prv_file = pub_file = NULL; -@@ -3620,6 +3641,15 @@ main(int argc, char **argv) +@@ -3794,6 +3815,15 @@ main(int argc, char **argv) key_type_name = DEFAULT_KEY_TYPE_NAME; type = sshkey_type_from_name(key_type_name); @@ -792,11 +769,11 @@ Index: openssh-8.8p1/ssh-keygen.c type_bits_valid(type, key_type_name, &bits); if (!quiet) -Index: openssh-8.8p1/ssh_config.5 +Index: openssh-9.6p1/ssh_config.5 =================================================================== ---- openssh-8.8p1.orig/ssh_config.5 -+++ openssh-8.8p1/ssh_config.5 -@@ -736,6 +736,8 @@ The argument to this keyword must be +--- 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). @@ -805,11 +782,11 @@ Index: openssh-8.8p1/ssh_config.5 .It Cm ForwardAgent Specifies whether the connection to the authentication agent (if any) will be forwarded to the remote machine. -Index: openssh-8.8p1/sshd.c +Index: openssh-9.6p1/sshd.c =================================================================== ---- openssh-8.8p1.orig/sshd.c -+++ openssh-8.8p1/sshd.c -@@ -126,6 +126,8 @@ +--- openssh-9.6p1.orig/sshd.c ++++ openssh-9.6p1/sshd.c +@@ -128,6 +128,8 @@ #include "srclimit.h" #include "dh.h" @@ -818,11 +795,11 @@ Index: openssh-8.8p1/sshd.c /* Re-exec fds */ #define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1) #define REEXEC_STARTUP_PIPE_FD (STDERR_FILENO + 2) -Index: openssh-8.8p1/sshd_config.5 +Index: openssh-9.6p1/sshd_config.5 =================================================================== ---- openssh-8.8p1.orig/sshd_config.5 -+++ openssh-8.8p1/sshd_config.5 -@@ -600,6 +600,8 @@ and +--- 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 . diff --git a/openssh-7.8p1-role-mls.patch b/openssh-7.8p1-role-mls.patch new file mode 100644 index 0000000..d3cc0b1 --- /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-8.0p1-gssapi-keyex.patch b/openssh-8.0p1-gssapi-keyex.patch index 7228a26..67af316 100644 --- a/openssh-8.0p1-gssapi-keyex.patch +++ b/openssh-8.0p1-gssapi-keyex.patch @@ -1,7 +1,7 @@ -Index: openssh-8.9p1/Makefile.in +Index: openssh-9.6p1/Makefile.in =================================================================== ---- openssh-8.9p1.orig/Makefile.in -+++ openssh-8.9p1/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 \ @@ -12,7 +12,6 @@ Index: openssh-8.9p1/Makefile.in @@ -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-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 \ @@ -20,11 +19,11 @@ Index: openssh-8.9p1/Makefile.in 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-8.9p1/auth.c +Index: openssh-9.6p1/auth.c =================================================================== ---- openssh-8.9p1.orig/auth.c -+++ openssh-8.9p1/auth.c -@@ -402,7 +402,8 @@ auth_root_allowed(struct ssh *ssh, const +--- 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 || @@ -34,7 +33,7 @@ Index: openssh-8.9p1/auth.c return 1; break; case PERMIT_FORCED_ONLY: -@@ -740,97 +741,6 @@ fakepw(void) +@@ -638,97 +639,6 @@ fakepw(void) } /* @@ -132,12 +131,12 @@ Index: openssh-8.9p1/auth.c * 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-8.9p1/auth2-gss.c +Index: openssh-9.6p1/auth2-gss.c =================================================================== ---- openssh-8.9p1.orig/auth2-gss.c -+++ openssh-8.9p1/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.33 2021/12/19 22:12:07 djm Exp $ */ + /* $OpenBSD: auth2-gss.c,v 1.34 2023/03/31 04:22:27 djm Exp $ */ /* - * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. @@ -145,7 +144,7 @@ Index: openssh-8.9p1/auth2-gss.c * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions -@@ -56,6 +56,48 @@ static int input_gssapi_exchange_complet +@@ -58,6 +58,48 @@ static int input_gssapi_exchange_complet static int input_gssapi_errtok(int, u_int32_t, struct ssh *); /* @@ -194,7 +193,7 @@ Index: openssh-8.9p1/auth2-gss.c * We only support those mechanisms that we know about (ie ones that we know * how to check local user kuserok and the like) */ -@@ -261,7 +303,8 @@ input_gssapi_exchange_complete(int type, +@@ -267,7 +309,8 @@ input_gssapi_exchange_complete(int type, if ((r = sshpkt_get_end(ssh)) != 0) fatal_fr(r, "parse packet"); @@ -204,7 +203,7 @@ Index: openssh-8.9p1/auth2-gss.c if ((!use_privsep || mm_is_monitor()) && (displayname = ssh_gssapi_displayname()) != NULL) -@@ -307,7 +350,8 @@ input_gssapi_mic(int type, u_int32_t ple +@@ -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)))) @@ -214,7 +213,7 @@ Index: openssh-8.9p1/auth2-gss.c else logit("GSSAPI MIC check failed"); -@@ -327,6 +371,12 @@ input_gssapi_mic(int type, u_int32_t ple +@@ -333,6 +377,12 @@ input_gssapi_mic(int type, u_int32_t ple return 0; } @@ -227,10 +226,10 @@ Index: openssh-8.9p1/auth2-gss.c Authmethod method_gssapi = { "gssapi-with-mic", NULL, -Index: openssh-8.9p1/auth2.c +Index: openssh-9.6p1/auth2.c =================================================================== ---- openssh-8.9p1.orig/auth2.c -+++ openssh-8.9p1/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; @@ -247,10 +246,10 @@ Index: openssh-8.9p1/auth2.c &method_gssapi, #endif &method_passwd, -Index: openssh-8.9p1/canohost.c +Index: openssh-9.6p1/canohost.c =================================================================== ---- openssh-8.9p1.orig/canohost.c -+++ openssh-8.9p1/canohost.c +--- openssh-9.6p1.orig/canohost.c ++++ openssh-9.6p1/canohost.c @@ -35,6 +35,99 @@ #include "canohost.h" #include "misc.h" @@ -351,10 +350,10 @@ Index: openssh-8.9p1/canohost.c void ipv64_normalise_mapped(struct sockaddr_storage *addr, socklen_t *len) { -Index: openssh-8.9p1/canohost.h +Index: openssh-9.6p1/canohost.h =================================================================== ---- openssh-8.9p1.orig/canohost.h -+++ openssh-8.9p1/canohost.h +--- openssh-9.6p1.orig/canohost.h ++++ openssh-9.6p1/canohost.h @@ -15,6 +15,9 @@ #ifndef _CANOHOST_H #define _CANOHOST_H @@ -365,13 +364,13 @@ Index: openssh-8.9p1/canohost.h char *get_peer_ipaddr(int); int get_peer_port(int); char *get_local_ipaddr(int); -Index: openssh-8.9p1/clientloop.c +Index: openssh-9.6p1/clientloop.c =================================================================== ---- openssh-8.9p1.orig/clientloop.c -+++ openssh-8.9p1/clientloop.c -@@ -118,6 +118,10 @@ - /* Permitted RSA signature algorithms for UpdateHostkeys proofs */ - #define HOSTKEY_PROOF_RSA_ALGS "rsa-sha2-512,rsa-sha2-256" +--- 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" @@ -380,28 +379,7 @@ Index: openssh-8.9p1/clientloop.c /* import options */ extern Options options; -#@@ -1349,9 +1353,18 @@ client_loop(struct ssh *ssh, int have_pt -## Replaced with the section below -# break; -# -# /* Do channel operations unless rekeying in progress. */ -#- if (!ssh_packet_is_rekeying(ssh)) -#+ if (!ssh_packet_is_rekeying(ssh)) { -# 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); -@@ -1349,6 +1353,14 @@ client_loop(struct ssh *ssh, int have_pt +@@ -1594,6 +1598,14 @@ client_loop(struct ssh *ssh, int have_pt /* Do channel operations. */ channel_after_poll(ssh, pfd, npfd_active); @@ -416,11 +394,11 @@ Index: openssh-8.9p1/clientloop.c /* Buffer input from the connection. */ if (conn_in_ready) client_process_net_input(ssh); -Index: openssh-8.9p1/configure.ac +Index: openssh-9.6p1/configure.ac =================================================================== ---- openssh-8.9p1.orig/configure.ac -+++ openssh-8.9p1/configure.ac -@@ -714,6 +714,30 @@ main() { if (NSVersionOfRunTimeLibrary(" +--- 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]) @@ -451,10 +429,10 @@ Index: openssh-8.9p1/configure.ac m4_pattern_allow([AU_IPv]) AC_CHECK_DECL([AU_IPv4], [], AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records]) -Index: openssh-8.9p1/gss-genr.c +Index: openssh-9.6p1/gss-genr.c =================================================================== ---- openssh-8.9p1.orig/gss-genr.c -+++ openssh-8.9p1/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 $ */ @@ -830,10 +808,10 @@ Index: openssh-8.9p1/gss-genr.c +} + #endif /* GSSAPI */ -Index: openssh-8.9p1/gss-serv-krb5.c +Index: openssh-9.6p1/gss-serv-krb5.c =================================================================== ---- openssh-8.9p1.orig/gss-serv-krb5.c -+++ openssh-8.9p1/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 $ */ @@ -970,10 +948,10 @@ Index: openssh-8.9p1/gss-serv-krb5.c }; #endif /* KRB5 */ -Index: openssh-8.9p1/gss-serv.c +Index: openssh-9.6p1/gss-serv.c =================================================================== ---- openssh-8.9p1.orig/gss-serv.c -+++ openssh-8.9p1/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 $ */ @@ -1270,11 +1248,11 @@ Index: openssh-8.9p1/gss-serv.c } /* Privileged */ -Index: openssh-8.9p1/kex.c +Index: openssh-9.6p1/kex.c =================================================================== ---- openssh-8.9p1.orig/kex.c -+++ openssh-8.9p1/kex.c -@@ -57,6 +57,10 @@ +--- openssh-9.6p1.orig/kex.c ++++ openssh-9.6p1/kex.c +@@ -64,6 +64,10 @@ #include "digest.h" #include "xmalloc.h" @@ -1285,7 +1263,7 @@ Index: openssh-8.9p1/kex.c #include "fips.h" /* prototype */ -@@ -119,6 +123,19 @@ static const struct kexalg kexalgs_all[] +@@ -121,6 +125,19 @@ static const struct kexalg kexalgs_all[] #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ { NULL, 0, -1, -1}, }; @@ -1305,7 +1283,7 @@ Index: openssh-8.9p1/kex.c static const struct kexalg kexalgs_fips140_2[] = { #ifdef WITH_OPENSSL -@@ -146,12 +163,12 @@ static const struct kexalg kexalgs_fips1 +@@ -148,12 +165,12 @@ static const struct kexalg kexalgs_fips1 /* Returns array of macs available depending on selected FIPS mode */ static const struct kexalg * @@ -1320,7 +1298,7 @@ Index: openssh-8.9p1/kex.c case 1: return kexalgs_fips140_2; default: -@@ -162,13 +179,13 @@ fips_select_kexalgs(void) +@@ -164,13 +181,13 @@ fips_select_kexalgs(void) } char * @@ -1336,7 +1314,7 @@ Index: openssh-8.9p1/kex.c if (ret != NULL) ret[rlen++] = sep; nlen = strlen(k->name); -@@ -183,15 +200,31 @@ kex_alg_list(char sep) +@@ -185,15 +202,31 @@ kex_alg_list(char sep) return ret; } @@ -1369,7 +1347,7 @@ Index: openssh-8.9p1/kex.c return NULL; } -@@ -363,6 +396,29 @@ kex_assemble_names(char **listp, const c +@@ -375,6 +408,29 @@ kex_assemble_names(char **listp, const c return r; } @@ -1399,7 +1377,7 @@ Index: openssh-8.9p1/kex.c /* * Fill out a proposal array with dynamically allocated values, which may * be modified as required for compatibility reasons. -@@ -765,6 +821,9 @@ kex_free(struct kex *kex) +@@ -1010,6 +1066,9 @@ kex_free(struct kex *kex) sshbuf_free(kex->session_id); sshbuf_free(kex->initial_sig); sshkey_free(kex->initial_hostkey); @@ -1409,10 +1387,10 @@ Index: openssh-8.9p1/kex.c free(kex->failed_choice); free(kex->hostkey_alg); free(kex->name); -Index: openssh-8.9p1/kex.h +Index: openssh-9.6p1/kex.h =================================================================== ---- openssh-8.9p1.orig/kex.h -+++ openssh-8.9p1/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, @@ -1429,7 +1407,7 @@ Index: openssh-8.9p1/kex.h KEX_MAX }; -@@ -159,6 +168,12 @@ struct kex { +@@ -164,6 +173,12 @@ struct kex { u_int flags; int hash_alg; int ec_nid; @@ -1442,7 +1420,7 @@ Index: openssh-8.9p1/kex.h char *failed_choice; int (*verify_host_key)(struct sshkey *, struct ssh *); struct sshkey *(*load_host_public_key)(int, int, struct ssh *); -@@ -180,8 +195,10 @@ struct kex { +@@ -185,8 +200,10 @@ struct kex { int kex_names_valid(const char *); char *kex_alg_list(char); @@ -1453,7 +1431,7 @@ Index: openssh-8.9p1/kex.h 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]); -@@ -209,6 +226,12 @@ int kexgex_client(struct ssh *); +@@ -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 *); @@ -1466,7 +1444,7 @@ Index: openssh-8.9p1/kex.h int kex_dh_keypair(struct kex *); int kex_dh_enc(struct kex *, const struct sshbuf *, struct sshbuf **, -@@ -241,6 +264,12 @@ int kexgex_hash(int, const struct sshbu +@@ -251,6 +274,12 @@ int kexgex_hash(int, const struct sshbu const BIGNUM *, const u_char *, size_t, u_char *, size_t *); @@ -1479,10 +1457,10 @@ Index: openssh-8.9p1/kex.h 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-8.9p1/kexdh.c +Index: openssh-9.6p1/kexdh.c =================================================================== ---- openssh-8.9p1.orig/kexdh.c -+++ openssh-8.9p1/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) { @@ -1507,10 +1485,10 @@ Index: openssh-8.9p1/kexdh.c kex->dh = dh_new_group16(); break; case KEX_DH_GRP18_SHA512: -Index: openssh-8.9p1/kexgen.c +Index: openssh-9.6p1/kexgen.c =================================================================== ---- openssh-8.9p1.orig/kexgen.c -+++ openssh-8.9p1/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); @@ -1520,10 +1498,10 @@ Index: openssh-8.9p1/kexgen.c kex_gen_hash( int hash_alg, const struct sshbuf *client_version, -Index: openssh-8.9p1/kexgssc.c +Index: openssh-9.6p1/kexgssc.c =================================================================== --- /dev/null -+++ openssh-8.9p1/kexgssc.c ++++ openssh-9.6p1/kexgssc.c @@ -0,0 +1,595 @@ +/* + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. @@ -2120,10 +2098,10 @@ Index: openssh-8.9p1/kexgssc.c + return r; +} +#endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */ -Index: openssh-8.9p1/kexgsss.c +Index: openssh-9.6p1/kexgsss.c =================================================================== --- /dev/null -+++ openssh-8.9p1/kexgsss.c ++++ openssh-9.6p1/kexgsss.c @@ -0,0 +1,474 @@ +/* + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. @@ -2599,11 +2577,11 @@ Index: openssh-8.9p1/kexgsss.c + return r; +} +#endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */ -Index: openssh-8.9p1/monitor.c +Index: openssh-9.6p1/monitor.c =================================================================== ---- openssh-8.9p1.orig/monitor.c -+++ openssh-8.9p1/monitor.c -@@ -145,6 +145,8 @@ int mm_answer_gss_setup_ctx(struct ssh * +--- 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 *); @@ -2612,7 +2590,7 @@ Index: openssh-8.9p1/monitor.c #endif #ifdef SSH_AUDIT_EVENTS -@@ -217,11 +219,18 @@ struct mon_table mon_dispatch_proto20[] +@@ -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}, @@ -2631,7 +2609,7 @@ Index: openssh-8.9p1/monitor.c #ifdef WITH_OPENSSL {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, #endif -@@ -290,6 +299,10 @@ monitor_child_preauth(struct ssh *ssh, s +@@ -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); @@ -2642,7 +2620,7 @@ Index: openssh-8.9p1/monitor.c /* The first few requests do not require asynchronous access */ while (!authenticated) { -@@ -401,6 +414,10 @@ monitor_child_postauth(struct ssh *ssh, +@@ -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); @@ -2653,7 +2631,7 @@ Index: openssh-8.9p1/monitor.c if (auth_opts->permit_pty_flag) { monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); -@@ -1747,6 +1764,17 @@ monitor_apply_keystate(struct ssh *ssh, +@@ -1745,6 +1762,17 @@ monitor_apply_keystate(struct ssh *ssh, # ifdef OPENSSL_HAS_ECC kex->kex[KEX_ECDH_SHA2] = kex_gen_server; # endif @@ -2671,7 +2649,7 @@ Index: openssh-8.9p1/monitor.c #endif /* WITH_OPENSSL */ kex->kex[KEX_C25519_SHA256] = kex_gen_server; kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; -@@ -1839,8 +1867,8 @@ mm_answer_gss_setup_ctx(struct ssh *ssh, +@@ -1837,8 +1865,8 @@ mm_answer_gss_setup_ctx(struct ssh *ssh, u_char *p; int r; @@ -2682,7 +2660,7 @@ Index: openssh-8.9p1/monitor.c if ((r = sshbuf_get_string(m, &p, &len)) != 0) fatal_fr(r, "parse"); -@@ -1872,8 +1900,8 @@ mm_answer_gss_accept_ctx(struct ssh *ssh +@@ -1870,8 +1898,8 @@ mm_answer_gss_accept_ctx(struct ssh *ssh OM_uint32 flags = 0; /* GSI needs this */ int r; @@ -2693,7 +2671,7 @@ Index: openssh-8.9p1/monitor.c if ((r = ssh_gssapi_get_buffer_desc(m, &in)) != 0) fatal_fr(r, "ssh_gssapi_get_buffer_desc"); -@@ -1893,6 +1921,7 @@ mm_answer_gss_accept_ctx(struct ssh *ssh +@@ -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); @@ -2701,7 +2679,7 @@ Index: openssh-8.9p1/monitor.c } return (0); } -@@ -1904,8 +1933,8 @@ mm_answer_gss_checkmic(struct ssh *ssh, +@@ -1902,8 +1931,8 @@ mm_answer_gss_checkmic(struct ssh *ssh, OM_uint32 ret; int r; @@ -2712,7 +2690,7 @@ Index: openssh-8.9p1/monitor.c if ((r = ssh_gssapi_get_buffer_desc(m, &gssbuf)) != 0 || (r = ssh_gssapi_get_buffer_desc(m, &mic)) != 0) -@@ -1931,13 +1960,17 @@ mm_answer_gss_checkmic(struct ssh *ssh, +@@ -1929,13 +1958,17 @@ mm_answer_gss_checkmic(struct ssh *ssh, int mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) { @@ -2734,7 +2712,7 @@ Index: openssh-8.9p1/monitor.c sshbuf_reset(m); if ((r = sshbuf_put_u32(m, authenticated)) != 0) -@@ -1946,7 +1979,11 @@ mm_answer_gss_userok(struct ssh *ssh, in +@@ -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); @@ -2747,7 +2725,7 @@ Index: openssh-8.9p1/monitor.c if ((displayname = ssh_gssapi_displayname()) != NULL) auth2_record_info(authctxt, "%s", displayname); -@@ -1954,5 +1991,85 @@ mm_answer_gss_userok(struct ssh *ssh, in +@@ -1952,5 +1989,85 @@ mm_answer_gss_userok(struct ssh *ssh, in /* Monitor loop will terminate if authenticated */ return (authenticated); } @@ -2833,10 +2811,10 @@ Index: openssh-8.9p1/monitor.c + #endif /* GSSAPI */ -Index: openssh-8.9p1/monitor.h +Index: openssh-9.6p1/monitor.h =================================================================== ---- openssh-8.9p1.orig/monitor.h -+++ openssh-8.9p1/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, @@ -2846,11 +2824,11 @@ Index: openssh-8.9p1/monitor.h }; struct ssh; -Index: openssh-8.9p1/monitor_wrap.c +Index: openssh-9.6p1/monitor_wrap.c =================================================================== ---- openssh-8.9p1.orig/monitor_wrap.c -+++ openssh-8.9p1/monitor_wrap.c -@@ -999,13 +999,15 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss +--- 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 @@ -2867,7 +2845,7 @@ Index: openssh-8.9p1/monitor_wrap.c mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, m); mm_request_receive_expect(pmonitor->m_recvfd, -@@ -1018,4 +1020,57 @@ mm_ssh_gssapi_userok(char *user) +@@ -1017,4 +1019,57 @@ mm_ssh_gssapi_userok(char *user) debug3_f("user %sauthenticated", authenticated ? "" : "not "); return (authenticated); } @@ -2925,10 +2903,10 @@ Index: openssh-8.9p1/monitor_wrap.c +} + #endif /* GSSAPI */ -Index: openssh-8.9p1/monitor_wrap.h +Index: openssh-9.6p1/monitor_wrap.h =================================================================== ---- openssh-8.9p1.orig/monitor_wrap.h -+++ openssh-8.9p1/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 *, @@ -2941,11 +2919,11 @@ Index: openssh-8.9p1/monitor_wrap.h #endif #ifdef USE_PAM -Index: openssh-8.9p1/readconf.c +Index: openssh-9.6p1/readconf.c =================================================================== ---- openssh-8.9p1.orig/readconf.c -+++ openssh-8.9p1/readconf.c -@@ -67,6 +67,7 @@ +--- openssh-9.6p1.orig/readconf.c ++++ openssh-9.6p1/readconf.c +@@ -70,6 +70,7 @@ #include "uidswap.h" #include "myproposal.h" #include "digest.h" @@ -2953,7 +2931,7 @@ Index: openssh-8.9p1/readconf.c #include "fips.h" -@@ -163,6 +164,8 @@ typedef enum { +@@ -166,6 +167,8 @@ typedef enum { oClearAllForwardings, oNoHostAuthenticationForLocalhost, oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, oAddressFamily, oGssAuthentication, oGssDelegateCreds, @@ -2962,7 +2940,7 @@ Index: openssh-8.9p1/readconf.c oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist, oHashKnownHosts, -@@ -208,10 +211,22 @@ static struct { +@@ -212,10 +215,22 @@ static struct { /* Sometimes-unsupported options */ #if defined(GSSAPI) { "gssapiauthentication", oGssAuthentication }, @@ -2985,7 +2963,7 @@ Index: openssh-8.9p1/readconf.c #endif #ifdef ENABLE_PKCS11 { "pkcs11provider", oPKCS11Provider }, -@@ -1125,10 +1140,42 @@ parse_time: +@@ -1212,10 +1227,42 @@ parse_time: intptr = &options->gss_authentication; goto parse_flag; @@ -3028,7 +3006,7 @@ Index: openssh-8.9p1/readconf.c case oBatchMode: intptr = &options->batch_mode; goto parse_flag; -@@ -2361,7 +2408,13 @@ initialize_options(Options * options) +@@ -2524,7 +2571,13 @@ initialize_options(Options * options) options->fwd_opts.streamlocal_bind_unlink = -1; options->pubkey_authentication = -1; options->gss_authentication = -1; @@ -3042,7 +3020,7 @@ Index: openssh-8.9p1/readconf.c options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->kbd_interactive_devices = NULL; -@@ -2518,8 +2571,18 @@ fill_default_options(Options * options) +@@ -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; @@ -3061,7 +3039,7 @@ Index: openssh-8.9p1/readconf.c if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) -@@ -3317,7 +3380,14 @@ dump_client_config(Options *o, const cha +@@ -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); @@ -3076,11 +3054,11 @@ Index: openssh-8.9p1/readconf.c #endif /* GSSAPI */ dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts); dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication); -Index: openssh-8.9p1/readconf.h +Index: openssh-9.6p1/readconf.h =================================================================== ---- openssh-8.9p1.orig/readconf.h -+++ openssh-8.9p1/readconf.h -@@ -39,7 +39,13 @@ typedef struct { +--- 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 */ @@ -3094,11 +3072,11 @@ Index: openssh-8.9p1/readconf.h int password_authentication; /* Try password * authentication. */ int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ -Index: openssh-8.9p1/servconf.c +Index: openssh-9.6p1/servconf.c =================================================================== ---- openssh-8.9p1.orig/servconf.c -+++ openssh-8.9p1/servconf.c -@@ -70,6 +70,7 @@ +--- openssh-9.6p1.orig/servconf.c ++++ openssh-9.6p1/servconf.c +@@ -68,6 +68,7 @@ #include "auth.h" #include "myproposal.h" #include "digest.h" @@ -3106,7 +3084,7 @@ Index: openssh-8.9p1/servconf.c #include "fips.h" static void add_listen_addr(ServerOptions *, const char *, -@@ -138,8 +139,11 @@ initialize_server_options(ServerOptions +@@ -136,8 +137,11 @@ initialize_server_options(ServerOptions options->kerberos_ticket_cleanup = -1; options->kerberos_get_afs_token = -1; options->gss_authentication=-1; @@ -3118,7 +3096,7 @@ Index: openssh-8.9p1/servconf.c options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->permit_empty_passwd = -1; -@@ -379,10 +383,18 @@ fill_default_server_options(ServerOption +@@ -381,10 +385,18 @@ fill_default_server_options(ServerOption options->kerberos_get_afs_token = 0; if (options->gss_authentication == -1) options->gss_authentication = 0; @@ -3137,7 +3115,7 @@ Index: openssh-8.9p1/servconf.c if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) -@@ -530,6 +542,7 @@ typedef enum { +@@ -543,6 +555,7 @@ typedef enum { sHostKeyAlgorithms, sPerSourceMaxStartups, sPerSourceNetBlockSize, sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, @@ -3145,7 +3123,7 @@ Index: openssh-8.9p1/servconf.c sAcceptEnv, sSetEnv, sPermitTunnel, sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory, sUsePrivilegeSeparation, sAllowAgentForwarding, -@@ -613,12 +626,22 @@ static struct { +@@ -627,12 +640,22 @@ static struct { #ifdef GSSAPI { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, @@ -3168,7 +3146,7 @@ Index: openssh-8.9p1/servconf.c { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, { "challengeresponseauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, /* alias */ -@@ -1603,6 +1626,10 @@ process_server_config_line_depth(ServerO +@@ -1646,6 +1669,10 @@ process_server_config_line_depth(ServerO intptr = &options->gss_authentication; goto parse_flag; @@ -3179,7 +3157,7 @@ Index: openssh-8.9p1/servconf.c case sGssCleanupCreds: intptr = &options->gss_cleanup_creds; goto parse_flag; -@@ -1611,6 +1638,22 @@ process_server_config_line_depth(ServerO +@@ -1654,6 +1681,22 @@ process_server_config_line_depth(ServerO intptr = &options->gss_strict_acceptor; goto parse_flag; @@ -3202,7 +3180,7 @@ Index: openssh-8.9p1/servconf.c case sPasswordAuthentication: intptr = &options->password_authentication; goto parse_flag; -@@ -2918,6 +2961,10 @@ dump_config(ServerOptions *o) +@@ -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); @@ -3213,11 +3191,11 @@ Index: openssh-8.9p1/servconf.c #endif dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication); dump_cfg_fmtint(sKbdInteractiveAuthentication, -Index: openssh-8.9p1/servconf.h +Index: openssh-9.6p1/servconf.h =================================================================== ---- openssh-8.9p1.orig/servconf.h -+++ openssh-8.9p1/servconf.h -@@ -141,8 +141,11 @@ typedef struct { +--- 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 */ @@ -3229,11 +3207,11 @@ Index: openssh-8.9p1/servconf.h int password_authentication; /* If true, permit password * authentication. */ int kbd_interactive_authentication; /* If true, permit */ -Index: openssh-8.9p1/session.c +Index: openssh-9.6p1/session.c =================================================================== ---- openssh-8.9p1.orig/session.c -+++ openssh-8.9p1/session.c -@@ -2708,13 +2708,19 @@ do_cleanup(struct ssh *ssh, Authctxt *au +--- 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 && @@ -3255,10 +3233,10 @@ Index: openssh-8.9p1/session.c #endif /* remove agent socket */ -Index: openssh-8.9p1/ssh-gss.h +Index: openssh-9.6p1/ssh-gss.h =================================================================== ---- openssh-8.9p1.orig/ssh-gss.h -+++ openssh-8.9p1/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 $ */ /* @@ -3375,11 +3353,11 @@ Index: openssh-8.9p1/ssh-gss.h #endif /* GSSAPI */ #endif /* _SSH_GSS_H */ -Index: openssh-8.9p1/ssh.1 +Index: openssh-9.6p1/ssh.1 =================================================================== ---- openssh-8.9p1.orig/ssh.1 -+++ openssh-8.9p1/ssh.1 -@@ -530,7 +530,13 @@ For full details of the options listed b +--- 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 @@ -3393,7 +3371,7 @@ Index: openssh-8.9p1/ssh.1 .It HashKnownHosts .It Host .It HostbasedAcceptedAlgorithms -@@ -607,6 +613,8 @@ flag), +@@ -624,6 +630,8 @@ flag), (supported message integrity codes), .Ar kex (key exchange algorithms), @@ -3401,12 +3379,12 @@ Index: openssh-8.9p1/ssh.1 +(GSSAPI key exchange algorithms), .Ar key (key types), - .Ar key-cert -Index: openssh-8.9p1/ssh.c + .Ar key-ca-sign +Index: openssh-9.6p1/ssh.c =================================================================== ---- openssh-8.9p1.orig/ssh.c -+++ openssh-8.9p1/ssh.c -@@ -781,6 +781,8 @@ main(int ac, char **av) +--- 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'); @@ -3415,7 +3393,7 @@ Index: openssh-8.9p1/ssh.c else if (strcmp(optarg, "key") == 0) cp = sshkey_alg_list(0, 0, 0, '\n'); else if (strcmp(optarg, "key-cert") == 0) -@@ -807,7 +809,7 @@ main(int ac, char **av) +@@ -862,7 +864,7 @@ main(int ac, char **av) cp[n] = '\n'; } else if (strcmp(optarg, "help") == 0) { cp = xstrdup( @@ -3424,10 +3402,10 @@ Index: openssh-8.9p1/ssh.c "key\nkey-cert\nkey-plain\nkey-sig\nmac\n" "protocol-version\nsig"); } -Index: openssh-8.9p1/ssh_config +Index: openssh-9.6p1/ssh_config =================================================================== ---- openssh-8.9p1.orig/ssh_config -+++ openssh-8.9p1/ssh_config +--- openssh-9.6p1.orig/ssh_config ++++ openssh-9.6p1/ssh_config @@ -40,6 +40,8 @@ Host * # HostbasedAuthentication no # GSSAPIAuthentication no @@ -3435,13 +3413,13 @@ Index: openssh-8.9p1/ssh_config +# GSSAPIKeyExchange no +# GSSAPITrustDNS no # BatchMode no - # CheckHostIP yes + # CheckHostIP no # AddressFamily any -Index: openssh-8.9p1/ssh_config.5 +Index: openssh-9.6p1/ssh_config.5 =================================================================== ---- openssh-8.9p1.orig/ssh_config.5 -+++ openssh-8.9p1/ssh_config.5 -@@ -835,10 +835,67 @@ The default is +--- 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 . @@ -3509,11 +3487,11 @@ Index: openssh-8.9p1/ssh_config.5 .It Cm HashKnownHosts Indicates that .Xr ssh 1 -Index: openssh-8.9p1/sshconnect2.c +Index: openssh-9.6p1/sshconnect2.c =================================================================== ---- openssh-8.9p1.orig/sshconnect2.c -+++ openssh-8.9p1/sshconnect2.c -@@ -81,8 +81,6 @@ +--- openssh-9.6p1.orig/sshconnect2.c ++++ openssh-9.6p1/sshconnect2.c +@@ -80,8 +80,6 @@ #endif /* import */ @@ -3522,7 +3500,7 @@ Index: openssh-8.9p1/sshconnect2.c extern Options options; /* -@@ -220,10 +218,44 @@ ssh_kex2(struct ssh *ssh, char *host, st +@@ -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; @@ -3567,7 +3545,7 @@ Index: openssh-8.9p1/sshconnect2.c if (options.rekey_limit || options.rekey_interval) ssh_packet_set_rekey_limits(ssh, options.rekey_limit, options.rekey_interval); -@@ -282,17 +314,47 @@ ssh_kex2(struct ssh *ssh, char *host, st +@@ -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 @@ -3616,7 +3594,7 @@ Index: openssh-8.9p1/sshconnect2.c if ((r = kex_prop2buf(ssh->kex->my, myproposal)) != 0) fatal_r(r, "kex_prop2buf"); -@@ -385,6 +447,7 @@ static int input_gssapi_response(int typ +@@ -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 *); @@ -3624,7 +3602,7 @@ Index: openssh-8.9p1/sshconnect2.c #endif void userauth(struct ssh *, char *); -@@ -401,6 +464,11 @@ static char *authmethods_get(void); +@@ -395,6 +458,11 @@ static char *authmethods_get(void); Authmethod authmethods[] = { #ifdef GSSAPI @@ -3636,7 +3614,7 @@ Index: openssh-8.9p1/sshconnect2.c {"gssapi-with-mic", userauth_gssapi, userauth_gssapi_cleanup, -@@ -776,12 +844,23 @@ userauth_gssapi(struct ssh *ssh) +@@ -766,12 +834,23 @@ userauth_gssapi(struct ssh *ssh) OM_uint32 min; int r, ok = 0; gss_OID mech = NULL; @@ -3661,7 +3639,7 @@ Index: openssh-8.9p1/sshconnect2.c /* Check to see whether the mechanism is usable before we offer it */ while (authctxt->mech_tried < authctxt->gss_supported_mechs->count && -@@ -790,13 +869,15 @@ userauth_gssapi(struct ssh *ssh) +@@ -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, @@ -3678,7 +3656,7 @@ Index: openssh-8.9p1/sshconnect2.c if (!ok || mech == NULL) return 0; -@@ -1037,6 +1118,55 @@ input_gssapi_error(int type, u_int32_t p +@@ -1020,6 +1101,55 @@ input_gssapi_error(int type, u_int32_t p free(lang); return r; } @@ -3734,11 +3712,11 @@ Index: openssh-8.9p1/sshconnect2.c #endif /* GSSAPI */ static int -Index: openssh-8.9p1/sshd.c +Index: openssh-9.6p1/sshd.c =================================================================== ---- openssh-8.9p1.orig/sshd.c -+++ openssh-8.9p1/sshd.c -@@ -813,8 +813,8 @@ notify_hostkeys(struct ssh *ssh) +--- 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) @@ -3749,7 +3727,7 @@ Index: openssh-8.9p1/sshd.c sshpkt_fatal(ssh, r, "%s: send", __func__); sshbuf_free(buf); } -@@ -1909,7 +1909,8 @@ main(int ac, char **av) +@@ -1944,7 +1944,8 @@ main(int ac, char **av) free(fp); } accumulate_host_timing_secret(cfg, NULL); @@ -3759,12 +3737,7 @@ Index: openssh-8.9p1/sshd.c logit("sshd: no hostkeys available -- exiting."); exit(1); } -@@ -2397,6 +2398,48 @@ do_ssh2_kex(struct ssh *ssh) -# myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal( -# ssh, list_hostkey_types()); -# myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey = -# compat_pkalg_proposal(ssh, list_hostkey_types()); -# +@@ -2421,6 +2422,48 @@ do_ssh2_kex(struct ssh *ssh) free(hkalgs); @@ -3813,7 +3786,7 @@ Index: openssh-8.9p1/sshd.c /* start key exchange */ if ((r = kex_setup(ssh, myproposal)) != 0) fatal_r(r, "kex_setup"); -@@ -2412,7 +2455,18 @@ do_ssh2_kex(struct ssh *ssh) +@@ -2438,7 +2481,18 @@ do_ssh2_kex(struct ssh *ssh) # ifdef OPENSSL_HAS_ECC kex->kex[KEX_ECDH_SHA2] = kex_gen_server; # endif @@ -3833,10 +3806,10 @@ Index: openssh-8.9p1/sshd.c 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-8.9p1/sshd_config +Index: openssh-9.6p1/sshd_config =================================================================== ---- openssh-8.9p1.orig/sshd_config -+++ openssh-8.9p1/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 @@ -3846,11 +3819,11 @@ Index: openssh-8.9p1/sshd_config # Set this to 'yes' to enable PAM authentication, account processing, # and session processing. If this is enabled, PAM authentication will -Index: openssh-8.9p1/sshd_config.5 +Index: openssh-9.6p1/sshd_config.5 =================================================================== ---- openssh-8.9p1.orig/sshd_config.5 -+++ openssh-8.9p1/sshd_config.5 -@@ -652,6 +652,11 @@ Specifies whether to automatically destr +--- 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 . @@ -3862,7 +3835,7 @@ Index: openssh-8.9p1/sshd_config.5 .It Cm GSSAPIStrictAcceptorCheck Determines whether to be strict about the identity of the GSSAPI acceptor a client authenticates against. -@@ -666,6 +671,31 @@ machine's default store. +@@ -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 . @@ -3894,11 +3867,11 @@ Index: openssh-8.9p1/sshd_config.5 .It Cm HostbasedAcceptedAlgorithms Specifies the signature algorithms that will be accepted for hostbased authentication as a list of comma-separated patterns. -Index: openssh-8.9p1/sshkey.c +Index: openssh-9.6p1/sshkey.c =================================================================== ---- openssh-8.9p1.orig/sshkey.c -+++ openssh-8.9p1/sshkey.c -@@ -127,6 +127,17 @@ +--- 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 @@ -3916,7 +3889,7 @@ Index: openssh-8.9p1/sshkey.c const struct sshkey_impl * const keyimpls[] = { &sshkey_ed25519_impl, -@@ -162,6 +179,7 @@ static const struct keytype keytypes[] = +@@ -165,6 +176,7 @@ const struct sshkey_impl * const keyimpl &sshkey_xmss_impl, &sshkey_xmss_cert_impl, #endif @@ -3924,7 +3897,7 @@ Index: openssh-8.9p1/sshkey.c NULL }; -@@ -286,7 +304,7 @@ sshkey_alg_list(int certs_only, int plai +@@ -320,7 +332,7 @@ sshkey_alg_list(int certs_only, int plai for (i = 0; keyimpls[i] != NULL; i++) { impl = keyimpls[i]; @@ -3933,10 +3906,10 @@ Index: openssh-8.9p1/sshkey.c continue; if (!include_sigonly && impl->sigonly) continue; -Index: openssh-8.9p1/sshkey.h +Index: openssh-9.6p1/sshkey.h =================================================================== ---- openssh-8.9p1.orig/sshkey.h -+++ openssh-8.9p1/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, @@ -3945,3 +3918,49 @@ Index: openssh-8.9p1/sshkey.h 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.4p1-pam_motd.patch b/openssh-8.4p1-pam_motd.patch index cfab0c7..a39b139 100644 --- a/openssh-8.4p1-pam_motd.patch +++ b/openssh-8.4p1-pam_motd.patch @@ -1,19 +1,13 @@ -Gemeinsame Unterverzeichnisse: openssh-8.4p1.orig/contrib und openssh-8.4p1/contrib. -Gemeinsame Unterverzeichnisse: openssh-8.4p1.orig/.github und openssh-8.4p1/.github. -Gemeinsame Unterverzeichnisse: openssh-8.4p1.orig/m4 und openssh-8.4p1/m4. -Gemeinsame Unterverzeichnisse: openssh-8.4p1.orig/openbsd-compat und openssh-8.4p1/openbsd-compat. -Gemeinsame Unterverzeichnisse: openssh-8.4p1.orig/regress und openssh-8.4p1/regress. 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,8 @@ +@@ -88,8 +88,7 @@ #X11DisplayOffset 10 #X11UseLocalhost yes #PermitTTY yes -#PrintMotd yes -#PrintLastLog yes +PrintMotd no -+PrintLastLog no #TCPKeepAlive yes #PermitUserEnvironment no #Compression delayed diff --git a/openssh-9.3p2.tar.gz b/openssh-9.3p2.tar.gz deleted file mode 100644 index dd4ac13..0000000 --- a/openssh-9.3p2.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:200ebe147f6cb3f101fd0cdf9e02442af7ddca298dffd9f456878e7ccac676e8 -size 1835850 diff --git a/openssh-9.3p2.tar.gz.asc b/openssh-9.3p2.tar.gz.asc deleted file mode 100644 index 4c69906..0000000 --- a/openssh-9.3p2.tar.gz.asc +++ /dev/null @@ -1,16 +0,0 @@ ------BEGIN PGP SIGNATURE----- - -iQIzBAABCgAdFiEEcWi5g4FaXu9ZpK39Kj9BTnNgYLoFAmS3g5wACgkQKj9BTnNg -YLrMYw//evjl0mlSnycb85tWASdBWQh28xQCouuqYhDhY+8kt6YpEx34r4zuXvL3 -pEN/F1ancNXwvlRPct/tF3OEQVpKHZqiRyfWuHHURSBLaGf9V1b+gQgfM4lEQNtH -8PqRj+ur8E2GMGxvxuDKPcfduCTFrjbPJ/0OCgquuEteSM6dgcClT7q5SKKpTVSa -jV0PaXeYgnaa+u+4GsH01oUteyJNmhvEa4T+fC1RDrct1DiieUQNkaw3pwMqYXA5 -8PldGatn/npNM5ZFW4uxTjbib2yJXNIEhUIzo2A00XWRG3jIArtRJwJ6ZSBahUE4 -PyasPMhJVIxIaKy5OL4s4FAd1goe2hBlPzmDhUJOhpFniLIZ9dS5AGaX4i2TjsZl -iaIwtE2VLIn3peKZPvm7SCBqyBoiPKC0BfHmVOYs8c1W5Q30jE+kCcTDrJhHl32/ -kN5khCHIg6bUc3JzFZM7Ib0tshNP5AY0pyduSEF7SPOB5Zz2E+EwkDmkrnw9FoMh -LCvSERDkBdxWD7okUdb0ARr564lShRjd2UTFZqv3Py4nVfvnP19RgCfakNg0CZ3w -VoLytn8OQ/joAx4GMWox6g5ieYqeQ2kLzXYfXObTlDIjxirFeiBYPh6Ln5oGl81/ -jx/172HqCzRDgUogtZ/BTwiLDEzTHG7YS5RDIUYkqEGkkjjj6gg= -=yVD2 ------END PGP SIGNATURE----- diff --git a/openssh-9.6p1.tar.gz b/openssh-9.6p1.tar.gz new file mode 100644 index 0000000..1173ae1 --- /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..e99892f --- /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 index b25b63e..289d01b 100644 --- a/openssh-askpass-gnome.changes +++ b/openssh-askpass-gnome.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +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 diff --git a/openssh-askpass-gnome.spec b/openssh-askpass-gnome.spec index 2d230ff..56c8891 100644 --- a/openssh-askpass-gnome.spec +++ b/openssh-askpass-gnome.spec @@ -18,7 +18,7 @@ %define _name openssh Name: openssh-askpass-gnome -Version: 9.3p2 +Version: 9.6p1 Release: 0 Summary: A GNOME-Based Passphrase Dialog for OpenSSH License: BSD-2-Clause diff --git a/openssh-cve-2023-48795.patch b/openssh-cve-2023-48795.patch deleted file mode 100644 index 5d9d843..0000000 --- a/openssh-cve-2023-48795.patch +++ /dev/null @@ -1,399 +0,0 @@ -Index: openssh-9.3p2/PROTOCOL -=================================================================== ---- openssh-9.3p2.orig/PROTOCOL -+++ openssh-9.3p2/PROTOCOL -@@ -104,6 +104,25 @@ http://git.libssh.org/users/aris/libssh. - - This is identical to curve25519-sha256 as later published in RFC8731. - -+1.9 transport: strict key exchange extension -+ -+OpenSSH supports a number of transport-layer hardening measures under -+a "strict KEX" feature. This feature is signalled similarly to the -+RFC8305 ext-info feature: by including a additional algorithm in the -+SSH2_MSG_KEXINIT kex_algorithms field. The client may append -+"kex-strict-c-v00@openssh.com" to its kex_algorithms and the server -+may append "kex-strict-s-v00@openssh.com". -+ -+When endpoint that supports this extension observes this algorithm -+name in a peer's KEXINIT packet, it MUST make the following changes to -+the the protocol: -+ -+a) During initial KEX, terminate the connection if any unexpected or -+ out-of-sequence packet is received. This includes terminating the -+ connection if the first packet received is not SSH2_MSG_KEXINIT. -+b) At each SSH2_MSG_NEWKEYS message, reset the packet sequence number -+ to zero. -+ - 2. Connection protocol changes - - 2.1. connection: Channel write close extension "eow@openssh.com" -Index: openssh-9.3p2/kex.c -=================================================================== ---- openssh-9.3p2.orig/kex.c -+++ openssh-9.3p2/kex.c -@@ -76,7 +76,7 @@ - #include "fips.h" - - /* prototype */ --static int kex_choose_conf(struct ssh *); -+static int kex_choose_conf(struct ssh *, uint32_t seq); - static int kex_input_newkeys(int, u_int32_t, struct ssh *); - - static const char * const proposal_names[PROPOSAL_MAX] = { -@@ -261,6 +261,18 @@ kex_names_valid(const char *names) - return 1; - } - -+/* returns non-zero if proposal contains any algorithm from algs */ -+static int -+has_any_alg(const char *proposal, const char *algs) -+{ -+ char *cp; -+ -+ if ((cp = match_list(proposal, algs, NULL)) == NULL) -+ return 0; -+ free(cp); -+ return 1; -+} -+ - /* - * Concatenate algorithm names, avoiding duplicates in the process. - * Caller must free returned string. -@@ -268,7 +280,7 @@ kex_names_valid(const char *names) - char * - kex_names_cat(const char *a, const char *b) - { -- char *ret = NULL, *tmp = NULL, *cp, *p, *m; -+ char *ret = NULL, *tmp = NULL, *cp, *p; - size_t len; - - if (a == NULL || *a == '\0') -@@ -285,10 +297,8 @@ kex_names_cat(const char *a, const char - } - strlcpy(ret, a, len); - for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) { -- if ((m = match_list(ret, p, NULL)) != NULL) { -- free(m); -+ if (has_any_alg(ret, p)) - continue; /* Algorithm already present */ -- } - if (strlcat(ret, ",", len) >= len || - strlcat(ret, p, len) >= len) { - free(tmp); -@@ -441,15 +451,23 @@ kex_proposal_populate_entries(struct ssh - const char *defpropclient[PROPOSAL_MAX] = { KEX_CLIENT }; - const char **defprop = ssh->kex->server ? defpropserver : defpropclient; - u_int i; -+ char *cp; - - if (prop == NULL) - fatal_f("proposal missing"); - -+ /* Append EXT_INFO signalling to KexAlgorithms */ -+ if (kexalgos == NULL) -+ kexalgos = defprop[PROPOSAL_KEX_ALGS]; -+ if ((cp = kex_names_cat(kexalgos, ssh->kex->server ? -+ "kex-strict-s-v00@openssh.com" : -+ "ext-info-c,kex-strict-c-v00@openssh.com")) == NULL) -+ fatal_f("kex_names_cat"); -+ - for (i = 0; i < PROPOSAL_MAX; i++) { - switch(i) { - case PROPOSAL_KEX_ALGS: -- prop[i] = compat_kex_proposal(ssh, -- kexalgos ? kexalgos : defprop[i]); -+ prop[i] = compat_kex_proposal(ssh, cp); - break; - case PROPOSAL_ENC_ALGS_CTOS: - case PROPOSAL_ENC_ALGS_STOC: -@@ -470,6 +488,7 @@ kex_proposal_populate_entries(struct ssh - prop[i] = xstrdup(defprop[i]); - } - } -+ free(cp); - } - - void -@@ -573,7 +592,12 @@ kex_protocol_error(int type, u_int32_t s - { - int r; - -- error("kex protocol error: type %d seq %u", type, seq); -+ /* If in strict mode, any unexpected message is an error */ -+ if ((ssh->kex->flags & KEX_INITIAL) && ssh->kex->kex_strict) { -+ ssh_packet_disconnect(ssh, "strict KEX violation: " -+ "unexpected packet type %u (seqnr %u)", type, seq); -+ } -+ error_f("type %u seq %u", type, seq); - if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 || - (r = sshpkt_put_u32(ssh, seq)) != 0 || - (r = sshpkt_send(ssh)) != 0) -@@ -651,7 +675,7 @@ kex_input_ext_info(int type, u_int32_t s - if (ninfo >= 1024) { - error("SSH2_MSG_EXT_INFO with too many entries, expected " - "<=1024, received %u", ninfo); -- return SSH_ERR_INVALID_FORMAT; -+ return dispatch_protocol_error(type, seq, ssh); - } - for (i = 0; i < ninfo; i++) { - if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0) -@@ -767,7 +791,7 @@ kex_input_kexinit(int type, u_int32_t se - error_f("no kex"); - return SSH_ERR_INTERNAL_ERROR; - } -- ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, NULL); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_protocol_error); - ptr = sshpkt_ptr(ssh, &dlen); - if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0) - return r; -@@ -803,7 +827,7 @@ kex_input_kexinit(int type, u_int32_t se - if (!(kex->flags & KEX_INIT_SENT)) - if ((r = kex_send_kexinit(ssh)) != 0) - return r; -- if ((r = kex_choose_conf(ssh)) != 0) -+ if ((r = kex_choose_conf(ssh, seq)) != 0) - return r; - - if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL) -@@ -1082,20 +1106,14 @@ proposals_match(char *my[PROPOSAL_MAX], - return (1); - } - --/* returns non-zero if proposal contains any algorithm from algs */ - static int --has_any_alg(const char *proposal, const char *algs) -+kexalgs_contains(char **peer, const char *ext) - { -- char *cp; -- -- if ((cp = match_list(proposal, algs, NULL)) == NULL) -- return 0; -- free(cp); -- return 1; -+ return has_any_alg(peer[PROPOSAL_KEX_ALGS], ext); - } - - static int --kex_choose_conf(struct ssh *ssh) -+kex_choose_conf(struct ssh *ssh, uint32_t seq) - { - struct kex *kex = ssh->kex; - struct newkeys *newkeys; -@@ -1120,13 +1138,23 @@ kex_choose_conf(struct ssh *ssh) - sprop=peer; - } - -- /* Check whether client supports ext_info_c */ -- if (kex->server && (kex->flags & KEX_INITIAL)) { -- char *ext; -- -- ext = match_list("ext-info-c", peer[PROPOSAL_KEX_ALGS], NULL); -- kex->ext_info_c = (ext != NULL); -- free(ext); -+ /* Check whether peer supports ext_info/kex_strict */ -+ if ((kex->flags & KEX_INITIAL) != 0) { -+ if (kex->server) { -+ kex->ext_info_c = kexalgs_contains(peer, "ext-info-c"); -+ kex->kex_strict = kexalgs_contains(peer, -+ "kex-strict-c-v00@openssh.com"); -+ } else { -+ kex->kex_strict = kexalgs_contains(peer, -+ "kex-strict-s-v00@openssh.com"); -+ } -+ if (kex->kex_strict) { -+ debug3_f("will use strict KEX ordering"); -+ if (seq != 0) -+ ssh_packet_disconnect(ssh, -+ "strict KEX violation: " -+ "KEXINIT was not the first packet"); -+ } - } - - /* Check whether client supports rsa-sha2 algorithms */ -Index: openssh-9.3p2/kex.h -=================================================================== ---- openssh-9.3p2.orig/kex.h -+++ openssh-9.3p2/kex.h -@@ -157,6 +157,7 @@ struct kex { - u_int kex_type; - char *server_sig_algs; - int ext_info_c; -+ int kex_strict; - struct sshbuf *my; - struct sshbuf *peer; - struct sshbuf *client_version; -Index: openssh-9.3p2/packet.c -=================================================================== ---- openssh-9.3p2.orig/packet.c -+++ openssh-9.3p2/packet.c -@@ -1236,6 +1236,11 @@ ssh_packet_send2_wrapped(struct ssh *ssh - state->p_send.bytes += len; - sshbuf_reset(state->outgoing_packet); - -+ if (type == SSH2_MSG_NEWKEYS && ssh->kex->kex_strict) { -+ debug_f("resetting send seqnr %u", state->p_send.seqnr); -+ state->p_send.seqnr = 0; -+ } -+ - if (type == SSH2_MSG_NEWKEYS) - r = ssh_set_newkeys(ssh, MODE_OUT); - else if (type == SSH2_MSG_USERAUTH_SUCCESS && state->server_side) -@@ -1364,8 +1369,7 @@ ssh_packet_read_seqnr(struct ssh *ssh, u - /* Stay in the loop until we have received a complete packet. */ - for (;;) { - /* Try to read a packet from the buffer. */ -- r = ssh_packet_read_poll_seqnr(ssh, typep, seqnr_p); -- if (r != 0) -+ if ((r = ssh_packet_read_poll_seqnr(ssh, typep, seqnr_p)) != 0) - break; - /* If we got a packet, return it. */ - if (*typep != SSH_MSG_NONE) -@@ -1649,6 +1630,7 @@ ssh_packet_read_poll2(struct ssh *ssh, u - if ((r = sshbuf_consume(state->input, mac->mac_len)) != 0) - goto out; - } -+ - if (seqnr_p != NULL) - *seqnr_p = state->p_read.seqnr; - if (++state->p_read.seqnr == 0) -@@ -1718,6 +1700,10 @@ ssh_packet_read_poll2(struct ssh *ssh, u - #endif - /* reset for next packet */ - state->packlen = 0; -+ if (*typep == SSH2_MSG_NEWKEYS && ssh->kex->kex_strict) { -+ debug_f("resetting read seqnr %u", state->p_read.seqnr); -+ state->p_read.seqnr = 0; -+ } - - if ((r = ssh_packet_check_rekey(ssh)) != 0) - return r; -@@ -1738,10 +1724,39 @@ ssh_packet_read_poll_seqnr(struct ssh *s - r = ssh_packet_read_poll2(ssh, typep, seqnr_p); - if (r != 0) - return r; -- if (*typep) { -- state->keep_alive_timeouts = 0; -- DBG(debug("received packet type %d", *typep)); -+ if (*typep == 0) { -+ /* no message ready */ -+ return 0; - } -+ state->keep_alive_timeouts = 0; -+ DBG(debug("received packet type %d", *typep)); -+ -+ /* Always process disconnect messages */ -+ if (*typep == SSH2_MSG_DISCONNECT) { -+ if ((r = sshpkt_get_u32(ssh, &reason)) != 0 || -+ (r = sshpkt_get_string(ssh, &msg, NULL)) != 0) -+ return r; -+ /* Ignore normal client exit notifications */ -+ do_log2(ssh->state->server_side && -+ reason == SSH2_DISCONNECT_BY_APPLICATION ? -+ SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR, -+ "Received disconnect from %s port %d:" -+ "%u: %.400s", ssh_remote_ipaddr(ssh), -+ ssh_remote_port(ssh), reason, msg); -+ free(msg); -+ return SSH_ERR_DISCONNECTED; -+ } -+ -+ /* -+ * Do not implicitly handle any messages here during initial -+ * KEX when in strict mode. They will be need to be allowed -+ * explicitly by the KEX dispatch table or they will generate -+ * protocol errors. -+ */ -+ if (ssh->kex != NULL && -+ (ssh->kex->flags & KEX_INITIAL) && ssh->kex->kex_strict) -+ return 0; -+ /* Implicitly handle transport-level messages */ - switch (*typep) { - case SSH2_MSG_IGNORE: - debug3("Received SSH2_MSG_IGNORE"); -@@ -1756,19 +1771,6 @@ ssh_packet_read_poll_seqnr(struct ssh *s - debug("Remote: %.900s", msg); - free(msg); - break; -- case SSH2_MSG_DISCONNECT: -- if ((r = sshpkt_get_u32(ssh, &reason)) != 0 || -- (r = sshpkt_get_string(ssh, &msg, NULL)) != 0) -- return r; -- /* Ignore normal client exit notifications */ -- do_log2(ssh->state->server_side && -- reason == SSH2_DISCONNECT_BY_APPLICATION ? -- SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR, -- "Received disconnect from %s port %d:" -- "%u: %.400s", ssh_remote_ipaddr(ssh), -- ssh_remote_port(ssh), reason, msg); -- free(msg); -- return SSH_ERR_DISCONNECTED; - case SSH2_MSG_UNIMPLEMENTED: - if ((r = sshpkt_get_u32(ssh, &seqnr)) != 0) - return r; -@@ -2300,6 +2302,7 @@ kex_to_blob(struct sshbuf *m, struct kex - (r = sshbuf_put_u32(m, kex->hostkey_type)) != 0 || - (r = sshbuf_put_u32(m, kex->hostkey_nid)) != 0 || - (r = sshbuf_put_u32(m, kex->kex_type)) != 0 || -+ (r = sshbuf_put_u32(m, kex->kex_strict)) != 0 || - (r = sshbuf_put_stringb(m, kex->my)) != 0 || - (r = sshbuf_put_stringb(m, kex->peer)) != 0 || - (r = sshbuf_put_stringb(m, kex->client_version)) != 0 || -@@ -2462,6 +2465,7 @@ kex_from_blob(struct sshbuf *m, struct k - (r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_type)) != 0 || - (r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_nid)) != 0 || - (r = sshbuf_get_u32(m, &kex->kex_type)) != 0 || -+ (r = sshbuf_get_u32(m, &kex->kex_strict)) != 0 || - (r = sshbuf_get_stringb(m, kex->my)) != 0 || - (r = sshbuf_get_stringb(m, kex->peer)) != 0 || - (r = sshbuf_get_stringb(m, kex->client_version)) != 0 || -@@ -2790,6 +2794,7 @@ sshpkt_disconnect(struct ssh *ssh, const - vsnprintf(buf, sizeof(buf), fmt, args); - va_end(args); - -+ debug2_f("sending SSH2_MSG_DISCONNECT: %s", buf); - if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 || - (r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_PROTOCOL_ERROR)) != 0 || - (r = sshpkt_put_cstring(ssh, buf)) != 0 || -Index: openssh-9.3p2/sshconnect2.c -=================================================================== ---- openssh-9.3p2.orig/sshconnect2.c -+++ openssh-9.3p2/sshconnect2.c -@@ -420,7 +420,6 @@ struct cauthmethod { - }; - - static int input_userauth_service_accept(int, u_int32_t, struct ssh *); --static int input_userauth_ext_info(int, u_int32_t, struct ssh *); - static int input_userauth_success(int, u_int32_t, struct ssh *); - static int input_userauth_failure(int, u_int32_t, struct ssh *); - static int input_userauth_banner(int, u_int32_t, struct ssh *); -@@ -540,7 +539,7 @@ ssh_userauth2(struct ssh *ssh, const cha - - ssh->authctxt = &authctxt; - ssh_dispatch_init(ssh, &input_userauth_error); -- ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &input_userauth_ext_info); -+ ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, kex_input_ext_info); - ssh_dispatch_set(ssh, SSH2_MSG_SERVICE_ACCEPT, &input_userauth_service_accept); - ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &authctxt.success); /* loop until success */ - pubkey_cleanup(ssh); -@@ -591,12 +590,6 @@ input_userauth_service_accept(int type, - return r; - } - --static int --input_userauth_ext_info(int type, u_int32_t seqnr, struct ssh *ssh) --{ -- return kex_input_ext_info(type, seqnr, ssh); --} -- - void - userauth(struct ssh *ssh, char *authlist) - { -@@ -675,6 +668,7 @@ input_userauth_success(int type, u_int32 - free(authctxt->methoddata); - authctxt->methoddata = NULL; - authctxt->success = 1; /* break out */ -+ ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, dispatch_protocol_error); - return 0; - } - diff --git a/openssh.changes b/openssh.changes index 469e000..20921de 100644 --- a/openssh.changes +++ b/openssh.changes @@ -1,10 +1,264 @@ ------------------------------------------------------------------- -Wed Dec 13 22:33:40 UTC 2023 - Hans Petter Jansson +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 @@ -46,6 +300,17 @@ Fri Jul 21 02:48:58 UTC 2023 - Simon Lees 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 diff --git a/openssh.spec b/openssh.spec index d79906b..b096164 100644 --- a/openssh.spec +++ b/openssh.spec @@ -37,7 +37,7 @@ %define _fillupdir %{_localstatedir}/adm/fillup-templates %endif Name: openssh -Version: 9.3p2 +Version: 9.6p1 Release: 0 Summary: Secure Shell Client and Server (Remote Login Program) License: BSD-2-Clause AND MIT @@ -115,8 +115,13 @@ Patch48: openssh-8.4p1-pam_motd.patch Patch49: openssh-do-not-send-empty-message.patch Patch50: openssh-openssl-3.patch Patch51: wtmpdb.patch -Patch52: openssh-cve-2023-48795.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 @@ -318,6 +323,10 @@ export LDFLAGS CFLAGS CXXFLAGS CPPFLAGS --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 @@ -338,8 +347,10 @@ install -m 644 %{SOURCE15} %{buildroot}%{_sysconfdir}/pam.d/sshd 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} @@ -377,6 +388,9 @@ install -D -m 0755 %{SOURCE9} %{buildroot}%{_sbindir}/sshd-gen-keys-start 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 @@ -486,8 +500,10 @@ test -f /etc/ssh/ssh_config.rpmsave && mv -v /etc/ssh/ssh_config.rpmsave /etc/ss %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}