Sync from SUSE:ALP:Source:Standard:1.0 openssh revision f793e41158efbf91a9de8e2e7a9a07fd

This commit is contained in:
Adrian Schröter 2024-03-15 15:48:53 +01:00
parent 5498cc7816
commit 00e6e9d3e4
18 changed files with 2729 additions and 742 deletions

197
logind_set_tty.patch Normal file
View File

@ -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 <wtmpdb.h>
#endif
+#ifdef USE_LOGIND
+# include <systemd/sd-bus.h>
+#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

View File

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

491
openssh-6.6p1-keycat.patch Normal file
View File

@ -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 <tmraz@redhat.com>
+*/
+
+#define _GNU_SOURCE
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <pwd.h>
+#include <fcntl.h>
+#include <unistd.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#include <security/pam_appl.h>
+
+#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 <user-name>\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 ""

View File

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

View File

@ -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 <unistd.h>
#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);

View File

@ -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 <sys/socket.h>
#include <sys/stat.h>
+#include "fips.h"
+
#ifdef WITH_OPENSSL
# define DEFAULT_KEY_TYPE_NAME "rsa"
#else
@@ -1037,11 +1039,13 @@ do_fingerprint(struct passwd *pw)
#include <openssl/evp.h>
#include <openssl/pem.h>
@@ -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 .

View File

@ -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 <dwalsh@redhat.com>
+ * Copyright (c) 2014 Petr Lautrbach <plautrba@redhat.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Linux-specific portability code - just SELinux support for sshd at present
+ */
+
+#include "includes.h"
+
+#if defined(WITH_SELINUX) || defined(LINUX_OOM_ADJUST)
+#include <errno.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#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 <selinux/selinux.h>
+#include <selinux/context.h>
+#include <selinux/get_context_list.h>
+#include <selinux/get_default_type.h>
+
+#ifdef HAVE_LINUX_AUDIT
+#include <libaudit.h>
+#include <unistd.h>
+#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);

File diff suppressed because it is too large Load Diff

View File

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

BIN
openssh-9.3p2.tar.gz (Stored with Git LFS)

Binary file not shown.

View File

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

BIN
openssh-9.6p1.tar.gz (Stored with Git LFS) Normal file

Binary file not shown.

16
openssh-9.6p1.tar.gz.asc Normal file
View File

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

View File

@ -1,3 +1,10 @@
-------------------------------------------------------------------
Sun Feb 25 18:26:23 UTC 2024 - Hans Petter Jansson <hpj@suse.com>
- 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 <sflees@suse.de>

View File

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

View File

@ -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;
}

View File

@ -1,10 +1,264 @@
-------------------------------------------------------------------
Wed Dec 13 22:33:40 UTC 2023 - Hans Petter Jansson <hpj@suse.com>
Sun Feb 25 18:26:23 UTC 2024 - Hans Petter Jansson <hpj@suse.com>
- 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 <hpj@suse.com>
- 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 <jsegitz@suse.com>
- 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 <dimstar@opensuse.org>
- 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 <kukuk@suse.com>
- Disable SLP by default for Factory and ALP (bsc#1214884)
-------------------------------------------------------------------
Fri Jul 21 02:48:58 UTC 2023 - Simon Lees <sflees@suse.de>
@ -46,6 +300,17 @@ Fri Jul 21 02:48:58 UTC 2023 - Simon Lees <sflees@suse.de>
may circumvent this restriction.
-------------------------------------------------------------------
Wed Jun 21 12:14:54 UTC 2023 - Thorsten Kukuk <kukuk@suse.com>
- 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 <kukuk@suse.com>
- logind_set_tty.patch: tell systemd-logind our current TTY
-------------------------------------------------------------------
Thu May 11 07:01:54 UTC 2023 - Antonio Larrosa <alarrosa@suse.com>

View File

@ -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}