Compare commits

..

20 commits

Author SHA1 Message Date
Mattias Ellert
513f05f80f Based on openssh-7.4p1-23.el7_9 2023-08-11 22:57:54 +02:00
Mattias Ellert
91484c75c8 Based on openssh-7.4p1-22.el7_9 2021-11-24 17:40:33 +01:00
Frank Scheiner
ed68bed373 Add HPN patch 2020-10-23 20:10:23 +02:00
Mattias Ellert
9bb59e17ee Based on openssh-7.4p1-21.el7 2019-08-07 23:08:32 +02:00
Mattias Ellert
1d6d885889 Change GSSAPITrustDNS default to no 2019-05-28 16:42:24 +02:00
Mattias Ellert
5308f95f9c Remove usage statistics collection support 2019-02-27 13:05:37 +01:00
Mattias Ellert
57d77f9250 Based on openssh-7.4p1-16.el7 2018-04-10 17:14:06 +02:00
Mattias Ellert
16c223fac6 Based on openssh-7.4p1-13.el7_4 2017-11-13 12:40:23 +01:00
Mattias Ellert
e59e91f6ab Based on openssh-6.6.1p1-35.el7_3
Update GSI patch with more openssl 1.1.0 fixes from Globus
2017-07-31 11:37:50 +02:00
Mattias Ellert
53e3b2afc3 Based on openssh-6.6.1p1-33.el7_3 2017-02-24 14:10:14 +01:00
Mattias Ellert
2202381388 Adding mechanism OID negotiation with the introduction of micv2 OID 2016-12-15 16:41:25 +01:00
Mattias Ellert
6348beb8a1 Based on openssh 6.6.1p1-31.el7 2016-12-15 09:18:40 +01:00
Mattias Ellert
aa9e2ef9b3 Based on openssh-6.6.1p1-25.el7_2 2016-06-26 07:42:37 +02:00
Mattias Ellert
92bc715130 Based on openssh-6.6.1p1-23.el7_2 2016-01-19 22:49:53 +01:00
Mattias Ellert
95ab173057 Fix typos in gsisshd.service file 2015-08-05 11:53:02 +02:00
Mattias Ellert
72c0682d9d Based on openssh-6.6.1p1-12.el7_1 2015-07-05 15:16:49 +02:00
Mattias Ellert
50cfa4c143 Based on openssh-6.4p1-8.el7 2014-07-16 23:13:46 +02:00
Mattias Ellert
4ba46b6c82 Based on openssh-6.4p1-1.el7 2014-01-28 09:34:16 +01:00
Mattias Ellert
509f103f2d Based on openssh-6.2p2-7.fc19 2013-12-12 03:15:00 +01:00
Mattias Ellert
da751ef47d Based on openssh-6.2p2-6.fc19 2013-11-26 16:01:28 +01:00
129 changed files with 19166 additions and 34432 deletions

2
.gitignore vendored
View file

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

View file

@ -1,144 +0,0 @@
From 99d8e250514023d3b88a1c9eb724c4898aba9827 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:28 +0200
Subject: [PATCH 02/50] openssh-6.6p1-privsep-selinux
---
openbsd-compat/port-linux-sshd.c | 22 ++++++++++++++++++++++
openbsd-compat/port-linux.h | 1 +
session.c | 16 +++++++++-------
sshd-auth.c | 4 ++++
sshd-session.c | 2 +-
5 files changed, 37 insertions(+), 8 deletions(-)
diff --git a/openbsd-compat/port-linux-sshd.c b/openbsd-compat/port-linux-sshd.c
index b9fbe38b..dfafc622 100644
--- a/openbsd-compat/port-linux-sshd.c
+++ b/openbsd-compat/port-linux-sshd.c
@@ -415,6 +415,28 @@ sshd_selinux_setup_exec_context(char *pwname)
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
diff --git a/openbsd-compat/port-linux.h b/openbsd-compat/port-linux.h
index 055c825e..498d242a 100644
--- a/openbsd-compat/port-linux.h
+++ b/openbsd-compat/port-linux.h
@@ -23,6 +23,7 @@ void ssh_selinux_setup_pty(char *, const char *);
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
diff --git a/session.c b/session.c
index 6444c77f..e4657cef 100644
--- a/session.c
+++ b/session.c
@@ -1350,7 +1350,7 @@ do_setusercontext(struct passwd *pw)
platform_setusercontext(pw);
- if (platform_privileged_uidswap()) {
+ if (platform_privileged_uidswap() && !is_child) {
#ifdef HAVE_LOGIN_CAP
if (setusercontext(lc, pw, pw->pw_uid,
(LOGIN_SETALL & ~(LOGIN_SETPATH|LOGIN_SETUSER))) < 0) {
@@ -1382,6 +1382,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);
@@ -1417,6 +1420,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");
@@ -1434,9 +1442,6 @@ do_pwchange(Session *s)
if (s->ttyfd != -1) {
fprintf(stderr,
"You must change your password now and log in again!\n");
-#ifdef WITH_SELINUX
- setexeccon(NULL);
-#endif
#ifdef PASSWD_NEEDS_USERNAME
execl(_PATH_PASSWD_PROG, "passwd", s->pw->pw_name,
(char *)NULL);
@@ -1649,9 +1654,6 @@ do_child(struct ssh *ssh, Session *s, const char *command)
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));
}
diff --git a/sshd-auth.c b/sshd-auth.c
index 30eecd8a..f957dc22 100644
--- a/sshd-auth.c
+++ b/sshd-auth.c
@@ -187,6 +187,10 @@ privsep_child_demote(void)
if ((box = ssh_sandbox_init(pmonitor)) == NULL)
fatal_f("ssh_sandbox_init failed");
#endif
+#ifdef WITH_SELINUX
+ ssh_selinux_change_context("sshd_net_t");
+#endif
+
/* Demote the child */
if (privsep_chroot) {
/* Change our root directory */
diff --git a/sshd-session.c b/sshd-session.c
index 74d2cbc7..4a148db4 100644
--- a/sshd-session.c
+++ b/sshd-session.c
@@ -432,7 +432,7 @@ privsep_postauth(struct ssh *ssh, Authctxt *authctxt)
* fd passing, as AFAIK PTY allocation on this platform doesn't require
* special privileges to begin with.
*/
-#if defined(DISABLE_FD_PASSING) && !defined(HAVE_CYGWIN)
+#if defined(DISABLE_FD_PASSING) && !defined(HAVE_CYGWIN) && !defined(WITH_SELINUX)
skip_privdrop = 1;
#endif
--
2.49.0

View file

@ -1,26 +0,0 @@
From 80359feb76fd8061b5ce18f73451d7b9db0c2477 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:28 +0200
Subject: [PATCH 06/50] openssh-5.8p2-sigpipe
---
ssh-keyscan.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/ssh-keyscan.c b/ssh-keyscan.c
index 3436c0b5..9f76ad22 100644
--- a/ssh-keyscan.c
+++ b/ssh-keyscan.c
@@ -798,6 +798,9 @@ main(int argc, char **argv)
if (maxfd > fdlim_get(0))
fdlim_set(maxfd);
fdcon = xcalloc(maxfd, sizeof(con));
+
+ signal(SIGPIPE, SIG_IGN);
+
read_wait = xcalloc(maxfd, sizeof(struct pollfd));
for (j = 0; j < maxfd; j++)
read_wait[j].fd = -1;
--
2.49.0

View file

@ -1,96 +0,0 @@
From 6b2a33044583e892badb9ac86cd2c6252b1a532f Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:28 +0200
Subject: [PATCH 08/50] openssh-5.1p1-askpass-progress
---
contrib/gnome-ssh-askpass2.c | 39 +++++++++++++++++++++++++++++++++---
1 file changed, 36 insertions(+), 3 deletions(-)
diff --git a/contrib/gnome-ssh-askpass2.c b/contrib/gnome-ssh-askpass2.c
index a62f9815..cb7152dc 100644
--- a/contrib/gnome-ssh-askpass2.c
+++ b/contrib/gnome-ssh-askpass2.c
@@ -58,6 +58,7 @@
#include <unistd.h>
#include <X11/Xlib.h>
+#include <glib.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <gdk/gdkkeysyms.h>
@@ -146,6 +147,17 @@ parse_env_hex_color(const char *env, GdkColor *c)
return 1;
}
+static void
+move_progress(GtkWidget *entry, gpointer progress)
+{
+ gdouble step;
+ g_return_if_fail(GTK_IS_PROGRESS_BAR(progress));
+
+ step = g_random_double_range(0.03, 0.1);
+ gtk_progress_bar_set_pulse_step(GTK_PROGRESS_BAR(progress), step);
+ gtk_progress_bar_pulse(GTK_PROGRESS_BAR(progress));
+}
+
static int
passphrase_dialog(char *message, int prompt_type)
{
@@ -153,7 +165,7 @@ passphrase_dialog(char *message, int prompt_type)
char *passphrase, *local;
int result, grab_tries, grab_server, grab_pointer;
int buttons, default_response;
- GtkWidget *parent_window, *dialog, *entry;
+ GtkWidget *parent_window, *dialog, *entry, *progress, *hbox;
GdkGrabStatus status;
GdkColor fg, bg;
int fg_set = 0, bg_set = 0;
@@ -199,14 +211,19 @@ passphrase_dialog(char *message, int prompt_type)
gtk_widget_modify_bg(dialog, GTK_STATE_NORMAL, &bg);
if (prompt_type == PROMPT_ENTRY || prompt_type == PROMPT_NONE) {
+ hbox = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, FALSE,
+ FALSE, 0);
+ gtk_widget_show(hbox);
+
entry = gtk_entry_new();
if (fg_set)
gtk_widget_modify_fg(entry, GTK_STATE_NORMAL, &fg);
if (bg_set)
gtk_widget_modify_bg(entry, GTK_STATE_NORMAL, &bg);
gtk_box_pack_start(
- GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))),
- entry, FALSE, FALSE, 0);
+ GTK_BOX(hbox), entry, TRUE, FALSE, 0);
+ gtk_entry_set_width_chars(GTK_ENTRY(entry), 2);
gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE);
gtk_widget_grab_focus(entry);
if (prompt_type == PROMPT_ENTRY) {
@@ -225,6 +242,22 @@ passphrase_dialog(char *message, int prompt_type)
g_signal_connect(G_OBJECT(entry), "key_press_event",
G_CALLBACK(check_none), dialog);
}
+
+ hbox = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
+ hbox, FALSE, FALSE, 8);
+ gtk_widget_show(hbox);
+
+ progress = gtk_progress_bar_new();
+
+ gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress),
+ "Passphrase length hidden intentionally");
+ gtk_box_pack_start(GTK_BOX(hbox), progress, TRUE,
+ TRUE, 5);
+ gtk_widget_show(progress);
+ g_signal_connect(G_OBJECT(entry), "changed",
+ G_CALLBACK(move_progress), progress);
+
}
/* Grab focus */
--
2.49.0

View file

@ -1,31 +0,0 @@
From 710ce53fdf1d32a0629fce2e42fb49d407e2b06c Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:28 +0200
Subject: [PATCH 09/50] openssh-4.3p2-askpass-grab-info
---
contrib/gnome-ssh-askpass2.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/contrib/gnome-ssh-askpass2.c b/contrib/gnome-ssh-askpass2.c
index cb7152dc..bbe93d83 100644
--- a/contrib/gnome-ssh-askpass2.c
+++ b/contrib/gnome-ssh-askpass2.c
@@ -70,8 +70,12 @@ report_failed_grab (GtkWidget *parent_window, const char *what)
err = gtk_message_dialog_new(GTK_WINDOW(parent_window), 0,
GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
- "Could not grab %s. A malicious client may be eavesdropping "
- "on your session.", what);
+ "SSH password dialog could not grab the %s input.\n"
+ "This might be caused by application such as screensaver, "
+ "however it could also mean that someone may be eavesdropping "
+ "on your session.\n"
+ "Either close the application which grabs the %s or "
+ "log out and log in again to prevent this from happening.", what, what);
gtk_window_set_position(GTK_WINDOW(err), GTK_WIN_POS_CENTER);
gtk_dialog_run(GTK_DIALOG(err));
--
2.49.0

View file

@ -1,146 +0,0 @@
From 5f21983f6472b26693babea4d6ca6b95a7dc7b05 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:28 +0200
Subject: [PATCH 10/50] openssh-8.7p1-redhat
---
ssh_config | 7 +++++++
ssh_config_redhat | 18 ++++++++++++++++++
sshd_config | 8 ++++++++
sshd_config.0 | 6 +++---
sshd_config.5 | 2 +-
sshd_config_redhat | 18 ++++++++++++++++++
sshd_config_redhat_cp | 7 +++++++
7 files changed, 62 insertions(+), 4 deletions(-)
create mode 100644 ssh_config_redhat
create mode 100644 sshd_config_redhat
create mode 100644 sshd_config_redhat_cp
diff --git a/ssh_config b/ssh_config
index cc566356..18169187 100644
--- a/ssh_config
+++ b/ssh_config
@@ -44,3 +44,10 @@
# ProxyCommand ssh -q -W %h:%p gateway.example.com
# RekeyLimit 1G 1h
# UserKnownHostsFile ~/.ssh/known_hosts.d/%k
+#
+# This system is following system-wide crypto policy.
+# To modify the crypto properties (Ciphers, MACs, ...), create a *.conf
+# file under /etc/ssh/ssh_config.d/ which will be automatically
+# included below. For more information, see manual page for
+# update-crypto-policies(8) and ssh_config(5).
+Include /etc/ssh/ssh_config.d/*.conf
diff --git a/ssh_config_redhat b/ssh_config_redhat
new file mode 100644
index 00000000..8b1b5902
--- /dev/null
+++ b/ssh_config_redhat
@@ -0,0 +1,18 @@
+# The options here are in the "Match final block" to be applied as the last
+# options and could be potentially overwritten by the user configuration
+Match final all
+ # Follow system-wide Crypto Policy, if defined:
+ Include /etc/crypto-policies/back-ends/openssh.config
+
+ GSSAPIAuthentication yes
+
+# If this option is set to yes then remote X11 clients will have full access
+# to the original X11 display. As virtually no X11 client supports the untrusted
+# mode correctly we set this to yes.
+ ForwardX11Trusted yes
+
+# rhbz#2352653 - export COLORTERM
+ SendEnv COLORTERM
+
+# Uncomment this if you want to use .local domain
+# Host *.local
diff --git a/sshd_config b/sshd_config
index 0f4a3a72..608203e4 100644
--- a/sshd_config
+++ b/sshd_config
@@ -10,6 +10,14 @@
# possible, but leave them commented. Uncommented options override the
# default value.
+# To modify the system-wide sshd configuration, create a *.conf file under
+# /etc/ssh/sshd_config.d/ which will be automatically included below
+Include /etc/ssh/sshd_config.d/*.conf
+
+# If you want to change the port on a SELinux system, you have to tell
+# SELinux about this change.
+# semanage port -a -t ssh_port_t -p tcp #PORTNUMBER
+#
#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
diff --git a/sshd_config.0 b/sshd_config.0
index 2f77b4f4..49349bb3 100644
--- a/sshd_config.0
+++ b/sshd_config.0
@@ -1219,9 +1219,9 @@ DESCRIPTION
SyslogFacility
Gives the facility code that is used when logging messages from
- sshd(8). The possible values are: DAEMON, USER, AUTH, LOCAL0,
- LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The
- default is AUTH.
+ sshd(8). The possible values are: DAEMON, USER, AUTH, AUTHPRIV,
+ LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
+ The default is AUTH.
TCPKeepAlive
Specifies whether the system should send TCP keepalive messages
diff --git a/sshd_config.5 b/sshd_config.5
index c0771737..035a50c8 100644
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -1942,7 +1942,7 @@ By default no subsystems are defined.
.It Cm SyslogFacility
Gives the facility code that is used when logging messages from
.Xr sshd 8 .
-The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2,
+The possible values are: DAEMON, USER, AUTH, AUTHPRIV, LOCAL0, LOCAL1, LOCAL2,
LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
The default is AUTH.
.It Cm TCPKeepAlive
diff --git a/sshd_config_redhat b/sshd_config_redhat
new file mode 100644
index 00000000..993a28d5
--- /dev/null
+++ b/sshd_config_redhat
@@ -0,0 +1,18 @@
+SyslogFacility AUTHPRIV
+
+KbdInteractiveAuthentication no
+
+GSSAPIAuthentication yes
+GSSAPICleanupCredentials no
+
+UsePAM yes
+
+X11Forwarding yes
+
+# rhbz#2352653 - accept COLORTERM
+ AcceptEnv COLORTERM
+
+# It is recommended to use pam_motd in /etc/pam.d/sshd instead of PrintMotd,
+# as it is more configurable and versatile than the built-in version.
+PrintMotd no
+
diff --git a/sshd_config_redhat_cp b/sshd_config_redhat_cp
new file mode 100644
index 00000000..1d592d13
--- /dev/null
+++ b/sshd_config_redhat_cp
@@ -0,0 +1,7 @@
+# This system is following system-wide crypto policy. The changes to
+# crypto properties (Ciphers, MACs, ...) will not have any effect in
+# this or following included files. To override some configuration option,
+# write it before this block or include it before this file.
+# Please, see manual pages for update-crypto-policies(8) and sshd_config(5).
+Include /etc/crypto-policies/back-ends/opensshserver.config
+
--
2.49.0

View file

@ -1,41 +0,0 @@
From 56b8d082bc9e25a77b5227d576f27088446c6fb9 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:28 +0200
Subject: [PATCH 11/50] openssh-7.8p1-UsePAM-warning
---
sshd-session.c | 4 ++++
sshd_config | 2 ++
2 files changed, 6 insertions(+)
diff --git a/sshd-session.c b/sshd-session.c
index a365f26f..a70b36c9 100644
--- a/sshd-session.c
+++ b/sshd-session.c
@@ -1127,6 +1127,10 @@ main(int ac, char **av)
"enabled authentication methods");
}
+ /* 'UsePAM no' is not supported in our builds */
+ if (! options.use_pam)
+ logit("WARNING: 'UsePAM no' is not supported in this build and may cause several problems.");
+
#ifdef WITH_OPENSSL
if (options.moduli_file != NULL)
dh_set_moduli_file(options.moduli_file);
diff --git a/sshd_config b/sshd_config
index 608203e4..48af6321 100644
--- a/sshd_config
+++ b/sshd_config
@@ -89,6 +89,8 @@ AuthorizedKeysFile .ssh/authorized_keys
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and KbdInteractiveAuthentication to 'no'.
+# WARNING: 'UsePAM no' is not supported in this build and may cause several
+# problems.
#UsePAM no
#AllowAgentForwarding yes
--
2.49.0

File diff suppressed because it is too large Load diff

View file

@ -1,665 +0,0 @@
From 5fca5946aa97dce23c6824c52b070a92532752a9 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:28 +0200
Subject: [PATCH 14/50] openssh-7.7p1-gssapi-new-unique
---
auth-krb5.c | 262 ++++++++++++++++++++++++++++++++++++++++++------
auth.h | 3 +-
gss-serv-krb5.c | 42 +++-----
gss-serv.c | 10 +-
servconf.c | 12 ++-
servconf.h | 2 +
session.c | 5 +-
ssh-gss.h | 4 +-
sshd-session.c | 2 +-
sshd_config.5 | 8 ++
10 files changed, 279 insertions(+), 71 deletions(-)
diff --git a/auth-krb5.c b/auth-krb5.c
index c99e4e43..77714e3d 100644
--- a/auth-krb5.c
+++ b/auth-krb5.c
@@ -51,6 +51,7 @@
#include <unistd.h>
#include <string.h>
#include <krb5.h>
+#include <profile.h>
extern ServerOptions options;
@@ -77,7 +78,7 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
#endif
krb5_error_code problem;
krb5_ccache ccache = NULL;
- int len;
+ char *ticket_name = NULL;
char *client, *platform_client;
const char *errmsg;
@@ -163,8 +164,8 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
goto out;
}
- problem = ssh_krb5_cc_gen(authctxt->krb5_ctx,
- &authctxt->krb5_fwd_ccache);
+ problem = ssh_krb5_cc_new_unique(authctxt->krb5_ctx,
+ &authctxt->krb5_fwd_ccache, &authctxt->krb5_set_env);
if (problem)
goto out;
@@ -179,15 +180,14 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
goto out;
#endif
- authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
+ problem = krb5_cc_get_full_name(authctxt->krb5_ctx,
+ authctxt->krb5_fwd_ccache, &ticket_name);
- len = strlen(authctxt->krb5_ticket_file) + 6;
- authctxt->krb5_ccname = xmalloc(len);
- snprintf(authctxt->krb5_ccname, len, "FILE:%s",
- authctxt->krb5_ticket_file);
+ authctxt->krb5_ccname = xstrdup(ticket_name);
+ krb5_free_string(authctxt->krb5_ctx, ticket_name);
#ifdef USE_PAM
- if (options.use_pam)
+ if (options.use_pam && authctxt->krb5_set_env)
do_pam_putenv("KRB5CCNAME", authctxt->krb5_ccname);
#endif
@@ -223,11 +223,54 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
void
krb5_cleanup_proc(Authctxt *authctxt)
{
+ struct stat krb5_ccname_stat;
+ char krb5_ccname[128], *krb5_ccname_dir_start, *krb5_ccname_dir_end;
+
debug("krb5_cleanup_proc called");
if (authctxt->krb5_fwd_ccache) {
- krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
+ krb5_context ctx = authctxt->krb5_ctx;
+ krb5_cccol_cursor cursor;
+ krb5_ccache ccache;
+ int ret;
+
+ krb5_cc_destroy(ctx, authctxt->krb5_fwd_ccache);
authctxt->krb5_fwd_ccache = NULL;
+
+ ret = krb5_cccol_cursor_new(ctx, &cursor);
+ if (ret)
+ goto out;
+
+ ret = krb5_cccol_cursor_next(ctx, cursor, &ccache);
+ if (ret == 0 && ccache != NULL) {
+ /* There is at least one other ccache in collection
+ * we can switch to */
+ krb5_cc_switch(ctx, ccache);
+ } else if (authctxt->krb5_ccname != NULL) {
+ /* Clean up the collection too */
+ strncpy(krb5_ccname, authctxt->krb5_ccname, sizeof(krb5_ccname) - 10);
+ krb5_ccname_dir_start = strchr(krb5_ccname, ':') + 1;
+ *krb5_ccname_dir_start++ = '\0';
+ if (strcmp(krb5_ccname, "DIR") == 0) {
+
+ strcat(krb5_ccname_dir_start, "/primary");
+
+ if (stat(krb5_ccname_dir_start, &krb5_ccname_stat) == 0) {
+ if (unlink(krb5_ccname_dir_start) == 0) {
+ krb5_ccname_dir_end = strrchr(krb5_ccname_dir_start, '/');
+ *krb5_ccname_dir_end = '\0';
+ if (rmdir(krb5_ccname_dir_start) == -1)
+ debug("cache dir '%s' remove failed: %s",
+ krb5_ccname_dir_start, strerror(errno));
+ }
+ else
+ debug("cache primary file '%s', remove failed: %s",
+ krb5_ccname_dir_start, strerror(errno));
+ }
+ }
+ }
+ krb5_cccol_cursor_free(ctx, &cursor);
}
+out:
if (authctxt->krb5_user) {
krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user);
authctxt->krb5_user = NULL;
@@ -238,36 +281,189 @@ krb5_cleanup_proc(Authctxt *authctxt)
}
}
-#ifndef HEIMDAL
-krb5_error_code
-ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
- int tmpfd, ret, oerrno;
- char ccname[40];
- mode_t old_umask;
- ret = snprintf(ccname, sizeof(ccname),
- "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
- if (ret < 0 || (size_t)ret >= sizeof(ccname))
- return ENOMEM;
-
- old_umask = umask(0177);
- tmpfd = mkstemp(ccname + strlen("FILE:"));
- oerrno = errno;
- umask(old_umask);
- if (tmpfd == -1) {
- logit("mkstemp(): %.100s", strerror(oerrno));
- return oerrno;
+#if !defined(HEIMDAL)
+int
+ssh_asprintf_append(char **dsc, const char *fmt, ...) {
+ char *src, *old;
+ va_list ap;
+ int i;
+
+ va_start(ap, fmt);
+ i = vasprintf(&src, fmt, ap);
+ va_end(ap);
+
+ if (i == -1 || src == NULL)
+ return -1;
+
+ old = *dsc;
+
+ i = asprintf(dsc, "%s%s", *dsc, src);
+ if (i == -1) {
+ *dsc = old;
+ free(src);
+ return -1;
+ }
+
+ free(old);
+ free(src);
+
+ return i;
+}
+
+int
+ssh_krb5_expand_template(char **result, const char *template) {
+ char *p_n, *p_o, *r, *tmp_template;
+
+ debug3_f("called, template = %s", template);
+ if (template == NULL)
+ return -1;
+
+ tmp_template = p_n = p_o = xstrdup(template);
+ r = xstrdup("");
+
+ while ((p_n = strstr(p_o, "%{")) != NULL) {
+
+ *p_n++ = '\0';
+ if (ssh_asprintf_append(&r, "%s", p_o) == -1)
+ goto cleanup;
+
+ if (strncmp(p_n, "{uid}", 5) == 0 || strncmp(p_n, "{euid}", 6) == 0 ||
+ strncmp(p_n, "{USERID}", 8) == 0) {
+ p_o = strchr(p_n, '}') + 1;
+ if (ssh_asprintf_append(&r, "%d", geteuid()) == -1)
+ goto cleanup;
+ continue;
+ }
+ else if (strncmp(p_n, "{TEMP}", 6) == 0) {
+ p_o = strchr(p_n, '}') + 1;
+ if (ssh_asprintf_append(&r, "/tmp") == -1)
+ goto cleanup;
+ continue;
+ } else {
+ p_o = strchr(p_n, '}') + 1;
+ *p_o = '\0';
+ debug_f("unsupported token %s in %s", p_n, template);
+ /* unknown token, fallback to the default */
+ goto cleanup;
+ }
}
- if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) {
+ if (ssh_asprintf_append(&r, "%s", p_o) == -1)
+ goto cleanup;
+
+ *result = r;
+ free(tmp_template);
+ return 0;
+
+cleanup:
+ free(r);
+ free(tmp_template);
+ return -1;
+}
+
+krb5_error_code
+ssh_krb5_get_cctemplate(krb5_context ctx, char **ccname) {
+ profile_t p;
+ int ret = 0;
+ char *value = NULL;
+
+ debug3_f("called");
+ ret = krb5_get_profile(ctx, &p);
+ if (ret)
+ return ret;
+
+ ret = profile_get_string(p, "libdefaults", "default_ccache_name", NULL, NULL, &value);
+ if (ret || !value)
+ return ret;
+
+ ret = ssh_krb5_expand_template(ccname, value);
+
+ debug3_f("returning with ccname = %s", *ccname);
+ return ret;
+}
+
+krb5_error_code
+ssh_krb5_cc_new_unique(krb5_context ctx, krb5_ccache *ccache, int *need_environment) {
+ int tmpfd, ret, oerrno, type_len;
+ char *ccname = NULL;
+ mode_t old_umask;
+ char *type = NULL, *colon = NULL;
+
+ debug3_f("called");
+ if (need_environment)
+ *need_environment = 0;
+ ret = ssh_krb5_get_cctemplate(ctx, &ccname);
+ if (ret || !ccname || options.kerberos_unique_ccache) {
+ /* Otherwise, go with the old method */
+ if (ccname)
+ free(ccname);
+ ccname = NULL;
+
+ ret = asprintf(&ccname,
+ "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
+ if (ret < 0)
+ return ENOMEM;
+
+ old_umask = umask(0177);
+ tmpfd = mkstemp(ccname + strlen("FILE:"));
oerrno = errno;
- logit("fchmod(): %.100s", strerror(oerrno));
+ umask(old_umask);
+ if (tmpfd == -1) {
+ logit("mkstemp(): %.100s", strerror(oerrno));
+ return oerrno;
+ }
+
+ if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) {
+ oerrno = errno;
+ logit("fchmod(): %.100s", strerror(oerrno));
+ close(tmpfd);
+ return oerrno;
+ }
+ /* make sure the KRB5CCNAME is set for non-standard location */
+ if (need_environment)
+ *need_environment = 1;
close(tmpfd);
- return oerrno;
}
- close(tmpfd);
- return (krb5_cc_resolve(ctx, ccname, ccache));
+ debug3_f("setting default ccname to %s", ccname);
+ /* set the default with already expanded user IDs */
+ ret = krb5_cc_set_default_name(ctx, ccname);
+ if (ret)
+ return ret;
+
+ if ((colon = strstr(ccname, ":")) != NULL) {
+ type_len = colon - ccname;
+ type = malloc((type_len + 1) * sizeof(char));
+ if (type == NULL)
+ return ENOMEM;
+ strncpy(type, ccname, type_len);
+ type[type_len] = 0;
+ } else {
+ type = strdup(ccname);
+ }
+
+ /* If we have a credential cache from krb5.conf, we need to switch
+ * a primary cache for this collection, if it supports that (non-FILE)
+ */
+ if (krb5_cc_support_switch(ctx, type)) {
+ debug3_f("calling cc_new_unique(%s)", ccname);
+ ret = krb5_cc_new_unique(ctx, type, NULL, ccache);
+ free(type);
+ if (ret)
+ return ret;
+
+ debug3_f("calling cc_switch()");
+ return krb5_cc_switch(ctx, *ccache);
+ } else {
+ /* Otherwise, we can not create a unique ccname here (either
+ * it is already unique from above or the type does not support
+ * collections
+ */
+ free(type);
+ debug3_f("calling cc_resolve(%s)", ccname);
+ return (krb5_cc_resolve(ctx, ccname, ccache));
+ }
}
#endif /* !HEIMDAL */
#endif /* KRB5 */
diff --git a/auth.h b/auth.h
index 83d07ae8..10e88e11 100644
--- a/auth.h
+++ b/auth.h
@@ -85,6 +85,7 @@ struct Authctxt {
krb5_principal krb5_user;
char *krb5_ticket_file;
char *krb5_ccname;
+ int krb5_set_env;
#endif
struct sshbuf *loginmsg;
@@ -245,7 +246,7 @@ FILE *auth_openprincipals(const char *, struct passwd *, int);
int sys_auth_passwd(struct ssh *, const char *);
#if defined(KRB5) && !defined(HEIMDAL)
-krb5_error_code ssh_krb5_cc_gen(krb5_context, krb5_ccache *);
+krb5_error_code ssh_krb5_cc_new_unique(krb5_context, krb5_ccache *, int *);
#endif
#endif /* AUTH_H */
diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c
index 14502c5a..df55512d 100644
--- a/gss-serv-krb5.c
+++ b/gss-serv-krb5.c
@@ -267,7 +267,7 @@ ssh_gssapi_krb5_cmdok(krb5_principal principal, const char *name,
/* This writes out any forwarded credentials from the structure populated
* during userauth. Called after we have setuid to the user */
-static void
+static int
ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
{
krb5_ccache ccache;
@@ -276,14 +276,15 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
OM_uint32 maj_status, min_status;
const char *new_ccname, *new_cctype;
const char *errmsg;
+ int set_env = 0;
if (client->creds == NULL) {
debug("No credentials stored");
- return;
+ return 0;
}
if (ssh_gssapi_krb5_init() == 0)
- return;
+ return 0;
#ifdef HEIMDAL
# ifdef HAVE_KRB5_CC_NEW_UNIQUE
@@ -297,14 +298,14 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
krb5_get_err_text(krb_context, problem));
# endif
krb5_free_error_message(krb_context, errmsg);
- return;
+ return 0;
}
#else
- if ((problem = ssh_krb5_cc_gen(krb_context, &ccache))) {
+ if ((problem = ssh_krb5_cc_new_unique(krb_context, &ccache, &set_env)) != 0) {
errmsg = krb5_get_error_message(krb_context, problem);
- logit("ssh_krb5_cc_gen(): %.100s", errmsg);
+ logit("ssh_krb5_cc_new_unique(): %.100s", errmsg);
krb5_free_error_message(krb_context, errmsg);
- return;
+ return 0;
}
#endif /* #ifdef HEIMDAL */
@@ -313,7 +314,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
errmsg = krb5_get_error_message(krb_context, problem);
logit("krb5_parse_name(): %.100s", errmsg);
krb5_free_error_message(krb_context, errmsg);
- return;
+ return 0;
}
if ((problem = krb5_cc_initialize(krb_context, ccache, princ))) {
@@ -322,7 +323,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
krb5_free_error_message(krb_context, errmsg);
krb5_free_principal(krb_context, princ);
krb5_cc_destroy(krb_context, ccache);
- return;
+ return 0;
}
krb5_free_principal(krb_context, princ);
@@ -331,32 +332,21 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
client->creds, ccache))) {
logit("gss_krb5_copy_ccache() failed");
krb5_cc_destroy(krb_context, ccache);
- return;
+ return 0;
}
new_cctype = krb5_cc_get_type(krb_context, ccache);
new_ccname = krb5_cc_get_name(krb_context, ccache);
-
- client->store.envvar = "KRB5CCNAME";
-#ifdef USE_CCAPI
- xasprintf(&client->store.envval, "API:%s", new_ccname);
- client->store.filename = NULL;
-#else
- if (new_ccname[0] == ':')
- new_ccname++;
xasprintf(&client->store.envval, "%s:%s", new_cctype, new_ccname);
- if (strcmp(new_cctype, "DIR") == 0) {
- char *p;
- p = strrchr(client->store.envval, '/');
- if (p)
- *p = '\0';
+
+ if (set_env) {
+ client->store.envvar = "KRB5CCNAME";
}
if ((strcmp(new_cctype, "FILE") == 0) || (strcmp(new_cctype, "DIR") == 0))
client->store.filename = xstrdup(new_ccname);
-#endif
#ifdef USE_PAM
- if (options.use_pam)
+ if (options.use_pam && set_env)
do_pam_putenv(client->store.envvar, client->store.envval);
#endif
@@ -364,7 +354,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
client->store.data = krb_context;
- return;
+ return set_env;
}
int
diff --git a/gss-serv.c b/gss-serv.c
index a5cca797..9d5435ed 100644
--- a/gss-serv.c
+++ b/gss-serv.c
@@ -414,13 +414,15 @@ ssh_gssapi_cleanup_creds(void)
}
/* As user */
-void
+int
ssh_gssapi_storecreds(void)
{
if (gssapi_client.mech && gssapi_client.mech->storecreds) {
- (*gssapi_client.mech->storecreds)(&gssapi_client);
+ return (*gssapi_client.mech->storecreds)(&gssapi_client);
} else
debug("ssh_gssapi_storecreds: Not a GSSAPI mechanism");
+
+ return 0;
}
/* This allows GSSAPI methods to do things to the child's environment based
@@ -500,9 +502,7 @@ ssh_gssapi_rekey_creds(void) {
char *envstr;
#endif
- if (gssapi_client.store.filename == NULL &&
- gssapi_client.store.envval == NULL &&
- gssapi_client.store.envvar == NULL)
+ if (gssapi_client.store.envval == NULL)
return;
ok = mm_ssh_gssapi_update_creds(&gssapi_client.store);
diff --git a/servconf.c b/servconf.c
index d4f7fd66..55aa5bf0 100644
--- a/servconf.c
+++ b/servconf.c
@@ -138,6 +138,7 @@ initialize_server_options(ServerOptions *options)
options->kerberos_or_local_passwd = -1;
options->kerberos_ticket_cleanup = -1;
options->kerberos_get_afs_token = -1;
+ options->kerberos_unique_ccache = -1;
options->gss_authentication=-1;
options->gss_keyex = -1;
options->gss_cleanup_creds = -1;
@@ -382,6 +383,8 @@ fill_default_server_options(ServerOptions *options)
options->kerberos_ticket_cleanup = 1;
if (options->kerberos_get_afs_token == -1)
options->kerberos_get_afs_token = 0;
+ if (options->kerberos_unique_ccache == -1)
+ options->kerberos_unique_ccache = 0;
if (options->gss_authentication == -1)
options->gss_authentication = 0;
if (options->gss_keyex == -1)
@@ -564,7 +567,7 @@ typedef enum {
sPort, sHostKeyFile, sLoginGraceTime,
sPermitRootLogin, sLogFacility, sLogLevel, sLogVerbose,
sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
- sKerberosGetAFSToken, sPasswordAuthentication,
+ sKerberosGetAFSToken, sKerberosUniqueCCache, sPasswordAuthentication,
sKbdInteractiveAuthentication, sListenAddress, sAddressFamily,
sPrintMotd, sPrintLastLog, sIgnoreRhosts,
sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
@@ -655,11 +658,13 @@ static struct {
#else
{ "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
#endif
+ { "kerberosuniqueccache", sKerberosUniqueCCache, SSHCFG_GLOBAL },
#else
{ "kerberosauthentication", sUnsupported, SSHCFG_ALL },
{ "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL },
{ "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
{ "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
+ { "kerberosuniqueccache", sUnsupported, SSHCFG_GLOBAL },
#endif
{ "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
{ "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
@@ -1668,6 +1673,10 @@ process_server_config_line_depth(ServerOptions *options, char *line,
intptr = &options->kerberos_get_afs_token;
goto parse_flag;
+ case sKerberosUniqueCCache:
+ intptr = &options->kerberos_unique_ccache;
+ goto parse_flag;
+
case sGssAuthentication:
intptr = &options->gss_authentication;
goto parse_flag;
@@ -3293,6 +3302,7 @@ dump_config(ServerOptions *o)
# ifdef USE_AFS
dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token);
# endif
+ dump_cfg_fmtint(sKerberosUniqueCCache, o->kerberos_unique_ccache);
#endif
#ifdef GSSAPI
dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
diff --git a/servconf.h b/servconf.h
index c3f50140..a4a38d6d 100644
--- a/servconf.h
+++ b/servconf.h
@@ -149,6 +149,8 @@ typedef struct {
* file on logout. */
int kerberos_get_afs_token; /* If true, try to get AFS token if
* authenticated with Kerberos. */
+ int kerberos_unique_ccache; /* If true, the acquired ticket will
+ * be stored in per-session ccache */
int gss_authentication; /* If true, permit GSSAPI authentication */
int gss_keyex; /* If true, permit GSSAPI key exchange */
int gss_cleanup_creds; /* If true, destroy cred cache on logout */
diff --git a/session.c b/session.c
index 89b3a9cf..2620dd11 100644
--- a/session.c
+++ b/session.c
@@ -1025,7 +1025,8 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell)
/* Allow any GSSAPI methods that we've used to alter
* the child's environment as they see fit
*/
- ssh_gssapi_do_child(&env, &envsize);
+ if (s->authctxt->krb5_set_env)
+ ssh_gssapi_do_child(&env, &envsize);
#endif
/* Set basic environment. */
@@ -1101,7 +1102,7 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell)
}
#endif
#ifdef KRB5
- if (s->authctxt->krb5_ccname)
+ if (s->authctxt->krb5_ccname && s->authctxt->krb5_set_env)
child_set_env(&env, &envsize, "KRB5CCNAME",
s->authctxt->krb5_ccname);
#endif
diff --git a/ssh-gss.h b/ssh-gss.h
index db34d77f..a894e23c 100644
--- a/ssh-gss.h
+++ b/ssh-gss.h
@@ -116,7 +116,7 @@ typedef struct ssh_gssapi_mech_struct {
int (*dochild) (ssh_gssapi_client *);
int (*userok) (ssh_gssapi_client *, char *);
int (*localname) (ssh_gssapi_client *, char **);
- void (*storecreds) (ssh_gssapi_client *);
+ int (*storecreds) (ssh_gssapi_client *);
int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *);
} ssh_gssapi_mech;
@@ -186,7 +186,7 @@ int ssh_gssapi_userok(char *name, struct passwd *, int kex);
OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
void ssh_gssapi_do_child(char ***, u_int *);
void ssh_gssapi_cleanup_creds(void);
-void ssh_gssapi_storecreds(void);
+int ssh_gssapi_storecreds(void);
const char *ssh_gssapi_displayname(void);
char *ssh_gssapi_server_mechanisms(void);
diff --git a/sshd-session.c b/sshd-session.c
index f8c8a797..478381db 100644
--- a/sshd-session.c
+++ b/sshd-session.c
@@ -1349,7 +1349,7 @@ main(int ac, char **av)
#ifdef GSSAPI
if (options.gss_authentication) {
temporarily_use_uid(authctxt->pw);
- ssh_gssapi_storecreds();
+ authctxt->krb5_set_env = ssh_gssapi_storecreds();
restore_uid();
}
#endif
diff --git a/sshd_config.5 b/sshd_config.5
index 8bc6586e..1251d4d5 100644
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -1033,6 +1033,14 @@ Specifies whether to automatically destroy the user's ticket cache
file on logout.
The default is
.Cm yes .
+.It Cm KerberosUniqueCCache
+Specifies whether to store the acquired tickets in the per-session credential
+cache under /tmp/ or whether to use per-user credential cache as configured in
+.Pa /etc/krb5.conf .
+The default value
+.Cm no
+can lead to overwriting previous tickets by subseqent connections to the same
+user account.
.It Cm KexAlgorithms
Specifies the permitted KEX (Key Exchange) algorithms that the server will
offer to clients.
--
2.49.0

View file

@ -1,28 +0,0 @@
From 20aabb2c445e29d211266ce7434bb0273edf88b9 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:28 +0200
Subject: [PATCH 17/50] openssh-6.4p1-fromto-remote
---
scp.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/scp.c b/scp.c
index 57c242ff..716ae386 100644
--- a/scp.c
+++ b/scp.c
@@ -1162,7 +1162,10 @@ toremote(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct)
addargs(&alist, "%s", ssh_program);
addargs(&alist, "-x");
addargs(&alist, "-oClearAllForwardings=yes");
- addargs(&alist, "-n");
+ if (isatty(fileno(stdin)))
+ addargs(&alist, "-t");
+ else
+ addargs(&alist, "-n");
for (j = 0; j < remote_remote_args.num; j++) {
addargs(&alist, "%s",
remote_remote_args.list[j]);
--
2.49.0

View file

@ -1,147 +0,0 @@
From 6481ac7fbd0027a7038560e0f51dd0af056cc229 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:28 +0200
Subject: [PATCH 18/50] openssh-6.6.1p1-selinux-contexts
---
openbsd-compat/port-linux-sshd.c | 69 +++++++++++++++++++++++++++++++-
openbsd-compat/port-linux.c | 2 +-
openbsd-compat/port-linux.h | 1 +
sshd-auth.c | 2 +-
4 files changed, 71 insertions(+), 3 deletions(-)
diff --git a/openbsd-compat/port-linux-sshd.c b/openbsd-compat/port-linux-sshd.c
index 8c5fc1fe..646f0887 100644
--- a/openbsd-compat/port-linux-sshd.c
+++ b/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"
@@ -450,7 +451,7 @@ sshd_selinux_setup_exec_context(char *pwname)
void
sshd_selinux_copy_context(void)
{
- security_context_t *ctx;
+ char *ctx;
if (!sshd_selinux_enabled())
return;
@@ -469,6 +470,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
diff --git a/openbsd-compat/port-linux.c b/openbsd-compat/port-linux.c
index 7426f6f7..9a6b1d6e 100644
--- a/openbsd-compat/port-linux.c
+++ b/openbsd-compat/port-linux.c
@@ -188,7 +188,7 @@ ssh_selinux_change_context(const char *newname)
xasprintf(&newctx, "%.*s%s%s", (int)(cx - oldctx + 1), oldctx,
newname, cx2 == NULL ? "" : cx2);
- debug3_f("setting context from '%s' to '%s'", oldctx, newctx);
+ debug_f("setting context from '%s' to '%s'", oldctx, newctx);
if (setcon(newctx) < 0)
do_log2_f(log_level, "setcon %s from %s failed with %s",
newctx, oldctx, strerror(errno));
diff --git a/openbsd-compat/port-linux.h b/openbsd-compat/port-linux.h
index 1b745a76..7f8ba200 100644
--- a/openbsd-compat/port-linux.h
+++ b/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
diff --git a/sshd-auth.c b/sshd-auth.c
index d51e4636..e4a8edfd 100644
--- a/sshd-auth.c
+++ b/sshd-auth.c
@@ -188,7 +188,7 @@ privsep_child_demote(void)
fatal_f("ssh_sandbox_init failed");
#endif
#ifdef WITH_SELINUX
- ssh_selinux_change_context("sshd_net_t");
+ sshd_selinux_change_privsep_preauth_context();
#endif
/* Demote the child */
--
2.49.0

View file

@ -1,255 +0,0 @@
From 825018f5f2d892655f3d63167a0d1f3391cec678 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:28 +0200
Subject: [PATCH 19/50] openssh-6.6.1p1-log-in-chroot
---
log.c | 11 +++++++++--
log.h | 1 +
monitor.c | 17 +++++++++++++++--
monitor.h | 2 +-
session.c | 26 +++++++++++++++-----------
sftp-server-main.c | 2 +-
sftp-server.c | 6 +++---
sftp.h | 2 +-
sshd-session.c | 7 ++++++-
9 files changed, 52 insertions(+), 22 deletions(-)
diff --git a/log.c b/log.c
index 6617f267..9782cfb0 100644
--- a/log.c
+++ b/log.c
@@ -196,6 +196,11 @@ void
log_init(const char *av0, LogLevel level, SyslogFacility facility,
int on_stderr)
{
+ log_init_handler(av0, level, facility, on_stderr, 1);
+}
+
+void
+log_init_handler(const char *av0, LogLevel level, SyslogFacility facility, int on_stderr, int reset_handler) {
#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
struct syslog_data sdata = SYSLOG_DATA_INIT;
#endif
@@ -208,8 +213,10 @@ log_init(const char *av0, LogLevel level, SyslogFacility facility,
exit(1);
}
- log_handler = NULL;
- log_handler_ctx = NULL;
+ if (reset_handler) {
+ log_handler = NULL;
+ log_handler_ctx = NULL;
+ }
log_on_stderr = on_stderr;
if (on_stderr)
diff --git a/log.h b/log.h
index 8e8dfc23..70048a8a 100644
--- a/log.h
+++ b/log.h
@@ -52,6 +52,7 @@ typedef enum {
typedef void (log_handler_fn)(LogLevel, int, const char *, void *);
void log_init(const char *, LogLevel, SyslogFacility, int);
+void log_init_handler(const char *, LogLevel, SyslogFacility, int, int);
LogLevel log_level_get(void);
int log_change_level(LogLevel);
int log_is_on_stderr(void);
diff --git a/monitor.c b/monitor.c
index 2ef16cc8..43c10a4e 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2001,9 +2001,22 @@ monitor_init(void)
}
void
-monitor_reinit(struct monitor *mon)
+monitor_reinit(struct monitor *mon, const char *chroot_dir)
{
- monitor_openfds(mon, 0);
+ struct stat dev_log_stat;
+ char *dev_log_path;
+ int do_logfds = 0;
+
+ if (chroot_dir != NULL) {
+ xasprintf(&dev_log_path, "%s/dev/log", chroot_dir);
+
+ if (stat(dev_log_path, &dev_log_stat) != 0) {
+ debug_f("/dev/log doesn't exist in %s chroot - will try to log via monitor using [postauth] suffix", chroot_dir);
+ do_logfds = 1;
+ }
+ free(dev_log_path);
+ }
+ monitor_openfds(mon, do_logfds);
}
#ifdef GSSAPI
diff --git a/monitor.h b/monitor.h
index dbc7e003..d4d631dd 100644
--- a/monitor.h
+++ b/monitor.h
@@ -85,7 +85,7 @@ struct monitor {
};
struct monitor *monitor_init(void);
-void monitor_reinit(struct monitor *);
+void monitor_reinit(struct monitor *, const char *);
struct Authctxt;
void monitor_child_preauth(struct ssh *, struct monitor *);
diff --git a/session.c b/session.c
index 2620dd11..54da09d5 100644
--- a/session.c
+++ b/session.c
@@ -169,6 +169,7 @@ login_cap_t *lc;
static int is_child = 0;
static int in_chroot = 0;
+static int have_dev_log = 1;
/* File containing userauth info, if ExposeAuthInfo set */
static char *auth_info_file = NULL;
@@ -670,6 +671,7 @@ do_exec(struct ssh *ssh, Session *s, const char *command)
int ret;
const char *forced = NULL, *tty = NULL;
char session_type[1024];
+ struct stat dev_log_stat;
if (options.adm_forced_command) {
original_command = command;
@@ -729,6 +731,10 @@ do_exec(struct ssh *ssh, Session *s, const char *command)
tty += 5;
}
+ if (lstat("/dev/log", &dev_log_stat) != 0) {
+ have_dev_log = 0;
+ }
+
verbose("Starting session: %s%s%s for %s from %.200s port %d id %d",
session_type,
tty == NULL ? "" : " on ",
@@ -1512,14 +1518,6 @@ child_close_fds(struct ssh *ssh)
/* Stop directing logs to a high-numbered fd before we close it */
log_redirect_stderr_to(NULL);
-
- /*
- * Close any extra open file descriptors so that we don't have them
- * hanging around in clients. Note that we want to do this after
- * initgroups, because at least on Solaris 2.3 it leaves file
- * descriptors open.
- */
- closefrom(STDERR_FILENO + 1);
}
/*
@@ -1652,8 +1650,6 @@ do_child(struct ssh *ssh, Session *s, const char *command)
exit(1);
}
- closefrom(STDERR_FILENO + 1);
-
do_rc_files(ssh, s, shell);
/* restore SIGPIPE for child */
@@ -1678,9 +1674,17 @@ do_child(struct ssh *ssh, Session *s, const char *command)
argv[i] = NULL;
optind = optreset = 1;
__progname = argv[0];
- exit(sftp_server_main(i, argv, s->pw));
+ exit(sftp_server_main(i, argv, s->pw, have_dev_log));
}
+ /*
+ * Close any extra open file descriptors so that we don't have them
+ * hanging around in clients. Note that we want to do this after
+ * initgroups, because at least on Solaris 2.3 it leaves file
+ * descriptors open.
+ */
+ closefrom(STDERR_FILENO + 1);
+
fflush(NULL);
/* Get the last component of the shell name. */
diff --git a/sftp-server-main.c b/sftp-server-main.c
index 2c70f89b..bbb79f27 100644
--- a/sftp-server-main.c
+++ b/sftp-server-main.c
@@ -48,5 +48,5 @@ main(int argc, char **argv)
return 1;
}
- return (sftp_server_main(argc, argv, user_pw));
+ return (sftp_server_main(argc, argv, user_pw, 0));
}
diff --git a/sftp-server.c b/sftp-server.c
index a4abb9f7..4985da38 100644
--- a/sftp-server.c
+++ b/sftp-server.c
@@ -1901,7 +1901,7 @@ sftp_server_usage(void)
}
int
-sftp_server_main(int argc, char **argv, struct passwd *user_pw)
+sftp_server_main(int argc, char **argv, struct passwd *user_pw, int reset_handler)
{
int i, r, in, out, ch, skipargs = 0, log_stderr = 0;
ssize_t len, olen;
@@ -1913,7 +1913,7 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
extern char *__progname;
__progname = ssh_get_progname(argv[0]);
- log_init(__progname, log_level, log_facility, log_stderr);
+ log_init_handler(__progname, log_level, log_facility, log_stderr, reset_handler);
pw = pwcopy(user_pw);
@@ -1986,7 +1986,7 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
}
}
- log_init(__progname, log_level, log_facility, log_stderr);
+ log_init_handler(__progname, log_level, log_facility, log_stderr, reset_handler);
/*
* On platforms where we can, avoid making /proc/self/{mem,maps}
diff --git a/sftp.h b/sftp.h
index 2bde8bb7..ddf1a396 100644
--- a/sftp.h
+++ b/sftp.h
@@ -97,5 +97,5 @@
struct passwd;
-int sftp_server_main(int, char **, struct passwd *);
+int sftp_server_main(int, char **, struct passwd *, int);
void sftp_server_cleanup_exit(int) __attribute__((noreturn));
diff --git a/sshd-session.c b/sshd-session.c
index 478381db..9342e416 100644
--- a/sshd-session.c
+++ b/sshd-session.c
@@ -437,7 +437,7 @@ privsep_postauth(struct ssh *ssh, Authctxt *authctxt)
#endif
/* New socket pair */
- monitor_reinit(pmonitor);
+ monitor_reinit(pmonitor, options.chroot_directory);
pmonitor->m_pid = fork();
if (pmonitor->m_pid == -1)
@@ -456,6 +456,11 @@ privsep_postauth(struct ssh *ssh, Authctxt *authctxt)
close(pmonitor->m_sendfd);
pmonitor->m_sendfd = -1;
+ close(pmonitor->m_log_recvfd);
+ pmonitor->m_log_recvfd = -1;
+
+ if (pmonitor->m_log_sendfd != -1)
+ set_log_handler(mm_log_handler, pmonitor);
/* Demote the private keys to public keys. */
demote_sensitive_data();
--
2.49.0

View file

@ -1,27 +0,0 @@
From 007ee98fa9100f7241985ac2a7eed71e17d89a9f Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:28 +0200
Subject: [PATCH 20/50] openssh-6.6.1p1-scp-non-existing-directory
---
scp.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/scp.c b/scp.c
index 716ae386..9554b188 100644
--- a/scp.c
+++ b/scp.c
@@ -1876,6 +1876,10 @@ sink(int argc, char **argv, const char *src)
free(vect[0]);
continue;
}
+ if (buf[0] == 'C' && ! exists && np[strlen(np)-1] == '/') {
+ errno = ENOTDIR;
+ goto bad;
+ }
omode = mode;
mode |= S_IWUSR;
if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) == -1) {
--
2.49.0

View file

@ -1,151 +0,0 @@
From 9c75c175e3555377328fc5fc9b06e94f129b7cd7 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:28 +0200
Subject: [PATCH 21/50] openssh-6.6p1-GSSAPIEnablek5users
---
gss-serv-krb5.c | 3 +--
servconf.c | 13 ++++++++++++-
servconf.h | 1 +
sshd_config | 1 +
sshd_config.5 | 6 ++++++
5 files changed, 21 insertions(+), 3 deletions(-)
diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c
index 187faf92..03188d9b 100644
--- a/gss-serv-krb5.c
+++ b/gss-serv-krb5.c
@@ -278,7 +278,6 @@ ssh_gssapi_krb5_cmdok(krb5_principal principal, const char *name,
FILE *fp;
char file[MAXPATHLEN];
char *line = NULL;
- char kuser[65]; /* match krb5_kuserok() */
struct stat st;
struct passwd *pw = the_authctxt->pw;
int found_principal = 0;
@@ -288,7 +287,7 @@ ssh_gssapi_krb5_cmdok(krb5_principal principal, const char *name,
snprintf(file, sizeof(file), "%s/.k5users", pw->pw_dir);
/* If both .k5login and .k5users DNE, self-login is ok. */
- if (!k5login_exists && (access(file, F_OK) == -1)) {
+ if ( !options.enable_k5users || (!k5login_exists && (access(file, F_OK) == -1))) {
return ssh_krb5_kuserok(krb_context, principal, luser,
k5login_exists);
}
diff --git a/servconf.c b/servconf.c
index 5dd5ca21..c0de7110 100644
--- a/servconf.c
+++ b/servconf.c
@@ -146,6 +146,7 @@ initialize_server_options(ServerOptions *options)
options->gss_store_rekey = -1;
options->gss_kex_algorithms = NULL;
options->use_kuserok = -1;
+ options->enable_k5users = -1;
options->password_authentication = -1;
options->kbd_interactive_authentication = -1;
options->permit_empty_passwd = -1;
@@ -402,6 +403,8 @@ fill_default_server_options(ServerOptions *options)
#endif
if (options->use_kuserok == -1)
options->use_kuserok = 1;
+ if (options->enable_k5users == -1)
+ options->enable_k5users = 0;
if (options->password_authentication == -1)
options->password_authentication = 1;
if (options->kbd_interactive_authentication == -1)
@@ -585,7 +588,7 @@ typedef enum {
sHostKeyAlgorithms, sPerSourceMaxStartups, sPerSourceNetBlockSize,
sPerSourcePenalties, sPerSourcePenaltyExemptList,
sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
- sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
+ sGssAuthentication, sGssCleanupCreds, sGssEnablek5users, sGssStrictAcceptor,
sGssKeyEx, sGssKexAlgorithms, sGssStoreRekey,
sAcceptEnv, sSetEnv, sPermitTunnel,
sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory,
@@ -681,6 +684,7 @@ static struct {
{ "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL },
{ "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL },
{ "gssapikexalgorithms", sGssKexAlgorithms, SSHCFG_GLOBAL },
+ { "gssapienablek5users", sGssEnablek5users, SSHCFG_ALL },
#else
{ "gssapiauthentication", sUnsupported, SSHCFG_ALL },
{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
@@ -689,6 +693,7 @@ static struct {
{ "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL },
{ "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL },
{ "gssapikexalgorithms", sUnsupported, SSHCFG_GLOBAL },
+ { "gssapienablek5users", sUnsupported, SSHCFG_ALL },
#endif
{ "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL },
{ "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL },
@@ -2450,6 +2455,10 @@ process_server_config_line_depth(ServerOptions *options, char *line,
intptr = &options->use_kuserok;
goto parse_flag;
+ case sGssEnablek5users:
+ intptr = &options->enable_k5users;
+ goto parse_flag;
+
case sMatch:
if (cmdline)
fatal("Match directive not supported as a command-line "
@@ -3005,6 +3014,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
M_CP_INTOPT(ip_qos_interactive);
M_CP_INTOPT(ip_qos_bulk);
M_CP_INTOPT(use_kuserok);
+ M_CP_INTOPT(enable_k5users);
M_CP_INTOPT(rekey_limit);
M_CP_INTOPT(rekey_interval);
M_CP_INTOPT(log_level);
@@ -3314,6 +3324,7 @@ dump_config(ServerOptions *o)
# endif
dump_cfg_fmtint(sKerberosUniqueCCache, o->kerberos_unique_ccache);
dump_cfg_fmtint(sKerberosUseKuserok, o->use_kuserok);
+ dump_cfg_fmtint(sGssEnablek5users, o->enable_k5users);
#endif
#ifdef GSSAPI
dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
diff --git a/servconf.h b/servconf.h
index 11de36a2..c08cf6a7 100644
--- a/servconf.h
+++ b/servconf.h
@@ -152,6 +152,7 @@ typedef struct {
int kerberos_unique_ccache; /* If true, the acquired ticket will
* be stored in per-session ccache */
int use_kuserok;
+ int enable_k5users;
int gss_authentication; /* If true, permit GSSAPI authentication */
int gss_keyex; /* If true, permit GSSAPI key exchange */
int gss_cleanup_creds; /* If true, destroy cred cache on logout */
diff --git a/sshd_config b/sshd_config
index ea5a878e..33713c88 100644
--- a/sshd_config
+++ b/sshd_config
@@ -82,6 +82,7 @@ AuthorizedKeysFile .ssh/authorized_keys
#GSSAPICleanupCredentials yes
#GSSAPIStrictAcceptorCheck yes
#GSSAPIKeyExchange no
+#GSSAPIEnablek5users no
# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
diff --git a/sshd_config.5 b/sshd_config.5
index 0fcb409a..fe246fc2 100644
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -739,6 +739,12 @@ Specifies whether to automatically destroy the user's credentials cache
on logout.
The default is
.Cm yes .
+.It Cm GSSAPIEnablek5users
+Specifies whether to look at .k5users file for GSSAPI authentication
+access control. Further details are described in
+.Xr ksu 1 .
+The default is
+.Cm no .
.It Cm GSSAPIKeyExchange
Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange
doesn't rely on ssh keys to verify host identity.
--
2.49.0

View file

@ -1,25 +0,0 @@
From 05b09904f431333e19cd24528ef66d1fd15e9efe Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:28 +0200
Subject: [PATCH 22/50] openssh-6.8p1-sshdT-output
---
servconf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/servconf.c b/servconf.c
index c0de7110..105e301d 100644
--- a/servconf.c
+++ b/servconf.c
@@ -3366,7 +3366,7 @@ dump_config(ServerOptions *o)
dump_cfg_string(sXAuthLocation, o->xauth_location);
dump_cfg_string(sCiphers, o->ciphers);
dump_cfg_string(sMacs, o->macs);
- dump_cfg_string(sBanner, o->banner);
+ dump_cfg_string(sBanner, o->banner != NULL ? o->banner : "none");
dump_cfg_string(sForceCommand, o->adm_forced_command);
dump_cfg_string(sChrootDirectory, o->chroot_directory);
dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys);
--
2.49.0

View file

@ -1,191 +0,0 @@
From 36e3430d1f81397d5f40600e075272a81f7effce Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:28 +0200
Subject: [PATCH 25/50] openssh-7.3p1-x11-max-displays
---
channels.c | 9 ++++++---
channels.h | 2 +-
servconf.c | 12 +++++++++++-
servconf.h | 2 ++
session.c | 5 +++--
sshd_config.5 | 7 +++++++
6 files changed, 30 insertions(+), 7 deletions(-)
diff --git a/channels.c b/channels.c
index d46531ce..7438c1a5 100644
--- a/channels.c
+++ b/channels.c
@@ -4996,7 +4996,7 @@ rdynamic_connect_finish(struct ssh *ssh, Channel *c)
*/
int
x11_create_display_inet(struct ssh *ssh, int x11_display_offset,
- int x11_use_localhost, int single_connection,
+ int x11_use_localhost, int x11_max_displays, int single_connection,
u_int *display_numberp, int **chanids)
{
Channel *nc = NULL;
@@ -5009,8 +5009,11 @@ x11_create_display_inet(struct ssh *ssh, int x11_display_offset,
x11_display_offset > UINT16_MAX - X11_BASE_PORT - MAX_DISPLAYS)
return -1;
+ /* Try to bind ports starting at 6000+X11DisplayOffset */
+ x11_max_displays = x11_max_displays + x11_display_offset;
+
for (display_number = x11_display_offset;
- display_number < MAX_DISPLAYS;
+ display_number < x11_max_displays;
display_number++) {
port = X11_BASE_PORT + display_number;
memset(&hints, 0, sizeof(hints));
@@ -5065,7 +5068,7 @@ x11_create_display_inet(struct ssh *ssh, int x11_display_offset,
if (num_socks > 0)
break;
}
- if (display_number >= MAX_DISPLAYS) {
+ if (display_number >= x11_max_displays || port < X11_BASE_PORT ) {
error("Failed to allocate internet-domain X11 display socket.");
return -1;
}
diff --git a/channels.h b/channels.h
index 134528d5..8a09a820 100644
--- a/channels.h
+++ b/channels.h
@@ -379,7 +379,7 @@ int permitopen_port(const char *);
void channel_set_x11_refuse_time(struct ssh *, time_t);
int x11_connect_display(struct ssh *);
-int x11_create_display_inet(struct ssh *, int, int, int, u_int *, int **);
+int x11_create_display_inet(struct ssh *, int, int, int, int, u_int *, int **);
void x11_request_forwarding_with_spoofing(struct ssh *, int,
const char *, const char *, const char *, int);
int x11_channel_used_recently(struct ssh *ssh);
diff --git a/servconf.c b/servconf.c
index 105e301d..15c99b30 100644
--- a/servconf.c
+++ b/servconf.c
@@ -117,6 +117,7 @@ initialize_server_options(ServerOptions *options)
options->print_lastlog = -1;
options->x11_forwarding = -1;
options->x11_display_offset = -1;
+ options->x11_max_displays = -1;
options->x11_use_localhost = -1;
options->permit_tty = -1;
options->permit_user_rc = -1;
@@ -353,6 +354,8 @@ fill_default_server_options(ServerOptions *options)
options->x11_forwarding = 0;
if (options->x11_display_offset == -1)
options->x11_display_offset = 10;
+ if (options->x11_max_displays == -1)
+ options->x11_max_displays = DEFAULT_MAX_DISPLAYS;
if (options->x11_use_localhost == -1)
options->x11_use_localhost = 1;
if (options->xauth_location == NULL)
@@ -576,7 +579,7 @@ typedef enum {
sKerberosGetAFSToken, sKerberosUniqueCCache, sKerberosUseKuserok, sPasswordAuthentication,
sKbdInteractiveAuthentication, sListenAddress, sAddressFamily,
sPrintMotd, sPrintLastLog, sIgnoreRhosts,
- sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
+ sX11Forwarding, sX11DisplayOffset, sX11MaxDisplays, sX11UseLocalhost,
sPermitTTY, sStrictModes, sEmptyPasswd, sTCPKeepAlive,
sPermitUserEnvironment, sAllowTcpForwarding, sCompression,
sRekeyLimit, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
@@ -714,6 +717,7 @@ static struct {
{ "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL },
{ "x11forwarding", sX11Forwarding, SSHCFG_ALL },
{ "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL },
+ { "x11maxdisplays", sX11MaxDisplays, SSHCFG_ALL },
{ "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL },
{ "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL },
{ "strictmodes", sStrictModes, SSHCFG_GLOBAL },
@@ -1750,6 +1754,10 @@ process_server_config_line_depth(ServerOptions *options, char *line,
*intptr = value;
break;
+ case sX11MaxDisplays:
+ intptr = &options->x11_max_displays;
+ goto parse_int;
+
case sX11UseLocalhost:
intptr = &options->x11_use_localhost;
goto parse_flag;
@@ -3004,6 +3012,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
M_CP_INTOPT(fwd_opts.streamlocal_bind_unlink);
M_CP_INTOPT(x11_display_offset);
M_CP_INTOPT(x11_forwarding);
+ M_CP_INTOPT(x11_max_displays);
M_CP_INTOPT(x11_use_localhost);
M_CP_INTOPT(permit_tty);
M_CP_INTOPT(permit_user_rc);
@@ -3299,6 +3308,7 @@ dump_config(ServerOptions *o)
#endif
dump_cfg_int(sLoginGraceTime, o->login_grace_time);
dump_cfg_int(sX11DisplayOffset, o->x11_display_offset);
+ dump_cfg_int(sX11MaxDisplays, o->x11_max_displays);
dump_cfg_int(sMaxAuthTries, o->max_authtries);
dump_cfg_int(sMaxSessions, o->max_sessions);
dump_cfg_int(sClientAliveInterval, o->client_alive_interval);
diff --git a/servconf.h b/servconf.h
index c08cf6a7..7c7e5d43 100644
--- a/servconf.h
+++ b/servconf.h
@@ -38,6 +38,7 @@
#define DEFAULT_AUTH_FAIL_MAX 6 /* Default for MaxAuthTries */
#define DEFAULT_SESSIONS_MAX 10 /* Default for MaxSessions */
+#define DEFAULT_MAX_DISPLAYS 1000 /* Maximum number of fake X11 displays to try. */
/* Magic name for internal sftp-server */
#define INTERNAL_SFTP_NAME "internal-sftp"
@@ -114,6 +115,7 @@ typedef struct {
int x11_forwarding; /* If true, permit inet (spoofing) X11 fwd. */
int x11_display_offset; /* What DISPLAY number to start
* searching at */
+ int x11_max_displays; /* Number of displays to search */
int x11_use_localhost; /* If true, use localhost for fake X11 server. */
char *xauth_location; /* Location of xauth program */
int permit_tty; /* If false, deny pty allocation */
diff --git a/session.c b/session.c
index 54da09d5..28bbb8a7 100644
--- a/session.c
+++ b/session.c
@@ -2611,8 +2611,9 @@ session_setup_x11fwd(struct ssh *ssh, Session *s)
return 0;
}
if (x11_create_display_inet(ssh, options.x11_display_offset,
- options.x11_use_localhost, s->single_connection,
- &s->display_number, &s->x11_chanids) == -1) {
+ options.x11_use_localhost, options.x11_max_displays,
+ s->single_connection, &s->display_number,
+ &s->x11_chanids) == -1) {
debug("x11_create_display_inet failed.");
return 0;
}
diff --git a/sshd_config.5 b/sshd_config.5
index fe246fc2..26fcdc84 100644
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -1391,6 +1391,7 @@ Available keywords are
.Cm TrustedUserCAKeys ,
.Cm UnusedConnectionTimeout ,
.Cm X11DisplayOffset ,
+.Cm X11MaxDisplays ,
.Cm X11Forwarding
and
.Cm X11UseLocalhost .
@@ -2111,6 +2112,12 @@ Specifies the first display number available for
X11 forwarding.
This prevents sshd from interfering with real X11 servers.
The default is 10.
+.It Cm X11MaxDisplays
+Specifies the maximum number of displays available for
+.Xr sshd 8 Ns 's
+X11 forwarding.
+This prevents sshd from exhausting local ports.
+The default is 1000.
.It Cm X11Forwarding
Specifies whether X11 forwarding is permitted.
The argument must be
--
2.49.0

View file

@ -1,312 +0,0 @@
From 43320351b6f150167190aacc84f2f87030fef3d2 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:28 +0200
Subject: [PATCH 26/50] openssh-7.6p1-cleanup-selinux
---
auth2-pubkey.c | 8 ++++--
misc.c | 5 ++--
misc.h | 2 +-
openbsd-compat/port-linux-sshd.c | 42 +++++++++++++++++---------------
openbsd-compat/port-linux.h | 4 +--
platform.c | 6 ++++-
sshconnect.c | 2 +-
sshd-auth.c | 2 +-
sshd-session.c | 6 +++--
9 files changed, 45 insertions(+), 32 deletions(-)
diff --git a/auth2-pubkey.c b/auth2-pubkey.c
index 267a27d2..0d5ae0df 100644
--- a/auth2-pubkey.c
+++ b/auth2-pubkey.c
@@ -77,6 +77,8 @@
/* import */
extern ServerOptions options;
+extern int inetd_flag;
+extern Authctxt *the_authctxt;
extern struct authmethod_cfg methodcfg_pubkey;
static char *
@@ -485,7 +487,8 @@ match_principals_command(struct passwd *user_pw, const struct sshkey *key,
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, the_authctxt)) == 0)
goto out;
uid_swapped = 1;
@@ -755,7 +758,8 @@ user_key_command_allowed2(struct passwd *user_pw, struct sshkey *key,
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, the_authctxt)) == 0)
goto out;
uid_swapped = 1;
diff --git a/misc.c b/misc.c
index 1e31acc9..09722962 100644
--- a/misc.c
+++ b/misc.c
@@ -2764,7 +2764,8 @@ stdfd_devnull(int do_stdin, int do_stdout, int do_stderr)
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;
@@ -2898,7 +2899,7 @@ subprocess(const char *tag, const char *command,
_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);
diff --git a/misc.h b/misc.h
index efecdf1a..9efa9cf4 100644
--- a/misc.h
+++ b/misc.h
@@ -122,7 +122,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 {
diff --git a/openbsd-compat/port-linux-sshd.c b/openbsd-compat/port-linux-sshd.c
index 646f0887..291b569a 100644
--- a/openbsd-compat/port-linux-sshd.c
+++ b/openbsd-compat/port-linux-sshd.c
@@ -49,10 +49,6 @@
#include <unistd.h>
#endif
-extern ServerOptions options;
-extern Authctxt *the_authctxt;
-extern int inetd_flag;
-
/* Wrapper around is_selinux_enabled() to log its return value once only */
int
sshd_selinux_enabled(void)
@@ -222,7 +218,8 @@ get_user_context(const char *sename, const char *role, const char *lvl,
}
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;
@@ -240,8 +237,8 @@ ssh_selinux_get_role_level(char **role, const char **level)
/* 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;
@@ -249,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) {
@@ -271,7 +268,7 @@ sshd_selinux_getctxbyname(char *pwname,
if (r == 0) {
/* If launched from xinetd, we must use current level */
- if (inetd_flag) {
+ if (inetd) {
security_context_t sshdsc=NULL;
if (getcon_raw(&sshdsc) < 0)
@@ -332,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;
@@ -341,11 +339,11 @@ sshd_selinux_setup_variables(int(*set_it)(char *, const char *))
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) {
+ if (inetd) {
use_current = "1";
} else {
use_current = "";
@@ -361,9 +359,10 @@ sshd_selinux_setup_variables(int(*set_it)(char *, const char *))
}
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
@@ -373,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");
@@ -407,7 +409,7 @@ sshd_selinux_setup_exec_context(char *pwname)
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) {
diff --git a/openbsd-compat/port-linux.h b/openbsd-compat/port-linux.h
index 7f8ba200..3cd7da6a 100644
--- a/openbsd-compat/port-linux.h
+++ b/openbsd-compat/port-linux.h
@@ -25,8 +25,8 @@ 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);
+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
diff --git a/platform.c b/platform.c
index 0d12f311..f0800b1f 100644
--- a/platform.c
+++ b/platform.c
@@ -33,6 +33,8 @@
#include "openbsd-compat/openbsd-compat.h"
extern ServerOptions options;
+extern int inetd_flag;
+extern Authctxt *the_authctxt;
/* return 1 if we are running with privilege to swap UIDs, 0 otherwise */
int
@@ -140,7 +142,9 @@ platform_setusercontext_post_groups(struct passwd *pw)
}
#endif /* HAVE_SETPCRED */
#ifdef WITH_SELINUX
- sshd_selinux_setup_exec_context(pw->pw_name);
+ sshd_selinux_setup_exec_context(pw->pw_name,
+ inetd_flag, do_pam_putenv, the_authctxt,
+ options.use_pam);
#endif
}
diff --git a/sshconnect.c b/sshconnect.c
index c86182d1..04084810 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -925,7 +925,7 @@ load_hostkeys_command(struct hostkeys *hostkeys, const char *command_template,
if ((pid = subprocess(tag, command, ac, av, &f,
SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_UNSAFE_PATH|
- SSH_SUBPROCESS_PRESERVE_ENV, NULL, NULL, NULL)) == 0)
+ SSH_SUBPROCESS_PRESERVE_ENV, NULL, NULL, NULL, 0, NULL)) == 0)
goto out;
load_hostkeys_file(hostkeys, hostfile_hostname, tag, f, 1);
diff --git a/sshd-auth.c b/sshd-auth.c
index e4a8edfd..897db9b4 100644
--- a/sshd-auth.c
+++ b/sshd-auth.c
@@ -122,7 +122,7 @@ char *config_file_name = _PATH_SERVER_CONFIG_FILE;
int debug_flag = 0;
/* Flag indicating that the daemon is being started from inetd. */
-static int inetd_flag = 0;
+int inetd_flag = 0;
/* Saved arguments to main(). */
static char **saved_argv;
diff --git a/sshd-session.c b/sshd-session.c
index 9342e416..81d30152 100644
--- a/sshd-session.c
+++ b/sshd-session.c
@@ -136,7 +136,7 @@ char *config_file_name = _PATH_SERVER_CONFIG_FILE;
int debug_flag = 0;
/* Flag indicating that the daemon is being started from inetd. */
-static int inetd_flag = 0;
+int inetd_flag = 0;
/* debug goes to stderr unless inetd_flag is set */
static int log_stderr = 0;
@@ -1359,7 +1359,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, do_pam_putenv, the_authctxt,
+ options.use_pam);
#endif
#ifdef USE_PAM
if (options.use_pam) {
--
2.49.0

View file

@ -1,58 +0,0 @@
From 35205319dd71d8e61c1596b8f9479df91aff7756 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:28 +0200
Subject: [PATCH 27/50] openssh-7.5p1-sandbox
---
sandbox-seccomp-filter.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/sandbox-seccomp-filter.c b/sandbox-seccomp-filter.c
index b31062c2..1fabf99d 100644
--- a/sandbox-seccomp-filter.c
+++ b/sandbox-seccomp-filter.c
@@ -277,6 +277,9 @@ static const struct sock_filter preauth_insns[] = {
#ifdef __NR_exit_group
SC_ALLOW(__NR_exit_group),
#endif
+#if defined(__NR_flock) && defined(__s390__)
+ SC_ALLOW(__NR_flock),
+#endif
#ifdef __NR_futex
SC_FUTEX(__NR_futex),
#endif
@@ -295,6 +298,21 @@ static const struct sock_filter preauth_insns[] = {
#ifdef __NR_getpid
SC_ALLOW(__NR_getpid),
#endif
+#ifdef __NR_getuid
+ SC_ALLOW(__NR_getuid),
+#endif
+#ifdef __NR_getuid32
+ SC_ALLOW(__NR_getuid32),
+#endif
+#ifdef __NR_geteuid
+ SC_ALLOW(__NR_geteuid),
+#endif
+#ifdef __NR_geteuid32
+ SC_ALLOW(__NR_geteuid32),
+#endif
+#ifdef __NR_gettid
+ SC_ALLOW(__NR_gettid),
+#endif
#ifdef __NR_getrandom
SC_ALLOW(__NR_getrandom),
#endif
@@ -304,6 +322,9 @@ static const struct sock_filter preauth_insns[] = {
#ifdef __NR_gettimeofday
SC_ALLOW(__NR_gettimeofday),
#endif
+#if defined(__NR_ipc) && defined(__s390__)
+ SC_ALLOW(__NR_ipc),
+#endif
#ifdef __NR_getuid
SC_ALLOW(__NR_getuid),
#endif
--
2.49.0

File diff suppressed because it is too large Load diff

View file

@ -1,27 +0,0 @@
From 507e6f245557ae7261806f7ecbd40697cb0dd389 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:28 +0200
Subject: [PATCH 29/50] openssh-7.8p1-scp-ipv6
---
scp.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/scp.c b/scp.c
index 9554b188..7f9795a5 100644
--- a/scp.c
+++ b/scp.c
@@ -1183,7 +1183,9 @@ toremote(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct)
addargs(&alist, "%s", host);
addargs(&alist, "%s", cmd);
addargs(&alist, "%s", src);
- addargs(&alist, "%s%s%s:%s",
+ addargs(&alist,
+ /* IPv6 address needs to be enclosed with sqare brackets */
+ strchr(host, ':') != NULL ? "%s%s[%s]:%s" : "%s%s%s:%s",
tuser ? tuser : "", tuser ? "@" : "",
thost, targ);
if (do_local_cmd(&alist) != 0)
--
2.49.0

View file

@ -1,654 +0,0 @@
From b436140fe3abd9f97f01f9af9f5da5cf6c5d7725 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:28 +0200
Subject: [PATCH 30/50] openssh-8.0p1-crypto-policies
---
ssh_config.5 | 164 ++++++++++++++++++++-------------------------
sshd_config.5 | 179 +++++++++++++++++++-------------------------------
2 files changed, 140 insertions(+), 203 deletions(-)
diff --git a/ssh_config.5 b/ssh_config.5
index 8d5d0722..a43b2a27 100644
--- a/ssh_config.5
+++ b/ssh_config.5
@@ -438,17 +438,13 @@ A single argument of
causes no CNAMEs to be considered for canonicalization.
This is the default behaviour.
.It Cm CASignatureAlgorithms
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies which algorithms are allowed for signing of certificates
by certificate authorities (CAs).
-The default is:
-.Bd -literal -offset indent
-ssh-ed25519,ecdsa-sha2-nistp256,
-ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
-sk-ssh-ed25519@openssh.com,
-sk-ecdsa-sha2-nistp256@openssh.com,
-rsa-sha2-512,rsa-sha2-256
-.Ed
-.Pp
If the specified list begins with a
.Sq +
character, then the specified algorithms will be appended to the default set
@@ -587,20 +583,25 @@ If the option is set to
(the default),
the check will not be executed.
.It Cm Ciphers
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies the ciphers allowed and their order of preference.
Multiple ciphers must be comma-separated.
If the specified list begins with a
.Sq +
-character, then the specified ciphers will be appended to the default set
-instead of replacing them.
+character, then the specified ciphers will be appended to the built-in
+openssh default set instead of replacing them.
If the specified list begins with a
.Sq -
character, then the specified ciphers (including wildcards) will be removed
-from the default set instead of replacing them.
+from the built-in openssh default set instead of replacing them.
If the specified list begins with a
.Sq ^
character, then the specified ciphers will be placed at the head of the
-default set.
+built-in openssh default set.
.Pp
The supported ciphers are:
.Bd -literal -offset indent
@@ -616,13 +617,6 @@ aes256-gcm@openssh.com
chacha20-poly1305@openssh.com
.Ed
.Pp
-The default is:
-.Bd -literal -offset indent
-chacha20-poly1305@openssh.com,
-aes128-gcm@openssh.com,aes256-gcm@openssh.com,
-aes128-ctr,aes192-ctr,aes256-ctr
-.Ed
-.Pp
The list of available ciphers may also be obtained using
.Qq ssh -Q cipher .
.It Cm ClearAllForwardings
@@ -1022,6 +1016,11 @@ command line will be passed untouched to the GSSAPI library.
The default is
.Dq no .
.It Cm GSSAPIKexAlgorithms
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
+.Xr update-crypto-policies 8 .
+.Pp
The list of key exchange algorithms that are offered for GSSAPI
key exchange. Possible values are
.Bd -literal -offset 3n
@@ -1034,10 +1033,8 @@ gss-nistp256-sha256-,
gss-curve25519-sha256-
.Ed
.Pp
-The default is
-.Dq gss-group14-sha256-,gss-group16-sha512-,gss-nistp256-sha256-,
-gss-curve25519-sha256-,gss-group14-sha1-,gss-gex-sha1- .
This option only applies to connections using GSSAPI.
+.Pp
.It Cm HashKnownHosts
Indicates that
.Xr ssh 1
@@ -1056,36 +1053,25 @@ will not be converted automatically,
but may be manually hashed using
.Xr ssh-keygen 1 .
.It Cm HostbasedAcceptedAlgorithms
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies the signature algorithms that will be used for hostbased
authentication as a comma-separated list of patterns.
Alternately if the specified list begins with a
.Sq +
character, then the specified signature algorithms will be appended
-to the default set instead of replacing them.
+to the built-in openssh default set instead of replacing them.
If the specified list begins with a
.Sq -
character, then the specified signature algorithms (including wildcards)
-will be removed from the default set instead of replacing them.
+will be removed from the built-in openssh default set instead of replacing them.
If the specified list begins with a
.Sq ^
character, then the specified signature algorithms will be placed
-at the head of the default set.
-The default for this option is:
-.Bd -literal -offset 3n
-ssh-ed25519-cert-v01@openssh.com,
-ecdsa-sha2-nistp256-cert-v01@openssh.com,
-ecdsa-sha2-nistp384-cert-v01@openssh.com,
-ecdsa-sha2-nistp521-cert-v01@openssh.com,
-sk-ssh-ed25519-cert-v01@openssh.com,
-sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
-rsa-sha2-512-cert-v01@openssh.com,
-rsa-sha2-256-cert-v01@openssh.com,
-ssh-ed25519,
-ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
-sk-ssh-ed25519@openssh.com,
-sk-ecdsa-sha2-nistp256@openssh.com,
-rsa-sha2-512,rsa-sha2-256
-.Ed
+at the head of the built-in openssh default set.
.Pp
The
.Fl Q
@@ -1138,6 +1124,17 @@ to prefer their algorithms.
.Pp
The list of available signature algorithms may also be obtained using
.Qq ssh -Q HostKeyAlgorithms .
+.Pp
+The proposed
+.Cm HostKeyAlgorithms
+during KEX are limited to the set of algorithms that is defined in
+.Cm PubkeyAcceptedAlgorithms
+and therefore they are indirectly affected by system-wide
+.Xr crypto_policies 7 .
+.Xr crypto_policies 7 can not handle the list of host key algorithms directly as doing so
+would break the order given by the
+.Pa known_hosts
+file.
.It Cm HostKeyAlias
Specifies an alias that should be used instead of the
real host name when looking up or saving the host key
@@ -1376,6 +1373,11 @@ it may be zero or more of:
and
.Cm pam .
.It Cm KexAlgorithms
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies the permitted KEX (Key Exchange) algorithms that will be used and
their preference order.
The selected algorithm will be the first algorithm in this list that
@@ -1384,29 +1386,17 @@ Multiple algorithms must be comma-separated.
.Pp
If the specified list begins with a
.Sq +
-character, then the specified algorithms will be appended to the default set
-instead of replacing them.
+character, then the specified methods will be appended to the built-in
+openssh default set instead of replacing them.
If the specified list begins with a
.Sq -
character, then the specified algorithms (including wildcards) will be removed
-from the default set instead of replacing them.
+from the built-in openssh default set instead of replacing them.
If the specified list begins with a
.Sq ^
character, then the specified algorithms will be placed at the head of the
-default set.
-.Pp
-The default is:
-.Bd -literal -offset indent
-mlkem768x25519-sha256,
-sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com,
-curve25519-sha256,curve25519-sha256@libssh.org,
-ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,
-diffie-hellman-group-exchange-sha256,
-diffie-hellman-group16-sha512,
-diffie-hellman-group18-sha512,
-diffie-hellman-group14-sha256
-.Ed
.Pp
+built-in openssh default set.
The list of supported key exchange algorithms may also be obtained using
.Qq ssh -Q kex .
.It Cm KnownHostsCommand
@@ -1522,37 +1512,33 @@ function, and all code in the
file.
This option is intended for debugging and no overrides are enabled by default.
.It Cm MACs
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies the MAC (message authentication code) algorithms
in order of preference.
The MAC algorithm is used for data integrity protection.
Multiple algorithms must be comma-separated.
If the specified list begins with a
.Sq +
-character, then the specified algorithms will be appended to the default set
-instead of replacing them.
+character, then the specified algorithms will be appended to the built-in
+openssh default set instead of replacing them.
If the specified list begins with a
.Sq -
character, then the specified algorithms (including wildcards) will be removed
-from the default set instead of replacing them.
+from the built-in openssh default set instead of replacing them.
If the specified list begins with a
.Sq ^
character, then the specified algorithms will be placed at the head of the
-default set.
+built-in openssh default set.
.Pp
The algorithms that contain
.Qq -etm
calculate the MAC after encryption (encrypt-then-mac).
These are considered safer and their use recommended.
.Pp
-The default is:
-.Bd -literal -offset indent
-umac-64-etm@openssh.com,umac-128-etm@openssh.com,
-hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,
-hmac-sha1-etm@openssh.com,
-umac-64@openssh.com,umac-128@openssh.com,
-hmac-sha2-256,hmac-sha2-512,hmac-sha1
-.Ed
-.Pp
The list of available MAC algorithms may also be obtained using
.Qq ssh -Q mac .
.It Cm NoHostAuthenticationForLocalhost
@@ -1741,39 +1727,31 @@ instead of continuing to execute and pass data.
The default is
.Cm no .
.It Cm PubkeyAcceptedAlgorithms
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies the signature algorithms that will be used for public key
authentication as a comma-separated list of patterns.
If the specified list begins with a
.Sq +
-character, then the algorithms after it will be appended to the default
-instead of replacing it.
+character, then the algorithms after it will be appended to the built-in
+openssh default instead of replacing it.
If the specified list begins with a
.Sq -
character, then the specified algorithms (including wildcards) will be removed
-from the default set instead of replacing them.
+from the built-in openssh default set instead of replacing them.
If the specified list begins with a
.Sq ^
character, then the specified algorithms will be placed at the head of the
-default set.
-The default for this option is:
-.Bd -literal -offset 3n
-ssh-ed25519-cert-v01@openssh.com,
-ecdsa-sha2-nistp256-cert-v01@openssh.com,
-ecdsa-sha2-nistp384-cert-v01@openssh.com,
-ecdsa-sha2-nistp521-cert-v01@openssh.com,
-sk-ssh-ed25519-cert-v01@openssh.com,
-sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
-rsa-sha2-512-cert-v01@openssh.com,
-rsa-sha2-256-cert-v01@openssh.com,
-ssh-ed25519,
-ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
-sk-ssh-ed25519@openssh.com,
-sk-ecdsa-sha2-nistp256@openssh.com,
-rsa-sha2-512,rsa-sha2-256
-.Ed
+built-in openssh default set.
.Pp
The list of available signature algorithms may also be obtained using
.Qq ssh -Q PubkeyAcceptedAlgorithms .
+.Pp
+This option affects also
+.Cm HostKeyAlgorithms
.It Cm PubkeyAuthentication
Specifies whether to try public key authentication.
The argument to this keyword must be
@@ -2497,7 +2475,9 @@ for those users who do not have a configuration file.
This file must be world-readable.
.El
.Sh SEE ALSO
-.Xr ssh 1
+.Xr ssh 1 ,
+.Xr crypto-policies 7 ,
+.Xr update-crypto-policies 8
.Sh AUTHORS
.An -nosplit
OpenSSH is a derivative of the original and free
diff --git a/sshd_config.5 b/sshd_config.5
index 26fcdc84..583a01cd 100644
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -379,17 +379,13 @@ If the argument is
then no banner is displayed.
By default, no banner is displayed.
.It Cm CASignatureAlgorithms
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies which algorithms are allowed for signing of certificates
by certificate authorities (CAs).
-The default is:
-.Bd -literal -offset indent
-ssh-ed25519,ecdsa-sha2-nistp256,
-ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
-sk-ssh-ed25519@openssh.com,
-sk-ecdsa-sha2-nistp256@openssh.com,
-rsa-sha2-512,rsa-sha2-256
-.Ed
-.Pp
If the specified list begins with a
.Sq +
character, then the specified algorithms will be appended to the default set
@@ -533,20 +529,25 @@ The default is
indicating not to
.Xr chroot 2 .
.It Cm Ciphers
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies the ciphers allowed.
Multiple ciphers must be comma-separated.
If the specified list begins with a
.Sq +
-character, then the specified ciphers will be appended to the default set
-instead of replacing them.
+character, then the specified ciphers will be appended to the built-in
+openssh default set instead of replacing them.
If the specified list begins with a
.Sq -
character, then the specified ciphers (including wildcards) will be removed
-from the default set instead of replacing them.
+from the built-in openssh default set instead of replacing them.
If the specified list begins with a
.Sq ^
character, then the specified ciphers will be placed at the head of the
-default set.
+built-in openssh default set.
.Pp
The supported ciphers are:
.Pp
@@ -573,13 +574,6 @@ aes256-gcm@openssh.com
chacha20-poly1305@openssh.com
.El
.Pp
-The default is:
-.Bd -literal -offset indent
-chacha20-poly1305@openssh.com,
-aes128-gcm@openssh.com,aes256-gcm@openssh.com,
-aes128-ctr,aes192-ctr,aes256-ctr
-.Ed
-.Pp
The list of available ciphers may also be obtained using
.Qq ssh -Q cipher .
.It Cm ClientAliveCountMax
@@ -774,53 +768,43 @@ For this to work
.Cm GSSAPIKeyExchange
needs to be enabled in the server and also used by the client.
.It Cm GSSAPIKexAlgorithms
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
+.Xr update-crypto-policies 8 .
+.Pp
The list of key exchange algorithms that are accepted by GSSAPI
key exchange. Possible values are
.Bd -literal -offset 3n
-gss-gex-sha1-,
-gss-group1-sha1-,
-gss-group14-sha1-,
-gss-group14-sha256-,
-gss-group16-sha512-,
-gss-nistp256-sha256-,
+gss-gex-sha1-
+gss-group1-sha1-
+gss-group14-sha1-
+gss-group14-sha256-
+gss-group16-sha512-
+gss-nistp256-sha256-
gss-curve25519-sha256-
.Ed
-.Pp
-The default is
-.Dq gss-group14-sha256-,gss-group16-sha512-,gss-nistp256-sha256-,
-gss-curve25519-sha256-,gss-group14-sha1-,gss-gex-sha1- .
This option only applies to connections using GSSAPI.
.It Cm HostbasedAcceptedAlgorithms
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies the signature algorithms that will be accepted for hostbased
authentication as a list of comma-separated patterns.
Alternately if the specified list begins with a
.Sq +
character, then the specified signature algorithms will be appended to
-the default set instead of replacing them.
+the built-in openssh default set instead of replacing them.
If the specified list begins with a
.Sq -
character, then the specified signature algorithms (including wildcards)
-will be removed from the default set instead of replacing them.
+will be removed from the built-in openssh default set instead of replacing them.
If the specified list begins with a
.Sq ^
character, then the specified signature algorithms will be placed at
-the head of the default set.
-The default for this option is:
-.Bd -literal -offset 3n
-ssh-ed25519-cert-v01@openssh.com,
-ecdsa-sha2-nistp256-cert-v01@openssh.com,
-ecdsa-sha2-nistp384-cert-v01@openssh.com,
-ecdsa-sha2-nistp521-cert-v01@openssh.com,
-sk-ssh-ed25519-cert-v01@openssh.com,
-sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
-rsa-sha2-512-cert-v01@openssh.com,
-rsa-sha2-256-cert-v01@openssh.com,
-ssh-ed25519,
-ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
-sk-ssh-ed25519@openssh.com,
-sk-ecdsa-sha2-nistp256@openssh.com,
-rsa-sha2-512,rsa-sha2-256
-.Ed
+the head of the built-in openssh default set.
.Pp
The list of available signature algorithms may also be obtained using
.Qq ssh -Q HostbasedAcceptedAlgorithms .
@@ -887,25 +871,14 @@ is specified, the location of the socket will be read from the
.Ev SSH_AUTH_SOCK
environment variable.
.It Cm HostKeyAlgorithms
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies the host key signature algorithms
that the server offers.
The default for this option is:
-.Bd -literal -offset 3n
-ssh-ed25519-cert-v01@openssh.com,
-ecdsa-sha2-nistp256-cert-v01@openssh.com,
-ecdsa-sha2-nistp384-cert-v01@openssh.com,
-ecdsa-sha2-nistp521-cert-v01@openssh.com,
-sk-ssh-ed25519-cert-v01@openssh.com,
-sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
-rsa-sha2-512-cert-v01@openssh.com,
-rsa-sha2-256-cert-v01@openssh.com,
-ssh-ed25519,
-ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
-sk-ssh-ed25519@openssh.com,
-sk-ecdsa-sha2-nistp256@openssh.com,
-rsa-sha2-512,rsa-sha2-256
-.Ed
-.Pp
The list of available signature algorithms may also be obtained using
.Qq ssh -Q HostKeyAlgorithms .
.It Cm IgnoreRhosts
@@ -1052,6 +1025,11 @@ Specifies whether to look at .k5login file for user's aliases.
The default is
.Cm yes .
.It Cm KexAlgorithms
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies the permitted KEX (Key Exchange) algorithms that the server will
offer to clients.
The ordering of this list is not important, as the client specifies the
@@ -1060,16 +1038,16 @@ Multiple algorithms must be comma-separated.
.Pp
If the specified list begins with a
.Sq +
-character, then the specified algorithms will be appended to the default set
-instead of replacing them.
+character, then the specified methods will be appended to the built-in
+openssh default set instead of replacing them.
If the specified list begins with a
.Sq -
character, then the specified algorithms (including wildcards) will be removed
-from the default set instead of replacing them.
+from the built-in openssh default set instead of replacing them.
If the specified list begins with a
.Sq ^
character, then the specified algorithms will be placed at the head of the
-default set.
+built-in openssh default set.
.Pp
The supported algorithms are:
.Pp
@@ -1106,14 +1084,6 @@ sntrup761x25519-sha512
sntrup761x25519-sha512@openssh.com
.El
.Pp
-The default is:
-.Bd -literal -offset indent
-mlkem768x25519-sha256,
-sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com,
-curve25519-sha256,curve25519-sha256@libssh.org,
-ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521
-.Ed
-.Pp
The list of supported key exchange algorithms may also be obtained using
.Qq ssh -Q KexAlgorithms .
.It Cm ListenAddress
@@ -1200,21 +1170,26 @@ function, and all code in the
file.
This option is intended for debugging and no overrides are enabled by default.
.It Cm MACs
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies the available MAC (message authentication code) algorithms.
The MAC algorithm is used for data integrity protection.
Multiple algorithms must be comma-separated.
If the specified list begins with a
.Sq +
-character, then the specified algorithms will be appended to the default set
-instead of replacing them.
+character, then the specified algorithms will be appended to the built-in
+openssh default set instead of replacing them.
If the specified list begins with a
.Sq -
character, then the specified algorithms (including wildcards) will be removed
-from the default set instead of replacing them.
+from the built-in openssh default set instead of replacing them.
If the specified list begins with a
.Sq ^
character, then the specified algorithms will be placed at the head of the
-default set.
+built-in openssh default set.
.Pp
The algorithms that contain
.Qq -etm
@@ -1257,15 +1232,6 @@ umac-64-etm@openssh.com
umac-128-etm@openssh.com
.El
.Pp
-The default is:
-.Bd -literal -offset indent
-umac-64-etm@openssh.com,umac-128-etm@openssh.com,
-hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,
-hmac-sha1-etm@openssh.com,
-umac-64@openssh.com,umac-128@openssh.com,
-hmac-sha2-256,hmac-sha2-512,hmac-sha1
-.Ed
-.Pp
The list of available MAC algorithms may also be obtained using
.Qq ssh -Q mac .
.It Cm Match
@@ -1753,36 +1719,25 @@ or equivalent.)
The default is
.Cm yes .
.It Cm PubkeyAcceptedAlgorithms
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies the signature algorithms that will be accepted for public key
authentication as a list of comma-separated patterns.
Alternately if the specified list begins with a
.Sq +
-character, then the specified algorithms will be appended to the default set
-instead of replacing them.
+character, then the specified algorithms will be appended to the built-in
+openssh default set instead of replacing them.
If the specified list begins with a
.Sq -
character, then the specified algorithms (including wildcards) will be removed
-from the default set instead of replacing them.
+from the built-in openssh default set instead of replacing them.
If the specified list begins with a
.Sq ^
character, then the specified algorithms will be placed at the head of the
-default set.
-The default for this option is:
-.Bd -literal -offset 3n
-ssh-ed25519-cert-v01@openssh.com,
-ecdsa-sha2-nistp256-cert-v01@openssh.com,
-ecdsa-sha2-nistp384-cert-v01@openssh.com,
-ecdsa-sha2-nistp521-cert-v01@openssh.com,
-sk-ssh-ed25519-cert-v01@openssh.com,
-sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
-rsa-sha2-512-cert-v01@openssh.com,
-rsa-sha2-256-cert-v01@openssh.com,
-ssh-ed25519,
-ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
-sk-ssh-ed25519@openssh.com,
-sk-ecdsa-sha2-nistp256@openssh.com,
-rsa-sha2-512,rsa-sha2-256
-.Ed
+built-in openssh default set.
.Pp
The list of available signature algorithms may also be obtained using
.Qq ssh -Q PubkeyAcceptedAlgorithms .
@@ -2289,7 +2244,9 @@ This file should be writable by root only, but it is recommended
.El
.Sh SEE ALSO
.Xr sftp-server 8 ,
-.Xr sshd 8
+.Xr sshd 8 ,
+.Xr crypto-policies 7 ,
+.Xr update-crypto-policies 8
.Sh AUTHORS
.An -nosplit
OpenSSH is a derivative of the original and free
--
2.49.0

View file

@ -1,157 +0,0 @@
From 430bd33963725beb8ec01a1e581529ae6bf6bec0 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:28 +0200
Subject: [PATCH 31/50] openssh-8.0p1-openssl-kdf
---
configure.ac | 1 +
kex.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 108 insertions(+)
diff --git a/configure.ac b/configure.ac
index d9bd2f51..d92a8580 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3137,6 +3137,7 @@ if test "x$openssl" = "xyes" ; then
HMAC_CTX_init \
RSA_generate_key_ex \
RSA_get_default_method \
+ EVP_KDF_CTX_new \
])
# OpenSSL_add_all_algorithms may be a macro.
diff --git a/kex.c b/kex.c
index 19a56e8e..8b200ff4 100644
--- a/kex.c
+++ b/kex.c
@@ -40,6 +40,11 @@
#ifdef WITH_OPENSSL
#include <openssl/crypto.h>
#include <openssl/dh.h>
+# ifdef HAVE_EVP_KDF_CTX_NEW
+# include <openssl/kdf.h>
+# include <openssl/param_build.h>
+# include <openssl/core_names.h>
+# endif
#endif
#include "ssh.h"
@@ -1078,6 +1083,107 @@ kex_choose_conf(struct ssh *ssh, uint32_t seq)
return r;
}
+#ifdef HAVE_EVP_KDF_CTX_NEW
+static const char *
+digest_to_md(int digest_type)
+{
+ switch (digest_type) {
+ case SSH_DIGEST_SHA1:
+ return SN_sha1;
+ case SSH_DIGEST_SHA256:
+ return SN_sha256;
+ case SSH_DIGEST_SHA384:
+ return SN_sha384;
+ case SSH_DIGEST_SHA512:
+ return SN_sha512;
+ }
+ return NULL;
+}
+
+static int
+derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen,
+ const struct sshbuf *shared_secret, u_char **keyp)
+{
+ struct kex *kex = ssh->kex;
+ u_char *key = NULL;
+ int r, key_len;
+
+ EVP_KDF *kdf = EVP_KDF_fetch(NULL, "SSHKDF", NULL);
+ EVP_KDF_CTX *ctx = EVP_KDF_CTX_new(kdf);
+ OSSL_PARAM_BLD *param_bld = OSSL_PARAM_BLD_new();
+ OSSL_PARAM *params = NULL;
+ const char *md = digest_to_md(kex->hash_alg);
+ char keytype = (char)id;
+
+ EVP_KDF_free(kdf);
+ if (!ctx) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ if (md == NULL) {
+ r = SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
+
+ if (param_bld == NULL) {
+ EVP_KDF_CTX_free(ctx);
+ return -1;
+ }
+ if ((key_len = ssh_digest_bytes(kex->hash_alg)) == 0) {
+ r = SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
+
+ key_len = ROUNDUP(need, key_len);
+ if ((key = calloc(1, key_len)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+
+ r = OSSL_PARAM_BLD_push_utf8_string(param_bld, OSSL_KDF_PARAM_DIGEST,
+ md, strlen(md)) && /* SN */
+ OSSL_PARAM_BLD_push_octet_string(param_bld, OSSL_KDF_PARAM_KEY,
+ sshbuf_ptr(shared_secret), sshbuf_len(shared_secret)) &&
+ OSSL_PARAM_BLD_push_octet_string(param_bld, OSSL_KDF_PARAM_SSHKDF_XCGHASH,
+ hash, hashlen) &&
+ OSSL_PARAM_BLD_push_octet_string(param_bld, OSSL_KDF_PARAM_SSHKDF_SESSION_ID,
+ sshbuf_ptr(kex->session_id), sshbuf_len(kex->session_id)) &&
+ OSSL_PARAM_BLD_push_utf8_string(param_bld, OSSL_KDF_PARAM_SSHKDF_TYPE,
+ &keytype, 1);
+ if (r != 1) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+
+ params = OSSL_PARAM_BLD_to_param(param_bld);
+ if (params == NULL) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ r = EVP_KDF_derive(ctx, key, key_len, params);
+ if (r != 1) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+#ifdef DEBUG_KEX
+ fprintf(stderr, "key '%c'== ", id);
+ dump_digest("key", key, key_len);
+#endif
+ *keyp = key;
+ key = NULL;
+ r = 0;
+
+out:
+ OSSL_PARAM_BLD_free(param_bld);
+ OSSL_PARAM_free(params);
+ free (key);
+ EVP_KDF_CTX_free(ctx);
+ if (r < 0) {
+ return r;
+ }
+ return 0;
+}
+#else
static int
derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen,
const struct sshbuf *shared_secret, u_char **keyp)
@@ -1141,6 +1247,7 @@ derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen,
ssh_digest_free(hashctx);
return r;
}
+#endif /* HAVE_OPENSSL_EVP_KDF_CTX_NEW */
#define NKEYS 6
int
--
2.49.0

View file

@ -1,52 +0,0 @@
From 6aa231d9acfeca870ee87e3bf9c4a1239518706d Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:28 +0200
Subject: [PATCH 32/50] openssh-8.2p1-visibility
---
regress/misc/sk-dummy/sk-dummy.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/regress/misc/sk-dummy/sk-dummy.c b/regress/misc/sk-dummy/sk-dummy.c
index 347b2122..344f8a8a 100644
--- a/regress/misc/sk-dummy/sk-dummy.c
+++ b/regress/misc/sk-dummy/sk-dummy.c
@@ -81,7 +81,7 @@ skdebug(const char *func, const char *fmt, ...)
#endif
}
-uint32_t
+uint32_t __attribute__((visibility("default")))
sk_api_version(void)
{
return SSH_SK_VERSION_MAJOR;
@@ -230,7 +230,7 @@ check_options(struct sk_option **options)
return 0;
}
-int
+int __attribute__((visibility("default")))
sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len,
const char *application, uint8_t flags, const char *pin,
struct sk_option **options, struct sk_enroll_response **enroll_response)
@@ -478,7 +478,7 @@ sig_ed25519(const uint8_t *message, size_t message_len,
return ret;
}
-int
+int __attribute__((visibility("default")))
sk_sign(uint32_t alg, const uint8_t *data, size_t datalen,
const char *application, const uint8_t *key_handle, size_t key_handle_len,
uint8_t flags, const char *pin, struct sk_option **options,
@@ -535,7 +535,7 @@ sk_sign(uint32_t alg, const uint8_t *data, size_t datalen,
return ret;
}
-int
+int __attribute__((visibility("default")))
sk_load_resident_keys(const char *pin, struct sk_option **options,
struct sk_resident_key ***rks, size_t *nrks)
{
--
2.49.0

View file

@ -1,33 +0,0 @@
From cfe5a99d335eb57b8c08b4eb6b4535dd042d96e3 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:28 +0200
Subject: [PATCH 33/50] openssh-8.2p1-x11-without-ipv6
---
channels.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/channels.c b/channels.c
index 7438c1a5..95836d50 100644
--- a/channels.c
+++ b/channels.c
@@ -5055,6 +5055,16 @@ x11_create_display_inet(struct ssh *ssh, int x11_display_offset,
debug2_f("bind port %d: %.100s", port,
strerror(errno));
close(sock);
+
+ /* do not remove successfully opened
+ * sockets if the request failed because
+ * the protocol IPv4/6 is not available
+ * (e.g. IPv6 may be disabled while being
+ * supported)
+ */
+ if (EADDRNOTAVAIL == errno)
+ continue;
+
for (n = 0; n < num_socks; n++)
close(socks[n]);
num_socks = 0;
--
2.49.0

View file

@ -1,56 +0,0 @@
From 8de0391e3b3eb75e23ee9f173f04a9c78f2b96c9 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:29 +0200
Subject: [PATCH 34/50] openssh-8.0p1-preserve-pam-errors
---
auth-pam.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/auth-pam.c b/auth-pam.c
index b4100ea1..a042c3c8 100644
--- a/auth-pam.c
+++ b/auth-pam.c
@@ -523,7 +523,11 @@ sshpam_thread(void *ctxtp)
goto auth_fail;
if (!do_pam_account()) {
- sshpam_err = PAM_ACCT_EXPIRED;
+ /* Preserve PAM_PERM_DENIED and PAM_USER_UNKNOWN.
+ * Backward compatibility for other errors. */
+ if (sshpam_err != PAM_PERM_DENIED
+ && sshpam_err != PAM_USER_UNKNOWN)
+ sshpam_err = PAM_ACCT_EXPIRED;
goto auth_fail;
}
if (sshpam_authctxt->force_pwchange) {
@@ -580,8 +584,10 @@ sshpam_thread(void *ctxtp)
pam_strerror(sshpam_handle, sshpam_err))) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
/* XXX - can't do much about an error here */
- if (sshpam_err == PAM_ACCT_EXPIRED)
- ssh_msg_send(ctxt->pam_csock, PAM_ACCT_EXPIRED, buffer);
+ if (sshpam_err == PAM_PERM_DENIED
+ || sshpam_err == PAM_USER_UNKNOWN
+ || sshpam_err == PAM_ACCT_EXPIRED)
+ ssh_msg_send(ctxt->pam_csock, sshpam_err, buffer);
else if (sshpam_maxtries_reached)
ssh_msg_send(ctxt->pam_csock, PAM_MAXTRIES, buffer);
else
@@ -890,9 +896,11 @@ sshpam_query(void *ctx, char **name, char **info,
free(msg);
break;
case PAM_ACCT_EXPIRED:
+ sshpam_account_status = 0;
+ /* FALLTHROUGH */
case PAM_MAXTRIES:
- if (type == PAM_ACCT_EXPIRED)
- sshpam_account_status = 0;
+ case PAM_USER_UNKNOWN:
+ case PAM_PERM_DENIED:
if (type == PAM_MAXTRIES)
sshpam_set_maxtries_reached(1);
/* FALLTHROUGH */
--
2.49.0

View file

@ -1,63 +0,0 @@
From a68f3741fdc01bf6823a69d2442caba7de9835f9 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:29 +0200
Subject: [PATCH 35/50] openssh-8.7p1-scp-kill-switch
---
pathnames.h | 1 +
scp.1 | 7 +++++++
scp.c | 8 ++++++++
3 files changed, 16 insertions(+)
diff --git a/pathnames.h b/pathnames.h
index 1158bec9..43f0c570 100644
--- a/pathnames.h
+++ b/pathnames.h
@@ -42,6 +42,7 @@
#define _PATH_HOST_XMSS_KEY_FILE SSHDIR "/ssh_host_xmss_key"
#define _PATH_HOST_RSA_KEY_FILE SSHDIR "/ssh_host_rsa_key"
#define _PATH_DH_MODULI SSHDIR "/moduli"
+#define _PATH_SCP_KILL_SWITCH SSHDIR "/disable_scp"
#ifndef _PATH_SSH_PROGRAM
#define _PATH_SSH_PROGRAM "/usr/bin/ssh"
diff --git a/scp.1 b/scp.1
index aa2e2d8b..373d7237 100644
--- a/scp.1
+++ b/scp.1
@@ -331,6 +331,13 @@ during download or upload.
By default a 32KB buffer is used.
.El
.El
+.Pp
+Usage of SCP protocol can be blocked by creating a world-readable
+.Ar /etc/ssh/disable_scp
+file. If this file exists, when SCP protocol is in use (either remotely or
+via the
+.Fl O
+option), the program will exit.
.Sh EXIT STATUS
.Ex -std scp
.Sh SEE ALSO
diff --git a/scp.c b/scp.c
index 7f9795a5..7ed1a54c 100644
--- a/scp.c
+++ b/scp.c
@@ -649,6 +649,14 @@ main(int argc, char **argv)
if (iamremote)
mode = MODE_SCP;
+ if (mode == MODE_SCP) {
+ FILE *f = fopen(_PATH_SCP_KILL_SWITCH, "r");
+ if (f != NULL) {
+ fclose(f);
+ fatal("SCP protocol is forbidden via %s", _PATH_SCP_KILL_SWITCH);
+ }
+ }
+
if ((pwd = getpwuid(userid = getuid())) == NULL)
fatal("unknown user %u", (u_int) userid);
--
2.49.0

View file

@ -1,200 +0,0 @@
From 99e1e3af524376788e591ca73387f1ca37e6f5ef Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:29 +0200
Subject: [PATCH 36/50] openssh-8.7p1-recursive-scp
---
scp.c | 2 +-
sftp-client.c | 60 +++++++++++++++++++++++++++++++++++++++------------
sftp-client.h | 4 ++--
sftp.c | 6 +++---
4 files changed, 52 insertions(+), 20 deletions(-)
diff --git a/scp.c b/scp.c
index 7ed1a54c..0c87dd0e 100644
--- a/scp.c
+++ b/scp.c
@@ -1388,7 +1388,7 @@ source_sftp(int argc, char *src, char *targ, struct sftp_conn *conn)
if (src_is_dir && iamrecursive) {
if (sftp_upload_dir(conn, src, abs_dst, pflag,
- SFTP_PROGRESS_ONLY, 0, 0, 1, 1) != 0) {
+ SFTP_PROGRESS_ONLY, 0, 0, 1, 1, 1) != 0) {
error("failed to upload directory %s to %s", src, targ);
errs = 1;
}
diff --git a/sftp-client.c b/sftp-client.c
index 9f8ab4af..873dec04 100644
--- a/sftp-client.c
+++ b/sftp-client.c
@@ -1003,7 +1003,7 @@ sftp_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
/* Implements both the realpath and expand-path operations */
static char *
-sftp_realpath_expand(struct sftp_conn *conn, const char *path, int expand)
+sftp_realpath_expand(struct sftp_conn *conn, const char *path, int expand, int create_dir)
{
struct sshbuf *msg;
u_int expected_id, count, id;
@@ -1049,11 +1049,43 @@ sftp_realpath_expand(struct sftp_conn *conn, const char *path, int expand)
if ((r = sshbuf_get_u32(msg, &status)) != 0 ||
(r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0)
fatal_fr(r, "parse status");
- error("%s %s: %s", expand ? "expand" : "realpath",
- path, *errmsg == '\0' ? fx2txt(status) : errmsg);
- free(errmsg);
- sshbuf_free(msg);
- return NULL;
+ if ((status == SSH2_FX_NO_SUCH_FILE) && create_dir) {
+ memset(&a, '\0', sizeof(a));
+ if ((r = sftp_mkdir(conn, path, &a, 0)) != 0) {
+ sshbuf_free(msg);
+ return NULL;
+ }
+ debug2("Sending SSH2_FXP_REALPATH \"%s\" - create dir", path);
+ send_string_request(conn, id, SSH2_FXP_REALPATH,
+ path, strlen(path));
+
+ get_msg(conn, msg);
+ if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
+ (r = sshbuf_get_u32(msg, &id)) != 0)
+ fatal_fr(r, "parse");
+
+ if (id != expected_id)
+ fatal("ID mismatch (%u != %u)", id, expected_id);
+
+ if (type == SSH2_FXP_STATUS) {
+ free(errmsg);
+
+ if ((r = sshbuf_get_u32(msg, &status)) != 0 ||
+ (r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0)
+ fatal_fr(r, "parse status");
+ error("%s %s: %s", expand ? "expand" : "realpath",
+ path, *errmsg == '\0' ? fx2txt(status) : errmsg);
+ free(errmsg);
+ sshbuf_free(msg);
+ return NULL;
+ }
+ } else {
+ error("%s %s: %s", expand ? "expand" : "realpath",
+ path, *errmsg == '\0' ? fx2txt(status) : errmsg);
+ free(errmsg);
+ sshbuf_free(msg);
+ return NULL;
+ }
} else if (type != SSH2_FXP_NAME)
fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
SSH2_FXP_NAME, type);
@@ -1078,9 +1110,9 @@ sftp_realpath_expand(struct sftp_conn *conn, const char *path, int expand)
}
char *
-sftp_realpath(struct sftp_conn *conn, const char *path)
+sftp_realpath(struct sftp_conn *conn, const char *path, int create_dir)
{
- return sftp_realpath_expand(conn, path, 0);
+ return sftp_realpath_expand(conn, path, 0, create_dir);
}
int
@@ -1094,9 +1126,9 @@ sftp_expand_path(struct sftp_conn *conn, const char *path)
{
if (!sftp_can_expand_path(conn)) {
debug3_f("no server support, fallback to realpath");
- return sftp_realpath_expand(conn, path, 0);
+ return sftp_realpath_expand(conn, path, 0, 0);
}
- return sftp_realpath_expand(conn, path, 1);
+ return sftp_realpath_expand(conn, path, 1, 0);
}
int
@@ -2016,7 +2048,7 @@ sftp_download_dir(struct sftp_conn *conn, const char *src, const char *dst,
char *src_canon;
int ret;
- if ((src_canon = sftp_realpath(conn, src)) == NULL) {
+ if ((src_canon = sftp_realpath(conn, src, 0)) == NULL) {
error("download \"%s\": path canonicalization failed", src);
return -1;
}
@@ -2366,12 +2398,12 @@ upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
int
sftp_upload_dir(struct sftp_conn *conn, const char *src, const char *dst,
int preserve_flag, int print_flag, int resume, int fsync_flag,
- int follow_link_flag, int inplace_flag)
+ int follow_link_flag, int inplace_flag, int create_dir)
{
char *dst_canon;
int ret;
- if ((dst_canon = sftp_realpath(conn, dst)) == NULL) {
+ if ((dst_canon = sftp_realpath(conn, dst, create_dir)) == NULL) {
error("upload \"%s\": path canonicalization failed", dst);
return -1;
}
@@ -2826,7 +2858,7 @@ sftp_crossload_dir(struct sftp_conn *from, struct sftp_conn *to,
char *from_path_canon;
int ret;
- if ((from_path_canon = sftp_realpath(from, from_path)) == NULL) {
+ if ((from_path_canon = sftp_realpath(from, from_path, 0)) == NULL) {
error("crossload \"%s\": path canonicalization failed",
from_path);
return -1;
diff --git a/sftp-client.h b/sftp-client.h
index 74cdae7d..00ed6630 100644
--- a/sftp-client.h
+++ b/sftp-client.h
@@ -111,7 +111,7 @@ int sftp_fsetstat(struct sftp_conn *, const u_char *, u_int, Attrib *);
int sftp_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a);
/* Canonicalise 'path' - caller must free result */
-char *sftp_realpath(struct sftp_conn *, const char *);
+char *sftp_realpath(struct sftp_conn *, const char *, int);
/* Canonicalisation with tilde expansion (requires server extension) */
char *sftp_expand_path(struct sftp_conn *, const char *);
@@ -163,7 +163,7 @@ int sftp_upload(struct sftp_conn *, const char *, const char *,
* times if 'pflag' is set
*/
int sftp_upload_dir(struct sftp_conn *, const char *, const char *,
- int, int, int, int, int, int);
+ int, int, int, int, int, int, int);
/*
* Download a 'from_path' from the 'from' connection and upload it to
diff --git a/sftp.c b/sftp.c
index bdedd141..322e6d1f 100644
--- a/sftp.c
+++ b/sftp.c
@@ -809,7 +809,7 @@ process_put(struct sftp_conn *conn, const char *src, const char *dst,
(rflag || global_rflag)) {
if (sftp_upload_dir(conn, g.gl_pathv[i], abs_dst,
pflag || global_pflag, 1, resume,
- fflag || global_fflag, 0, 0) == -1)
+ fflag || global_fflag, 0, 0, 0) == -1)
err = -1;
} else {
if (sftp_upload(conn, g.gl_pathv[i], abs_dst,
@@ -1644,7 +1644,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
if (path1 == NULL || *path1 == '\0')
path1 = xstrdup(startdir);
path1 = sftp_make_absolute(path1, *pwd);
- if ((tmp = sftp_realpath(conn, path1)) == NULL) {
+ if ((tmp = sftp_realpath(conn, path1, 0)) == NULL) {
err = 1;
break;
}
@@ -2249,7 +2249,7 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
}
#endif /* USE_LIBEDIT */
- if ((remote_path = sftp_realpath(conn, ".")) == NULL)
+ if ((remote_path = sftp_realpath(conn, ".", 0)) == NULL)
fatal("Need cwd");
startdir = xstrdup(remote_path);
--
2.49.0

View file

@ -1,37 +0,0 @@
From 286bc4a302b5130f732c857095ae665f7bea01dd Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:29 +0200
Subject: [PATCH 37/50] openssh-8.7p1-minrsabits
---
readconf.c | 1 +
servconf.c | 1 +
2 files changed, 2 insertions(+)
diff --git a/readconf.c b/readconf.c
index 6c04ed43..f340bf50 100644
--- a/readconf.c
+++ b/readconf.c
@@ -343,6 +343,7 @@ static struct {
{ "securitykeyprovider", oSecurityKeyProvider },
{ "knownhostscommand", oKnownHostsCommand },
{ "requiredrsasize", oRequiredRSASize },
+ { "rsaminsize", oRequiredRSASize }, /* alias */
{ "enableescapecommandline", oEnableEscapeCommandline },
{ "obscurekeystroketiming", oObscureKeystrokeTiming },
{ "channeltimeout", oChannelTimeout },
diff --git a/servconf.c b/servconf.c
index 15c99b30..84891544 100644
--- a/servconf.c
+++ b/servconf.c
@@ -788,6 +788,7 @@ static struct {
{ "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL },
{ "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL },
{ "requiredrsasize", sRequiredRSASize, SSHCFG_ALL },
+ { "rsaminsize", sRequiredRSASize, SSHCFG_ALL }, /* alias */
{ "channeltimeout", sChannelTimeout, SSHCFG_ALL },
{ "unusedconnectiontimeout", sUnusedConnectionTimeout, SSHCFG_ALL },
{ "sshdsessionpath", sSshdSessionPath, SSHCFG_GLOBAL },
--
2.49.0

View file

@ -1,25 +0,0 @@
From 26af04432f6404eb03780265a5cce948ecfec8dc Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:29 +0200
Subject: [PATCH 38/50] openssh-8.7p1-ibmca
---
openbsd-compat/bsd-closefrom.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/openbsd-compat/bsd-closefrom.c b/openbsd-compat/bsd-closefrom.c
index f6112458..417c2048 100644
--- a/openbsd-compat/bsd-closefrom.c
+++ b/openbsd-compat/bsd-closefrom.c
@@ -16,7 +16,7 @@
#include "includes.h"
-#if !defined(HAVE_CLOSEFROM) || defined(BROKEN_CLOSEFROM)
+#if !defined(HAVE_CLOSEFROM) || defined(BROKEN_CLOSEFROM) || (defined __s390__)
#include <sys/types.h>
#include <unistd.h>
--
2.49.0

File diff suppressed because it is too large Load diff

View file

@ -1,203 +0,0 @@
From c288d4a26ad44dc481c9d18d2920c9d70474833c Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:29 +0200
Subject: [PATCH 40/50] openssh-7.1p2-audit-race-condition
---
monitor_wrap.c | 46 +++++++++++++++++++++++++++++++++++++
monitor_wrap.h | 2 ++
session.c | 61 ++++++++++++++++++++++++++++++++++++++++++++------
3 files changed, 102 insertions(+), 7 deletions(-)
diff --git a/monitor_wrap.c b/monitor_wrap.c
index 1a079c15..768a59f9 100644
--- a/monitor_wrap.c
+++ b/monitor_wrap.c
@@ -1415,4 +1415,50 @@ mm_audit_destroy_sensitive_data(struct ssh *ssh, const char *fp, pid_t pid, uid_
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_SERVER_KEY_FREE, m);
sshbuf_free(m);
}
+
+int mm_forward_audit_messages(int fdin)
+{
+ u_char buf[4];
+ u_int blen, msg_len;
+ struct sshbuf *m;
+ int r, ret = 0;
+
+ debug3_f("entering");
+ if ((m = sshbuf_new()) == NULL)
+ fatal_f("sshbuf_new failed");
+ do {
+ blen = atomicio(read, fdin, buf, sizeof(buf));
+ if (blen == 0) /* closed pipe */
+ break;
+ if (blen != sizeof(buf)) {
+ error_f("Failed to read the buffer from child");
+ ret = -1;
+ break;
+ }
+
+ msg_len = get_u32(buf);
+ if (msg_len > 256 * 1024)
+ fatal_f("read: bad msg_len %d", msg_len);
+ sshbuf_reset(m);
+ if ((r = sshbuf_reserve(m, msg_len, NULL)) != 0)
+ fatal_fr(r, "buffer error");
+ if (atomicio(read, fdin, sshbuf_mutable_ptr(m), msg_len) != msg_len) {
+ error_f("Failed to read the the buffer content from the child");
+ ret = -1;
+ break;
+ }
+ if (atomicio(vwrite, pmonitor->m_recvfd, buf, blen) != blen ||
+ atomicio(vwrite, pmonitor->m_recvfd, sshbuf_mutable_ptr(m), msg_len) != msg_len) {
+ error_f("Failed to write the message to the monitor");
+ ret = -1;
+ break;
+ }
+ } while (1);
+ sshbuf_free(m);
+ return ret;
+}
+void mm_set_monitor_pipe(int fd)
+{
+ pmonitor->m_recvfd = fd;
+}
#endif /* SSH_AUDIT_EVENTS */
diff --git a/monitor_wrap.h b/monitor_wrap.h
index 661ed63b..e957ba6e 100644
--- a/monitor_wrap.h
+++ b/monitor_wrap.h
@@ -93,6 +93,8 @@ void mm_audit_unsupported_body(struct ssh *, int);
void mm_audit_kex_body(struct ssh *, int, char *, char *, char *, char *, pid_t, uid_t);
void mm_audit_session_key_free_body(struct ssh *, int, pid_t, uid_t);
void mm_audit_destroy_sensitive_data(struct ssh *, const char *, pid_t, uid_t);
+int mm_forward_audit_messages(int);
+void mm_set_monitor_pipe(int);
#endif
struct Session;
diff --git a/session.c b/session.c
index 83fc9418..b4753d93 100644
--- a/session.c
+++ b/session.c
@@ -167,6 +167,10 @@ static Session *sessions = NULL;
login_cap_t *lc;
#endif
+#ifdef SSH_AUDIT_EVENTS
+int paudit[2];
+#endif
+
static int is_child = 0;
static int in_chroot = 0;
static int have_dev_log = 1;
@@ -390,6 +394,8 @@ xauth_valid_string(const char *s)
return 1;
}
+void child_destory_sensitive_data(struct ssh *ssh);
+
#define USE_PIPES 1
/*
* This is called to fork and execute a command when we have no tty. This
@@ -513,6 +519,8 @@ do_exec_no_pty(struct ssh *ssh, Session *s, const char *command)
close(err[0]);
#endif
+ child_destory_sensitive_data(ssh);
+
/* Do processing for the child (exec command etc). */
do_child(ssh, s, command);
/* NOTREACHED */
@@ -630,6 +638,9 @@ do_exec_pty(struct ssh *ssh, Session *s, const char *command)
/* Close the extra descriptor for the pseudo tty. */
close(ttyfd);
+ /* Do this early, so we will not block large MOTDs */
+ child_destory_sensitive_data(ssh);
+
/* record login, etc. similar to login(1) */
#ifndef HAVE_OSF_SIA
do_login(ssh, s, command);
@@ -766,6 +777,8 @@ do_exec(struct ssh *ssh, Session *s, const char *command)
}
if (s->command != NULL && s->ptyfd == -1)
s->command_handle = mm_audit_run_command(ssh, s->command);
+ if (pipe(paudit) < 0)
+ fatal("pipe: %s", strerror(errno));
#endif
if (s->ttyfd != -1)
ret = do_exec_pty(ssh, s, command);
@@ -781,6 +794,20 @@ do_exec(struct ssh *ssh, Session *s, const char *command)
*/
sshbuf_reset(loginmsg);
+#ifdef SSH_AUDIT_EVENTS
+ close(paudit[1]);
+ if (ret == 0) {
+ /*
+ * Read the audit messages from forked child and send them
+ * back to monitor. We don't want to communicate directly,
+ * because the messages might get mixed up.
+ * Continue after the pipe gets closed (all messages sent).
+ */
+ ret = mm_forward_audit_messages(paudit[0]);
+ }
+ close(paudit[0]);
+#endif /* SSH_AUDIT_EVENTS */
+
return ret;
}
@@ -1532,6 +1559,33 @@ child_close_fds(struct ssh *ssh)
log_redirect_stderr_to(NULL);
}
+void
+child_destory_sensitive_data(struct ssh *ssh)
+{
+#ifdef SSH_AUDIT_EVENTS
+ int pparent = paudit[1];
+ close(paudit[0]);
+ /* Hack the monitor pipe to avoid race condition with parent */
+ mm_set_monitor_pipe(pparent);
+#endif
+
+ /* remove hostkey from the child's memory */
+ /* FIXME beldmit destroy_sensitive_data(ssh); */
+ /*
+ * We can audit this, because we hacked the pipe to direct the
+ * messages over postauth child. But this message requires answer
+ * which we can't do using one-way pipe.
+ */
+ packet_destroy_all(ssh, 0, 1);
+ /* XXX this will clean the rest but should not audit anymore */
+ /* packet_clear_keys(ssh); */
+
+#ifdef SSH_AUDIT_EVENTS
+ /* Notify parent that we are done */
+ close(pparent);
+#endif
+}
+
/*
* Performs common processing for the child, such as setting up the
* environment, closing extra file descriptors, setting the user and group
@@ -1549,13 +1603,6 @@ do_child(struct ssh *ssh, Session *s, const char *command)
sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id));
- /* remove keys from memory */
- destroy_sensitive_data(ssh);
- ssh_packet_clear_keys(ssh);
- /* Don't audit this - both us and the parent would be talking to the
- monitor over a single socket, with no synchronization. */
- packet_destroy_all(ssh, 0, 1);
-
/* Force a password change */
if (s->authctxt->force_pwchange) {
do_setusercontext(pw);
--
2.49.0

View file

@ -1,265 +0,0 @@
From 80d967a18261156573e7385f8e534a89d2767d67 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:29 +0200
Subject: [PATCH 41/50] openssh-9.0p1-audit-log
---
audit-bsm.c | 2 +-
audit-linux.c | 76 +++++++++++++++++++++++++++++++++++++++++++--------
audit.c | 18 +++++++++---
audit.h | 2 +-
4 files changed, 81 insertions(+), 17 deletions(-)
diff --git a/audit-bsm.c b/audit-bsm.c
index a49abb92..c6f56553 100644
--- a/audit-bsm.c
+++ b/audit-bsm.c
@@ -405,7 +405,7 @@ audit_session_close(struct logininfo *li)
}
int
-audit_keyusage(struct ssh *ssh, int host_user, char *fp, int rv)
+audit_keyusage(struct ssh *ssh, int host_user, char *key_fp, const struct sshkey_cert *cert, const char *issuer_fp, int rv)
{
/* not implemented */
}
diff --git a/audit-linux.c b/audit-linux.c
index d484b82b..dcfde3a9 100644
--- a/audit-linux.c
+++ b/audit-linux.c
@@ -52,7 +52,7 @@ extern u_int utmp_len;
const char *audit_username(void);
static void
-linux_audit_user_logxxx(int uid, const char *username,
+linux_audit_user_logxxx(int uid, const char *username, const char *hostname,
const char *ip, const char *ttyn, int success, int event)
{
int audit_fd, rc, saved_errno;
@@ -66,7 +66,7 @@ linux_audit_user_logxxx(int uid, const char *username,
}
rc = audit_log_acct_message(audit_fd, event,
NULL, "login", username ? username : "(unknown)",
- username == NULL ? uid : -1, NULL, ip, ttyn, success);
+ username == NULL ? uid : -1, hostname, ip, ttyn, success);
saved_errno = errno;
close(audit_fd);
@@ -137,10 +137,12 @@ fatal_report:
}
int
-audit_keyusage(struct ssh *ssh, int host_user, char *fp, int rv)
+audit_keyusage(struct ssh *ssh, int host_user, const char *key_fp, const struct sshkey_cert *cert, const char *issuer_fp, int rv)
{
char buf[AUDIT_LOG_SIZE];
int audit_fd, rc, saved_errno;
+ const char *rip;
+ u_int i;
audit_fd = audit_open();
if (audit_fd < 0) {
@@ -150,14 +152,44 @@ audit_keyusage(struct ssh *ssh, int host_user, char *fp, int rv)
else
return 0; /* Must prevent login */
}
+ rip = ssh_remote_ipaddr(ssh);
snprintf(buf, sizeof(buf), "%s_auth grantors=auth-key", host_user ? "pubkey" : "hostbased");
rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH, NULL,
- buf, audit_username(), -1, NULL, ssh_remote_ipaddr(ssh), NULL, rv);
+ buf, audit_username(), -1, NULL, rip, NULL, rv);
if ((rc < 0) && ((rc != -1) || (getuid() == 0)))
goto out;
- snprintf(buf, sizeof(buf), "op=negotiate kind=auth-key fp=%s", fp);
+ snprintf(buf, sizeof(buf), "op=negotiate kind=auth-key fp=%s", key_fp);
rc = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER, buf, NULL,
- ssh_remote_ipaddr(ssh), NULL, rv);
+ rip, NULL, rv);
+ if ((rc < 0) && ((rc != -1) || (getuid() == 0)))
+ goto out;
+
+ if (cert) {
+ char *pbuf;
+
+ pbuf = audit_encode_nv_string("key_id", cert->key_id, 0);
+ if (pbuf == NULL)
+ goto out;
+ snprintf(buf, sizeof(buf), "cert %s cert_serial=%llu cert_issuer_alg=\"%s\" cert_issuer_fp=\"%s\"",
+ pbuf, (unsigned long long)cert->serial, sshkey_type(cert->signature_key), issuer_fp);
+ free(pbuf);
+ rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH, NULL,
+ buf, audit_username(), -1, NULL, rip, NULL, rv);
+ if ((rc < 0) && ((rc != -1) || (getuid() == 0)))
+ goto out;
+
+ for (i = 0; cert->principals != NULL && i < cert->nprincipals; i++) {
+ pbuf = audit_encode_nv_string("cert_principal", cert->principals[i], 0);
+ if (pbuf == NULL)
+ goto out;
+ snprintf(buf, sizeof(buf), "principal %s", pbuf);
+ free(pbuf);
+ rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH, NULL,
+ buf, audit_username(), -1, NULL, rip, NULL, rv);
+ if ((rc < 0) && ((rc != -1) || (getuid() == 0)))
+ goto out;
+ }
+ }
out:
saved_errno = errno;
audit_close(audit_fd);
@@ -179,26 +211,34 @@ audit_connection_from(const char *host, int port)
int
audit_run_command(struct ssh *ssh, const char *command)
{
+ char * audit_hostname = options.use_dns ? remote_hostname(ssh) : NULL;
if (!user_login_count++)
linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL,
+ audit_hostname,
ssh_remote_ipaddr(ssh),
"ssh", 1, AUDIT_USER_LOGIN);
linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL,
+ audit_hostname,
ssh_remote_ipaddr(ssh),
"ssh", 1, AUDIT_USER_START);
+ free(audit_hostname);
return 0;
}
void
audit_end_command(struct ssh *ssh, int handle, const char *command)
{
+ char * audit_hostname = options.use_dns ? remote_hostname(ssh) : NULL;
linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL,
+ audit_hostname,
ssh_remote_ipaddr(ssh),
"ssh", 1, AUDIT_USER_END);
if (user_login_count && !--user_login_count)
linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL,
+ audit_hostname,
ssh_remote_ipaddr(ssh),
"ssh", 1, AUDIT_USER_LOGOUT);
+ free(audit_hostname);
}
void
@@ -211,31 +251,41 @@ void
audit_session_open(struct logininfo *li)
{
if (!user_login_count++)
- linux_audit_user_logxxx(li->uid, NULL, li->hostname,
+ linux_audit_user_logxxx(li->uid, NULL,
+ options.use_dns ? li->hostname : NULL,
+ options.use_dns ? NULL : li->hostname,
li->line, 1, AUDIT_USER_LOGIN);
- linux_audit_user_logxxx(li->uid, NULL, li->hostname,
+ linux_audit_user_logxxx(li->uid, NULL,
+ options.use_dns ? li->hostname : NULL,
+ options.use_dns ? NULL : li->hostname,
li->line, 1, AUDIT_USER_START);
}
void
audit_session_close(struct logininfo *li)
{
- linux_audit_user_logxxx(li->uid, NULL, li->hostname,
+ linux_audit_user_logxxx(li->uid, NULL,
+ options.use_dns ? li->hostname : NULL,
+ options.use_dns ? NULL : li->hostname,
li->line, 1, AUDIT_USER_END);
if (user_login_count && !--user_login_count)
- linux_audit_user_logxxx(li->uid, NULL, li->hostname,
+ linux_audit_user_logxxx(li->uid, NULL,
+ options.use_dns ? li->hostname : NULL,
+ options.use_dns ? NULL : li->hostname,
li->line, 1, AUDIT_USER_LOGOUT);
}
void
audit_event(struct ssh *ssh, ssh_audit_event_t event)
{
+ char * audit_hostname = options.use_dns ? remote_hostname(ssh) : NULL;
+
switch(event) {
case SSH_NOLOGIN:
case SSH_LOGIN_ROOT_DENIED:
linux_audit_user_auth(-1, audit_username(),
ssh_remote_ipaddr(ssh), "ssh", 0, event);
- linux_audit_user_logxxx(-1, audit_username(),
+ linux_audit_user_logxxx(-1, audit_username(), audit_hostname,
ssh_remote_ipaddr(ssh), "ssh", 0, AUDIT_USER_LOGIN);
break;
case SSH_AUTH_FAIL_PASSWD:
@@ -255,9 +305,11 @@ audit_event(struct ssh *ssh, ssh_audit_event_t event)
if (user_login_count) {
while (user_login_count--)
linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL,
+ audit_hostname,
ssh_remote_ipaddr(ssh),
"ssh", 1, AUDIT_USER_END);
linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL,
+ audit_hostname,
ssh_remote_ipaddr(ssh),
"ssh", 1, AUDIT_USER_LOGOUT);
}
@@ -266,12 +318,14 @@ audit_event(struct ssh *ssh, ssh_audit_event_t event)
case SSH_CONNECTION_ABANDON:
case SSH_INVALID_USER:
linux_audit_user_logxxx(-1, audit_username(),
+ audit_hostname,
ssh_remote_ipaddr(ssh), "ssh", 0, AUDIT_USER_LOGIN);
break;
default:
debug("%s: unhandled event %d", __func__, event);
break;
}
+ free(audit_hostname);
}
void
diff --git a/audit.c b/audit.c
index d0433c3a..28d51a14 100644
--- a/audit.c
+++ b/audit.c
@@ -116,12 +116,22 @@ audit_event_lookup(ssh_audit_event_t ev)
void
audit_key(struct ssh *ssh, int host_user, int *rv, const struct sshkey *key)
{
- char *fp;
+ char *key_fp = NULL;
+ char *issuer_fp = NULL;
+ struct sshkey_cert *cert = NULL;
- fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_HEX);
- if (audit_keyusage(ssh, host_user, fp, (*rv == 0)) == 0)
+ key_fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_HEX);
+ if (sshkey_is_cert(key) && key->cert != NULL && key->cert->signature_key != NULL) {
+ cert = key->cert;
+ issuer_fp = sshkey_fingerprint(cert->signature_key,
+ options.fingerprint_hash, SSH_FP_DEFAULT);
+ }
+ if (audit_keyusage(ssh, host_user, key_fp, cert, issuer_fp, (*rv == 0)) == 0)
*rv = -SSH_ERR_INTERNAL_ERROR;
- free(fp);
+ if (key_fp)
+ free(key_fp);
+ if (issuer_fp)
+ free(issuer_fp);
}
void
diff --git a/audit.h b/audit.h
index 45d66ccf..05ac132c 100644
--- a/audit.h
+++ b/audit.h
@@ -64,7 +64,7 @@ void audit_session_close(struct logininfo *);
int audit_run_command(struct ssh *, const char *);
void audit_end_command(struct ssh *, int, const char *);
ssh_audit_event_t audit_classify_auth(const char *);
-int audit_keyusage(struct ssh *, int, char *, int);
+int audit_keyusage(struct ssh *, int, const char *, const struct sshkey_cert *, const char *, int);
void audit_key(struct ssh *, int, int *, const struct sshkey *);
void audit_unsupported(struct ssh *, int);
void audit_kex(struct ssh *, int, char *, char *, char *, char *);
--
2.49.0

View file

@ -1,763 +0,0 @@
From 79f9b2763d85ec592cb7e54dcf1c695d8dd138b1 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 28 Aug 2025 14:01:38 +0200
Subject: [PATCH 42/54] openssh-7.7p1-fips
---
dh.c | 41 ++++++++++++++++++++++
dh.h | 1 +
kex-names.c | 6 +++-
kex.c | 3 +-
kexgen.c | 74 ++++++++++++++++++++++++++++++++--------
kexgexc.c | 5 +++
myproposal.h | 33 ++++++++++++++++++
readconf.c | 16 ++++++---
sandbox-seccomp-filter.c | 3 ++
servconf.c | 16 ++++++---
ssh-ed25519.c | 9 +++++
ssh-gss.h | 5 +++
ssh-keygen.c | 22 ++++++++++--
ssh-rsa.c | 3 ++
ssh.c | 5 +++
sshconnect2.c | 9 ++++-
sshd-session.c | 1 +
sshd.c | 13 +++++++
sshkey.c | 37 ++++++++++++++++++++
19 files changed, 272 insertions(+), 30 deletions(-)
diff --git a/dh.c b/dh.c
index 168dea1dd..8c9a29fa7 100644
--- a/dh.c
+++ b/dh.c
@@ -36,6 +36,7 @@
#include <openssl/bn.h>
#include <openssl/dh.h>
+#include <openssl/fips.h>
#include "dh.h"
#include "pathnames.h"
@@ -164,6 +165,12 @@ choose_dh(int min, int wantbits, int max)
int best, bestcount, which, linenum;
struct dhgroup dhg;
+ if (FIPS_mode()) {
+ verbose("Using arbitrary primes is not allowed in FIPS mode."
+ " Falling back to known groups.");
+ return (dh_new_group_fallback(max));
+ }
+
if ((f = fopen(get_moduli_filename(), "r")) == NULL) {
logit("WARNING: could not open %s (%s), using fixed modulus",
get_moduli_filename(), strerror(errno));
@@ -502,4 +509,38 @@ dh_estimate(int bits)
return 8192;
}
+/*
+ * Compares the received DH parameters with known-good groups,
+ * which might be either from group14, group16 or group18.
+ */
+int
+dh_is_known_group(const DH *dh)
+{
+ const BIGNUM *p, *g;
+ const BIGNUM *known_p, *known_g;
+ DH *known = NULL;
+ int bits = 0, rv = 0;
+
+ DH_get0_pqg(dh, &p, NULL, &g);
+ bits = BN_num_bits(p);
+
+ if (bits <= 3072) {
+ known = dh_new_group14();
+ } else if (bits <= 6144) {
+ known = dh_new_group16();
+ } else {
+ known = dh_new_group18();
+ }
+
+ DH_get0_pqg(known, &known_p, NULL, &known_g);
+
+ if (BN_cmp(g, known_g) == 0 &&
+ BN_cmp(p, known_p) == 0) {
+ rv = 1;
+ }
+
+ DH_free(known);
+ return rv;
+}
+
#endif /* WITH_OPENSSL */
diff --git a/dh.h b/dh.h
index c6326a39d..e51e292b8 100644
--- a/dh.h
+++ b/dh.h
@@ -45,6 +45,7 @@ DH *dh_new_group_fallback(int);
int dh_gen_key(DH *, int);
int dh_pub_is_valid(const DH *, const BIGNUM *);
+int dh_is_known_group(const DH *);
u_int dh_estimate(int);
void dh_set_moduli_file(const char *);
diff --git a/kex-names.c b/kex-names.c
index 6c0b7c2b3..cd3902ad2 100644
--- a/kex-names.c
+++ b/kex-names.c
@@ -33,6 +33,7 @@
#ifdef WITH_OPENSSL
#include <openssl/crypto.h>
+#include <openssl/fips.h>
#include <openssl/evp.h>
#endif
@@ -206,7 +207,10 @@ kex_names_valid(const char *names)
for ((p = strsep(&cp, ",")); p && *p != '\0';
(p = strsep(&cp, ","))) {
if (kex_alg_by_name(p) == NULL) {
- error("Unsupported KEX algorithm \"%.100s\"", p);
+ if (FIPS_mode())
+ error("\"%.100s\" is not allowed in FIPS mode", p);
+ else
+ error("Unsupported KEX algorithm \"%.100s\"", p);
free(s);
return 0;
}
diff --git a/kex.c b/kex.c
index 62f607d6f..71fbe5cbe 100644
--- a/kex.c
+++ b/kex.c
@@ -40,6 +40,7 @@
#ifdef WITH_OPENSSL
#include <openssl/crypto.h>
#include <openssl/dh.h>
+#include <openssl/fips.h>
# ifdef HAVE_EVP_KDF_CTX_NEW
# include <openssl/kdf.h>
# include <openssl/param_build.h>
@@ -109,7 +110,7 @@ kex_proposal_populate_entries(struct ssh *ssh, char *prop[PROPOSAL_MAX],
/* Append EXT_INFO signalling to KexAlgorithms */
if (kexalgos == NULL)
- kexalgos = defprop[PROPOSAL_KEX_ALGS];
+ kexalgos = FIPS_mode() ? KEX_DEFAULT_KEX_FIPS : defprop[PROPOSAL_KEX_ALGS];
if ((cp = kex_names_cat(kexalgos, ssh->kex->server ?
"ext-info-s,kex-strict-s-v00@openssh.com" :
"ext-info-c,kex-strict-c-v00@openssh.com")) == NULL)
diff --git a/kexgen.c b/kexgen.c
index 15df591ca..eecdceba2 100644
--- a/kexgen.c
+++ b/kexgen.c
@@ -31,6 +31,7 @@
#include <stdio.h>
#include <string.h>
#include <signal.h>
+#include <openssl/fips.h>
#include "sshkey.h"
#include "kex.h"
@@ -115,13 +116,28 @@ kex_gen_client(struct ssh *ssh)
break;
#endif
case KEX_C25519_SHA256:
- r = kex_c25519_keypair(kex);
+ if (FIPS_mode()) {
+ logit_f("Key exchange type c25519 is not allowed in FIPS mode");
+ r = SSH_ERR_INVALID_ARGUMENT;
+ } else {
+ r = kex_c25519_keypair(kex);
+ }
break;
case KEX_KEM_SNTRUP761X25519_SHA512:
- r = kex_kem_sntrup761x25519_keypair(kex);
+ if (FIPS_mode()) {
+ logit_f("Key exchange type sntrup761 is not allowed in FIPS mode");
+ r = SSH_ERR_INVALID_ARGUMENT;
+ } else {
+ r = kex_kem_sntrup761x25519_keypair(kex);
+ }
break;
case KEX_KEM_MLKEM768X25519_SHA256:
- r = kex_kem_mlkem768x25519_keypair(kex);
+ if (FIPS_mode()) {
+ logit_f("Key exchange type mlkem768x25519 is not allowed in FIPS mode");
+ r = SSH_ERR_INVALID_ARGUMENT;
+ } else {
+ r = kex_kem_mlkem768x25519_keypair(kex);
+ }
break;
default:
r = SSH_ERR_INVALID_ARGUMENT;
@@ -189,15 +205,30 @@ input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh)
break;
#endif
case KEX_C25519_SHA256:
- r = kex_c25519_dec(kex, server_blob, &shared_secret);
+ if (FIPS_mode()) {
+ logit_f("Key exchange type c25519 is not allowed in FIPS mode");
+ r = SSH_ERR_INVALID_ARGUMENT;
+ } else {
+ r = kex_c25519_dec(kex, server_blob, &shared_secret);
+ }
break;
case KEX_KEM_SNTRUP761X25519_SHA512:
- r = kex_kem_sntrup761x25519_dec(kex, server_blob,
- &shared_secret);
+ if (FIPS_mode()) {
+ logit_f("Key exchange type sntrup761 is not allowed in FIPS mode");
+ r = SSH_ERR_INVALID_ARGUMENT;
+ } else {
+ r = kex_kem_sntrup761x25519_dec(kex, server_blob,
+ &shared_secret);
+ }
break;
case KEX_KEM_MLKEM768X25519_SHA256:
- r = kex_kem_mlkem768x25519_dec(kex, server_blob,
- &shared_secret);
+ if (FIPS_mode()) {
+ logit_f("Key exchange type mlkem768x25519 is not allowed in FIPS mode");
+ r = SSH_ERR_INVALID_ARGUMENT;
+ } else {
+ r = kex_kem_mlkem768x25519_dec(kex, server_blob,
+ &shared_secret);
+ }
break;
default:
r = SSH_ERR_INVALID_ARGUMENT;
@@ -312,16 +343,31 @@ input_kex_gen_init(int type, u_int32_t seq, struct ssh *ssh)
break;
#endif
case KEX_C25519_SHA256:
- r = kex_c25519_enc(kex, client_pubkey, &server_pubkey,
- &shared_secret);
+ if (FIPS_mode()) {
+ logit_f("Key exchange type c25519 is not allowed in FIPS mode");
+ r = SSH_ERR_INVALID_ARGUMENT;
+ } else {
+ r = kex_c25519_enc(kex, client_pubkey, &server_pubkey,
+ &shared_secret);
+ }
break;
case KEX_KEM_SNTRUP761X25519_SHA512:
- r = kex_kem_sntrup761x25519_enc(kex, client_pubkey,
- &server_pubkey, &shared_secret);
+ if (FIPS_mode()) {
+ logit_f("Key exchange type sntrup761 is not allowed in FIPS mode");
+ r = SSH_ERR_INVALID_ARGUMENT;
+ } else {
+ r = kex_kem_sntrup761x25519_enc(kex, client_pubkey,
+ &server_pubkey, &shared_secret);
+ }
break;
case KEX_KEM_MLKEM768X25519_SHA256:
- r = kex_kem_mlkem768x25519_enc(kex, client_pubkey,
- &server_pubkey, &shared_secret);
+ if (FIPS_mode()) {
+ logit_f("Key exchange type mlkem768x25519 is not allowed in FIPS mode");
+ r = SSH_ERR_INVALID_ARGUMENT;
+ } else {
+ r = kex_kem_mlkem768x25519_enc(kex, client_pubkey,
+ &server_pubkey, &shared_secret);
+ }
break;
default:
r = SSH_ERR_INVALID_ARGUMENT;
diff --git a/kexgexc.c b/kexgexc.c
index e99e0cf21..4c3feae09 100644
--- a/kexgexc.c
+++ b/kexgexc.c
@@ -28,6 +28,7 @@
#ifdef WITH_OPENSSL
+#include <openssl/fips.h>
#include <sys/types.h>
#include <openssl/dh.h>
@@ -115,6 +116,10 @@ input_kex_dh_gex_group(int type, u_int32_t seq, struct ssh *ssh)
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
+ if (FIPS_mode() && dh_is_known_group(kex->dh) == 0) {
+ r = SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
p = g = NULL; /* belong to kex->dh now */
/* generate and send 'e', client DH public key */
diff --git a/myproposal.h b/myproposal.h
index 8fe9276c2..3e0ec6826 100644
--- a/myproposal.h
+++ b/myproposal.h
@@ -58,6 +58,18 @@
"rsa-sha2-512," \
"rsa-sha2-256"
+#define KEX_FIPS_PK_ALG \
+ "ecdsa-sha2-nistp256-cert-v01@openssh.com," \
+ "ecdsa-sha2-nistp384-cert-v01@openssh.com," \
+ "ecdsa-sha2-nistp521-cert-v01@openssh.com," \
+ "rsa-sha2-512-cert-v01@openssh.com," \
+ "rsa-sha2-256-cert-v01@openssh.com," \
+ "ecdsa-sha2-nistp256," \
+ "ecdsa-sha2-nistp384," \
+ "ecdsa-sha2-nistp521," \
+ "rsa-sha2-512," \
+ "rsa-sha2-256"
+
#define KEX_SERVER_ENCRYPT \
"chacha20-poly1305@openssh.com," \
"aes128-gcm@openssh.com,aes256-gcm@openssh.com," \
@@ -79,6 +91,27 @@
#define KEX_CLIENT_MAC KEX_SERVER_MAC
+#define KEX_FIPS_ENCRYPT \
+ "aes128-ctr,aes192-ctr,aes256-ctr," \
+ "aes128-cbc,3des-cbc," \
+ "aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se," \
+ "aes128-gcm@openssh.com,aes256-gcm@openssh.com"
+#define KEX_DEFAULT_KEX_FIPS \
+ "ecdh-sha2-nistp256," \
+ "ecdh-sha2-nistp384," \
+ "ecdh-sha2-nistp521," \
+ "diffie-hellman-group-exchange-sha256," \
+ "diffie-hellman-group16-sha512," \
+ "diffie-hellman-group18-sha512," \
+ "diffie-hellman-group14-sha256"
+#define KEX_FIPS_MAC \
+ "hmac-sha1," \
+ "hmac-sha2-256," \
+ "hmac-sha2-512," \
+ "hmac-sha1-etm@openssh.com," \
+ "hmac-sha2-256-etm@openssh.com," \
+ "hmac-sha2-512-etm@openssh.com"
+
/* Not a KEX value, but here so all the algorithm defaults are together */
#define SSH_ALLOWED_CA_SIGALGS \
"ssh-ed25519," \
diff --git a/readconf.c b/readconf.c
index f340bf501..ea9d293c3 100644
--- a/readconf.c
+++ b/readconf.c
@@ -43,6 +43,7 @@
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
+#include <openssl/fips.h>
#ifdef USE_SYSTEM_GLOB
# include <glob.h>
#else
@@ -3043,11 +3044,16 @@ fill_default_options(Options * options)
all_key = sshkey_alg_list(0, 0, 1, ',');
all_sig = sshkey_alg_list(0, 1, 1, ',');
/* remove unsupported algos from default lists */
- def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher);
- def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac);
- def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex);
- def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
- def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig);
+ def_cipher = match_filter_allowlist((FIPS_mode() ?
+ KEX_FIPS_ENCRYPT : KEX_CLIENT_ENCRYPT), all_cipher);
+ def_mac = match_filter_allowlist((FIPS_mode() ?
+ KEX_FIPS_MAC : KEX_CLIENT_MAC), all_mac);
+ def_kex = match_filter_allowlist((FIPS_mode() ?
+ KEX_DEFAULT_KEX_FIPS : KEX_CLIENT_KEX), all_kex);
+ def_key = match_filter_allowlist((FIPS_mode() ?
+ KEX_FIPS_PK_ALG : KEX_DEFAULT_PK_ALG), all_key);
+ def_sig = match_filter_allowlist((FIPS_mode() ?
+ KEX_FIPS_PK_ALG : SSH_ALLOWED_CA_SIGALGS), all_sig);
#define ASSEMBLE(what, defaults, all) \
do { \
if ((r = kex_assemble_names(&options->what, \
diff --git a/sandbox-seccomp-filter.c b/sandbox-seccomp-filter.c
index 1fabf99d0..ccb61586e 100644
--- a/sandbox-seccomp-filter.c
+++ b/sandbox-seccomp-filter.c
@@ -230,6 +230,9 @@ static const struct sock_filter preauth_insns[] = {
#ifdef __NR_open
SC_DENY(__NR_open, EACCES),
#endif
+#ifdef __NR_socket
+ SC_DENY(__NR_socket, EACCES),
+#endif
#ifdef __NR_openat
SC_DENY(__NR_openat, EACCES),
#endif
diff --git a/servconf.c b/servconf.c
index 84891544b..8b708cbf4 100644
--- a/servconf.c
+++ b/servconf.c
@@ -37,6 +37,7 @@
#include <limits.h>
#include <stdarg.h>
#include <errno.h>
+#include <openssl/fips.h>
#ifdef HAVE_UTIL_H
#include <util.h>
#endif
@@ -247,11 +248,16 @@ assemble_algorithms(ServerOptions *o)
all_key = sshkey_alg_list(0, 0, 1, ',');
all_sig = sshkey_alg_list(0, 1, 1, ',');
/* remove unsupported algos from default lists */
- def_cipher = match_filter_allowlist(KEX_SERVER_ENCRYPT, all_cipher);
- def_mac = match_filter_allowlist(KEX_SERVER_MAC, all_mac);
- def_kex = match_filter_allowlist(KEX_SERVER_KEX, all_kex);
- def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
- def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig);
+ def_cipher = match_filter_allowlist((FIPS_mode() ?
+ KEX_FIPS_ENCRYPT : KEX_SERVER_ENCRYPT), all_cipher);
+ def_mac = match_filter_allowlist((FIPS_mode() ?
+ KEX_FIPS_MAC : KEX_SERVER_MAC), all_mac);
+ def_kex = match_filter_allowlist((FIPS_mode() ?
+ KEX_DEFAULT_KEX_FIPS : KEX_SERVER_KEX), all_kex);
+ def_key = match_filter_allowlist((FIPS_mode() ?
+ KEX_FIPS_PK_ALG : KEX_DEFAULT_PK_ALG), all_key);
+ def_sig = match_filter_allowlist((FIPS_mode() ?
+ KEX_FIPS_PK_ALG : SSH_ALLOWED_CA_SIGALGS), all_sig);
#define ASSEMBLE(what, defaults, all) \
do { \
if ((r = kex_assemble_names(&o->what, defaults, all)) != 0) \
diff --git a/ssh-ed25519.c b/ssh-ed25519.c
index 22d8db026..41942f4e5 100644
--- a/ssh-ed25519.c
+++ b/ssh-ed25519.c
@@ -24,6 +24,7 @@
#include <string.h>
#include <stdarg.h>
+#include <openssl/fips.h>
#include "log.h"
#include "sshbuf.h"
@@ -164,6 +165,10 @@ ssh_ed25519_sign(struct sshkey *key,
key->ed25519_sk == NULL ||
datalen >= INT_MAX - crypto_sign_ed25519_BYTES)
return SSH_ERR_INVALID_ARGUMENT;
+ if (FIPS_mode()) {
+ logit_f("Ed25519 keys are not allowed in FIPS mode");
+ return SSH_ERR_INVALID_ARGUMENT;
+ }
smlen = slen = datalen + crypto_sign_ed25519_BYTES;
if ((sig = malloc(slen)) == NULL)
return SSH_ERR_ALLOC_FAIL;
@@ -221,6 +226,10 @@ ssh_ed25519_verify(const struct sshkey *key,
dlen >= INT_MAX - crypto_sign_ed25519_BYTES ||
sig == NULL || siglen == 0)
return SSH_ERR_INVALID_ARGUMENT;
+ if (FIPS_mode()) {
+ logit_f("Ed25519 keys are not allowed in FIPS mode");
+ return SSH_ERR_INVALID_ARGUMENT;
+ }
if ((b = sshbuf_from(sig, siglen)) == NULL)
return SSH_ERR_ALLOC_FAIL;
diff --git a/ssh-gss.h b/ssh-gss.h
index a894e23c9..329dc9da0 100644
--- a/ssh-gss.h
+++ b/ssh-gss.h
@@ -88,6 +88,11 @@ extern char **k5users_allowed_cmds;
KEX_GSS_GRP14_SHA1_ID "," \
KEX_GSS_GEX_SHA1_ID
+#define GSS_KEX_DEFAULT_KEX_FIPS \
+ KEX_GSS_GRP14_SHA256_ID "," \
+ KEX_GSS_GRP16_SHA512_ID "," \
+ KEX_GSS_NISTP256_SHA256_ID
+
#include "digest.h" /* SSH_DIGEST_MAX_LENGTH */
typedef struct {
diff --git a/ssh-keygen.c b/ssh-keygen.c
index 16cff9473..792aafde0 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -20,6 +20,7 @@
#ifdef WITH_OPENSSL
#include <openssl/evp.h>
+#include <openssl/fips.h>
#include <openssl/pem.h>
#include "openbsd-compat/openssl-compat.h"
#endif
@@ -68,6 +69,7 @@
#include "cipher.h"
#define DEFAULT_KEY_TYPE_NAME "ed25519"
+#define FIPS_DEFAULT_KEY_TYPE_NAME "rsa"
/*
* Default number of bits in the RSA, DSA and ECDSA keys. These value can be
@@ -202,6 +204,12 @@ type_bits_valid(int type, const char *name, u_int32_t *bitsp)
#endif
}
#ifdef WITH_OPENSSL
+ if (FIPS_mode()) {
+ if (type == KEY_DSA)
+ fatal("DSA keys are not allowed in FIPS mode");
+ if (type == KEY_ED25519 || type == KEY_ED25519_SK)
+ fatal("ED25519 keys are not allowed in FIPS mode");
+ }
switch (type) {
case KEY_DSA:
if (*bitsp != 1024)
@@ -259,7 +267,7 @@ ask_filename(struct passwd *pw, const char *prompt)
char *name = NULL;
if (key_type_name == NULL)
- name = _PATH_SSH_CLIENT_ID_ED25519;
+ name = FIPS_mode() ? _PATH_SSH_CLIENT_ID_RSA : _PATH_SSH_CLIENT_ID_ED25519;
else {
switch (sshkey_type_from_shortname(key_type_name)) {
#ifdef WITH_DSA
@@ -1144,9 +1152,17 @@ do_gen_all_hostkeys(struct passwd *pw)
first = 1;
printf("%s: generating new host keys: ", __progname);
}
+ type = sshkey_type_from_shortname(key_types[i].key_type);
+
+ /* Skip the keys that are not supported in FIPS mode */
+ if (FIPS_mode() && (type == KEY_DSA || type == KEY_ED25519)) {
+ logit("Skipping %s key in FIPS mode",
+ key_types[i].key_type_display);
+ goto next;
+ }
+
printf("%s ", key_types[i].key_type_display);
fflush(stdout);
- type = sshkey_type_from_shortname(key_types[i].key_type);
if ((fd = mkstemp(prv_tmp)) == -1) {
error("Could not save your private key in %s: %s",
prv_tmp, strerror(errno));
@@ -3849,7 +3865,7 @@ main(int argc, char **argv)
}
if (key_type_name == NULL)
- key_type_name = DEFAULT_KEY_TYPE_NAME;
+ key_type_name = FIPS_mode() ? FIPS_DEFAULT_KEY_TYPE_NAME : DEFAULT_KEY_TYPE_NAME;
type = sshkey_type_from_shortname(key_type_name);
type_bits_valid(type, key_type_name, &bits);
diff --git a/ssh-rsa.c b/ssh-rsa.c
index 3ad1fddc4..6c2f771a3 100644
--- a/ssh-rsa.c
+++ b/ssh-rsa.c
@@ -23,6 +23,7 @@
#include <openssl/evp.h>
#include <openssl/err.h>
+#include <openssl/fips.h>
#include <stdarg.h>
#include <string.h>
@@ -142,6 +143,8 @@ ssh_rsa_generate(struct sshkey *k, int bits)
goto out;
}
if (EVP_PKEY_keygen(ctx, &res) <= 0 || res == NULL) {
+ if (FIPS_mode())
+ logit_f("the key length might be unsupported by FIPS mode approved key generation method");
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
diff --git a/ssh.c b/ssh.c
index 98b103c9e..abc8b8439 100644
--- a/ssh.c
+++ b/ssh.c
@@ -78,6 +78,7 @@
#include <openssl/evp.h>
#include <openssl/err.h>
#endif
+#include <openssl/fips.h>
#include "openbsd-compat/openssl-compat.h"
#include "openbsd-compat/sys-queue.h"
@@ -1642,6 +1643,10 @@ main(int ac, char **av)
exit(0);
}
+ if (FIPS_mode()) {
+ debug("FIPS mode initialized");
+ }
+
/* Expand SecurityKeyProvider if it refers to an environment variable */
if (options.sk_provider != NULL && *options.sk_provider == '$' &&
strlen(options.sk_provider) > 1) {
diff --git a/sshconnect2.c b/sshconnect2.c
index 0af15bcc1..3e02f485d 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -45,6 +45,8 @@
#include <vis.h>
#endif
+#include <openssl/fips.h>
+
#include "openbsd-compat/sys-queue.h"
#include "xmalloc.h"
@@ -262,6 +264,9 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port,
#if defined(GSSAPI) && defined(WITH_OPENSSL)
if (options.gss_keyex) {
+ char * gss_kex_filtered = FIPS_mode() ?
+ match_filter_allowlist(options.gss_kex_algorithms, GSS_KEX_DEFAULT_KEX_FIPS) : xstrdup(options.gss_kex_algorithms);
+
/* Add the GSSAPI mechanisms currently supported on this
* client to the key exchange algorithm proposal */
orig = myproposal[PROPOSAL_KEX_ALGS];
@@ -281,7 +286,9 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port,
}
gss = ssh_gssapi_client_mechanisms(gss_host,
- options.gss_client_identity, options.gss_kex_algorithms);
+ options.gss_client_identity, gss_kex_filtered);
+ free(gss_kex_filtered);
+
if (gss) {
debug("Offering GSSAPI proposal: %s", gss);
xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
diff --git a/sshd-session.c b/sshd-session.c
index a808ac9a6..a67a78391 100644
--- a/sshd-session.c
+++ b/sshd-session.c
@@ -62,6 +62,7 @@
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
+#include <openssl/fips.h>
#include "openbsd-compat/openssl-compat.h"
#endif
diff --git a/sshd.c b/sshd.c
index 8a99f0b29..5ff0b5ff0 100644
--- a/sshd.c
+++ b/sshd.c
@@ -52,6 +52,7 @@
#endif
#include <pwd.h>
#include <signal.h>
+#include <syslog.h>
#include <stdarg.h>
#include <time.h>
#include <stdio.h>
@@ -63,6 +64,7 @@
#ifdef WITH_OPENSSL
#include <openssl/evp.h>
#include <openssl/rand.h>
+#include <openssl/fips.h>
#include "openbsd-compat/openssl-compat.h"
#endif
@@ -1611,6 +1613,13 @@ main(int ac, char **av)
&key, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR)
do_log2_r(r, ll, "Unable to load host key \"%s\"",
options.host_key_files[i]);
+ if (FIPS_mode() && key != NULL && (sshkey_type_plain(key->type) == KEY_ED25519_SK
+ || sshkey_type_plain(key->type) == KEY_ED25519)) {
+ logit_f("sshd: Ed25519 keys are not allowed in FIPS mode, skipping %s", options.host_key_files[i]);
+ sshkey_free(key);
+ key = NULL;
+ continue;
+ }
if (sshkey_is_sk(key) &&
key->sk_flags & SSH_SK_USER_PRESENCE_REQD) {
debug("host key %s requires user presence, ignoring",
@@ -1830,6 +1839,10 @@ main(int ac, char **av)
/* Reinitialize the log (because of the fork above). */
log_init(__progname, options.log_level, options.log_facility, log_stderr);
+ if (FIPS_mode()) {
+ debug("FIPS mode initialized");
+ }
+
/*
* Chdir to the root directory so that the current disk can be
* unmounted if desired.
diff --git a/sshkey.c b/sshkey.c
index 4e41a78c7..ca1cdb642 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -35,6 +35,7 @@
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/pem.h>
+#include <openssl/fips.h>
#endif
#include "crypto_api.h"
@@ -59,6 +60,7 @@
#define SSHKEY_INTERNAL
#include "sshkey.h"
#include "match.h"
+#include "log.h"
#include "ssh-sk.h"
#ifdef WITH_XMSS
@@ -408,6 +410,18 @@ sshkey_alg_list(int certs_only, int plain_only, int include_sigonly, char sep)
impl = keyimpls[i];
if (impl->name == NULL || impl->type == KEY_NULL)
continue;
+ if (FIPS_mode()) {
+ switch (impl->type) {
+ case KEY_ED25519:
+ case KEY_ED25519_SK:
+ case KEY_ED25519_CERT:
+ case KEY_ED25519_SK_CERT:
+ continue;
+ break;
+ default:
+ break;
+ }
+ }
if (!include_sigonly && impl->sigonly)
continue;
if ((certs_only && !impl->cert) || (plain_only && impl->cert))
@@ -1441,6 +1455,20 @@ sshkey_read(struct sshkey *ret, char **cpp)
return SSH_ERR_EC_CURVE_MISMATCH;
}
+ switch (type) {
+ case KEY_ED25519:
+ case KEY_ED25519_SK:
+ case KEY_ED25519_CERT:
+ case KEY_ED25519_SK_CERT:
+ if (FIPS_mode()) {
+ sshkey_free(k);
+ logit_f("Ed25519 keys are not allowed in FIPS mode");
+ return SSH_ERR_INVALID_ARGUMENT;
+ }
+ break;
+ default:
+ break;
+ }
/* Fill in ret from parsed key */
sshkey_free_contents(ret);
*ret = *k;
@@ -2275,6 +2303,11 @@ sshkey_sign(struct sshkey *key,
*lenp = 0;
if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE)
return SSH_ERR_INVALID_ARGUMENT;
+ if (FIPS_mode() && ((key->type == KEY_ED25519_SK) || (key->type == KEY_ED25519_SK_CERT))) {
+ logit_f("Ed25519 keys are not allowed in FIPS mode");
+ return SSH_ERR_INVALID_ARGUMENT;
+ }
+ /* Fallthrough */
if ((impl = sshkey_impl_from_key(key)) == NULL)
return SSH_ERR_KEY_TYPE_UNKNOWN;
if ((r = sshkey_unshield_private(key)) != 0)
@@ -2311,6 +2344,10 @@ sshkey_verify(const struct sshkey *key,
*detailsp = NULL;
if (siglen == 0 || dlen > SSH_KEY_MAX_SIGN_DATA_SIZE)
return SSH_ERR_INVALID_ARGUMENT;
+ if (FIPS_mode() && ((key->type == KEY_ED25519_SK) || (key->type == KEY_ED25519_SK_CERT))) {
+ logit_f("Ed25519 keys are not allowed in FIPS mode");
+ return SSH_ERR_INVALID_ARGUMENT;
+ }
if ((impl = sshkey_impl_from_key(key)) == NULL)
return SSH_ERR_KEY_TYPE_UNKNOWN;
return impl->funcs->verify(key, sig, siglen, data, dlen,
--
2.51.0

View file

@ -1,47 +0,0 @@
From 299a602802d7c7d121306eb2aeae1502871a35cb Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:29 +0200
Subject: [PATCH 43/50] openssh-8.7p1-ssh-manpage
---
ssh.1 | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/ssh.1 b/ssh.1
index 6a9fbdc5..755cdef2 100644
--- a/ssh.1
+++ b/ssh.1
@@ -510,12 +510,12 @@ For full details of the options listed below, and their possible values, see
.It BatchMode
.It BindAddress
.It BindInterface
-.It CASignatureAlgorithms
.It CanonicalDomains
.It CanonicalizeFallbackLocal
.It CanonicalizeHostname
.It CanonicalizeMaxDots
.It CanonicalizePermittedCNAMEs
+.It CASignatureAlgorithms
.It CertificateFile
.It ChannelTimeout
.It CheckHostIP
@@ -528,6 +528,7 @@ For full details of the options listed below, and their possible values, see
.It ControlPath
.It ControlPersist
.It DynamicForward
+.It EnableSSHKeysign
.It EnableEscapeCommandline
.It EnableSSHKeysign
.It EscapeChar
@@ -588,6 +589,8 @@ For full details of the options listed below, and their possible values, see
.It RemoteCommand
.It RemoteForward
.It RequestTTY
+.It RevokedHostKeys
+.It SecurityKeyProvider
.It RequiredRSASize
.It RevokedHostKeys
.It SecurityKeyProvider
--
2.49.0

View file

@ -1,133 +0,0 @@
From 5c92430c08ac392b5b2ace899cc043247c923734 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:29 +0200
Subject: [PATCH 44/50] openssh-8.7p1-negotiate-supported-algs
---
regress/hostkey-agent.sh | 32 +++++++++++++++++++++++++-------
sshconnect2.c | 17 +++++++++++++++--
2 files changed, 40 insertions(+), 9 deletions(-)
diff --git a/regress/hostkey-agent.sh b/regress/hostkey-agent.sh
index 28dcfe17..b9e716dc 100644
--- a/regress/hostkey-agent.sh
+++ b/regress/hostkey-agent.sh
@@ -17,8 +17,21 @@ trace "make CA key"
${SSHKEYGEN} -qt ed25519 -f $OBJ/agent-ca -N '' || fatal "ssh-keygen CA"
+PUBKEY_ACCEPTED_ALGOS=`$SSH -G "example.com" | \
+ grep -i "PubkeyAcceptedAlgorithms" | cut -d ' ' -f2- | tr "," "|"`
+SSH_ACCEPTED_KEYTYPES=`echo "$SSH_KEYTYPES" | egrep "$PUBKEY_ACCEPTED_ALGOS"`
+echo $PUBKEY_ACCEPTED_ALGOS | grep "rsa"
+r=$?
+if [ $r == 0 ]; then
+echo $SSH_ACCEPTED_KEYTYPES | grep "rsa"
+r=$?
+if [ $r -ne 0 ]; then
+SSH_ACCEPTED_KEYTYPES="$SSH_ACCEPTED_KEYTYPES ssh-rsa"
+fi
+fi
+
trace "load hostkeys"
-for k in $SSH_KEYTYPES ; do
+for k in $SSH_ACCEPTED_KEYTYPES ; do
${SSHKEYGEN} -qt $k -f $OBJ/agent-key.$k -N '' || fatal "ssh-keygen $k"
${SSHKEYGEN} -s $OBJ/agent-ca -qh -n localhost-with-alias \
-I localhost-with-alias $OBJ/agent-key.$k.pub || \
@@ -32,12 +45,16 @@ rm $OBJ/agent-ca # Don't need CA private any more either
unset SSH_AUTH_SOCK
-for k in $SSH_KEYTYPES ; do
+for k in $SSH_ACCEPTED_KEYTYPES ; do
verbose "key type $k"
+ hka=$k
+ if [ $k = "ssh-rsa" ]; then
+ hka="rsa-sha2-512"
+ fi
cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy
- echo "HostKeyAlgorithms $k" >> $OBJ/sshd_proxy
+ echo "HostKeyAlgorithms $hka" >> $OBJ/sshd_proxy
echo "Hostkey $OBJ/agent-key.${k}" >> $OBJ/sshd_proxy
- opts="-oHostKeyAlgorithms=$k -F $OBJ/ssh_proxy"
+ opts="-oHostKeyAlgorithms=$hka -F $OBJ/ssh_proxy"
( printf 'localhost-with-alias,127.0.0.1,::1 ' ;
cat $OBJ/agent-key.$k.pub) > $OBJ/known_hosts
SSH_CONNECTION=`${SSH} $opts host 'echo $SSH_CONNECTION'`
@@ -50,15 +67,16 @@ for k in $SSH_KEYTYPES ; do
done
SSH_CERTTYPES=`ssh -Q key-sig | grep 'cert-v01@openssh.com' | maybe_filter_sk`
+SSH_ACCEPTED_CERTTYPES=`echo "$SSH_CERTTYPES" | egrep "$PUBKEY_ACCEPTED_ALGOS"`
# Prepare sshd_proxy for certificates.
cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy
HOSTKEYALGS=""
-for k in $SSH_CERTTYPES ; do
+for k in $SSH_ACCEPTED_CERTTYPES ; do
test -z "$HOSTKEYALGS" || HOSTKEYALGS="${HOSTKEYALGS},"
HOSTKEYALGS="${HOSTKEYALGS}${k}"
done
-for k in $SSH_KEYTYPES ; do
+for k in $SSH_ACCEPTED_KEYTYPES ; do
echo "Hostkey $OBJ/agent-key.${k}.pub" >> $OBJ/sshd_proxy
echo "HostCertificate $OBJ/agent-key.${k}-cert.pub" >> $OBJ/sshd_proxy
test -f $OBJ/agent-key.${k}.pub || fatal "no $k key"
@@ -70,7 +88,7 @@ echo "HostKeyAlgorithms $HOSTKEYALGS" >> $OBJ/sshd_proxy
( printf '@cert-authority localhost-with-alias ' ;
cat $OBJ/agent-ca.pub) > $OBJ/known_hosts
-for k in $SSH_CERTTYPES ; do
+for k in $SSH_ACCEPTED_CERTTYPES ; do
verbose "cert type $k"
opts="-oHostKeyAlgorithms=$k -F $OBJ/ssh_proxy"
SSH_CONNECTION=`${SSH} $opts host 'echo $SSH_CONNECTION'`
diff --git a/sshconnect2.c b/sshconnect2.c
index 14f7671a..ad3f560f 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -221,7 +221,7 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port,
const struct ssh_conn_info *cinfo)
{
char *myproposal[PROPOSAL_MAX];
- char *all_key, *hkalgs = NULL;
+ char *all_key, *hkalgs = NULL, *filtered_algs = NULL;
int r, use_known_hosts_order = 0;
#if defined(GSSAPI) && defined(WITH_OPENSSL)
@@ -257,10 +257,22 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port,
if (use_known_hosts_order)
hkalgs = order_hostkeyalgs(host, hostaddr, port, cinfo);
+ filtered_algs = hkalgs ? match_filter_allowlist(hkalgs, options.pubkey_accepted_algos)
+ : match_filter_allowlist(options.hostkeyalgorithms,
+ options.pubkey_accepted_algos);
+ if (filtered_algs == NULL) {
+ if (hkalgs)
+ fatal_f("No match between algorithms for %s (host %s) and pubkey accepted algorithms %s",
+ hkalgs, host, options.pubkey_accepted_algos);
+ else
+ fatal_f("No match between host key algorithms %s and pubkey accepted algorithms %s",
+ options.hostkeyalgorithms, options.pubkey_accepted_algos);
+ }
+
kex_proposal_populate_entries(ssh, myproposal,
options.kex_algorithms, options.ciphers, options.macs,
compression_alg_list(options.compression),
- hkalgs ? hkalgs : options.hostkeyalgorithms);
+ filtered_algs);
#if defined(GSSAPI) && defined(WITH_OPENSSL)
if (options.gss_keyex) {
@@ -304,6 +316,7 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port,
#endif
free(hkalgs);
+ free(filtered_algs);
/* start key exchange */
if ((r = kex_setup(ssh, myproposal)) != 0)
--
2.49.0

View file

@ -1,616 +0,0 @@
From be23afbab800c9b5ffea56b3f410a04156c08df2 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:29 +0200
Subject: [PATCH 45/50] openssh-9.0p1-evp-fips-kex
---
dh.c | 98 +++++++++++++++++++++++++++++++++-----
kex.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
kex.h | 6 +++
kexdh.c | 52 ++++++++++++++++++--
kexecdh.c | 129 ++++++++++++++++++++++++++++++++++++++++----------
5 files changed, 382 insertions(+), 42 deletions(-)
diff --git a/dh.c b/dh.c
index 8c9a29fa..ea0a0b09 100644
--- a/dh.c
+++ b/dh.c
@@ -37,6 +37,9 @@
#include <openssl/bn.h>
#include <openssl/dh.h>
#include <openssl/fips.h>
+#include <openssl/evp.h>
+#include <openssl/core_names.h>
+#include <openssl/param_build.h>
#include "dh.h"
#include "pathnames.h"
@@ -290,10 +293,15 @@ dh_pub_is_valid(const DH *dh, const BIGNUM *dh_pub)
int
dh_gen_key(DH *dh, int need)
{
- int pbits;
- const BIGNUM *dh_p, *pub_key;
+ const BIGNUM *dh_p, *dh_g;
+ BIGNUM *pub_key = NULL, *priv_key = NULL;
+ EVP_PKEY *pkey = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
+ OSSL_PARAM_BLD *param_bld = NULL;
+ OSSL_PARAM *params = NULL;
+ int pbits, r = 0;
- DH_get0_pqg(dh, &dh_p, NULL, NULL);
+ DH_get0_pqg(dh, &dh_p, NULL, &dh_g);
if (need < 0 || dh_p == NULL ||
(pbits = BN_num_bits(dh_p)) <= 0 ||
@@ -301,19 +309,85 @@ dh_gen_key(DH *dh, int need)
return SSH_ERR_INVALID_ARGUMENT;
if (need < 256)
need = 256;
+
+ if ((param_bld = OSSL_PARAM_BLD_new()) == NULL ||
+ (ctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL)) == NULL) {
+ OSSL_PARAM_BLD_free(param_bld);
+ return SSH_ERR_ALLOC_FAIL;
+ }
+
+ if (OSSL_PARAM_BLD_push_BN(param_bld,
+ OSSL_PKEY_PARAM_FFC_P, dh_p) != 1 ||
+ OSSL_PARAM_BLD_push_BN(param_bld,
+ OSSL_PKEY_PARAM_FFC_G, dh_g) != 1) {
+ error_f("Could not set p,q,g parameters");
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
/*
* Pollard Rho, Big step/Little Step attacks are O(sqrt(n)),
* so double requested need here.
*/
- if (!DH_set_length(dh, MINIMUM(need * 2, pbits - 1)))
- return SSH_ERR_LIBCRYPTO_ERROR;
-
- if (DH_generate_key(dh) == 0)
- return SSH_ERR_LIBCRYPTO_ERROR;
- DH_get0_key(dh, &pub_key, NULL);
- if (!dh_pub_is_valid(dh, pub_key))
- return SSH_ERR_INVALID_FORMAT;
- return 0;
+ if (OSSL_PARAM_BLD_push_int(param_bld,
+ OSSL_PKEY_PARAM_DH_PRIV_LEN,
+ MINIMUM(need * 2, pbits - 1)) != 1 ||
+ (params = OSSL_PARAM_BLD_to_param(param_bld)) == NULL) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ if (EVP_PKEY_fromdata_init(ctx) != 1) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ if (EVP_PKEY_fromdata(ctx, &pkey,
+ EVP_PKEY_KEY_PARAMETERS, params) != 1) {
+ error_f("Failed key generation");
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+
+ /* reuse context for key generation */
+ EVP_PKEY_CTX_free(ctx);
+ ctx = NULL;
+
+ if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL ||
+ EVP_PKEY_keygen_init(ctx) != 1) {
+ error_f("Could not create or init context");
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ if (EVP_PKEY_generate(ctx, &pkey) != 1) {
+ error_f("Could not generate keys");
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ if (EVP_PKEY_public_check(ctx) != 1) {
+ error_f("The public key is incorrect");
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+
+ if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PUB_KEY,
+ &pub_key) != 1 ||
+ EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY,
+ &priv_key) != 1 ||
+ DH_set0_key(dh, pub_key, priv_key) != 1) {
+ error_f("Could not set pub/priv keys to DH struct");
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+
+ /* transferred */
+ pub_key = NULL;
+ priv_key = NULL;
+out:
+ OSSL_PARAM_free(params);
+ OSSL_PARAM_BLD_free(param_bld);
+ EVP_PKEY_CTX_free(ctx);
+ EVP_PKEY_free(pkey);
+ BN_clear_free(pub_key);
+ BN_clear_free(priv_key);
+ return r;
}
DH *
diff --git a/kex.c b/kex.c
index 71fbe5cb..ce6a7b81 100644
--- a/kex.c
+++ b/kex.c
@@ -1614,3 +1614,142 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms,
return r;
}
+#ifdef WITH_OPENSSL
+/*
+ * Creates an EVP_PKEY from the given parameters and keys.
+ * The private key can be omitted.
+ */
+EVP_PKEY *
+sshkey_create_evp(OSSL_PARAM_BLD *param_bld, EVP_PKEY_CTX *ctx)
+{
+ EVP_PKEY *ret = NULL;
+ OSSL_PARAM *params = NULL;
+ if (param_bld == NULL || ctx == NULL) {
+ debug2_f("param_bld or ctx is NULL");
+ return NULL;
+ }
+ if ((params = OSSL_PARAM_BLD_to_param(param_bld)) == NULL) {
+ debug2_f("Could not build param list");
+ return NULL;
+ }
+ if (EVP_PKEY_fromdata_init(ctx) != 1 ||
+ EVP_PKEY_fromdata(ctx, &ret, EVP_PKEY_KEYPAIR, params) != 1) {
+ debug2_f("EVP_PKEY_fromdata failed");
+ OSSL_PARAM_free(params);
+ return NULL;
+ }
+ return ret;
+}
+
+int
+kex_create_evp_ec(EC_KEY *k, int ecdsa_nid, EVP_PKEY **pkey)
+{
+ OSSL_PARAM_BLD *param_bld = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
+ BN_CTX *bn_ctx = NULL;
+ uint8_t *pub_ser = NULL;
+ const char *group_name;
+ const EC_POINT *pub = NULL;
+ const BIGNUM *priv = NULL;
+ int ret = 0;
+
+ if (k == NULL)
+ return SSH_ERR_INVALID_ARGUMENT;
+ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)) == NULL ||
+ (param_bld = OSSL_PARAM_BLD_new()) == NULL ||
+ (bn_ctx = BN_CTX_new()) == NULL) {
+ ret = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+
+ if ((group_name = OSSL_EC_curve_nid2name(ecdsa_nid)) == NULL ||
+ OSSL_PARAM_BLD_push_utf8_string(param_bld,
+ OSSL_PKEY_PARAM_GROUP_NAME,
+ group_name,
+ strlen(group_name)) != 1) {
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ if ((pub = EC_KEY_get0_public_key(k)) != NULL) {
+ const EC_GROUP *group;
+ size_t len;
+
+ group = EC_KEY_get0_group(k);
+ len = EC_POINT_point2oct(group, pub,
+ POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
+ if ((pub_ser = malloc(len)) == NULL) {
+ ret = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ EC_POINT_point2oct(group,
+ pub,
+ POINT_CONVERSION_UNCOMPRESSED,
+ pub_ser,
+ len,
+ bn_ctx);
+ if (OSSL_PARAM_BLD_push_octet_string(param_bld,
+ OSSL_PKEY_PARAM_PUB_KEY,
+ pub_ser,
+ len) != 1) {
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ }
+ if ((priv = EC_KEY_get0_private_key(k)) != NULL &&
+ OSSL_PARAM_BLD_push_BN(param_bld,
+ OSSL_PKEY_PARAM_PRIV_KEY, priv) != 1) {
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ if ((*pkey = sshkey_create_evp(param_bld, ctx)) == NULL) {
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+
+out:
+ OSSL_PARAM_BLD_free(param_bld);
+ EVP_PKEY_CTX_free(ctx);
+ BN_CTX_free(bn_ctx);
+ free(pub_ser);
+ return ret;
+}
+
+int
+kex_create_evp_dh(EVP_PKEY **pkey, const BIGNUM *p, const BIGNUM *q,
+ const BIGNUM *g, const BIGNUM *pub, const BIGNUM *priv)
+{
+ OSSL_PARAM_BLD *param_bld = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
+ int r = 0;
+
+ /* create EVP_PKEY-DH key */
+ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL)) == NULL ||
+ (param_bld = OSSL_PARAM_BLD_new()) == NULL) {
+ error_f("EVP_PKEY_CTX or PARAM_BLD init failed");
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if (OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_P, p) != 1 ||
+ OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_Q, q) != 1 ||
+ OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_G, g) != 1 ||
+ OSSL_PARAM_BLD_push_BN(param_bld,
+ OSSL_PKEY_PARAM_PUB_KEY, pub) != 1) {
+ error_f("Failed pushing params to OSSL_PARAM_BLD");
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ if (priv != NULL &&
+ OSSL_PARAM_BLD_push_BN(param_bld,
+ OSSL_PKEY_PARAM_PRIV_KEY, priv) != 1) {
+ error_f("Failed pushing private key to OSSL_PARAM_BLD");
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ if ((*pkey = sshkey_create_evp(param_bld, ctx)) == NULL)
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+out:
+ OSSL_PARAM_BLD_free(param_bld);
+ EVP_PKEY_CTX_free(ctx);
+ return r;
+}
+#endif /* WITH_OPENSSL */
diff --git a/kex.h b/kex.h
index 6a55aadf..48f3bb87 100644
--- a/kex.h
+++ b/kex.h
@@ -37,6 +37,9 @@
# include <openssl/bn.h>
# include <openssl/dh.h>
# include <openssl/ecdsa.h>
+# include <openssl/evp.h>
+# include <openssl/core_names.h>
+# include <openssl/param_build.h>
# ifdef OPENSSL_HAS_ECC
# include <openssl/ec.h>
# else /* OPENSSL_HAS_ECC */
@@ -311,6 +314,9 @@ int kexc25519_shared_key_ext(const u_char key[CURVE25519_SIZE],
const u_char pub[CURVE25519_SIZE], struct sshbuf *out, int)
__attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE)))
__attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE)));
+int kex_create_evp_dh(EVP_PKEY **, const BIGNUM *, const BIGNUM *,
+ const BIGNUM *, const BIGNUM *, const BIGNUM *);
+int kex_create_evp_ec(EC_KEY *k, int ecdsa_nid, EVP_PKEY **pkey);
#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH)
void dump_digest(const char *, const u_char *, int);
diff --git a/kexdh.c b/kexdh.c
index 0faab21b..32e1de51 100644
--- a/kexdh.c
+++ b/kexdh.c
@@ -35,6 +35,10 @@
#include "openbsd-compat/openssl-compat.h"
#include <openssl/dh.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/core_names.h>
+#include <openssl/param_build.h>
#include "sshkey.h"
#include "kex.h"
@@ -83,9 +87,12 @@ int
kex_dh_compute_key(struct kex *kex, BIGNUM *dh_pub, struct sshbuf *out)
{
BIGNUM *shared_secret = NULL;
+ const BIGNUM *pub, *priv, *p, *q, *g;
+ EVP_PKEY *pkey = NULL, *dh_pkey = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
u_char *kbuf = NULL;
size_t klen = 0;
- int kout, r;
+ int r = 0;
#ifdef DEBUG_KEXDH
fprintf(stderr, "dh_pub= ");
@@ -100,24 +107,59 @@ kex_dh_compute_key(struct kex *kex, BIGNUM *dh_pub, struct sshbuf *out)
r = SSH_ERR_MESSAGE_INCOMPLETE;
goto out;
}
- klen = DH_size(kex->dh);
+
+ DH_get0_key(kex->dh, &pub, &priv);
+ DH_get0_pqg(kex->dh, &p, &q, &g);
+ /* import key */
+ r = kex_create_evp_dh(&pkey, p, q, g, pub, priv);
+ if (r != 0) {
+ error_f("Could not create EVP_PKEY for dh");
+ ERR_print_errors_fp(stderr);
+ goto out;
+ }
+ /* import peer key
+ * the parameters should be the same as with pkey
+ */
+ r = kex_create_evp_dh(&dh_pkey, p, q, g, dh_pub, NULL);
+ if (r != 0) {
+ error_f("Could not import peer key for dh");
+ ERR_print_errors_fp(stderr);
+ goto out;
+ }
+
+ if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL) {
+ error_f("Could not init EVP_PKEY_CTX for dh");
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if (EVP_PKEY_derive_init(ctx) != 1 ||
+ EVP_PKEY_derive_set_peer(ctx, dh_pkey) != 1 ||
+ EVP_PKEY_derive(ctx, NULL, &klen) != 1) {
+ error_f("Could not get key size");
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
if ((kbuf = malloc(klen)) == NULL ||
(shared_secret = BN_new()) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if ((kout = DH_compute_key(kbuf, dh_pub, kex->dh)) < 0 ||
- BN_bin2bn(kbuf, kout, shared_secret) == NULL) {
+ if (EVP_PKEY_derive(ctx, kbuf, &klen) != 1 ||
+ BN_bin2bn(kbuf, klen, shared_secret) == NULL) {
+ error_f("Could not derive key");
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
#ifdef DEBUG_KEXDH
- dump_digest("shared secret", kbuf, kout);
+ dump_digest("shared secret", kbuf, klen);
#endif
r = sshbuf_put_bignum2(out, shared_secret);
out:
freezero(kbuf, klen);
BN_clear_free(shared_secret);
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_free(dh_pkey);
+ EVP_PKEY_CTX_free(ctx);
return r;
}
diff --git a/kexecdh.c b/kexecdh.c
index efb2e55a..d92ba54f 100644
--- a/kexecdh.c
+++ b/kexecdh.c
@@ -35,17 +35,57 @@
#include <signal.h>
#include <openssl/ecdh.h>
+#include <openssl/evp.h>
+#include <openssl/core_names.h>
+#include <openssl/param_build.h>
+#include <openssl/err.h>
#include "sshkey.h"
#include "kex.h"
#include "sshbuf.h"
#include "digest.h"
#include "ssherr.h"
+#include "log.h"
static int
kex_ecdh_dec_key_group(struct kex *, const struct sshbuf *, EC_KEY *key,
const EC_GROUP *, struct sshbuf **);
+static EC_KEY *
+generate_ec_keys(int ec_nid)
+{
+ EC_KEY *client_key = NULL;
+ EVP_PKEY *pkey = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
+ OSSL_PARAM_BLD *param_bld = NULL;
+ OSSL_PARAM *params = NULL;
+ const char *group_name;
+
+ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)) == NULL ||
+ (param_bld = OSSL_PARAM_BLD_new()) == NULL)
+ goto out;
+ if ((group_name = OSSL_EC_curve_nid2name(ec_nid)) == NULL ||
+ OSSL_PARAM_BLD_push_utf8_string(param_bld,
+ OSSL_PKEY_PARAM_GROUP_NAME, group_name, 0) != 1 ||
+ (params = OSSL_PARAM_BLD_to_param(param_bld)) == NULL) {
+ error_f("Could not create OSSL_PARAM");
+ goto out;
+ }
+ if (EVP_PKEY_keygen_init(ctx) != 1 ||
+ EVP_PKEY_CTX_set_params(ctx, params) != 1 ||
+ EVP_PKEY_generate(ctx, &pkey) != 1 ||
+ (client_key = EVP_PKEY_get1_EC_KEY(pkey)) == NULL) {
+ error_f("Could not generate ec keys");
+ goto out;
+ }
+out:
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_CTX_free(ctx);
+ OSSL_PARAM_BLD_free(param_bld);
+ OSSL_PARAM_free(params);
+ return client_key;
+}
+
int
kex_ecdh_keypair(struct kex *kex)
{
@@ -55,11 +95,7 @@ kex_ecdh_keypair(struct kex *kex)
struct sshbuf *buf = NULL;
int r;
- if ((client_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if (EC_KEY_generate_key(client_key) != 1) {
+ if ((client_key = generate_ec_keys(kex->ec_nid)) == NULL) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
@@ -101,11 +137,7 @@ kex_ecdh_enc(struct kex *kex, const struct sshbuf *client_blob,
*server_blobp = NULL;
*shared_secretp = NULL;
- if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if (EC_KEY_generate_key(server_key) != 1) {
+ if ((server_key = generate_ec_keys(kex->ec_nid)) == NULL) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
@@ -140,11 +172,21 @@ kex_ecdh_dec_key_group(struct kex *kex, const struct sshbuf *ec_blob,
{
struct sshbuf *buf = NULL;
BIGNUM *shared_secret = NULL;
- EC_POINT *dh_pub = NULL;
- u_char *kbuf = NULL;
- size_t klen = 0;
+ EVP_PKEY_CTX *ctx = NULL;
+ EVP_PKEY *pkey = NULL, *dh_pkey = NULL;
+ OSSL_PARAM_BLD *param_bld = NULL;
+ OSSL_PARAM *params = NULL;
+ u_char *kbuf = NULL, *pub = NULL;
+ size_t klen = 0, publen;
+ const char *group_name;
int r;
+ /* import EC_KEY to EVP_PKEY */
+ if ((r = kex_create_evp_ec(key, kex->ec_nid, &pkey)) != 0) {
+ error_f("Could not create EVP_PKEY");
+ goto out;
+ }
+
*shared_secretp = NULL;
if ((buf = sshbuf_new()) == NULL) {
@@ -153,45 +195,82 @@ kex_ecdh_dec_key_group(struct kex *kex, const struct sshbuf *ec_blob,
}
if ((r = sshbuf_put_stringb(buf, ec_blob)) != 0)
goto out;
- if ((dh_pub = EC_POINT_new(group)) == NULL) {
+
+ /* the public key is in the buffer in octet string UNCOMPRESSED
+ * format. See sshbuf_put_ec */
+ if ((r = sshbuf_get_string(buf, &pub, &publen)) != 0)
+ goto out;
+ sshbuf_reset(buf);
+ if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL ||
+ (param_bld = OSSL_PARAM_BLD_new()) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if ((r = sshbuf_get_ec(buf, dh_pub, group)) != 0) {
+ if ((group_name = OSSL_EC_curve_nid2name(kex->ec_nid)) == NULL) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ if (OSSL_PARAM_BLD_push_octet_string(param_bld,
+ OSSL_PKEY_PARAM_PUB_KEY, pub, publen) != 1 ||
+ OSSL_PARAM_BLD_push_utf8_string(param_bld,
+ OSSL_PKEY_PARAM_GROUP_NAME, group_name, 0) != 1 ||
+ (params = OSSL_PARAM_BLD_to_param(param_bld)) == NULL) {
+ error_f("Failed to set params for dh_pkey");
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ if (EVP_PKEY_fromdata_init(ctx) != 1 ||
+ EVP_PKEY_fromdata(ctx, &dh_pkey,
+ EVP_PKEY_PUBLIC_KEY, params) != 1 ||
+ EVP_PKEY_public_check(ctx) != 1) {
+ error_f("Peer public key import failed");
+ r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
- sshbuf_reset(buf);
#ifdef DEBUG_KEXECDH
fputs("public key:\n", stderr);
- sshkey_dump_ec_point(group, dh_pub);
+ EVP_PKEY_print_public_fp(stderr, dh_pkey, 0, NULL);
#endif
- if (sshkey_ec_validate_public(group, dh_pub) != 0) {
- r = SSH_ERR_MESSAGE_INCOMPLETE;
+ EVP_PKEY_CTX_free(ctx);
+ ctx = NULL;
+ if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL ||
+ EVP_PKEY_derive_init(ctx) != 1 ||
+ EVP_PKEY_derive_set_peer(ctx, dh_pkey) != 1 ||
+ EVP_PKEY_derive(ctx, NULL, &klen) != 1) {
+ error_f("Failed to get derive information");
+ r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
- klen = (EC_GROUP_get_degree(group) + 7) / 8;
- if ((kbuf = malloc(klen)) == NULL ||
- (shared_secret = BN_new()) == NULL) {
+ if ((kbuf = malloc(klen)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if (ECDH_compute_key(kbuf, klen, dh_pub, key, NULL) != (int)klen ||
- BN_bin2bn(kbuf, klen, shared_secret) == NULL) {
+ if (EVP_PKEY_derive(ctx, kbuf, &klen) != 1) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
#ifdef DEBUG_KEXECDH
dump_digest("shared secret", kbuf, klen);
#endif
+ if ((shared_secret = BN_new()) == NULL ||
+ (BN_bin2bn(kbuf, klen, shared_secret) == NULL)) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
if ((r = sshbuf_put_bignum2(buf, shared_secret)) != 0)
goto out;
*shared_secretp = buf;
buf = NULL;
out:
- EC_POINT_clear_free(dh_pub);
+ EVP_PKEY_CTX_free(ctx);
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_free(dh_pkey);
+ OSSL_PARAM_BLD_free(param_bld);
+ OSSL_PARAM_free(params);
BN_clear_free(shared_secret);
freezero(kbuf, klen);
+ freezero(pub, publen);
sshbuf_free(buf);
return r;
}
--
2.49.0

View file

@ -1,334 +0,0 @@
From e4ca3b9dba1cc832a9974493c91207d42e218a68 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:29 +0200
Subject: [PATCH 46/50] openssh-8.7p1-nohostsha1proof
---
compat.c | 6 +++++
compat.h | 2 +-
monitor.c | 27 ++++++++++++++++------
regress/unittests/kex/test_kex.c | 3 ++-
regress/unittests/sshkey/test_file.c | 3 ++-
regress/unittests/sshkey/test_fuzz.c | 3 ++-
regress/unittests/sshkey/test_sshkey.c | 32 +++++++++++++++++---------
serverloop.c | 6 ++++-
ssh-rsa.c | 3 ++-
sshconnect2.c | 8 +++++++
sshd-session.c | 21 +++++++++++++++++
11 files changed, 90 insertions(+), 24 deletions(-)
diff --git a/compat.c b/compat.c
index b59f0bfc..4e611dc3 100644
--- a/compat.c
+++ b/compat.c
@@ -42,6 +42,7 @@ void
compat_banner(struct ssh *ssh, const char *version)
{
int i;
+ int forbid_ssh_rsa = 0;
static struct {
char *pat;
int bugs;
@@ -125,16 +126,21 @@ compat_banner(struct ssh *ssh, const char *version)
};
/* process table, return first match */
+ forbid_ssh_rsa = (ssh->compat & SSH_RH_RSASIGSHA);
ssh->compat = 0;
for (i = 0; check[i].pat; i++) {
if (match_pattern_list(version, check[i].pat, 0) == 1) {
debug_f("match: %s pat %s compat 0x%08x",
version, check[i].pat, check[i].bugs);
ssh->compat = check[i].bugs;
+ if (forbid_ssh_rsa)
+ ssh->compat |= SSH_RH_RSASIGSHA;
return;
}
}
debug_f("no match: %s", version);
+ if (forbid_ssh_rsa)
+ ssh->compat |= SSH_RH_RSASIGSHA;
}
/* Always returns pointer to allocated memory, caller must free. */
diff --git a/compat.h b/compat.h
index 1a19060f..2e6db5bf 100644
--- a/compat.h
+++ b/compat.h
@@ -30,7 +30,7 @@
#define SSH_BUG_UTF8TTYMODE 0x00000001
#define SSH_BUG_SIGTYPE 0x00000002
#define SSH_BUG_SIGTYPE74 0x00000004
-/* #define unused 0x00000008 */
+#define SSH_RH_RSASIGSHA 0x00000008
#define SSH_OLD_SESSIONID 0x00000010
/* #define unused 0x00000020 */
#define SSH_BUG_DEBUG 0x00000040
diff --git a/monitor.c b/monitor.c
index fbc35782..19cb058e 100644
--- a/monitor.c
+++ b/monitor.c
@@ -747,11 +747,12 @@ mm_answer_sign(struct ssh *ssh, int sock, struct sshbuf *m)
struct sshkey *pubkey, *key;
struct sshbuf *sigbuf = NULL;
u_char *p = NULL, *signature = NULL;
- char *alg = NULL;
- size_t datlen, siglen;
- int r, is_proof = 0, keyid;
- u_int compat;
+ char *alg = NULL, *effective_alg;
+ size_t datlen, siglen, alglen;
+ int r, is_proof = 0;
+ u_int keyid, compat;
const char proof_req[] = "hostkeys-prove-00@openssh.com";
+ const char safe_rsa[] = "rsa-sha2-256";
debug3_f("entering");
@@ -809,18 +810,30 @@ mm_answer_sign(struct ssh *ssh, int sock, struct sshbuf *m)
}
if ((key = get_hostkey_by_index(keyid)) != NULL) {
- if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, alg,
+ if (ssh->compat & SSH_RH_RSASIGSHA && strcmp(alg, "ssh-rsa") == 0
+ && (sshkey_type_plain(key->type) == KEY_RSA)) {
+ effective_alg = safe_rsa;
+ } else {
+ effective_alg = alg;
+ }
+ if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, effective_alg,
options.sk_provider, NULL, compat)) != 0)
fatal_fr(r, "sign");
} else if ((key = get_hostkey_public_by_index(keyid, ssh)) != NULL &&
auth_sock > 0) {
+ if (ssh->compat & SSH_RH_RSASIGSHA && strcmp(alg, "ssh-rsa") == 0
+ && (sshkey_type_plain(key->type) == KEY_RSA)) {
+ effective_alg = safe_rsa;
+ } else {
+ effective_alg = alg;
+ }
if ((r = ssh_agent_sign(auth_sock, key, &signature, &siglen,
- p, datlen, alg, compat)) != 0)
+ p, datlen, effective_alg, compat)) != 0)
fatal_fr(r, "agent sign");
} else
fatal_f("no hostkey from index %d", keyid);
- debug3_f("%s %s signature len=%zu", alg,
+ debug3_f("%s (effective: %s) %s signature len=%zu", alg, effective_alg,
is_proof ? "hostkey proof" : "KEX", siglen);
sshbuf_reset(m);
diff --git a/regress/unittests/kex/test_kex.c b/regress/unittests/kex/test_kex.c
index caf8f57f..09016aea 100644
--- a/regress/unittests/kex/test_kex.c
+++ b/regress/unittests/kex/test_kex.c
@@ -97,7 +97,8 @@ do_kex_with_key(char *kex, int keytype, int bits)
memcpy(kex_params.proposal, myproposal, sizeof(myproposal));
if (kex != NULL)
kex_params.proposal[PROPOSAL_KEX_ALGS] = kex;
- keyname = strdup(sshkey_ssh_name(private));
+ keyname = (strcmp(sshkey_ssh_name(private), "ssh-rsa")) ?
+ strdup(sshkey_ssh_name(private)) : strdup("rsa-sha2-256");
ASSERT_PTR_NE(keyname, NULL);
kex_params.proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = keyname;
ASSERT_INT_EQ(ssh_init(&client, 0, &kex_params), 0);
diff --git a/regress/unittests/sshkey/test_file.c b/regress/unittests/sshkey/test_file.c
index 3babe604..cc80fe97 100644
--- a/regress/unittests/sshkey/test_file.c
+++ b/regress/unittests/sshkey/test_file.c
@@ -109,6 +109,7 @@ sshkey_file_tests(void)
sshkey_free(k2);
TEST_DONE();
+ /* Skip this test, SHA1 signatures are not supported
TEST_START("load RSA cert with SHA1 signature");
ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1_sha1"), &k2), 0);
ASSERT_PTR_NE(k2, NULL);
@@ -116,7 +117,7 @@ sshkey_file_tests(void)
ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1);
ASSERT_STRING_EQ(k2->cert->signature_type, "ssh-rsa");
sshkey_free(k2);
- TEST_DONE();
+ TEST_DONE(); */
TEST_START("load RSA cert with SHA512 signature");
ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1_sha512"), &k2), 0);
diff --git a/regress/unittests/sshkey/test_fuzz.c b/regress/unittests/sshkey/test_fuzz.c
index 0aff7c9b..951122e1 100644
--- a/regress/unittests/sshkey/test_fuzz.c
+++ b/regress/unittests/sshkey/test_fuzz.c
@@ -338,13 +338,14 @@ sshkey_fuzz_tests(void)
TEST_DONE();
#ifdef WITH_OPENSSL
+ /* Skip this test, SHA1 signatures are not supported
TEST_START("fuzz RSA sig");
buf = load_file("rsa_1");
ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
sshbuf_free(buf);
sig_fuzz(k1, "ssh-rsa");
sshkey_free(k1);
- TEST_DONE();
+ TEST_DONE();*/
TEST_START("fuzz RSA SHA256 sig");
buf = load_file("rsa_1");
diff --git a/regress/unittests/sshkey/test_sshkey.c b/regress/unittests/sshkey/test_sshkey.c
index 5bf4b65c..6d0a35bb 100644
--- a/regress/unittests/sshkey/test_sshkey.c
+++ b/regress/unittests/sshkey/test_sshkey.c
@@ -61,6 +61,9 @@ build_cert(struct sshbuf *b, struct sshkey *k, const char *type,
u_char *sigblob;
size_t siglen;
+ /* ssh-rsa implies SHA1, forbidden in DEFAULT cp */
+ int expected = (sig_alg == NULL || strcmp(sig_alg, "ssh-rsa") == 0) ? SSH_ERR_LIBCRYPTO_ERROR : 0;
+
ca_buf = sshbuf_new();
ASSERT_PTR_NE(ca_buf, NULL);
ASSERT_INT_EQ(sshkey_putb(ca_key, ca_buf), 0);
@@ -102,8 +105,9 @@ build_cert(struct sshbuf *b, struct sshkey *k, const char *type,
ASSERT_INT_EQ(sshbuf_put_string(b, NULL, 0), 0); /* reserved */
ASSERT_INT_EQ(sshbuf_put_stringb(b, ca_buf), 0); /* signature key */
ASSERT_INT_EQ(sshkey_sign(sign_key, &sigblob, &siglen,
- sshbuf_ptr(b), sshbuf_len(b), sig_alg, NULL, NULL, 0), 0);
- ASSERT_INT_EQ(sshbuf_put_string(b, sigblob, siglen), 0); /* signature */
+ sshbuf_ptr(b), sshbuf_len(b), sig_alg, NULL, NULL, 0), expected);
+ if (expected == 0)
+ ASSERT_INT_EQ(sshbuf_put_string(b, sigblob, siglen), 0); /* signature */
free(sigblob);
sshbuf_free(ca_buf);
@@ -120,16 +124,22 @@ signature_test(struct sshkey *k, struct sshkey *bad, const char *sig_alg,
{
size_t len;
u_char *sig;
+ /* ssh-rsa implies SHA1, forbidden in DEFAULT cp in RHEL, permitted in Fedora */
+ int expected = (sig_alg && strcmp(sig_alg, "ssh-rsa") == 0) ? sshkey_sign(k, &sig, &len, d, l, sig_alg, NULL, NULL, 0) : 0;
+ if (k && (sshkey_type_plain(k->type) == KEY_DSA || sshkey_type_plain(k->type) == KEY_DSA_CERT))
+ expected = sshkey_sign(k, &sig, &len, d, l, sig_alg, NULL, NULL, 0);
ASSERT_INT_EQ(sshkey_sign(k, &sig, &len, d, l, sig_alg,
- NULL, NULL, 0), 0);
- ASSERT_SIZE_T_GT(len, 8);
- ASSERT_PTR_NE(sig, NULL);
- ASSERT_INT_EQ(sshkey_verify(k, sig, len, d, l, NULL, 0, NULL), 0);
- ASSERT_INT_NE(sshkey_verify(bad, sig, len, d, l, NULL, 0, NULL), 0);
- /* Fuzz test is more comprehensive, this is just a smoke test */
- sig[len - 5] ^= 0x10;
- ASSERT_INT_NE(sshkey_verify(k, sig, len, d, l, NULL, 0, NULL), 0);
+ NULL, NULL, 0), expected);
+ if (expected == 0) {
+ ASSERT_SIZE_T_GT(len, 8);
+ ASSERT_PTR_NE(sig, NULL);
+ ASSERT_INT_EQ(sshkey_verify(k, sig, len, d, l, NULL, 0, NULL), 0);
+ ASSERT_INT_NE(sshkey_verify(bad, sig, len, d, l, NULL, 0, NULL), 0);
+ /* Fuzz test is more comprehensive, this is just a smoke test */
+ sig[len - 5] ^= 0x10;
+ ASSERT_INT_NE(sshkey_verify(k, sig, len, d, l, NULL, 0, NULL), 0);
+ }
free(sig);
}
@@ -526,7 +536,7 @@ sshkey_tests(void)
ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_1.pub"), &k2,
NULL), 0);
k3 = get_private("rsa_1");
- build_cert(b, k2, "ssh-rsa-cert-v01@openssh.com", k3, k1, NULL);
+ build_cert(b, k2, "ssh-rsa-cert-v01@openssh.com", k3, k1, "rsa-sha2-256");
ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(b), sshbuf_len(b), &k4),
SSH_ERR_KEY_CERT_INVALID_SIGN_KEY);
ASSERT_PTR_EQ(k4, NULL);
diff --git a/serverloop.c b/serverloop.c
index 40ddfb04..9c5b1567 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -80,6 +80,7 @@
#include "auth-options.h"
#include "serverloop.h"
#include "ssherr.h"
+#include "compat.h"
extern ServerOptions options;
@@ -699,7 +700,10 @@ server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp)
else if (ssh->kex->flags & KEX_RSA_SHA2_256_SUPPORTED)
sigalg = "rsa-sha2-256";
}
-
+ if (ssh->compat & SSH_RH_RSASIGSHA && sigalg == NULL) {
+ sigalg = "rsa-sha2-512";
+ debug3_f("SHA1 signature is not supported, falling back to %s", sigalg);
+ }
debug3_f("sign %s key (index %d) using sigalg %s",
sshkey_type(key), ndx, sigalg == NULL ? "default" : sigalg);
if ((r = sshbuf_put_cstring(sigbuf,
diff --git a/ssh-rsa.c b/ssh-rsa.c
index 6c2f771a..8dd4ab01 100644
--- a/ssh-rsa.c
+++ b/ssh-rsa.c
@@ -509,7 +509,8 @@ ssh_rsa_verify(const struct sshkey *key,
ret = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
- if (hash_alg != want_alg) {
+ if (hash_alg != want_alg && want_alg != SSH_DIGEST_SHA1) {
+ debug_f("Unexpected digest algorithm: got %d, wanted %d", hash_alg, want_alg);
ret = SSH_ERR_SIGNATURE_INVALID;
goto out;
}
diff --git a/sshconnect2.c b/sshconnect2.c
index ad3f560f..3941e089 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -1434,6 +1434,14 @@ identity_sign(struct identity *id, u_char **sigp, size_t *lenp,
retried = 1;
goto retry_pin;
}
+ if ((r == SSH_ERR_LIBCRYPTO_ERROR) && strcmp("ssh-rsa", alg)) {
+ char rsa_safe_alg[] = "rsa-sha2-512";
+ debug3_f("trying to fallback to algorithm %s", rsa_safe_alg);
+
+ if ((r = sshkey_sign(sign_key, sigp, lenp, data, datalen,
+ rsa_safe_alg, options.sk_provider, pin, compat)) != 0)
+ debug_fr(r, "sshkey_sign - RSA fallback");
+ }
goto out;
}
diff --git a/sshd-session.c b/sshd-session.c
index a808ac9a..c3349a8a 100644
--- a/sshd-session.c
+++ b/sshd-session.c
@@ -1316,6 +1316,27 @@ main(int ac, char **av)
check_ip_options(ssh);
+ {
+ struct sshkey *rsakey = NULL;
+ rsakey = get_hostkey_private_by_type(KEY_RSA, 0, ssh);
+ if (rsakey == NULL)
+ rsakey = get_hostkey_private_by_type(KEY_RSA_CERT, 0, ssh);
+
+ if (rsakey != NULL) {
+ size_t sign_size = 0;
+ u_char *tmp = NULL;
+ u_char data[] = "Test SHA1 vector";
+ int res;
+
+ res = sshkey_sign(rsakey, &tmp, &sign_size, data, sizeof(data), NULL, NULL, NULL, 0);
+ free(tmp);
+ if (res == SSH_ERR_LIBCRYPTO_ERROR) {
+ verbose_f("SHA1 in signatures is disabled for RSA keys");
+ ssh->compat |= SSH_RH_RSASIGSHA;
+ }
+ }
+ }
+
/* Prepare the channels layer */
channel_init_channels(ssh);
channel_set_af(ssh, options.address_family);
--
2.49.0

View file

@ -1,25 +0,0 @@
From 497de886faaddec60b7ad1013396c7d4f3145968 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:29 +0200
Subject: [PATCH 47/50] openssh-9.6p1-pam-rhost
---
auth-pam.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/auth-pam.c b/auth-pam.c
index a042c3c8..a321e0d3 100644
--- a/auth-pam.c
+++ b/auth-pam.c
@@ -741,7 +741,7 @@ sshpam_init(struct ssh *ssh, Authctxt *authctxt)
sshpam_laddr = get_local_ipaddr(
ssh_packet_get_connection_in(ssh));
}
- if (sshpam_rhost != NULL) {
+ if (sshpam_rhost != NULL && strcmp(sshpam_rhost, "UNKNOWN") != 0) {
debug("PAM: setting PAM_RHOST to \"%s\"", sshpam_rhost);
sshpam_err = pam_set_item(sshpam_handle, PAM_RHOST,
sshpam_rhost);
--
2.49.0

View file

@ -1,25 +0,0 @@
From b97b1040bc0918fe9be89cdb482d046270e92d9c Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:29 +0200
Subject: [PATCH 48/50] openssh-9.9p1-separate-keysign
---
ssh_config.5 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ssh_config.5 b/ssh_config.5
index a43b2a27..9d5da2a6 100644
--- a/ssh_config.5
+++ b/ssh_config.5
@@ -797,7 +797,7 @@ or
This option should be placed in the non-hostspecific section.
See
.Xr ssh-keysign 8
-for more information.
+for more information. ssh-keysign should be installed explicitly.
.It Cm EscapeChar
Sets the escape character (default:
.Ql ~ ) .
--
2.49.0

View file

@ -1,398 +0,0 @@
From 0a621a2ccb8444e4c6da906b0e112e0522658122 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:29 +0200
Subject: [PATCH 49/50] openssh-9.9p1-openssl-mlkem
---
kex-names.c | 20 +++
kexmlkem768x25519.c | 291 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 311 insertions(+)
diff --git a/kex-names.c b/kex-names.c
index cd3902ad..36a953ab 100644
--- a/kex-names.c
+++ b/kex-names.c
@@ -108,6 +108,19 @@ static const struct kexalg gss_kexalgs[] = {
{ NULL, 0, -1, -1},
};
+static int is_mlkem768_available()
+{
+ static int is_fetched = -1;
+
+ if (is_fetched == -1) {
+ EVP_KEM *mlkem768 = EVP_KEM_fetch(NULL, "mlkem768", NULL);
+ is_fetched = mlkem768 != NULL ? 1 : 0;
+ EVP_KEM_free(mlkem768);
+ }
+
+ return is_fetched;
+}
+
static char *
kex_alg_list_internal(char sep, const struct kexalg *algs)
{
@@ -116,6 +129,9 @@ kex_alg_list_internal(char sep, const struct kexalg *algs)
const struct kexalg *k;
for (k = algs; k->name != NULL; k++) {
+ if (strcmp(k->name, KEX_MLKEM768X25519_SHA256) == 0
+ && !is_mlkem768_available())
+ continue;
if (ret != NULL)
ret[rlen++] = sep;
nlen = strlen(k->name);
@@ -147,6 +163,10 @@ kex_alg_by_name(const char *name)
{
const struct kexalg *k;
+ if (strcmp(name, KEX_MLKEM768X25519_SHA256) == 0
+ && !is_mlkem768_available())
+ return NULL;
+
for (k = kexalgs; k->name != NULL; k++) {
if (strcmp(k->name, name) == 0)
return k;
diff --git a/kexmlkem768x25519.c b/kexmlkem768x25519.c
index 2b5d3960..670049dc 100644
--- a/kexmlkem768x25519.c
+++ b/kexmlkem768x25519.c
@@ -48,10 +48,127 @@
#ifdef USE_MLKEM768X25519
#include "libcrux_mlkem768_sha3.h"
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <stdio.h>
+
+static int
+mlkem768_keypair_gen(unsigned char *pubkeybuf, unsigned char *privkeybuf)
+{
+ EVP_PKEY_CTX *ctx = NULL;
+ EVP_PKEY *pkey = NULL;
+ int ret = SSH_ERR_INTERNAL_ERROR;
+ size_t pubkey_size = crypto_kem_mlkem768_PUBLICKEYBYTES, privkey_size = crypto_kem_mlkem768_SECRETKEYBYTES;
+
+ ctx = EVP_PKEY_CTX_new_from_name(NULL, "mlkem768", NULL);
+ if (ctx == NULL) {
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
+ goto err;
+ }
+
+ if (EVP_PKEY_keygen_init(ctx) <= 0
+ || EVP_PKEY_keygen(ctx, &pkey) <= 0) {
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
+ goto err;
+ }
+
+ if (EVP_PKEY_get_raw_public_key(pkey, pubkeybuf, &pubkey_size) <= 0
+ || EVP_PKEY_get_raw_private_key(pkey, privkeybuf, &privkey_size) <= 0) {
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
+ goto err;
+ }
+
+ if (privkey_size != crypto_kem_mlkem768_SECRETKEYBYTES
+ || pubkey_size != crypto_kem_mlkem768_PUBLICKEYBYTES) {
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
+ goto err;
+ }
+ ret = 0;
+
+ err:
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_CTX_free(ctx);
+ if (ret == SSH_ERR_LIBCRYPTO_ERROR)
+ ERR_print_errors_fp(stderr);
+ return ret;
+}
+
+static int
+mlkem768_encap_secret(const u_char *pubkeybuf, u_char *secret, u_char *out)
+{
+ EVP_PKEY *pkey = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
+ int r = SSH_ERR_INTERNAL_ERROR;
+ size_t outlen = crypto_kem_mlkem768_CIPHERTEXTBYTES,
+ secretlen = crypto_kem_mlkem768_BYTES;
+
+ pkey = EVP_PKEY_new_raw_public_key_ex(NULL, "mlkem768", NULL,
+ pubkeybuf, crypto_kem_mlkem768_PUBLICKEYBYTES);
+ if (pkey == NULL) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto err;
+ }
+
+ ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL);
+ if (ctx == NULL
+ || EVP_PKEY_encapsulate_init(ctx, NULL) <= 0
+ || EVP_PKEY_encapsulate(ctx, out, &outlen, secret, &secretlen) <= 0
+ || secretlen != crypto_kem_mlkem768_BYTES
+ || outlen != crypto_kem_mlkem768_CIPHERTEXTBYTES) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto err;
+ }
+ r = 0;
+
+ err:
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_CTX_free(ctx);
+ if (r == SSH_ERR_LIBCRYPTO_ERROR)
+ ERR_print_errors_fp(stderr);
+
+ return r;
+}
+
+static int
+mlkem768_decap_secret(const u_char *privkeybuf, const u_char *wrapped, u_char *secret)
+{
+ EVP_PKEY *pkey = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
+ int r = SSH_ERR_INTERNAL_ERROR;
+ size_t wrappedlen = crypto_kem_mlkem768_CIPHERTEXTBYTES,
+ secretlen = crypto_kem_mlkem768_BYTES;
+
+ pkey = EVP_PKEY_new_raw_private_key_ex(NULL, "mlkem768", NULL,
+ privkeybuf, crypto_kem_mlkem768_SECRETKEYBYTES);
+ if (pkey == NULL) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto err;
+ }
+
+ ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL);
+ if (ctx == NULL
+ || EVP_PKEY_decapsulate_init(ctx, NULL) <= 0
+ || EVP_PKEY_decapsulate(ctx, secret, &secretlen, wrapped, wrappedlen) <= 0
+ || secretlen != crypto_kem_mlkem768_BYTES) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto err;
+ }
+ r = 0;
+
+ err:
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_CTX_free(ctx);
+
+ if (r == SSH_ERR_LIBCRYPTO_ERROR)
+ ERR_print_errors_fp(stderr);
+
+ return r;
+}
int
kex_kem_mlkem768x25519_keypair(struct kex *kex)
{
+#if 0
struct sshbuf *buf = NULL;
u_char rnd[LIBCRUX_ML_KEM_KEY_PAIR_PRNG_LEN], *cp = NULL;
size_t need;
@@ -86,6 +203,36 @@ kex_kem_mlkem768x25519_keypair(struct kex *kex)
explicit_bzero(rnd, sizeof(rnd));
sshbuf_free(buf);
return r;
+#else
+ struct sshbuf *buf = NULL;
+ u_char *cp = NULL;
+ size_t need;
+ int r = SSH_ERR_INTERNAL_ERROR;
+
+ if ((buf = sshbuf_new()) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ need = crypto_kem_mlkem768_PUBLICKEYBYTES + CURVE25519_SIZE;
+ if ((r = sshbuf_reserve(buf, need, &cp)) != 0)
+ goto out;
+ if ((r = mlkem768_keypair_gen(cp, kex->mlkem768_client_key)) != 0)
+ goto out;
+#ifdef DEBUG_KEXECDH
+ dump_digest("client public key mlkem768:", cp,
+ crypto_kem_mlkem768_PUBLICKEYBYTES);
+#endif
+ cp += crypto_kem_mlkem768_PUBLICKEYBYTES;
+ kexc25519_keygen(kex->c25519_client_key, cp);
+#ifdef DEBUG_KEXECDH
+ dump_digest("client public key c25519:", cp, CURVE25519_SIZE);
+#endif
+ /* success */
+ r = 0;
+ kex->client_pub = buf;
+ buf = NULL;
+ out:
+ sshbuf_free(buf);
+ return r;
+#endif
}
int
@@ -93,6 +240,7 @@ kex_kem_mlkem768x25519_enc(struct kex *kex,
const struct sshbuf *client_blob, struct sshbuf **server_blobp,
struct sshbuf **shared_secretp)
{
+#if 0
struct sshbuf *server_blob = NULL;
struct sshbuf *buf = NULL;
const u_char *client_pub;
@@ -185,12 +333,97 @@ kex_kem_mlkem768x25519_enc(struct kex *kex,
sshbuf_free(server_blob);
sshbuf_free(buf);
return r;
+#else
+ struct sshbuf *server_blob = NULL;
+ struct sshbuf *buf = NULL;
+ const u_char *client_pub;
+ u_char server_pub[CURVE25519_SIZE], server_key[CURVE25519_SIZE];
+ u_char hash[SSH_DIGEST_MAX_LENGTH];
+ size_t need;
+ int r = SSH_ERR_INTERNAL_ERROR;
+ struct libcrux_mlkem768_enc_result enc; /* FIXME */
+
+ *server_blobp = NULL;
+ *shared_secretp = NULL;
+
+ /* client_blob contains both KEM and ECDH client pubkeys */
+ need = crypto_kem_mlkem768_PUBLICKEYBYTES + CURVE25519_SIZE;
+ if (sshbuf_len(client_blob) != need) {
+ r = SSH_ERR_SIGNATURE_INVALID;
+ goto out;
+ }
+ client_pub = sshbuf_ptr(client_blob);
+#ifdef DEBUG_KEXECDH
+ dump_digest("client public key mlkem768:", client_pub,
+ crypto_kem_mlkem768_PUBLICKEYBYTES);
+ dump_digest("client public key 25519:",
+ client_pub + crypto_kem_mlkem768_PUBLICKEYBYTES,
+ CURVE25519_SIZE);
+#endif
+
+ /* allocate buffer for concatenation of KEM key and ECDH shared key */
+ /* the buffer will be hashed and the result is the shared secret */
+ if ((buf = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ /* allocate space for encrypted KEM key and ECDH pub key */
+ if ((server_blob = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if (mlkem768_encap_secret(client_pub, enc.snd, enc.fst.value) != 0)
+ goto out;
+
+ /* generate ECDH key pair, store server pubkey after ciphertext */
+ kexc25519_keygen(server_key, server_pub);
+ if ((r = sshbuf_put(buf, enc.snd, sizeof(enc.snd))) != 0 ||
+ (r = sshbuf_put(server_blob, enc.fst.value, sizeof(enc.fst.value))) != 0 ||
+ (r = sshbuf_put(server_blob, server_pub, sizeof(server_pub))) != 0)
+ goto out;
+ /* append ECDH shared key */
+ client_pub += crypto_kem_mlkem768_PUBLICKEYBYTES;
+ if ((r = kexc25519_shared_key_ext(server_key, client_pub, buf, 1)) < 0)
+ goto out;
+ if ((r = ssh_digest_buffer(kex->hash_alg, buf, hash, sizeof(hash))) != 0)
+ goto out;
+#ifdef DEBUG_KEXECDH
+ dump_digest("server public key 25519:", server_pub, CURVE25519_SIZE);
+ dump_digest("server cipher text:",
+ enc.fst.value, sizeof(enc.fst.value));
+ dump_digest("server kem key:", enc.snd, sizeof(enc.snd));
+ dump_digest("concatenation of KEM key and ECDH shared key:",
+ sshbuf_ptr(buf), sshbuf_len(buf));
+#endif
+ /* string-encoded hash is resulting shared secret */
+ sshbuf_reset(buf);
+ if ((r = sshbuf_put_string(buf, hash,
+ ssh_digest_bytes(kex->hash_alg))) != 0)
+ goto out;
+#ifdef DEBUG_KEXECDH
+ dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf));
+#endif
+ /* success */
+ r = 0;
+ *server_blobp = server_blob;
+ *shared_secretp = buf;
+ server_blob = NULL;
+ buf = NULL;
+ out:
+ explicit_bzero(hash, sizeof(hash));
+ explicit_bzero(server_key, sizeof(server_key));
+ explicit_bzero(&enc, sizeof(enc));
+ sshbuf_free(server_blob);
+ sshbuf_free(buf);
+ return r;
+#endif
}
int
kex_kem_mlkem768x25519_dec(struct kex *kex,
const struct sshbuf *server_blob, struct sshbuf **shared_secretp)
{
+#if 0
struct sshbuf *buf = NULL;
u_char mlkem_key[crypto_kem_mlkem768_BYTES];
const u_char *ciphertext, *server_pub;
@@ -258,6 +491,64 @@ kex_kem_mlkem768x25519_dec(struct kex *kex,
explicit_bzero(mlkem_key, sizeof(mlkem_key));
sshbuf_free(buf);
return r;
+#else
+ struct sshbuf *buf = NULL;
+ const u_char *ciphertext, *server_pub;
+ u_char hash[SSH_DIGEST_MAX_LENGTH];
+ u_char decap[crypto_kem_mlkem768_BYTES];
+ size_t need;
+ int r;
+
+ *shared_secretp = NULL;
+
+ need = crypto_kem_mlkem768_CIPHERTEXTBYTES + CURVE25519_SIZE;
+ if (sshbuf_len(server_blob) != need) {
+ r = SSH_ERR_SIGNATURE_INVALID;
+ goto out;
+ }
+ ciphertext = sshbuf_ptr(server_blob);
+ server_pub = ciphertext + crypto_kem_mlkem768_CIPHERTEXTBYTES;
+ /* hash concatenation of KEM key and ECDH shared key */
+ if ((buf = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+#ifdef DEBUG_KEXECDH
+ dump_digest("server cipher text:", ciphertext, crypto_kem_mlkem768_CIPHERTEXTBYTES);
+ dump_digest("server public key c25519:", server_pub, CURVE25519_SIZE);
+#endif
+ if ((r = mlkem768_decap_secret(kex->mlkem768_client_key, ciphertext, decap)) != 0)
+ goto out;
+ if ((r = sshbuf_put(buf, decap, sizeof(decap))) != 0)
+ goto out;
+ if ((r = kexc25519_shared_key_ext(kex->c25519_client_key, server_pub,
+ buf, 1)) < 0)
+ goto out;
+ if ((r = ssh_digest_buffer(kex->hash_alg, buf,
+ hash, sizeof(hash))) != 0)
+ goto out;
+#ifdef DEBUG_KEXECDH
+ dump_digest("client kem key:", decap, sizeof(decap));
+ dump_digest("concatenation of KEM key and ECDH shared key:",
+ sshbuf_ptr(buf), sshbuf_len(buf));
+#endif
+ sshbuf_reset(buf);
+ if ((r = sshbuf_put_string(buf, hash,
+ ssh_digest_bytes(kex->hash_alg))) != 0)
+ goto out;
+#ifdef DEBUG_KEXECDH
+ dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf));
+#endif
+ /* success */
+ r = 0;
+ *shared_secretp = buf;
+ buf = NULL;
+ out:
+ explicit_bzero(hash, sizeof(hash));
+ explicit_bzero(decap, sizeof(decap));
+ sshbuf_free(buf);
+ return r;
+#endif
}
#else /* USE_MLKEM768X25519 */
int
--
2.49.0

View file

@ -1,25 +0,0 @@
From fd32e753ae7f3b314712e6aa8b2bed3c1fca1ef5 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Fri, 16 May 2025 14:53:54 +0200
Subject: [PATCH 50/51] openssh-9.9p2-error_processing
---
ssh-agent.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/ssh-agent.c b/ssh-agent.c
index 798bf9b6..dfb6ac72 100644
--- a/ssh-agent.c
+++ b/ssh-agent.c
@@ -1377,6 +1377,8 @@ process_add_identity(SocketEntry *e)
if ((r = sshkey_private_deserialize(e->request, &k)) != 0 ||
k == NULL ||
(r = sshbuf_get_cstring(e->request, &comment, NULL)) != 0) {
+ if (!r) /* k == NULL */
+ r = SSH_ERR_INTERNAL_ERROR;
error_fr(r, "parse");
goto out;
}
--
2.49.0

View file

@ -1,27 +0,0 @@
From 4965cdbc1ee1e6a0c665797bb8b944d96d3d411f Mon Sep 17 00:00:00 2001
From: Zoltan Fridrich <zfridric@redhat.com>
Date: Wed, 16 Apr 2025 15:11:59 +0200
Subject: [PATCH 51/53] Provide better error for non-supported private keys
Signed-off-by: Zoltan Fridrich <zfridric@redhat.com>
---
sshkey.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/sshkey.c b/sshkey.c
index ca1cdb642..aada474e0 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -3582,6 +3582,9 @@ translate_libcrypto_error(unsigned long pem_err)
return SSH_ERR_LIBCRYPTO_ERROR;
}
case ERR_LIB_ASN1:
+#ifdef ERR_LIB_OSSL_DECODER
+ case ERR_LIB_OSSL_DECODER:
+#endif
return SSH_ERR_INVALID_FORMAT;
}
return SSH_ERR_LIBCRYPTO_ERROR;
--
2.49.0

View file

@ -1,86 +0,0 @@
From 9ed09ef158a113e21be7b3fefa7c5f932632749b Mon Sep 17 00:00:00 2001
From: Zoltan Fridrich <zfridric@redhat.com>
Date: Mon, 5 May 2025 11:52:25 +0200
Subject: [PATCH 52/53] Ignore bad hostkeys in known_hosts file
Signed-off-by: Zoltan Fridrich <zfridric@redhat.com>
---
hostfile.c | 15 +++++++++++++++
hostfile.h | 1 +
ssh.c | 2 ++
3 files changed, 18 insertions(+)
diff --git a/hostfile.c b/hostfile.c
index c5669c703..5c402f501 100644
--- a/hostfile.c
+++ b/hostfile.c
@@ -63,6 +63,14 @@
#include "hmac.h"
#include "sshbuf.h"
+static int required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
+
+void
+hostfile_set_minimum_rsa_size(int size)
+{
+ required_rsa_size = size;
+}
+
/* XXX hmac is too easy to dictionary attack; use bcrypt? */
static int
@@ -233,6 +241,7 @@ record_hostkey(struct hostkey_foreach_line *l, void *_ctx)
struct load_callback_ctx *ctx = (struct load_callback_ctx *)_ctx;
struct hostkeys *hostkeys = ctx->hostkeys;
struct hostkey_entry *tmp;
+ int r = 0;
if (l->status == HKF_STATUS_INVALID) {
/* XXX make this verbose() in the future */
@@ -241,6 +250,12 @@ record_hostkey(struct hostkey_foreach_line *l, void *_ctx)
return 0;
}
+ if ((r = sshkey_check_rsa_length(l->key, required_rsa_size)) != 0) {
+ debug2_f("%s:%ld: ignoring hostkey: %s",
+ l->path, l->linenum, ssh_err(r));
+ return 0;
+ }
+
debug3_f("found %skey type %s in file %s:%lu",
l->marker == MRK_NONE ? "" :
(l->marker == MRK_CA ? "ca " : "revoked "),
diff --git a/hostfile.h b/hostfile.h
index a24a4e329..0e9b1a19a 100644
--- a/hostfile.h
+++ b/hostfile.h
@@ -119,5 +119,6 @@ int hostkeys_foreach_file(const char *path, FILE *f,
const char *host, const char *ip, u_int options, u_int note);
void hostfile_create_user_ssh_dir(const char *, int);
+void hostfile_set_minimum_rsa_size(int);
#endif
diff --git a/ssh.c b/ssh.c
index abc8b8439..33787a8d4 100644
--- a/ssh.c
+++ b/ssh.c
@@ -110,6 +110,7 @@
#include "ssherr.h"
#include "myproposal.h"
#include "utf8.h"
+#include "hostfile.h"
#ifdef ENABLE_PKCS11
#include "ssh-pkcs11.h"
@@ -1397,6 +1398,7 @@ main(int ac, char **av)
options.update_hostkeys = 0;
}
}
+ hostfile_set_minimum_rsa_size(options.required_rsa_size);
if (options.connection_attempts <= 0)
fatal("Invalid number of ConnectionAttempts");
--
2.49.0

View file

@ -1,450 +0,0 @@
From 5d5a66e96ad03132f65371070f4fa475f10207d9 Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <abokovoy@redhat.com>
Date: Mon, 10 Jun 2024 23:00:03 +0300
Subject: [PATCH] support authentication indicators in GSSAPI
RFC 6680 defines a set of GSSAPI extensions to handle attributes
associated with the GSSAPI names. MIT Kerberos and FreeIPA use
name attributes to add information about pre-authentication methods used
to acquire the initial Kerberos ticket. The attribute 'auth-indicators'
may contain list of strings that KDC has associated with the ticket
issuance process.
Use authentication indicators to authorise or deny access to SSH server.
GSSAPIIndicators setting allows to specify a list of possible indicators
that a Kerberos ticket presented must or must not contain. More details
on the syntax are provided in sshd_config(5) man page.
Fixes: https://bugzilla.mindrot.org/show_bug.cgi?id=2696
Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
---
configure.ac | 1 +
gss-serv-krb5.c | 64 +++++++++++++++++++++++++++---
gss-serv.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++-
servconf.c | 15 ++++++-
servconf.h | 2 +
ssh-gss.h | 7 ++++
sshd_config.5 | 44 +++++++++++++++++++++
7 files changed, 228 insertions(+), 8 deletions(-)
diff --git a/configure.ac b/configure.ac
index d92a85809..2cbe20bf3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -5004,6 +5004,7 @@ AC_ARG_WITH([kerberos5],
AC_CHECK_HEADERS([gssapi.h gssapi/gssapi.h])
AC_CHECK_HEADERS([gssapi_krb5.h gssapi/gssapi_krb5.h])
AC_CHECK_HEADERS([gssapi_generic.h gssapi/gssapi_generic.h])
+ AC_CHECK_HEADERS([gssapi_ext.h gssapi/gssapi_ext.h])
AC_SEARCH_LIBS([k_hasafs], [kafs], [AC_DEFINE([USE_AFS], [1],
[Define this if you want to use libkafs' AFS support])])
diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c
index 03188d9b3..2c786ef14 100644
--- a/gss-serv-krb5.c
+++ b/gss-serv-krb5.c
@@ -43,6 +43,7 @@
#include "log.h"
#include "misc.h"
#include "servconf.h"
+#include "match.h"
#include "ssh-gss.h"
@@ -87,6 +88,32 @@ ssh_gssapi_krb5_init(void)
return 1;
}
+/* Check if any of the indicators in the Kerberos ticket match
+ * one of indicators in the list of allowed/denied rules.
+ * In case of the match, apply the decision from the rule.
+ * In case of no indicator from the ticket matching the rule, deny
+ */
+
+static int
+ssh_gssapi_check_indicators(ssh_gssapi_client *client, int *matched)
+{
+ int ret;
+ u_int i;
+
+ /* Check indicators */
+ for (i = 0; client->indicators[i] != NULL; i++) {
+ ret = match_pattern_list(client->indicators[i],
+ options.gss_indicators, 1);
+ /* negative or positive match */
+ if (ret != 0) {
+ *matched = i;
+ return ret;
+ }
+ }
+ /* No rule matched */
+ return 0;
+}
+
/* Check if this user is OK to login. This only works with krb5 - other
* GSSAPI mechanisms will need their own.
* Returns true if the user is OK to log in, otherwise returns 0
@@ -193,7 +220,7 @@ static int
ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name)
{
krb5_principal princ;
- int retval;
+ int retval, matched;
const char *errmsg;
int k5login_exists;
@@ -216,17 +243,42 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name)
if (k5login_exists &&
ssh_krb5_kuserok(krb_context, princ, name, k5login_exists)) {
retval = 1;
- logit("Authorized to %s, krb5 principal %s (krb5_kuserok)",
- name, (char *)client->displayname.value);
+ errmsg = "krb5_kuserok";
} else if (ssh_gssapi_krb5_cmdok(princ, client->exportedname.value,
name, k5login_exists)) {
retval = 1;
- logit("Authorized to %s, krb5 principal %s "
- "(ssh_gssapi_krb5_cmdok)",
- name, (char *)client->displayname.value);
+ errmsg = "ssh_gssapi_krb5_cmdok";
} else
retval = 0;
+ if ((retval == 1) && (options.gss_indicators != NULL)) {
+ /* At this point the configuration enforces presence of indicators
+ * so we drop the authorization result again */
+ retval = 0;
+ if (client->indicators) {
+ matched = -1;
+ retval = ssh_gssapi_check_indicators(client, &matched);
+ if (retval != 0) {
+ retval = (retval == 1);
+ logit("Ticket contains indicator %s, "
+ "krb5 principal %s is %s",
+ client->indicators[matched],
+ (char *)client->displayname.value,
+ retval ? "allowed" : "denied");
+ goto cont;
+ }
+ }
+ if (retval == 0) {
+ logit("GSSAPI authentication indicators enforced "
+ "but not matched. krb5 principal %s denied",
+ (char *)client->displayname.value);
+ }
+ }
+cont:
+ if (retval == 1) {
+ logit("Authorized to %s, krb5 principal %s (%s)",
+ name, (char *)client->displayname.value, errmsg);
+ }
krb5_free_principal(krb_context, princ);
return retval;
}
diff --git a/gss-serv.c b/gss-serv.c
index 9d5435eda..5c0491cf1 100644
--- a/gss-serv.c
+++ b/gss-serv.c
@@ -54,7 +54,7 @@ extern ServerOptions options;
static ssh_gssapi_client gssapi_client =
{ GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, GSS_C_NO_CREDENTIAL,
- GSS_C_NO_NAME, NULL, {NULL, NULL, NULL, NULL, NULL}, 0, 0};
+ GSS_C_NO_NAME, NULL, {NULL, NULL, NULL, NULL, NULL}, 0, 0, NULL};
ssh_gssapi_mech gssapi_null_mech =
{ NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL, NULL};
@@ -296,6 +296,92 @@ ssh_gssapi_parse_ename(Gssctxt *ctx, gss_buffer_t ename, gss_buffer_t name)
return GSS_S_COMPLETE;
}
+
+/* Extract authentication indicators from the Kerberos ticket. Authentication
+ * indicators are GSSAPI name attributes for the name "auth-indicators".
+ * Multiple indicators might be present in the ticket.
+ * Each indicator is a utf8 string. */
+
+#define AUTH_INDICATORS_TAG "auth-indicators"
+
+/* Privileged (called from accept_secure_ctx) */
+static OM_uint32
+ssh_gssapi_getindicators(Gssctxt *ctx, gss_name_t gss_name, ssh_gssapi_client *client)
+{
+ gss_buffer_set_t attrs = GSS_C_NO_BUFFER_SET;
+ gss_buffer_desc value = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc display_value = GSS_C_EMPTY_BUFFER;
+ int is_mechname, authenticated, complete, more;
+ size_t count, i;
+
+ ctx->major = gss_inquire_name(&ctx->minor, gss_name,
+ &is_mechname, NULL, &attrs);
+ if (ctx->major != GSS_S_COMPLETE) {
+ return (ctx->major);
+ }
+
+ if (attrs == GSS_C_NO_BUFFER_SET) {
+ /* No indicators in the ticket */
+ return (0);
+ }
+
+ count = 0;
+ for (i = 0; i < attrs->count; i++) {
+ /* skip anything but auth-indicators */
+ if (((sizeof(AUTH_INDICATORS_TAG) - 1) != attrs->elements[i].length) ||
+ strncmp(AUTH_INDICATORS_TAG,
+ attrs->elements[i].value,
+ sizeof(AUTH_INDICATORS_TAG) - 1) != 0)
+ continue;
+ count++;
+ }
+
+ if (count == 0) {
+ /* No auth-indicators in the ticket */
+ (void) gss_release_buffer_set(&ctx->minor, &attrs);
+ return (0);
+ }
+
+ client->indicators = recallocarray(NULL, 0, count + 1, sizeof(char*));
+ count = 0;
+ for (i = 0; i < attrs->count; i++) {
+ authenticated = 0;
+ complete = 0;
+ more = -1;
+ /* skip anything but auth-indicators */
+ if (((sizeof(AUTH_INDICATORS_TAG) - 1) != attrs->elements[i].length) ||
+ strncmp(AUTH_INDICATORS_TAG,
+ attrs->elements[i].value,
+ sizeof(AUTH_INDICATORS_TAG) - 1) != 0)
+ continue;
+ /* retrieve all indicators */
+ while (more != 0) {
+ value.value = NULL;
+ display_value.value = NULL;
+ ctx->major = gss_get_name_attribute(&ctx->minor, gss_name,
+ &attrs->elements[i], &authenticated,
+ &complete, &value, &display_value, &more);
+ if (ctx->major != GSS_S_COMPLETE) {
+ goto out;
+ }
+
+ if ((value.value != NULL) && authenticated) {
+ client->indicators[count] = xmalloc(value.length + 1);
+ memcpy(client->indicators[count], value.value, value.length);
+ client->indicators[count][value.length] = '\0';
+ count++;
+ }
+ }
+ }
+
+out:
+ (void) gss_release_buffer(&ctx->minor, &value);
+ (void) gss_release_buffer(&ctx->minor, &display_value);
+ (void) gss_release_buffer_set(&ctx->minor, &attrs);
+ return (ctx->major);
+}
+
+
/* Extract the client details from a given context. This can only reliably
* be called once for a context */
@@ -385,6 +471,12 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client)
}
gss_release_buffer(&ctx->minor, &ename);
+ /* Retrieve authentication indicators, if they exist */
+ if ((ctx->major = ssh_gssapi_getindicators(ctx,
+ ctx->client, client))) {
+ ssh_gssapi_error(ctx);
+ return (ctx->major);
+ }
/* We can't copy this structure, so we just move the pointer to it */
client->creds = ctx->client_creds;
@@ -447,6 +539,7 @@ int
ssh_gssapi_userok(char *user, struct passwd *pw, int kex)
{
OM_uint32 lmin;
+ size_t i;
(void) kex; /* used in privilege separation */
@@ -465,6 +558,14 @@ ssh_gssapi_userok(char *user, struct passwd *pw, int kex)
gss_release_buffer(&lmin, &gssapi_client.displayname);
gss_release_buffer(&lmin, &gssapi_client.exportedname);
gss_release_cred(&lmin, &gssapi_client.creds);
+
+ if (gssapi_client.indicators != NULL) {
+ for(i = 0; gssapi_client.indicators[i] != NULL; i++) {
+ free(gssapi_client.indicators[i]);
+ }
+ free(gssapi_client.indicators);
+ }
+
explicit_bzero(&gssapi_client,
sizeof(ssh_gssapi_client));
return 0;
diff --git a/servconf.c b/servconf.c
index e7e4ad046..aab653244 100644
--- a/servconf.c
+++ b/servconf.c
@@ -147,6 +147,7 @@ initialize_server_options(ServerOptions *options)
options->gss_strict_acceptor = -1;
options->gss_store_rekey = -1;
options->gss_kex_algorithms = NULL;
+ options->gss_indicators = NULL;
options->use_kuserok = -1;
options->enable_k5users = -1;
options->password_authentication = -1;
@@ -598,7 +599,7 @@ typedef enum {
sPerSourcePenalties, sPerSourcePenaltyExemptList,
sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
sGssAuthentication, sGssCleanupCreds, sGssEnablek5users, sGssStrictAcceptor,
- sGssKeyEx, sGssKexAlgorithms, sGssStoreRekey,
+ sGssKeyEx, sGssIndicators, sGssKexAlgorithms, sGssStoreRekey,
sAcceptEnv, sSetEnv, sPermitTunnel,
sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory,
sUsePrivilegeSeparation, sAllowAgentForwarding,
@@ -694,6 +695,7 @@ static struct {
{ "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL },
{ "gssapikexalgorithms", sGssKexAlgorithms, SSHCFG_GLOBAL },
{ "gssapienablek5users", sGssEnablek5users, SSHCFG_ALL },
+ { "gssapiindicators", sGssIndicators, SSHCFG_ALL },
#else
{ "gssapiauthentication", sUnsupported, SSHCFG_ALL },
{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
@@ -703,6 +705,7 @@ static struct {
{ "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL },
{ "gssapikexalgorithms", sUnsupported, SSHCFG_GLOBAL },
{ "gssapienablek5users", sUnsupported, SSHCFG_ALL },
+ { "gssapiindicators", sUnsupported, SSHCFG_ALL },
#endif
{ "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL },
{ "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL },
@@ -1730,6 +1733,15 @@ process_server_config_line_depth(ServerOptions *options, char *line,
options->gss_kex_algorithms = xstrdup(arg);
break;
+ case sGssIndicators:
+ arg = argv_next(&ac, &av);
+ if (!arg || *arg == '\0')
+ fatal("%s line %d: %s missing argument.",
+ filename, linenum, keyword);
+ if (options->gss_indicators == NULL)
+ options->gss_indicators = xstrdup(arg);
+ break;
+
case sPasswordAuthentication:
intptr = &options->password_authentication;
goto parse_flag;
@@ -3351,6 +3363,7 @@ dump_config(ServerOptions *o)
dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor);
dump_cfg_fmtint(sGssStoreRekey, o->gss_store_rekey);
dump_cfg_string(sGssKexAlgorithms, o->gss_kex_algorithms);
+ dump_cfg_string(sGssIndicators, o->gss_indicators);
#endif
dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
dump_cfg_fmtint(sKbdInteractiveAuthentication,
diff --git a/servconf.h b/servconf.h
index 7c7e5d434..7c41df417 100644
--- a/servconf.h
+++ b/servconf.h
@@ -181,6 +181,7 @@ typedef struct {
char **allow_groups;
u_int num_deny_groups;
char **deny_groups;
+ char *gss_indicators;
u_int num_subsystems;
char **subsystem_name;
@@ -310,6 +311,7 @@ TAILQ_HEAD(include_list, include_item);
M_CP_STROPT(routing_domain); \
M_CP_STROPT(permit_user_env_allowlist); \
M_CP_STROPT(pam_service_name); \
+ M_CP_STROPT(gss_indicators); \
M_CP_STRARRAYOPT(authorized_keys_files, num_authkeys_files); \
M_CP_STRARRAYOPT(allow_users, num_allow_users); \
M_CP_STRARRAYOPT(deny_users, num_deny_users); \
diff --git a/ssh-gss.h b/ssh-gss.h
index a894e23c9..59cf46d47 100644
--- a/ssh-gss.h
+++ b/ssh-gss.h
@@ -34,6 +34,12 @@
#include <gssapi/gssapi.h>
#endif
+#ifdef HAVE_GSSAPI_EXT_H
+#include <gssapi_ext.h>
+#elif defined(HAVE_GSSAPI_GSSAPI_EXT_H)
+#include <gssapi/gssapi_ext.h>
+#endif
+
#ifdef KRB5
# ifndef HEIMDAL
# ifdef HAVE_GSSAPI_GENERIC_H
@@ -107,6 +113,7 @@ typedef struct {
ssh_gssapi_ccache store;
int used;
int updated;
+ char **indicators; /* auth indicators */
} ssh_gssapi_client;
typedef struct ssh_gssapi_mech_struct {
diff --git a/sshd_config.5 b/sshd_config.5
index 583a01cdb..90ab87edd 100644
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -785,6 +785,50 @@ gss-nistp256-sha256-
gss-curve25519-sha256-
.Ed
This option only applies to connections using GSSAPI.
+.It Cm GSSAPIIndicators
+Specifies whether to accept or deny GSSAPI authenticated access if Kerberos
+mechanism is used and Kerberos ticket contains a particular set of
+authentication indicators. The values can be specified as a comma-separated list
+.Cm [!]name1,[!]name2,... .
+When indicator's name is prefixed with !, the authentication indicator 'name'
+will deny access to the system. Otherwise, one of non-negated authentication
+indicators must be present in the Kerberos ticket to allow access. If
+.Cm GSSAPIIndicators
+is defined, a Kerberos ticket that has indicators but does not match the
+policy will get denial. If at least one indicator is configured, whether for
+access or denial, tickets without authentication indicators will be explicitly
+rejected.
+.Pp
+By default systems using MIT Kerberos 1.17 or later will not assign any
+indicators. SPAKE and PKINIT methods add authentication indicators
+to all successful authentications. The SPAKE pre-authentication method is
+preferred over an encrypted timestamp pre-authentication when passwords used to
+authenticate user principals. Kerberos KDCs built with Heimdal Kerberos
+(including Samba AD DC built with Heimdal) do not add authentication
+indicators. However, OpenSSH built against Heimdal Kerberos library is able to
+inquire authentication indicators and thus can be used to check for their presence.
+.Pp
+Indicator name is case-sensitive and depends on the configuration of a
+particular Kerberos deployment. Indicators available in MIT Kerberos and
+FreeIPA environments:
+.Pp
+.Bl -tag -width XXXX -offset indent -compact
+.It Cm hardened
+SPAKE or encrypted timestamp pre-authentication mechanisms in MIT Kerberos and FreeIPA
+.It Cm pkinit
+smartcard or PKCS11 token-based pre-authentication in MIT Kerberos and FreeIPA
+.It Cm radius
+pre-authentication based on a RADIUS server in MIT Kerberos and FreeIPA
+.It Cm otp
+TOTP/HOTP-based two-factor pre-authentication in FreeIPA
+.It Cm idp
+OAuth2-based pre-authentication in FreeIPA using an external identity provider
+and device authorization grant flow
+.It Cm passkey
+FIDO2-based pre-authentication in FreeIPA, using FIDO2 USB and NFC tokens
+.El
+.Pp
+The default is to not use GSSAPI authentication indicators for access decisions.
.It Cm HostbasedAcceptedAlgorithms
The default is handled system-wide by
.Xr crypto-policies 7 .
--
2.49.0

View file

@ -1,257 +0,0 @@
From 24c411970682dc67873c36bac05b4b460d68a628 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:29 +0200
Subject: [PATCH 50/50] openssh-6.7p1-coverity
---
auth-krb5.c | 2 ++
gss-genr.c | 3 ++-
krl.c | 3 +++
loginrec.c | 2 ++
misc.c | 3 +++
monitor.c | 4 ++--
openbsd-compat/bindresvport.c | 2 +-
openbsd-compat/bsd-pselect.c | 8 ++++----
readconf.c | 1 +
servconf.c | 5 +++--
serverloop.c | 2 +-
ssh-agent.c | 1 +
ssh-keygen.c | 3 +++
13 files changed, 28 insertions(+), 11 deletions(-)
diff --git a/auth-krb5.c b/auth-krb5.c
index bae153c9..209a3265 100644
--- a/auth-krb5.c
+++ b/auth-krb5.c
@@ -427,6 +427,7 @@ ssh_krb5_cc_new_unique(krb5_context ctx, krb5_ccache *ccache, int *need_environm
umask(old_umask);
if (tmpfd == -1) {
logit("mkstemp(): %.100s", strerror(oerrno));
+ free(ccname);
return oerrno;
}
@@ -434,6 +435,7 @@ ssh_krb5_cc_new_unique(krb5_context ctx, krb5_ccache *ccache, int *need_environm
oerrno = errno;
logit("fchmod(): %.100s", strerror(oerrno));
close(tmpfd);
+ free(ccname);
return oerrno;
}
/* make sure the KRB5CCNAME is set for non-standard location */
diff --git a/gss-genr.c b/gss-genr.c
index 3034370c..c357e973 100644
--- a/gss-genr.c
+++ b/gss-genr.c
@@ -168,8 +168,9 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check,
enclen = __b64_ntop(digest,
ssh_digest_bytes(SSH_DIGEST_MD5), encoded,
ssh_digest_bytes(SSH_DIGEST_MD5) * 2);
-
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
cp = strncpy(s, kex, strlen(kex));
+#pragma GCC diagnostic pop
for ((p = strsep(&cp, ",")); p && *p != '\0';
(p = strsep(&cp, ","))) {
if (sshbuf_len(buf) != 0 &&
diff --git a/krl.c b/krl.c
index 0d0f6953..d8517f12 100644
--- a/krl.c
+++ b/krl.c
@@ -1202,6 +1202,7 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key)
return r;
erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha1s, &rb);
free(rb.blob);
+ rb.blob = NULL; /* make coverity happy */
if (erb != NULL) {
KRL_DBG(("revoked by key SHA1"));
return SSH_ERR_KEY_REVOKED;
@@ -1212,6 +1213,7 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key)
return r;
erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha256s, &rb);
free(rb.blob);
+ rb.blob = NULL; /* make coverity happy */
if (erb != NULL) {
KRL_DBG(("revoked by key SHA256"));
return SSH_ERR_KEY_REVOKED;
@@ -1223,6 +1225,7 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key)
return r;
erb = RB_FIND(revoked_blob_tree, &krl->revoked_keys, &rb);
free(rb.blob);
+ rb.blob = NULL; /* make coverity happy */
if (erb != NULL) {
KRL_DBG(("revoked by explicit key"));
return SSH_ERR_KEY_REVOKED;
diff --git a/loginrec.c b/loginrec.c
index c4a9bd48..2583612c 100644
--- a/loginrec.c
+++ b/loginrec.c
@@ -683,9 +683,11 @@ construct_utmp(struct logininfo *li,
*/
/* Use strncpy because we don't necessarily want null termination */
+ /* coverity[buffer_size_warning : FALSE] */
strncpy(ut->ut_name, li->username,
MIN_SIZEOF(ut->ut_name, li->username));
# ifdef HAVE_HOST_IN_UTMP
+ /* coverity[buffer_size_warning : FALSE] */
strncpy(ut->ut_host, li->hostname,
MIN_SIZEOF(ut->ut_host, li->hostname));
# endif
diff --git a/misc.c b/misc.c
index 09722962..cd71c1b2 100644
--- a/misc.c
+++ b/misc.c
@@ -1556,6 +1556,8 @@ sanitise_stdfd(void)
}
if (nullfd > STDERR_FILENO)
close(nullfd);
+ /* coverity[leaked_handle : FALSE]*/
+ /* coverity[leaked_handle : FALSE]*/
}
char *
@@ -2749,6 +2751,7 @@ stdfd_devnull(int do_stdin, int do_stdout, int do_stderr)
}
if (devnull > STDERR_FILENO)
close(devnull);
+ /* coverity[leaked_handle : FALSE]*/
return ret;
}
diff --git a/monitor.c b/monitor.c
index 19cb058e..58fbac9d 100644
--- a/monitor.c
+++ b/monitor.c
@@ -415,7 +415,7 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor)
mm_get_keystate(ssh, pmonitor);
/* Drain any buffered messages from the child */
- while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0)
+ while (pmonitor->m_log_recvfd >= 0 && monitor_read_log(pmonitor) == 0)
;
if (pmonitor->m_recvfd >= 0)
@@ -1813,7 +1813,7 @@ mm_answer_pty(struct ssh *ssh, int sock, struct sshbuf *m)
s->ptymaster = s->ptyfd;
debug3_f("tty %s ptyfd %d", s->tty, s->ttyfd);
-
+ /* coverity[leaked_handle : FALSE] */
return (0);
error:
diff --git a/openbsd-compat/bindresvport.c b/openbsd-compat/bindresvport.c
index 346c7fe5..f42792fd 100644
--- a/openbsd-compat/bindresvport.c
+++ b/openbsd-compat/bindresvport.c
@@ -59,7 +59,7 @@ bindresvport_sa(int sd, struct sockaddr *sa)
struct sockaddr_in6 *in6;
u_int16_t *portp;
u_int16_t port;
- socklen_t salen;
+ socklen_t salen = sizeof(struct sockaddr_storage);
int i;
if (sa == NULL) {
diff --git a/openbsd-compat/bsd-pselect.c b/openbsd-compat/bsd-pselect.c
index 26bdc3e0..8e2939b9 100644
--- a/openbsd-compat/bsd-pselect.c
+++ b/openbsd-compat/bsd-pselect.c
@@ -85,13 +85,13 @@ pselect_notify_setup(void)
static void
pselect_notify_parent(void)
{
- if (notify_pipe[1] != -1)
+ if (notify_pipe[1] >= 0)
(void)write(notify_pipe[1], "", 1);
}
static void
pselect_notify_prepare(fd_set *readset)
{
- if (notify_pipe[0] != -1)
+ if (notify_pipe[0] >= 0)
FD_SET(notify_pipe[0], readset);
}
static void
@@ -99,8 +99,8 @@ pselect_notify_done(fd_set *readset)
{
char c;
- if (notify_pipe[0] != -1 && FD_ISSET(notify_pipe[0], readset)) {
- while (read(notify_pipe[0], &c, 1) != -1)
+ if (notify_pipe[0] >= 0 && FD_ISSET(notify_pipe[0], readset)) {
+ while (read(notify_pipe[0], &c, 1) >= 0)
debug2_f("reading");
FD_CLR(notify_pipe[0], readset);
}
diff --git a/readconf.c b/readconf.c
index ea9d293c..9680c38c 100644
--- a/readconf.c
+++ b/readconf.c
@@ -2164,6 +2164,7 @@ parse_pubkey_algos:
} else if (r != 0) {
error("%.200s line %d: glob failed for %s.",
filename, linenum, arg2);
+ free(arg2);
goto out;
}
free(arg2);
diff --git a/servconf.c b/servconf.c
index 8b708cbf..e7e4ad04 100644
--- a/servconf.c
+++ b/servconf.c
@@ -2293,8 +2293,9 @@ process_server_config_line_depth(ServerOptions *options, char *line,
if (*activep && *charptr == NULL) {
*charptr = tilde_expand_filename(arg, getuid());
/* increase optional counter */
- if (intptr != NULL)
- *intptr = *intptr + 1;
+ /* DEAD CODE intptr is still NULL ;)
+ if (intptr != NULL)
+ *intptr = *intptr + 1; */
}
break;
diff --git a/serverloop.c b/serverloop.c
index 9c5b1567..768ee9fa 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -511,7 +511,7 @@ server_request_tun(struct ssh *ssh)
debug_f("invalid tun");
goto done;
}
- if (auth_opts->force_tun_device != -1) {
+ if (auth_opts->force_tun_device >= 0) {
if (tun != SSH_TUNID_ANY &&
auth_opts->force_tun_device != (int)tun)
goto done;
diff --git a/ssh-agent.c b/ssh-agent.c
index 798bf9b6..0e39dff7 100644
--- a/ssh-agent.c
+++ b/ssh-agent.c
@@ -1593,6 +1593,7 @@ sanitize_pkcs11_provider(const char *provider)
if (pkcs11_uri_parse(provider, uri) != 0) {
error("Failed to parse PKCS#11 URI");
+ pkcs11_uri_cleanup(uri);
return NULL;
}
/* validate also provider from URI */
diff --git a/ssh-keygen.c b/ssh-keygen.c
index 792aafde..96b3474d 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -2424,6 +2424,9 @@ update_krl_from_file(struct passwd *pw, const char *file, int wild_ca,
r = ssh_krl_revoke_key_sha256(krl, blob, blen);
if (r != 0)
fatal_fr(r, "revoke key failed");
+ freezero(blob, blen);
+ blob = NULL;
+ blen = 0;
} else {
if (strncasecmp(cp, "key:", 4) == 0) {
cp += 4;
--
2.49.0

File diff suppressed because it is too large Load diff

View file

@ -1,2 +0,0 @@
#Type Name ID GECOS Home directory Shell
u sshd 74 "Privilege-separated SSH" /usr/share/empty.sshd -

File diff suppressed because it is too large Load diff

View file

@ -1,15 +0,0 @@
[Unit]
Description=Update gsissh host key permissions
Documentation=https://fedoraproject.org/wiki/Changes/SSHKeySignSuidBit
Before=gsisshd.service
After=gsissh-keygen.target
ConditionPathExists=!/var/lib/.gsissh-host-keys-migration
[Service]
Type=oneshot
ExecStart=-/usr/libexec/gsissh/ssh-host-keys-migration.sh
ExecStart=touch /var/lib/.gsissh-host-keys-migration
RemainAfterExit=yes
[Install]
WantedBy=gsisshd.service

View file

@ -1,36 +0,0 @@
#!/usr/bin/bash
set -eu -o pipefail
# Detect existing non-conforming host keys and perform the permissions migration
# https://fedoraproject.org/wiki/Changes/SSHKeySignSuidBit
#
# Example output looks like:
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @ WARNING: UNPROTECTED PRIVATE KEY FILE! @
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# Permissions 0640 for '/etc/ssh/ssh_host_rsa_key' are too open.
# It is required that your private key files are NOT accessible by others.
# This private key will be ignored.
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @ WARNING: UNPROTECTED PRIVATE KEY FILE! @
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# Permissions 0640 for '/etc/ssh/ssh_host_ecdsa_key' are too open.
# It is required that your private key files are NOT accessible by others.
# This private key will be ignored.
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @ WARNING: UNPROTECTED PRIVATE KEY FILE! @
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# Permissions 0640 for '/etc/ssh/ssh_host_ed25519_key' are too open.
# It is required that your private key files are NOT accessible by others.
# This private key will be ignored.
# gsisshd: no hostkeys available -- exiting.
#
output="$(gsisshd -T 2>&1 || true)" # expected to fail
while read line; do
if [[ $line =~ ^Permissions\ [0-9]+\ for\ \'(.*)\'\ are\ too\ open. ]]; then
keyfile=${BASH_REMATCH[1]}
echo $line
echo -e "\t-> changing permissions on $keyfile"
chmod --verbose g-r $keyfile
chown --verbose root:root $keyfile
fi
done <<< "$output"

View file

@ -1,45 +1,154 @@
#!/bin/bash
# Create the host keys for the gsissh server.
KEYTYPE=$1
case $KEYTYPE in
"dsa") ;& # disabled in FIPS
"ed25519")
FIPS=/proc/sys/crypto/fips_enabled
if [[ -r "$FIPS" && $(cat $FIPS) == "1" ]]; then
exit 0
fi ;;
"rsa")
if [[ ! -z $SSH_RSA_BITS ]]; then
SSH_KEYGEN_OPTIONS="-b $SSH_RSA_BITS"
fi ;; # always ok
"ecdsa")
if [[ ! -z $SSH_ECDSA_BITS ]]; then
SSH_KEYGEN_OPTIONS="-b $SSH_ECDSA_BITS"
fi ;;
*) # wrong argument
exit 12 ;;
esac
KEY=/etc/gsissh/ssh_host_${KEYTYPE}_key
#
# The creation is controlled by the $AUTOCREATE_SERVER_KEYS environment
# variable.
AUTOCREATE_SERVER_KEYS="RSA ECDSA ED25519"
# source function library
. /etc/rc.d/init.d/functions
# Some functions to make the below more readable
KEYGEN=/usr/bin/gsissh-keygen
if [[ ! -x $KEYGEN ]]; then
exit 13
RSA1_KEY=/etc/gsissh/ssh_host_key
RSA_KEY=/etc/gsissh/ssh_host_rsa_key
DSA_KEY=/etc/gsissh/ssh_host_dsa_key
ECDSA_KEY=/etc/gsissh/ssh_host_ecdsa_key
ED25519_KEY=/etc/gsissh/ssh_host_ed25519_key
# pull in sysconfig settings
[ -f /etc/sysconfig/gsisshd ] && . /etc/sysconfig/gsisshd
fips_enabled() {
if [ -r /proc/sys/crypto/fips_enabled ]; then
cat /proc/sys/crypto/fips_enabled
else
echo 0
fi
}
do_rsa1_keygen() {
if [ ! -s $RSA1_KEY -a `fips_enabled` -eq 0 ]; then
echo -n $"Generating SSH1 RSA host key: "
rm -f $RSA1_KEY
if test ! -f $RSA1_KEY && $KEYGEN -q -t rsa1 -f $RSA1_KEY -C '' -N '' >&/dev/null; then
chgrp ssh_keys $RSA1_KEY
chmod 640 $RSA1_KEY
chmod 644 $RSA1_KEY.pub
if [ -x /sbin/restorecon ]; then
/sbin/restorecon $RSA1_KEY{,.pub}
fi
success $"RSA1 key generation"
echo
else
failure $"RSA1 key generation"
echo
exit 1
fi
fi
}
do_rsa_keygen() {
if [ ! -s $RSA_KEY ]; then
echo -n $"Generating SSH2 RSA host key: "
rm -f $RSA_KEY
if test ! -f $RSA_KEY && $KEYGEN -q -t rsa -f $RSA_KEY -C '' -N '' >&/dev/null; then
chgrp ssh_keys $RSA_KEY
chmod 640 $RSA_KEY
chmod 644 $RSA_KEY.pub
if [ -x /sbin/restorecon ]; then
/sbin/restorecon $RSA_KEY{,.pub}
fi
success $"RSA key generation"
echo
else
failure $"RSA key generation"
echo
exit 1
fi
fi
}
do_dsa_keygen() {
if [ ! -s $DSA_KEY -a `fips_enabled` -eq 0 ]; then
echo -n $"Generating SSH2 DSA host key: "
rm -f $DSA_KEY
if test ! -f $DSA_KEY && $KEYGEN -q -t dsa -f $DSA_KEY -C '' -N '' >&/dev/null; then
chgrp ssh_keys $DSA_KEY
chmod 640 $DSA_KEY
chmod 644 $DSA_KEY.pub
if [ -x /sbin/restorecon ]; then
/sbin/restorecon $DSA_KEY{,.pub}
fi
success $"DSA key generation"
echo
else
failure $"DSA key generation"
echo
exit 1
fi
fi
}
do_ecdsa_keygen() {
if [ ! -s $ECDSA_KEY ]; then
echo -n $"Generating SSH2 ECDSA host key: "
rm -f $ECDSA_KEY
if test ! -f $ECDSA_KEY && $KEYGEN -q -t ecdsa -f $ECDSA_KEY -C '' -N '' >&/dev/null; then
chgrp ssh_keys $ECDSA_KEY
chmod 640 $ECDSA_KEY
chmod 644 $ECDSA_KEY.pub
if [ -x /sbin/restorecon ]; then
/sbin/restorecon $ECDSA_KEY{,.pub}
fi
success $"ECDSA key generation"
echo
else
failure $"ECDSA key generation"
echo
exit 1
fi
fi
}
do_ed25519_keygen() {
if [ ! -s $ED25519_KEY -a `fips_enabled` -eq 0 ]; then
echo -n $"Generating SSH2 ED25519 host key: "
rm -f $ED25519_KEY
if test ! -f $ED25519_KEY && $KEYGEN -q -t ed25519 -f $ED25519_KEY -C '' -N '' >&/dev/null; then
chgrp ssh_keys $ED25519_KEY
chmod 640 $ED25519_KEY
chmod 644 $ED25519_KEY.pub
if [ -x /sbin/restorecon ]; then
/sbin/restorecon $ED25519_KEY{,.pub}
fi
success $"ED25519 key generation"
echo
else
failure $"ED25519 key generation"
echo
exit 1
fi
fi
}
if [ "x${AUTOCREATE_SERVER_KEYS}" == "xNO" ]; then
exit 0
fi
# remove old keys
rm -f $KEY{,.pub}
# legacy options
case $AUTOCREATE_SERVER_KEYS in
NODSA) AUTOCREATE_SERVER_KEYS="RSA ECDSA ED25519";;
RSAONLY) AUTOCREATE_SERVER_KEYS="RSA";;
YES) AUTOCREATE_SERVER_KEYS="DSA RSA ECDSA ED25519";;
esac
# create new keys
if ! $KEYGEN -q -t $KEYTYPE $SSH_KEYGEN_OPTIONS -f $KEY -C '' -N '' >&/dev/null; then
exit 1
fi
# sanitize permissions
/usr/bin/chmod 600 $KEY
/usr/bin/chmod 644 $KEY.pub
if [[ -x /usr/sbin/restorecon ]]; then
/usr/sbin/restorecon $KEY{,.pub}
fi
exit 0
for KEY in $AUTOCREATE_SERVER_KEYS; do
case $KEY in
DSA) do_dsa_keygen;;
RSA) do_rsa_keygen;;
ECDSA) do_ecdsa_keygen;;
ED25519) do_ed25519_keygen;;
esac
done

11
gsisshd-keygen.service Normal file
View file

@ -0,0 +1,11 @@
[Unit]
Description=gsissh Server Key Generation
ConditionFileNotEmpty=|!/etc/gsissh/ssh_host_rsa_key
ConditionFileNotEmpty=|!/etc/gsissh/ssh_host_ecdsa_key
ConditionFileNotEmpty=|!/etc/gsissh/ssh_host_ed25519_key
PartOf=gsisshd.service gsisshd.socket
[Service]
ExecStart=/usr/sbin/gsisshd-keygen
Type=oneshot
RemainAfterExit=yes

View file

@ -1,5 +0,0 @@
[Unit]
Wants=gsisshd-keygen@rsa.service
Wants=gsisshd-keygen@ecdsa.service
Wants=gsisshd-keygen@ed25519.service
PartOf=gsisshd.service

View file

@ -1,14 +0,0 @@
[Unit]
Description=gsissh %i Server Key Generation
ConditionFileNotEmpty=|!/etc/gsissh/ssh_host_%i_key
[Service]
Type=oneshot
# Set option as empty variable to suppress warnings upon expanding the command line
# when the config file under /etc does not exist or is empty.
Environment=OPTIONS=
EnvironmentFile=-/etc/sysconfig/gsisshd
ExecStart=/usr/libexec/gsissh/sshd-keygen %i
[Install]
WantedBy=gsisshd-keygen.target

View file

@ -1,7 +1,9 @@
#%PAM-1.0
auth required pam_sepermit.so
auth substack password-auth
auth include postlogin
account required pam_sepermit.so
# Used with polkit to reauthorize users in remote sessions
-auth optional pam_reauthorize.so prepare
account required pam_nologin.so
account include password-auth
password include password-auth
@ -12,6 +14,7 @@ session required pam_loginuid.so
session required pam_selinux.so open env_params
session required pam_namespace.so
session optional pam_keyinit.so force revoke
session optional pam_motd.so
session include password-auth
session include postlogin
# Used with polkit to reauthorize users in remote sessions
-session optional pam_reauthorize.so prepare

View file

@ -1,17 +1,11 @@
[Unit]
Description=gsissh server daemon
Documentation=man:gsisshd(8) man:gsisshd_config(5)
After=network.target gsisshd-keygen.target
Wants=gsisshd-keygen.target
# Migration for Fedora 38 change to remove group ownership for standard host keys
# See https://fedoraproject.org/wiki/Changes/SSHKeySignSuidBit
Wants=gsissh-host-keys-migration.service
After=network.target gsisshd-keygen.service
Wants=gsisshd-keygen.service
[Service]
Type=notify
# Set option as empty variable to suppress warnings upon expanding the command line
# when the config file under /etc does not exist or is empty.
Environment=OPTIONS=
EnvironmentFile=-/etc/sysconfig/gsisshd
ExecStart=/usr/sbin/gsisshd -D $OPTIONS
ExecReload=/bin/kill -HUP $MAINPID

View file

@ -1,11 +1,15 @@
# Configuration file for the gsisshd service.
# Configuration file for the sshd service.
# The server keys are automatically generated if they are missing.
# To change the automatic creation, adjust gsisshd.service options for
# example using systemctl enable gsisshd-keygen@dsa.service to allow creation
# of DSA key or systemctl mask gsisshd-keygen@rsa.service to disable RSA key
# creation.
# To change the automatic creation uncomment and change the appropriate
# line. Accepted key types are: DSA RSA ECDSA ED25519.
# The default is "RSA ECDSA ED25519"
#SSH_RSA_BITS=3072
#SSH_ECDSA_BITS=256
OPTIONS=""
# AUTOCREATE_SERVER_KEYS=""
# AUTOCREATE_SERVER_KEYS="RSA ECDSA ED25519"
# Do not change this option unless you have hardware random
# generator and you REALLY know what you are doing
SSH_USE_STRONG_RNG=0
# SSH_USE_STRONG_RNG=1

View file

@ -1,18 +1,10 @@
[Unit]
Description=gsissh per-connection server daemon
Documentation=man:gsisshd(8) man:gsisshd_config(5)
Wants=gsisshd-keygen.target
After=gsisshd-keygen.target
# Migration for Fedora 38 change to remove group ownership for standard host keys
# See https://fedoraproject.org/wiki/Changes/SSHKeySignSuidBit
Wants=gsissh-host-keys-migration.service
Wants=gsisshd-keygen.service
After=gsisshd-keygen.service
[Service]
# Set option as empty variable to suppress warnings upon expanding the command line
# when the config file under /etc does not exist or is empty.
Environment=OPTIONS=
EnvironmentFile=-/etc/sysconfig/gsisshd
ExecStart=-/usr/sbin/gsisshd -i $OPTIONS
ExecStart=-/usr/sbin/gsisshd -i $OPTIONS -o "AuthorizedKeysFile ${CREDENTIALS_DIRECTORY}/ssh.ephemeral-authorized_keys-all .ssh/authorized_keys"
StandardInput=socket
ImportCredential=ssh.ephemeral-authorized_keys-all

View file

@ -0,0 +1,19 @@
diff -up openssh-7.4p1/contrib/gnome-ssh-askpass2.c.grab-info openssh-7.4p1/contrib/gnome-ssh-askpass2.c
--- openssh-7.4p1/contrib/gnome-ssh-askpass2.c.grab-info 2016-12-23 13:31:22.645213115 +0100
+++ openssh-7.4p1/contrib/gnome-ssh-askpass2.c 2016-12-23 13:31:40.997216691 +0100
@@ -65,9 +65,12 @@ report_failed_grab (GtkWidget *parent_wi
err = gtk_message_dialog_new(GTK_WINDOW(parent_window), 0,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
- "Could not grab %s. "
- "A malicious client may be eavesdropping "
- "on your session.", what);
+ "SSH password dialog could not grab the %s input.\n"
+ "This might be caused by application such as screensaver, "
+ "however it could also mean that someone may be eavesdropping "
+ "on your session.\n"
+ "Either close the application which grabs the %s or "
+ "log out and log in again to prevent this from happening.", what, what);
gtk_window_set_position(GTK_WINDOW(err), GTK_WIN_POS_CENTER);
gtk_dialog_run(GTK_DIALOG(err));

View file

@ -0,0 +1,81 @@
diff -up openssh-7.4p1/contrib/gnome-ssh-askpass2.c.progress openssh-7.4p1/contrib/gnome-ssh-askpass2.c
--- openssh-7.4p1/contrib/gnome-ssh-askpass2.c.progress 2016-12-19 05:59:41.000000000 +0100
+++ openssh-7.4p1/contrib/gnome-ssh-askpass2.c 2016-12-23 13:31:16.545211926 +0100
@@ -53,6 +53,7 @@
#include <string.h>
#include <unistd.h>
#include <X11/Xlib.h>
+#include <glib.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
@@ -81,13 +82,24 @@ ok_dialog(GtkWidget *entry, gpointer dia
gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
}
+static void
+move_progress(GtkWidget *entry, gpointer progress)
+{
+ gdouble step;
+ g_return_if_fail(GTK_IS_PROGRESS_BAR(progress));
+
+ step = g_random_double_range(0.03, 0.1);
+ gtk_progress_bar_set_pulse_step(GTK_PROGRESS_BAR(progress), step);
+ gtk_progress_bar_pulse(GTK_PROGRESS_BAR(progress));
+}
+
static int
passphrase_dialog(char *message)
{
const char *failed;
char *passphrase, *local;
int result, grab_tries, grab_server, grab_pointer;
- GtkWidget *parent_window, *dialog, *entry;
+ GtkWidget *parent_window, *dialog, *entry, *progress, *hbox;
GdkGrabStatus status;
grab_server = (getenv("GNOME_SSH_ASKPASS_GRAB_SERVER") != NULL);
@@ -104,14 +116,32 @@ passphrase_dialog(char *message)
"%s",
message);
+ hbox = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, FALSE,
+ FALSE, 0);
+ gtk_widget_show(hbox);
+
entry = gtk_entry_new();
gtk_box_pack_start(
- GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), entry,
- FALSE, FALSE, 0);
+ GTK_BOX(hbox), entry,
+ TRUE, FALSE, 0);
+ gtk_entry_set_width_chars(GTK_ENTRY(entry), 2);
gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE);
gtk_widget_grab_focus(entry);
gtk_widget_show(entry);
+ hbox = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, FALSE,
+ FALSE, 8);
+ gtk_widget_show(hbox);
+
+ progress = gtk_progress_bar_new();
+
+ gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress), "Passphrase length hidden intentionally");
+ gtk_box_pack_start(GTK_BOX(hbox), progress, TRUE,
+ TRUE, 5);
+ gtk_widget_show(progress);
+
gtk_window_set_title(GTK_WINDOW(dialog), "OpenSSH");
gtk_window_set_position (GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE);
@@ -120,6 +150,8 @@ passphrase_dialog(char *message)
gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
g_signal_connect(G_OBJECT(entry), "activate",
G_CALLBACK(ok_dialog), dialog);
+ g_signal_connect(G_OBJECT(entry), "changed",
+ G_CALLBACK(move_progress), progress);
gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE);

View file

@ -1,17 +1,7 @@
From cf6d48305cf6601448ea7a0d96ae825cbbbf0a2c Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:28 +0200
Subject: [PATCH 07/50] openssh-7.2p2-x11
---
channels.c | 25 +++++++++++++++++++------
1 file changed, 19 insertions(+), 6 deletions(-)
diff --git a/channels.c b/channels.c
index bfe2e3b2..d46531ce 100644
--- a/channels.c
+++ b/channels.c
@@ -5098,11 +5098,13 @@ x11_create_display_inet(struct ssh *ssh, int x11_display_offset,
diff -up openssh-5.3p1/channels.c.bz595935 openssh-5.3p1/channels.c
--- openssh-5.3p1/channels.c.bz595935 2010-08-12 14:19:28.000000000 +0200
+++ openssh-5.3p1/channels.c 2010-08-12 14:33:51.000000000 +0200
@@ -3990,21 +3990,24 @@ x11_create_display_inet(int x11_display_
}
static int
@ -24,10 +14,8 @@ index bfe2e3b2..d46531ce 100644
+ if (len <= 0)
+ return -1;
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock == -1) {
if (sock < 0)
error("socket: %.100s", strerror(errno));
@@ -5110,11 +5112,12 @@ connect_local_xsocket_path(const char *pathname)
}
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
- strlcpy(addr.sun_path, pathname, sizeof addr.sun_path);
@ -42,7 +30,7 @@ index bfe2e3b2..d46531ce 100644
return -1;
}
@@ -5122,8 +5125,18 @@ static int
@@ -3207,8 +3210,18 @@ static int
connect_local_xsocket(u_int dnr)
{
char buf[1024];
@ -62,7 +50,4 @@ index bfe2e3b2..d46531ce 100644
+ return -1;
}
#ifdef __APPLE__
--
2.49.0
int

View file

@ -0,0 +1,12 @@
diff -up openssh-5.8p1/packet.c.packet openssh-5.8p1/packet.c
--- openssh-5.8p1/packet.c.packet 2011-04-05 13:29:06.998648899 +0200
+++ openssh-5.8p1/packet.c 2011-04-05 13:30:32.967648596 +0200
@@ -294,6 +294,8 @@ packet_connection_is_on_socket(void)
struct sockaddr_storage from, to;
socklen_t fromlen, tolen;
+ if (!state)
+ return 0;
if (state->connection_in == -1 || state->connection_out == -1)
return 0;

View file

@ -0,0 +1,12 @@
diff -up openssh-5.8p2/ssh-keyscan.c.sigpipe openssh-5.8p2/ssh-keyscan.c
--- openssh-5.8p2/ssh-keyscan.c.sigpipe 2011-08-23 18:30:33.873025916 +0200
+++ openssh-5.8p2/ssh-keyscan.c 2011-08-23 18:32:24.574025362 +0200
@@ -715,6 +715,8 @@ main(int argc, char **argv)
fdlim_set(maxfd);
fdcon = xcalloc(maxfd, sizeof(con));
+ signal(SIGPIPE, SIG_IGN);
+
read_wait_nfdset = howmany(maxfd, NFDBITS);
read_wait = xcalloc(read_wait_nfdset, sizeof(fd_mask));

View file

@ -1,18 +1,7 @@
From 388be633842a9f3e4b0a76fe40cf7035912a913a Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:28 +0200
Subject: [PATCH 05/50] openssh-5.9p1-ipv6man
---
ssh.1 | 2 ++
sshd.8 | 2 ++
2 files changed, 4 insertions(+)
diff --git a/ssh.1 b/ssh.1
index 697f4e42..db92ac9a 100644
--- a/ssh.1
+++ b/ssh.1
@@ -1663,6 +1663,8 @@ manual page for more information.
diff -up openssh-5.9p0/ssh.1.ipv6man openssh-5.9p0/ssh.1
--- openssh-5.9p0/ssh.1.ipv6man 2011-08-05 22:17:32.000000000 +0200
+++ openssh-5.9p0/ssh.1 2011-08-31 13:08:34.880024485 +0200
@@ -1400,6 +1400,8 @@ manual page for more information.
.Nm
exits with the exit status of the remote command or with 255
if an error occurred.
@ -21,11 +10,10 @@ index 697f4e42..db92ac9a 100644
.Sh SEE ALSO
.Xr scp 1 ,
.Xr sftp 1 ,
diff --git a/sshd.8 b/sshd.8
index 08ebf53a..2aa73271 100644
--- a/sshd.8
+++ b/sshd.8
@@ -1018,6 +1018,8 @@ concurrently for different ports, this contains the process ID of the one
diff -up openssh-5.9p0/sshd.8.ipv6man openssh-5.9p0/sshd.8
--- openssh-5.9p0/sshd.8.ipv6man 2011-08-05 22:17:32.000000000 +0200
+++ openssh-5.9p0/sshd.8 2011-08-31 13:10:34.129039094 +0200
@@ -940,6 +940,8 @@ concurrently for different ports, this c
started last).
The content of this file is not sensitive; it can be world-readable.
.El
@ -34,6 +22,3 @@ index 08ebf53a..2aa73271 100644
.Sh SEE ALSO
.Xr scp 1 ,
.Xr sftp 1 ,
--
2.49.0

View file

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

143
openssh-6.2p1-vendor.patch Normal file
View file

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

View file

@ -0,0 +1,101 @@
diff -up openssh-5.9p1/cipher-ctr.c.ctr-evp openssh-5.9p1/cipher-ctr.c
--- openssh-5.9p1/cipher-ctr.c.ctr-evp 2012-01-11 09:24:06.000000000 +0100
+++ openssh-5.9p1/cipher-ctr.c 2012-01-11 15:54:04.675956600 +0100
@@ -38,7 +38,7 @@ void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, in
struct ssh_aes_ctr_ctx
{
- AES_KEY aes_ctx;
+ EVP_CIPHER_CTX ecbctx;
u_char aes_counter[AES_BLOCK_SIZE];
};
@@ -63,21 +63,42 @@ ssh_aes_ctr(EVP_CIPHER_CTX *ctx, u_char
{
struct ssh_aes_ctr_ctx *c;
size_t n = 0;
- u_char buf[AES_BLOCK_SIZE];
+ u_char ctrbuf[AES_BLOCK_SIZE*256];
+ u_char buf[AES_BLOCK_SIZE*256];
if (len == 0)
return (1);
if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL)
return (0);
- while ((len--) > 0) {
+ for (; len > 0; len -= sizeof(u_int)) {
+ u_int r,a,b;
+
if (n == 0) {
- AES_encrypt(c->aes_counter, buf, &c->aes_ctx);
- ssh_ctr_inc(c->aes_counter, AES_BLOCK_SIZE);
+ int outl, i, buflen;
+
+ buflen = MIN(len, sizeof(ctrbuf));
+
+ for(i = 0; i < buflen; i += AES_BLOCK_SIZE) {
+ memcpy(&ctrbuf[i], c->aes_counter, AES_BLOCK_SIZE);
+ ssh_ctr_inc(c->aes_counter, AES_BLOCK_SIZE);
+ }
+
+ EVP_EncryptUpdate(&c->ecbctx, buf, &outl,
+ ctrbuf, buflen);
}
- *(dest++) = *(src++) ^ buf[n];
- n = (n + 1) % AES_BLOCK_SIZE;
+
+ memcpy(&a, src, sizeof(a));
+ memcpy(&b, &buf[n], sizeof(b));
+ r = a ^ b;
+ memcpy(dest, &r, sizeof(r));
+ src += sizeof(a);
+ dest += sizeof(r);
+
+ n = (n + sizeof(b)) % sizeof(buf);
}
+ memset(ctrbuf, '\0', sizeof(ctrbuf));
+ memset(buf, '\0', sizeof(buf));
return (1);
}
@@ -91,9 +112,28 @@ ssh_aes_ctr_init(EVP_CIPHER_CTX *ctx, co
c = xmalloc(sizeof(*c));
EVP_CIPHER_CTX_set_app_data(ctx, c);
}
- if (key != NULL)
- AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
- &c->aes_ctx);
+
+ EVP_CIPHER_CTX_init(&c->ecbctx);
+
+ if (key != NULL) {
+ const EVP_CIPHER *cipher;
+ switch(EVP_CIPHER_CTX_key_length(ctx)*8) {
+ case 128:
+ cipher = EVP_aes_128_ecb();
+ break;
+ case 192:
+ cipher = EVP_aes_192_ecb();
+ break;
+ case 256:
+ cipher = EVP_aes_256_ecb();
+ break;
+ default:
+ fatal("ssh_aes_ctr_init: wrong aes key length");
+ }
+ if(!EVP_EncryptInit_ex(&c->ecbctx, cipher, NULL, key, NULL))
+ fatal("ssh_aes_ctr_init: cannot initialize aes encryption");
+ EVP_CIPHER_CTX_set_padding(&c->ecbctx, 0);
+ }
if (iv != NULL)
memcpy(c->aes_counter, iv, AES_BLOCK_SIZE);
return (1);
@@ -105,6 +145,7 @@ ssh_aes_ctr_cleanup(EVP_CIPHER_CTX *ctx)
struct ssh_aes_ctr_ctx *c;
if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
+ EVP_CIPHER_CTX_cleanup(&c->ecbctx);
memset(c, 0, sizeof(*c));
free(c);
EVP_CIPHER_CTX_set_app_data(ctx, NULL);

View file

@ -0,0 +1,249 @@
diff -up openssh-6.3p1/auth-krb5.c.ccache_name openssh-6.3p1/auth-krb5.c
--- openssh-6.3p1/auth-krb5.c.ccache_name 2013-10-23 22:03:52.322950759 +0200
+++ openssh-6.3p1/auth-krb5.c 2013-10-23 22:04:24.295799873 +0200
@@ -50,7 +50,9 @@
#include <errno.h>
#include <unistd.h>
#include <string.h>
+#include <sys/stat.h>
#include <krb5.h>
+#include <profile.h>
extern ServerOptions options;
@@ -91,6 +93,7 @@ auth_krb5_password(Authctxt *authctxt, c
#endif
krb5_error_code problem;
krb5_ccache ccache = NULL;
+ const char *ccache_type;
int len;
char *client, *platform_client;
const char *errmsg;
@@ -191,12 +194,30 @@ auth_krb5_password(Authctxt *authctxt, c
goto out;
#endif
+ ccache_type = krb5_cc_get_type(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
- len = strlen(authctxt->krb5_ticket_file) + 6;
+ if (authctxt->krb5_ticket_file[0] == ':')
+ authctxt->krb5_ticket_file++;
+
+ len = strlen(authctxt->krb5_ticket_file) + strlen(ccache_type) + 2;
authctxt->krb5_ccname = xmalloc(len);
- snprintf(authctxt->krb5_ccname, len, "FILE:%s",
+
+#ifdef USE_CCAPI
+ snprintf(authctxt->krb5_ccname, len, "API:%s",
authctxt->krb5_ticket_file);
+#else
+ snprintf(authctxt->krb5_ccname, len, "%s:%s",
+ ccache_type, authctxt->krb5_ticket_file);
+#endif
+
+ if (strcmp(ccache_type, "DIR") == 0) {
+ char *p;
+ p = strrchr(authctxt->krb5_ccname, '/');
+ if (p)
+ *p = '\0';
+ }
+
#ifdef USE_PAM
if (options.use_pam)
@@ -235,10 +256,36 @@ auth_krb5_password(Authctxt *authctxt, c
void
krb5_cleanup_proc(Authctxt *authctxt)
{
+ struct stat krb5_ccname_stat;
+ char krb5_ccname[128], *krb5_ccname_dir_start, *krb5_ccname_dir_end;
+
debug("krb5_cleanup_proc called");
if (authctxt->krb5_fwd_ccache) {
krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
authctxt->krb5_fwd_ccache = NULL;
+
+ if (authctxt->krb5_ccname != NULL) {
+ strncpy(krb5_ccname, authctxt->krb5_ccname, sizeof(krb5_ccname) - 10);
+ krb5_ccname_dir_start = strchr(krb5_ccname, ':') + 1;
+ *krb5_ccname_dir_start++ = '\0';
+ if (strcmp(krb5_ccname, "DIR") == 0) {
+
+ strcat(krb5_ccname_dir_start, "/primary");
+
+ if (stat(krb5_ccname_dir_start, &krb5_ccname_stat) == 0) {
+ if (unlink(krb5_ccname_dir_start) == 0) {
+ krb5_ccname_dir_end = strrchr(krb5_ccname_dir_start, '/');
+ *krb5_ccname_dir_end = '\0';
+ if (rmdir(krb5_ccname_dir_start) == -1)
+ debug("cache dir '%s' remove failed: %s", krb5_ccname_dir_start, strerror(errno));
+ }
+ else
+ debug("cache primary file '%s', remove failed: %s",
+ krb5_ccname_dir_start, strerror(errno)
+ );
+ }
+ }
+ }
}
if (authctxt->krb5_user) {
krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user);
@@ -250,34 +295,139 @@ krb5_cleanup_proc(Authctxt *authctxt)
}
}
+int
+ssh_asprintf_append(char **dsc, const char *fmt, ...) {
+ char *src, *old;
+ va_list ap;
+ int i;
+
+ va_start(ap, fmt);
+ i = vasprintf(&src, fmt, ap);
+ va_end(ap);
+
+ if (i == -1 || src == NULL)
+ return -1;
+
+ old = *dsc;
+
+ i = asprintf(dsc, "%s%s", *dsc, src);
+ if (i == -1 || src == NULL) {
+ free(src);
+ return -1;
+ }
+
+ free(old);
+ free(src);
+
+ return i;
+}
+
+int
+ssh_krb5_expand_template(char **result, const char *template) {
+ char *p_n, *p_o, *r, *tmp_template;
+
+ if (template == NULL)
+ return -1;
+
+ tmp_template = p_n = p_o = xstrdup(template);
+ r = xstrdup("");
+
+ while ((p_n = strstr(p_o, "%{")) != NULL) {
+
+ *p_n++ = '\0';
+ if (ssh_asprintf_append(&r, "%s", p_o) == -1)
+ goto cleanup;
+
+ if (strncmp(p_n, "{uid}", 5) == 0 || strncmp(p_n, "{euid}", 6) == 0 ||
+ strncmp(p_n, "{USERID}", 8) == 0) {
+ p_o = strchr(p_n, '}') + 1;
+ if (ssh_asprintf_append(&r, "%d", geteuid()) == -1)
+ goto cleanup;
+ continue;
+ }
+ else if (strncmp(p_n, "{TEMP}", 6) == 0) {
+ p_o = strchr(p_n, '}') + 1;
+ if (ssh_asprintf_append(&r, "/tmp") == -1)
+ goto cleanup;
+ continue;
+ } else {
+ p_o = strchr(p_n, '}') + 1;
+ p_o = '\0';
+ debug("%s: unsupported token %s in %s", __func__, p_n, template);
+ /* unknown token, fallback to the default */
+ goto cleanup;
+ }
+ }
+
+ if (ssh_asprintf_append(&r, "%s", p_o) == -1)
+ goto cleanup;
+
+ *result = r;
+ free(tmp_template);
+ return 0;
+
+cleanup:
+ free(r);
+ free(tmp_template);
+ return -1;
+}
+
+krb5_error_code
+ssh_krb5_get_cctemplate(krb5_context ctx, char **ccname) {
+ profile_t p;
+ int ret = 0;
+ char *value = NULL;
+
+ ret = krb5_get_profile(ctx, &p);
+ if (ret)
+ return ret;
+
+ ret = profile_get_string(p, "libdefaults", "default_ccache_name", NULL, NULL, &value);
+ if (ret)
+ return ret;
+
+ ret = ssh_krb5_expand_template(ccname, value);
+
+ return ret;
+}
+
#ifndef HEIMDAL
krb5_error_code
ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
int tmpfd, ret, oerrno;
- char ccname[40];
+ char *ccname;
+#ifdef USE_CCAPI
+ char cctemplate[] = "API:krb5cc_%d";
+#else
mode_t old_umask;
+ char cctemplate[] = "FILE:/tmp/krb5cc_%d_XXXXXXXXXX";
- ret = snprintf(ccname, sizeof(ccname),
- "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
- if (ret < 0 || (size_t)ret >= sizeof(ccname))
- return ENOMEM;
-
- old_umask = umask(0177);
- tmpfd = mkstemp(ccname + strlen("FILE:"));
- oerrno = errno;
- umask(old_umask);
- if (tmpfd == -1) {
- logit("mkstemp(): %.100s", strerror(oerrno));
- return oerrno;
- }
+#endif
+
+ ret = ssh_krb5_get_cctemplate(ctx, &ccname);
- if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) {
+ if (ret) {
+ ret = asprintf(&ccname, cctemplate, geteuid());
+ if (ret == -1)
+ return ENOMEM;
+ old_umask = umask(0177);
+ tmpfd = mkstemp(ccname + strlen("FILE:"));
oerrno = errno;
- logit("fchmod(): %.100s", strerror(oerrno));
+ umask(old_umask);
+ if (tmpfd == -1) {
+ logit("mkstemp(): %.100s", strerror(oerrno));
+ return oerrno;
+ }
+
+ if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) {
+ oerrno = errno;
+ logit("fchmod(): %.100s", strerror(oerrno));
+ close(tmpfd);
+ return oerrno;
+ }
close(tmpfd);
- return oerrno;
}
- close(tmpfd);
+ debug("%s: Setting ccname to %s", __func__, ccname);
return (krb5_cc_resolve(ctx, ccname, ccache));
}

View file

@ -0,0 +1,16 @@
diff --git a/scp.c b/scp.c
index d98fa67..25d347b 100644
--- a/scp.c
+++ b/scp.c
@@ -638,7 +638,10 @@ toremote(char *targ, int argc, char **argv)
addargs(&alist, "%s", ssh_program);
addargs(&alist, "-x");
addargs(&alist, "-oClearAllForwardings=yes");
- addargs(&alist, "-n");
+ if (isatty(fileno(stdin)))
+ addargs(&alist, "-t");
+ else
+ addargs(&alist, "-n");
for (j = 0; j < remote_remote_args.num; j++) {
addargs(&alist, "%s",
remote_remote_args.list[j]);

View file

@ -0,0 +1,12 @@
diff --git a/ssh_config b/ssh_config
index 03a228f..49a4f6c 100644
--- a/ssh_config
+++ b/ssh_config
@@ -46,3 +46,7 @@
# VisualHostKey no
# ProxyCommand ssh -q -W %h:%p gateway.example.com
# RekeyLimit 1G 1h
+#
+# Uncomment this if you want to use .local domain
+# Host *.local
+# CheckHostIP no

View file

@ -0,0 +1,12 @@
diff --git a/session.c b/session.c
index 626a642..b186ca1 100644
--- a/session.c
+++ b/session.c
@@ -1859,6 +1859,7 @@ do_child(Session *s, const char *command)
if (s->is_subsystem == SUBSYSTEM_INT_SFTP_ERROR) {
printf("This service allows sftp connections only.\n");
+ logit("The session allows sftp connections only");
fflush(NULL);
exit(1);
} else if (s->is_subsystem == SUBSYSTEM_INT_SFTP) {

View file

@ -0,0 +1,17 @@
diff --git a/openbsd-compat/port-linux.c b/openbsd-compat/port-linux.c
index 22ea8ef..2660085 100644
--- a/openbsd-compat/port-linux.c
+++ b/openbsd-compat/port-linux.c
@@ -116,7 +116,11 @@ ssh_selinux_setup_pty(char *pwname, const char *tty)
debug3("%s: setting TTY context on %s", __func__, tty);
- user_ctx = ssh_selinux_getctxbyname(pwname);
+ if (getexeccon(&user_ctx) != 0) {
+ error("%s: getexeccon: %s", __func__, strerror(errno));
+ goto out;
+ }
+
/* XXX: should these calls fatal() upon failure in enforcing mode? */

View file

@ -0,0 +1,131 @@
diff -up openssh-7.4p1/gss-serv-krb5.c.GSSAPIEnablek5users openssh-7.4p1/gss-serv-krb5.c
--- openssh-7.4p1/gss-serv-krb5.c.GSSAPIEnablek5users 2017-02-09 10:10:47.403859893 +0100
+++ openssh-7.4p1/gss-serv-krb5.c 2017-02-09 10:10:47.414859882 +0100
@@ -260,7 +260,6 @@ ssh_gssapi_krb5_cmdok(krb5_principal pri
FILE *fp;
char file[MAXPATHLEN];
char line[BUFSIZ];
- char kuser[65]; /* match krb5_kuserok() */
struct stat st;
struct passwd *pw = the_authctxt->pw;
int found_principal = 0;
@@ -269,7 +268,7 @@ ssh_gssapi_krb5_cmdok(krb5_principal pri
snprintf(file, sizeof(file), "%s/.k5users", pw->pw_dir);
/* If both .k5login and .k5users DNE, self-login is ok. */
- if (!k5login_exists && (access(file, F_OK) == -1)) {
+ if ( !options.enable_k5users || (!k5login_exists && (access(file, F_OK) == -1))) {
return ssh_krb5_kuserok(krb_context, principal, luser,
k5login_exists);
}
diff -up openssh-7.4p1/servconf.c.GSSAPIEnablek5users openssh-7.4p1/servconf.c
--- openssh-7.4p1/servconf.c.GSSAPIEnablek5users 2017-02-09 10:10:47.404859892 +0100
+++ openssh-7.4p1/servconf.c 2017-02-09 10:18:45.800385543 +0100
@@ -166,6 +166,7 @@ initialize_server_options(ServerOptions
options->ip_qos_bulk = -1;
options->version_addendum = NULL;
options->use_kuserok = -1;
+ options->enable_k5users = -1;
options->fingerprint_hash = -1;
options->disable_forwarding = -1;
}
@@ -337,6 +338,8 @@ fill_default_server_options(ServerOption
options->show_patchlevel = 0;
if (options->use_kuserok == -1)
options->use_kuserok = 1;
+ if (options->enable_k5users == -1)
+ options->enable_k5users = 0;
if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
options->fwd_opts.streamlocal_bind_mask = 0177;
if (options->fwd_opts.streamlocal_bind_unlink == -1)
@@ -418,7 +421,7 @@ typedef enum {
sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedKeyTypes,
sHostKeyAlgorithms,
sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
- sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
+ sGssAuthentication, sGssCleanupCreds, sGssEnablek5users, sGssStrictAcceptor,
sGssKeyEx, sGssStoreRekey, sAcceptEnv, sPermitTunnel,
sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
sUsePrivilegeSeparation, sAllowAgentForwarding,
@@ -497,12 +500,14 @@ static struct {
{ "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },
{ "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL },
{ "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL },
+ { "gssapienablek5users", sGssEnablek5users, SSHCFG_ALL },
#else
{ "gssapiauthentication", sUnsupported, SSHCFG_ALL },
{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
{ "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },
{ "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL },
{ "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL },
+ { "gssapienablek5users", sUnsupported, SSHCFG_ALL },
#endif
{ "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL },
{ "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL },
@@ -1653,6 +1658,10 @@ process_server_config_line(ServerOptions
intptr = &options->use_kuserok;
goto parse_flag;
+ case sGssEnablek5users:
+ intptr = &options->enable_k5users;
+ goto parse_flag;
+
case sPermitOpen:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
@@ -2026,6 +2035,7 @@ copy_set_server_options(ServerOptions *d
M_CP_INTOPT(ip_qos_interactive);
M_CP_INTOPT(ip_qos_bulk);
M_CP_INTOPT(use_kuserok);
+ M_CP_INTOPT(enable_k5users);
M_CP_INTOPT(rekey_limit);
M_CP_INTOPT(rekey_interval);
@@ -2319,6 +2329,7 @@ dump_config(ServerOptions *o)
dump_cfg_fmtint(sStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep);
dump_cfg_fmtint(sKerberosUseKuserok, o->use_kuserok);
+ dump_cfg_fmtint(sGssEnablek5users, o->enable_k5users);
dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash);
/* string arguments */
diff -up openssh-7.4p1/servconf.h.GSSAPIEnablek5users openssh-7.4p1/servconf.h
--- openssh-7.4p1/servconf.h.GSSAPIEnablek5users 2017-02-09 10:10:47.404859892 +0100
+++ openssh-7.4p1/servconf.h 2017-02-09 10:10:47.415859881 +0100
@@ -174,7 +174,8 @@ typedef struct {
int num_permitted_opens;
- int use_kuserok;
+ int use_kuserok;
+ int enable_k5users;
char *chroot_directory;
char *revoked_keys_file;
char *trusted_user_ca_keys;
diff -up openssh-7.4p1/sshd_config.5.GSSAPIEnablek5users openssh-7.4p1/sshd_config.5
--- openssh-7.4p1/sshd_config.5.GSSAPIEnablek5users 2017-02-09 10:10:47.415859881 +0100
+++ openssh-7.4p1/sshd_config.5 2017-02-09 10:19:29.420336796 +0100
@@ -633,6 +633,12 @@ Specifies whether key exchange based on
doesn't rely on ssh keys to verify host identity.
The default is
.Dq no .
+.It Cm GSSAPIEnablek5users
+Specifies whether to look at .k5users file for GSSAPI authentication
+access control. Further details are described in
+.Xr ksu 1 .
+The default is
+.Cm no .
.It Cm GSSAPIStrictAcceptorCheck
Determines whether to be strict about the identity of the GSSAPI acceptor
a client authenticates against.
diff -up openssh-7.4p1/sshd_config.GSSAPIEnablek5users openssh-7.4p1/sshd_config
--- openssh-7.4p1/sshd_config.GSSAPIEnablek5users 2017-02-09 10:10:47.404859892 +0100
+++ openssh-7.4p1/sshd_config 2017-02-09 10:10:47.415859881 +0100
@@ -80,6 +80,7 @@ GSSAPIAuthentication yes
GSSAPICleanupCredentials no
#GSSAPIStrictAcceptorCheck yes
#GSSAPIKeyExchange no
+#GSSAPIEnablek5users no
# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will

View file

@ -1,17 +1,7 @@
From 28333f1dfe68b0ffc80c2a4799759587b4c32d3e Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:28 +0200
Subject: [PATCH 04/50] openssh-6.6p1-allow-ip-opts
---
sshd-session.c | 32 ++++++++++++++++++++++++++------
1 file changed, 26 insertions(+), 6 deletions(-)
diff --git a/sshd-session.c b/sshd-session.c
index 4a148db4..a365f26f 100644
--- a/sshd-session.c
+++ b/sshd-session.c
@@ -778,12 +778,32 @@ check_ip_options(struct ssh *ssh)
diff -up openssh/sshd.c.ip-opts openssh/sshd.c
--- openssh/sshd.c.ip-opts 2016-07-25 13:58:48.998507834 +0200
+++ openssh/sshd.c 2016-07-25 14:01:28.346469878 +0200
@@ -1507,12 +1507,29 @@ check_ip_options(struct ssh *ssh)
if (getsockopt(sock_in, IPPROTO_IP, IP_OPTIONS, opts,
&option_size) >= 0 && option_size != 0) {
@ -31,14 +21,11 @@ index 4a148db4..a365f26f 100644
+ case 130:
+ case 133:
+ case 134:
+ if (i + 1 < option_size && opts[i + 1] >= 2) {
+ i += opts[i + 1];
+ break;
+ }
+ /* FALLTHROUGH */
+ i += opts[i + 1];
+ break;
+ default:
+ /* Fail, fatally, if we detect either loose or strict
+ * or incorrect source routing options. */
+ * source routing options. */
+ text[0] = '\0';
+ for (i = 0; i < option_size; i++)
+ snprintf(text + i*3, sizeof(text) - i*3,
@ -48,8 +35,5 @@ index 4a148db4..a365f26f 100644
+ }
+ } while (i < option_size);
}
return;
#endif /* IP_OPTIONS */
}
--
2.49.0

View file

@ -0,0 +1,40 @@
diff --git a/sshd_config.5 b/sshd_config.5
index 2320128..6244e68 100644
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -120,6 +120,8 @@ The allow/deny directives are processed in the following order:
.Cm DenyGroups ,
and finally
.Cm AllowGroups .
+All of the specified user and group tests must succeed, before user
+is allowed to log in.
.Pp
See PATTERNS in
.Xr ssh_config 5
@@ -160,6 +162,8 @@ The allow/deny directives are processed in the following order:
.Cm DenyGroups ,
and finally
.Cm AllowGroups .
+All of the specified user and group tests must succeed, before user
+is allowed to log in.
.Pp
See PATTERNS in
.Xr ssh_config 5
@@ -430,6 +434,8 @@ The allow/deny directives are processed in the following order:
.Cm DenyGroups ,
and finally
.Cm AllowGroups .
+All of the specified user and group tests must succeed, before user
+is allowed to log in.
.Pp
See PATTERNS in
.Xr ssh_config 5
@@ -449,6 +455,8 @@ The allow/deny directives are processed in the following order:
.Cm DenyGroups ,
and finally
.Cm AllowGroups .
+All of the specified user and group tests must succeed, before user
+is allowed to log in.
.Pp
See PATTERNS in
.Xr ssh_config 5

View file

@ -0,0 +1,183 @@
diff -up openssh-7.4p1/monitor_wrap.c.audit-race openssh-7.4p1/monitor_wrap.c
--- openssh-7.4p1/monitor_wrap.c.audit-race 2017-02-09 14:07:56.870994116 +0100
+++ openssh-7.4p1/monitor_wrap.c 2017-02-09 14:07:56.874994112 +0100
@@ -1107,4 +1107,48 @@ mm_audit_destroy_sensitive_data(const ch
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_SERVER_KEY_FREE, &m);
buffer_free(&m);
}
+
+int mm_forward_audit_messages(int fdin)
+{
+ u_char buf[4];
+ u_int blen, msg_len;
+ Buffer m;
+ int ret = 0;
+
+ debug3("%s: entering", __func__);
+ buffer_init(&m);
+ do {
+ blen = atomicio(read, fdin, buf, sizeof(buf));
+ if (blen == 0) /* closed pipe */
+ break;
+ if (blen != sizeof(buf)) {
+ error("%s: Failed to read the buffer from child", __func__);
+ ret = -1;
+ break;
+ }
+
+ msg_len = get_u32(buf);
+ if (msg_len > 256 * 1024)
+ fatal("%s: read: bad msg_len %d", __func__, msg_len);
+ buffer_clear(&m);
+ buffer_append_space(&m, msg_len);
+ if (atomicio(read, fdin, buffer_ptr(&m), msg_len) != msg_len) {
+ error("%s: Failed to read the the buffer content from the child", __func__);
+ ret = -1;
+ break;
+ }
+ if (atomicio(vwrite, pmonitor->m_recvfd, buf, blen) != blen ||
+ atomicio(vwrite, pmonitor->m_recvfd, buffer_ptr(&m), msg_len) != msg_len) {
+ error("%s: Failed to write the message to the monitor", __func__);
+ ret = -1;
+ break;
+ }
+ } while (1);
+ buffer_free(&m);
+ return ret;
+}
+void mm_set_monitor_pipe(int fd)
+{
+ pmonitor->m_recvfd = fd;
+}
#endif /* SSH_AUDIT_EVENTS */
diff -up openssh-7.4p1/monitor_wrap.h.audit-race openssh-7.4p1/monitor_wrap.h
--- openssh-7.4p1/monitor_wrap.h.audit-race 2017-02-09 14:07:56.870994116 +0100
+++ openssh-7.4p1/monitor_wrap.h 2017-02-09 14:07:56.874994112 +0100
@@ -80,6 +80,8 @@ void mm_audit_unsupported_body(int);
void mm_audit_kex_body(int, char *, char *, char *, char *, pid_t, uid_t);
void mm_audit_session_key_free_body(int, pid_t, uid_t);
void mm_audit_destroy_sensitive_data(const char *, pid_t, uid_t);
+int mm_forward_audit_messages(int);
+void mm_set_monitor_pipe(int);
#endif
struct Session;
diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c
--- openssh-7.4p1/session.c.audit-race 2017-02-09 14:07:56.871994115 +0100
+++ openssh-7.4p1/session.c 2017-02-09 14:09:44.710893783 +0100
@@ -162,6 +162,10 @@ static Session *sessions = NULL;
login_cap_t *lc;
#endif
+#ifdef SSH_AUDIT_EVENTS
+int paudit[2];
+#endif
+
static int is_child = 0;
static int in_chroot = 0;
static int have_dev_log = 1;
@@ -289,6 +293,8 @@ xauth_valid_string(const char *s)
return 1;
}
+void child_destory_sensitive_data();
+
#define USE_PIPES 1
/*
* This is called to fork and execute a command when we have no tty. This
@@ -424,6 +430,8 @@ do_exec_no_pty(Session *s, const char *c
cray_init_job(s->pw); /* set up cray jid and tmpdir */
#endif
+ child_destory_sensitive_data();
+
/* Do processing for the child (exec command etc). */
do_child(s, command);
/* NOTREACHED */
@@ -547,6 +555,9 @@ do_exec_pty(Session *s, const char *comm
/* Close the extra descriptor for the pseudo tty. */
close(ttyfd);
+ /* Do this early, so we will not block large MOTDs */
+ child_destory_sensitive_data();
+
/* record login, etc. similar to login(1) */
#ifdef _UNICOS
cray_init_job(s->pw); /* set up cray jid and tmpdir */
@@ -717,6 +728,8 @@ do_exec(Session *s, const char *command)
}
if (s->command != NULL && s->ptyfd == -1)
s->command_handle = PRIVSEP(audit_run_command(s->command));
+ if (pipe(paudit) < 0)
+ fatal("pipe: %s", strerror(errno));
#endif
if (s->ttyfd != -1)
ret = do_exec_pty(s, command);
@@ -732,6 +745,20 @@ do_exec(Session *s, const char *command)
*/
buffer_clear(&loginmsg);
+#ifdef SSH_AUDIT_EVENTS
+ close(paudit[1]);
+ if (use_privsep && ret == 0) {
+ /*
+ * Read the audit messages from forked child and send them
+ * back to monitor. We don't want to communicate directly,
+ * because the messages might get mixed up.
+ * Continue after the pipe gets closed (all messages sent).
+ */
+ ret = mm_forward_audit_messages(paudit[0]);
+ }
+ close(paudit[0]);
+#endif /* SSH_AUDIT_EVENTS */
+
return ret;
}
@@ -1542,6 +1569,33 @@ child_close_fds(void)
endpwent();
}
+void
+child_destory_sensitive_data()
+{
+#ifdef SSH_AUDIT_EVENTS
+ int pparent = paudit[1];
+ close(paudit[0]);
+ /* Hack the monitor pipe to avoid race condition with parent */
+ if (use_privsep)
+ mm_set_monitor_pipe(pparent);
+#endif
+
+ /* remove hostkey from the child's memory */
+ destroy_sensitive_data(use_privsep);
+ /*
+ * We can audit this, because we hacked the pipe to direct the
+ * messages over postauth child. But this message requires answer
+ * which we can't do using one-way pipe.
+ */
+ packet_destroy_all(0, 1);
+
+#ifdef SSH_AUDIT_EVENTS
+ /* Notify parent that we are done */
+ close(pparent);
+#endif
+
+}
+
/*
* Performs common processing for the child, such as setting up the
* environment, closing extra file descriptors, setting the user and group
@@ -1558,12 +1612,6 @@ do_child(Session *s, const char *command
struct passwd *pw = s->pw;
int r = 0;
- /* remove hostkey from the child's memory */
- destroy_sensitive_data(1);
- /* Don't audit this - both us and the parent would be talking to the
- monitor over a single socket, with no synchronization. */
- packet_destroy_all(0, 1);
-
/* Force a password change */
if (s->authctxt->force_pwchange) {
do_setusercontext(pw);

292
openssh-6.6p1-entropy.patch Normal file
View file

@ -0,0 +1,292 @@
diff --git a/entropy.c b/entropy.c
index 2d483b3..b361a04 100644
--- a/entropy.c
+++ b/entropy.c
@@ -234,6 +234,9 @@ seed_rng(void)
memset(buf, '\0', sizeof(buf));
#endif /* OPENSSL_PRNG_ONLY */
+#ifdef __linux__
+ linux_seed();
+#endif /* __linux__ */
if (RAND_status() != 1)
fatal("PRNG is not seeded");
}
diff --git a/openbsd-compat/Makefile.in b/openbsd-compat/Makefile.in
index b912dbe..9206337 100644
--- a/openbsd-compat/Makefile.in
+++ b/openbsd-compat/Makefile.in
@@ -20,7 +20,7 @@ OPENBSD=base64.o basename.o bcrypt_pbkdf.o bindresvport.o blowfish.o daemon.o di
COMPAT=arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o getrrsetbyname-ldns.o bsd-err.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-setres_id.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xcrypt.o kludge-fd_set.o
-PORTS=port-aix.o port-irix.o port-linux.o port-linux-sshd.o port-solaris.o port-tun.o port-uw.o
+PORTS=port-aix.o port-irix.o port-linux.o port-linux-sshd.o port-linux-prng.o port-solaris.o port-tun.o port-uw.o
.c.o:
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
diff -up openssh-7.4p1/openbsd-compat/port-linux.h.entropy openssh-7.4p1/openbsd-compat/port-linux.h
--- openssh-7.4p1/openbsd-compat/port-linux.h.entropy 2016-12-23 18:34:27.747753563 +0100
+++ openssh-7.4p1/openbsd-compat/port-linux.h 2016-12-23 18:34:27.769753570 +0100
@@ -34,4 +34,6 @@ void oom_adjust_restore(void);
void oom_adjust_setup(void);
#endif
+void linux_seed(void);
+
#endif /* ! _PORT_LINUX_H */
diff --git a/openbsd-compat/port-linux-prng.c b/openbsd-compat/port-linux-prng.c
new file mode 100644
index 0000000..92a617c
--- /dev/null
+++ b/openbsd-compat/port-linux-prng.c
@@ -0,0 +1,59 @@
+/* $Id: port-linux.c,v 1.11.4.2 2011/02/04 00:43:08 djm Exp $ */
+
+/*
+ * Copyright (c) 2011 Jan F. Chadima <jchadima@redhat.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Linux-specific portability code - prng support
+ */
+
+#include "includes.h"
+
+#include <errno.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <openssl/rand.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 "key.h"
+#include "hostfile.h"
+#include "auth.h"
+
+void
+linux_seed(void)
+{
+ char *env = getenv("SSH_USE_STRONG_RNG");
+ char *random = "/dev/random";
+ size_t len, ienv, randlen = 14;
+
+ if (!env || !strcmp(env, "0"))
+ random = "/dev/urandom";
+ else if ((ienv = atoi(env)) > randlen)
+ randlen = ienv;
+
+ errno = 0;
+ if ((len = RAND_load_file(random, randlen)) != randlen) {
+ if (errno)
+ fatal ("cannot read from %s, %s", random, strerror(errno));
+ else
+ fatal ("EOF reading %s", random);
+ }
+}
diff --git a/ssh-add.0 b/ssh-add.0
index ba43fee..0b2629a 100644
--- a/ssh-add.0
+++ b/ssh-add.0
@@ -82,6 +82,16 @@ ENVIRONMENT
Identifies the path of a UNIX-domain socket used to communicate
with the agent.
+ SSH_USE_STRONG_RNG
+ The reseeding of the OpenSSL random generator is usually done
+ from /dev/urandom. If the SSH_USE_STRONG_RNG environment vari-
+ able is set to value other than 0 the OpenSSL random generator is
+ reseeded from /dev/random. The number of bytes read is defined
+ by the SSH_USE_STRONG_RNG value. Minimum is 14 bytes. This set-
+ ting is not recommended on the computers without the hardware
+ random generator because insufficient entropy causes the connec-
+ tion to be blocked until enough entropy is available.
+
FILES
~/.ssh/identity
Contains the protocol version 1 RSA authentication identity of
diff --git a/ssh-add.1 b/ssh-add.1
index 4812448..16305bf 100644
--- a/ssh-add.1
+++ b/ssh-add.1
@@ -161,6 +161,20 @@ to make this work.)
Identifies the path of a
.Ux Ns -domain
socket used to communicate with the agent.
+.It Ev SSH_USE_STRONG_RNG
+The reseeding of the OpenSSL random generator is usually done from
+.Cm /dev/urandom .
+If the
+.Cm SSH_USE_STRONG_RNG
+environment variable is set to value other than
+.Cm 0
+the OpenSSL random generator is reseeded from
+.Cm /dev/random .
+The number of bytes read is defined by the SSH_USE_STRONG_RNG value.
+Minimum is 14 bytes.
+This setting is not recommended on the computers without the hardware
+random generator because insufficient entropy causes the connection to
+be blocked until enough entropy is available.
.El
.Sh FILES
.Bl -tag -width Ds
diff --git a/ssh-agent.1 b/ssh-agent.1
index 281ecbd..1a9a635 100644
--- a/ssh-agent.1
+++ b/ssh-agent.1
@@ -201,6 +201,24 @@ sockets used to contain the connection to the authentication agent.
These sockets should only be readable by the owner.
The sockets should get automatically removed when the agent exits.
.El
+.Sh ENVIRONMENT
+.Bl -tag -width Ds -compact
+.Pp
+.It Pa SSH_USE_STRONG_RNG
+The reseeding of the OpenSSL random generator is usually done from
+.Cm /dev/urandom .
+If the
+.Cm SSH_USE_STRONG_RNG
+environment variable is set to value other than
+.Cm 0
+the OpenSSL random generator is reseeded from
+.Cm /dev/random .
+The number of bytes read is defined by the SSH_USE_STRONG_RNG value.
+Minimum is 14 bytes.
+This setting is not recommended on the computers without the hardware
+random generator because insufficient entropy causes the connection to
+be blocked until enough entropy is available.
+.El
.Sh SEE ALSO
.Xr ssh 1 ,
.Xr ssh-add 1 ,
diff --git a/ssh-keygen.1 b/ssh-keygen.1
index 12e00d4..1b51a4a 100644
--- a/ssh-keygen.1
+++ b/ssh-keygen.1
@@ -832,6 +832,24 @@ Contains Diffie-Hellman groups used for DH-GEX.
The file format is described in
.Xr moduli 5 .
.El
+.Sh ENVIRONMENT
+.Bl -tag -width Ds -compact
+.Pp
+.It Pa SSH_USE_STRONG_RNG
+The reseeding of the OpenSSL random generator is usually done from
+.Cm /dev/urandom .
+If the
+.Cm SSH_USE_STRONG_RNG
+environment variable is set to value other than
+.Cm 0
+the OpenSSL random generator is reseeded from
+.Cm /dev/random .
+The number of bytes read is defined by the SSH_USE_STRONG_RNG value.
+Minimum is 14 bytes.
+This setting is not recommended on the computers without the hardware
+random generator because insufficient entropy causes the connection to
+be blocked until enough entropy is available.
+.El
.Sh SEE ALSO
.Xr ssh 1 ,
.Xr ssh-add 1 ,
diff --git a/ssh-keysign.8 b/ssh-keysign.8
index 69d0829..02d79f8 100644
--- a/ssh-keysign.8
+++ b/ssh-keysign.8
@@ -80,6 +80,24 @@ must be set-uid root if host-based authentication is used.
If these files exist they are assumed to contain public certificate
information corresponding with the private keys above.
.El
+.Sh ENVIRONMENT
+.Bl -tag -width Ds -compact
+.Pp
+.It Pa SSH_USE_STRONG_RNG
+The reseeding of the OpenSSL random generator is usually done from
+.Cm /dev/urandom .
+If the
+.Cm SSH_USE_STRONG_RNG
+environment variable is set to value other than
+.Cm 0
+the OpenSSL random generator is reseeded from
+.Cm /dev/random .
+The number of bytes read is defined by the SSH_USE_STRONG_RNG value.
+Minimum is 14 bytes.
+This setting is not recommended on the computers without the hardware
+random generator because insufficient entropy causes the connection to
+be blocked until enough entropy is available.
+.El
.Sh SEE ALSO
.Xr ssh 1 ,
.Xr ssh-keygen 1 ,
diff --git a/ssh.1 b/ssh.1
index 929904b..f65e42f 100644
--- a/ssh.1
+++ b/ssh.1
@@ -1309,6 +1309,23 @@ For more information, see the
.Cm PermitUserEnvironment
option in
.Xr sshd_config 5 .
+.Sh ENVIRONMENT
+.Bl -tag -width Ds -compact
+.It Ev SSH_USE_STRONG_RNG
+The reseeding of the OpenSSL random generator is usually done from
+.Cm /dev/urandom .
+If the
+.Cm SSH_USE_STRONG_RNG
+environment variable is set to value other than
+.Cm 0
+the OpenSSL random generator is reseeded from
+.Cm /dev/random .
+The number of bytes read is defined by the SSH_USE_STRONG_RNG value.
+Minimum is 14 bytes.
+This setting is not recommended on the computers without the hardware
+random generator because insufficient entropy causes the connection to
+be blocked until enough entropy is available.
+.El
.Sh FILES
.Bl -tag -width Ds -compact
.It Pa ~/.rhosts
diff --git a/sshd.8 b/sshd.8
index c2c237f..058d37a 100644
--- a/sshd.8
+++ b/sshd.8
@@ -951,6 +951,24 @@ concurrently for different ports, this contains the process ID of the one
started last).
The content of this file is not sensitive; it can be world-readable.
.El
+.Sh ENVIRONMENT
+.Bl -tag -width Ds -compact
+.Pp
+.It Pa SSH_USE_STRONG_RNG
+The reseeding of the OpenSSL random generator is usually done from
+.Cm /dev/urandom .
+If the
+.Cm SSH_USE_STRONG_RNG
+environment variable is set to value other than
+.Cm 0
+the OpenSSL random generator is reseeded from
+.Cm /dev/random .
+The number of bytes read is defined by the SSH_USE_STRONG_RNG value.
+Minimum is 14 bytes.
+This setting is not recommended on the computers without the hardware
+random generator because insufficient entropy causes the connection to
+be blocked until enough entropy is available.
+.El
.Sh IPV6
IPv6 address can be used everywhere where IPv4 address. In all entries must be the IPv6 address enclosed in square brackets. Note: The square brackets are metacharacters for the shell and must be escaped in shell.
.Sh SEE ALSO

View file

@ -1,17 +1,5 @@
From f5e5ee321def2a3674600714ad98fd1ca9b2cff1 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:28 +0200
Subject: [PATCH 13/50] openssh-6.6p1-force_krb
---
gss-serv-krb5.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++-
session.c | 23 +++++++
ssh-gss.h | 4 ++
sshd.8 | 7 +++
4 files changed, 189 insertions(+), 1 deletion(-)
diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c
index 8d2b677f..14502c5a 100644
index 42de994..60de320 100644
--- a/gss-serv-krb5.c
+++ b/gss-serv-krb5.c
@@ -32,7 +32,9 @@
@ -23,16 +11,16 @@ index 8d2b677f..14502c5a 100644
+#include <unistd.h>
#include "xmalloc.h"
#include "sshkey.h"
@@ -44,6 +46,7 @@
#include "key.h"
@@ -40,6 +42,7 @@
#include "buffer.h"
#include "ssh-gss.h"
+extern Authctxt *the_authctxt;
extern ServerOptions options;
#ifdef HEIMDAL
@@ -55,6 +58,13 @@ extern ServerOptions options;
@@ -55,6 +59,13 @@ extern ServerOptions options;
# include <gssapi/gssapi_krb5.h>
#endif
@ -46,7 +34,7 @@ index 8d2b677f..14502c5a 100644
static krb5_context krb_context = NULL;
/* Initialise the krb5 library, for the stuff that GSSAPI won't do */
@@ -87,6 +97,7 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name)
@@ -87,6 +98,7 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name)
krb5_principal princ;
int retval;
const char *errmsg;
@ -54,7 +42,7 @@ index 8d2b677f..14502c5a 100644
if (ssh_gssapi_krb5_init() == 0)
return 0;
@@ -98,10 +109,22 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name)
@@ -98,10 +110,22 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name)
krb5_free_error_message(krb_context, errmsg);
return 0;
}
@ -78,7 +66,7 @@ index 8d2b677f..14502c5a 100644
} else
retval = 0;
@@ -109,6 +132,137 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name)
@@ -109,6 +133,135 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name)
return retval;
}
@ -109,14 +97,13 @@ index 8d2b677f..14502c5a 100644
+{
+ FILE *fp;
+ char file[MAXPATHLEN];
+ char *line = NULL;
+ char line[BUFSIZ];
+ char kuser[65]; /* match krb5_kuserok() */
+ struct stat st;
+ struct passwd *pw = the_authctxt->pw;
+ int found_principal = 0;
+ int ncommands = 0, allcommands = 0;
+ u_long linenum = 0;
+ size_t linesize = 0;
+ u_long linenum;
+
+ snprintf(file, sizeof(file), "%s/.k5users", pw->pw_dir);
+ /* If both .k5login and .k5users DNE, self-login is ok. */
@ -160,9 +147,9 @@ index 8d2b677f..14502c5a 100644
+ k5users_allowed_cmds = xcalloc(++ncommands,
+ sizeof(*k5users_allowed_cmds));
+
+ /* Check each line. ksu allows unlimited length lines. */
+ while (!allcommands && getline(&line, &linesize, fp) != -1) {
+ linenum++;
+ /* Check each line. ksu allows unlimited length lines. We don't. */
+ while (!allcommands && read_keyfile_line(fp, file, line, sizeof(line),
+ &linenum) != -1) {
+ char *token;
+
+ /* we parse just like ksu, even though we could do better */
@ -195,7 +182,6 @@ index 8d2b677f..14502c5a 100644
+ }
+ }
+ }
+ free(line);
+ if (k5users_allowed_cmds) {
+ /* terminate vector */
+ k5users_allowed_cmds[ncommands-1] = NULL;
@ -217,11 +203,11 @@ index 8d2b677f..14502c5a 100644
/* This writes out any forwarded credentials from the structure populated
* during userauth. Called after we have setuid to the user */
diff --git a/session.c b/session.c
index cbfbcee8..89b3a9cf 100644
index b5dc144..ba4589b 100644
--- a/session.c
+++ b/session.c
@@ -680,6 +680,29 @@ do_exec(struct ssh *ssh, Session *s, const char *command)
command = auth_opts->force_command;
@@ -806,6 +806,29 @@ do_exec(Session *s, const char *command)
command = forced_command;
forced = "(key-option)";
}
+#ifdef GSSAPI
@ -247,11 +233,11 @@ index cbfbcee8..89b3a9cf 100644
+#endif
+#endif
+
s->forced = 0;
if (forced != NULL) {
s->forced = 1;
if (IS_INTERNAL_SFTP(command)) {
s->is_subsystem = s->is_subsystem ?
diff --git a/ssh-gss.h b/ssh-gss.h
index 8ec45192..db34d77f 100644
index 0374c88..509109a 100644
--- a/ssh-gss.h
+++ b/ssh-gss.h
@@ -49,6 +49,10 @@
@ -266,10 +252,10 @@ index 8ec45192..db34d77f 100644
/* draft-ietf-secsh-gsskeyex-06 */
diff --git a/sshd.8 b/sshd.8
index 2aa73271..049d0a94 100644
index 058d37a..5c4f15b 100644
--- a/sshd.8
+++ b/sshd.8
@@ -286,6 +286,7 @@ Finally, the server and the client enter an authentication dialog.
@@ -327,6 +327,7 @@ Finally, the server and the client enter an authentication dialog.
The client tries to authenticate itself using
host-based authentication,
public key authentication,
@ -277,7 +263,7 @@ index 2aa73271..049d0a94 100644
challenge-response authentication,
or password authentication.
.Pp
@@ -874,6 +875,12 @@ This file is used in exactly the same way as
@@ -800,6 +801,12 @@ This file is used in exactly the same way as
but allows host-based authentication without permitting login with
rlogin/rsh.
.Pp
@ -290,6 +276,3 @@ index 2aa73271..049d0a94 100644
.It Pa ~/.ssh/
This directory is the default location for all user-specific configuration
and authentication information.
--
2.49.0

View file

@ -1,24 +1,11 @@
From 25540939422660b024b8832f67eab82267aa8df6 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:28 +0200
Subject: [PATCH 15/50] openssh-7.2p2-k5login_directory
---
auth-krb5.c | 16 ++++++++++++++++
auth.h | 2 ++
gss-serv-krb5.c | 21 ++++++++++++++++++++-
sshd.8 | 4 ++++
4 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/auth-krb5.c b/auth-krb5.c
index 77714e3d..74f56d47 100644
index 2b02a04..19b9364 100644
--- a/auth-krb5.c
+++ b/auth-krb5.c
@@ -465,5 +465,21 @@ ssh_krb5_cc_new_unique(krb5_context ctx, krb5_ccache *ccache, int *need_environm
return (krb5_cc_resolve(ctx, ccname, ccache));
}
@@ -375,6 +375,22 @@ cleanup:
return -1;
}
+
+/*
+ * Reads k5login_directory option from the krb5.conf
+ */
@ -34,26 +21,27 @@ index 77714e3d..74f56d47 100644
+ return profile_get_string(p, "libdefaults", "k5login_directory", NULL, NULL,
+ k5login_directory);
+}
#endif /* !HEIMDAL */
#endif /* KRB5 */
+
krb5_error_code
ssh_krb5_get_cctemplate(krb5_context ctx, char **ccname) {
profile_t p;
diff --git a/auth.h b/auth.h
index 10e88e11..39163035 100644
index f9d191c..c432d2f 100644
--- a/auth.h
+++ b/auth.h
@@ -247,6 +247,8 @@ int sys_auth_passwd(struct ssh *, const char *);
@@ -222,5 +222,7 @@ int sys_auth_passwd(Authctxt *, const char *);
#if defined(KRB5) && !defined(HEIMDAL)
krb5_error_code ssh_krb5_cc_new_unique(krb5_context, krb5_ccache *, int *);
#include <krb5.h>
krb5_error_code ssh_krb5_cc_gen(krb5_context, krb5_ccache *);
+krb5_error_code ssh_krb5_get_k5login_directory(krb5_context ctx,
+ char **k5login_directory);
#endif
#endif /* AUTH_H */
#endif
diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c
index df55512d..820f794c 100644
index a7c0c5f..df8cc9a 100644
--- a/gss-serv-krb5.c
+++ b/gss-serv-krb5.c
@@ -144,8 +144,27 @@ ssh_gssapi_k5login_exists()
@@ -244,8 +244,27 @@ ssh_gssapi_k5login_exists()
{
char file[MAXPATHLEN];
struct passwd *pw = the_authctxt->pw;
@ -61,7 +49,7 @@ index df55512d..820f794c 100644
+ int ret = 0;
+
+ ret = ssh_krb5_get_k5login_directory(krb_context, &k5login_directory);
+ debug3_f("k5login_directory = %s (rv=%d)", k5login_directory, ret);
+ debug3("%s: k5login_directory = %s (rv=%d)", __func__, k5login_directory, ret);
+ if (k5login_directory == NULL || ret != 0) {
+ /* If not set, the library will look for k5login
+ * files in the user's home directory, with the filename .k5login.
@ -76,17 +64,17 @@ index df55512d..820f794c 100644
+ k5login_directory[strlen(k5login_directory)-1] != '/' ? "/" : "",
+ pw->pw_name);
+ }
+ debug_f("Checking existence of file %s", file);
+ debug("%s: Checking existence of file %s", __func__, file);
- snprintf(file, sizeof(file), "%s/.k5login", pw->pw_dir);
return access(file, F_OK) == 0;
}
diff --git a/sshd.8 b/sshd.8
index 049d0a94..6784286d 100644
index 5c4f15b..135e290 100644
--- a/sshd.8
+++ b/sshd.8
@@ -880,6 +880,10 @@ rlogin/rsh.
@@ -806,6 +806,10 @@ rlogin/rsh.
These files enforce GSSAPI/Kerberos authentication access control.
Further details are described in
.Xr ksu 1 .
@ -97,6 +85,3 @@ index 049d0a94..6784286d 100644
.Pp
.It Pa ~/.ssh/
This directory is the default location for all user-specific configuration
--
2.49.0

View file

@ -1,26 +1,61 @@
From 5e35e18a419a5a66b6e1cb2b98beaaf4d9db0dc6 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:28 +0200
Subject: [PATCH 03/50] openssh-6.6p1-keycat
---
HOWTO.ssh-keycat | 12 ++
Makefile.in | 8 +-
configure.ac | 6 +
misc.c | 7 +
openbsd-compat/port-linux-sshd.c | 44 +++++-
openbsd-compat/port-linux.h | 2 +
platform.c | 2 +-
ssh-keycat.c | 241 +++++++++++++++++++++++++++++++
8 files changed, 314 insertions(+), 8 deletions(-)
create mode 100644 HOWTO.ssh-keycat
create mode 100644 ssh-keycat.c
diff --git a/HOWTO.ssh-keycat b/HOWTO.ssh-keycat
new file mode 100644
index 00000000..630ec628
--- /dev/null
+++ b/HOWTO.ssh-keycat
diff -up openssh-7.4p1/auth2-pubkey.c.keycat openssh-7.4p1/auth2-pubkey.c
--- openssh-7.4p1/auth2-pubkey.c.keycat 2017-02-08 14:32:33.015581448 +0100
+++ openssh-7.4p1/auth2-pubkey.c 2017-02-08 14:40:26.125216292 +0100
@@ -1043,6 +1043,14 @@ user_key_command_allowed2(struct passwd
xasprintf(&command, "%s %s", av[0], av[1]);
}
+#ifdef WITH_SELINUX
+ if (sshd_selinux_setup_env_variables() < 0) {
+ error ("failed to copy environment: %s",
+ strerror(errno));
+ _exit(127);
+ }
+#endif
+
if ((pid = subprocess("AuthorizedKeysCommand", pw, command,
ac, av, &f)) == 0)
goto out;
diff -up openssh-7.4p1/configure.ac.keycat openssh-7.4p1/configure.ac
--- openssh-7.4p1/configure.ac.keycat 2017-02-08 14:32:33.011581451 +0100
+++ openssh-7.4p1/configure.ac 2017-02-08 14:32:33.016581448 +0100
@@ -3129,6 +3129,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])
@@ -3139,6 +3140,7 @@ AC_ARG_WITH([pam],
;;
*)
SSHDLIBS="$SSHDLIBS -ldl"
+ KEYCATLIBS="$KEYCATLIBS -ldl"
;;
esac
fi
@@ -4255,6 +4257,7 @@ AC_ARG_WITH([selinux],
)
AC_SUBST([SSHLIBS])
AC_SUBST([SSHDLIBS])
+AC_SUBST([KEYCATLIBS])
# Check whether user wants Kerberos 5 support
KRB5_MSG="no"
@@ -5206,6 +5209,9 @@ fi
if test ! -z "${SSHLIBS}"; then
echo " +for ssh: ${SSHLIBS}"
fi
+if test ! -z "${KEYCATLIBS}"; then
+echo " +for ssh-keycat: ${KEYCATLIBS}"
+fi
echo ""
diff -up openssh-7.4p1/HOWTO.ssh-keycat.keycat openssh-7.4p1/HOWTO.ssh-keycat
--- openssh-7.4p1/HOWTO.ssh-keycat.keycat 2017-02-08 14:32:33.014581449 +0100
+++ openssh-7.4p1/HOWTO.ssh-keycat 2017-02-08 14:32:33.014581449 +0100
@@ -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
@ -34,116 +69,72 @@ index 00000000..630ec628
+ PubkeyAuthentication yes
+
+
diff --git a/Makefile.in b/Makefile.in
index 4617cebc..438efc51 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -23,6 +23,7 @@ SSH_PROGRAM=@bindir@/ssh
ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass
SFTP_SERVER=$(libexecdir)/sftp-server
diff -up openssh-7.4p1/Makefile.in.keycat openssh-7.4p1/Makefile.in
--- openssh-7.4p1/Makefile.in.keycat 2017-02-08 14:32:33.012581451 +0100
+++ openssh-7.4p1/Makefile.in 2017-02-08 14:38:28.839306815 +0100
@@ -27,6 +27,7 @@ SFTP_SERVER=$(libexecdir)/sftp-server
SSH_KEYSIGN=$(libexecdir)/ssh-keysign
SSH_LDAP_HELPER=$(libexecdir)/ssh-ldap-helper
SSH_LDAP_WRAPPER=$(libexecdir)/ssh-ldap-wrapper
+SSH_KEYCAT=$(libexecdir)/ssh-keycat
SSHD_SESSION=$(libexecdir)/sshd-session
SSHD_AUTH=$(libexecdir)/sshd-auth
SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
@@ -57,6 +58,7 @@ CHANNELLIBS=@CHANNELLIBS@
K5LIBS=@K5LIBS@
PRIVSEP_PATH=@PRIVSEP_PATH@
SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@
@@ -51,6 +52,7 @@ K5LIBS=@K5LIBS@
GSSLIBS=@GSSLIBS@
SSHLIBS=@SSHLIBS@
SSHDLIBS=@SSHDLIBS@
+KEYCATLIBS=@KEYCATLIBS@
LIBEDIT=@LIBEDIT@
LIBFIDO2=@LIBFIDO2@
LIBWTMPDB=@LIBWTMPDB@
@@ -74,7 +76,7 @@ MKDIR_P=@MKDIR_P@
AR=@AR@
AWK=@AWK@
@@ -65,7 +67,7 @@ EXEEXT=@EXEEXT@
MANFMT=@MANFMT@
INSTALL_SSH_LDAP_HELPER=@INSTALL_SSH_LDAP_HELPER@
.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-ldap-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-ldap-helper$(EXEEXT) ssh-keycat$(EXEEXT)
-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) sshd-session$(EXEEXT) sshd-auth$(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) $(SK_STANDALONE)
+TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) sshd-session$(EXEEXT) sshd-auth$(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) $(SK_STANDALONE)
LIBOPENSSH_OBJS=\
ssh_api.o \
@@ -190,6 +192,9 @@ ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT)
ssh-ldap-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o
$(LD) -o $@ ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat -lfipscheck $(LIBS)
XMSS_OBJS=\
ssh-xmss.o \
@@ -260,6 +262,9 @@ ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a $(P11HELPER_OBJS)
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-keycat$(EXEEXT): $(LIBCOMPAT) $(SSHDOBJS) libssh.a ssh-keycat.o
+ $(LD) -o $@ ssh-keycat.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(KEYCATLIBS) $(SSHLIBS)
+
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYSCAN_OBJS)
$(LD) -o $@ $(SSHKEYSCAN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) $(CHANNELLIBS)
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o
$(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
@@ -447,6 +452,7 @@ install-files:
$(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) ssh-sk-helper$(EXEEXT) $(DESTDIR)$(SSH_SK_HELPER)$(EXEEXT)
@@ -332,6 +337,7 @@ install-files:
$(INSTALL) -m 0700 $(STRIP_OPT) ssh-ldap-helper $(DESTDIR)$(SSH_LDAP_HELPER) ; \
$(INSTALL) -m 0700 ssh-ldap-wrapper $(DESTDIR)$(SSH_LDAP_WRAPPER) ; \
fi
+ $(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 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
diff --git a/configure.ac b/configure.ac
index ee77a048..d546788c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3566,6 +3566,7 @@ AC_ARG_WITH([pam],
PAM_MSG="yes"
diff -up openssh-7.4p1/openbsd-compat/port-linux.h.keycat openssh-7.4p1/openbsd-compat/port-linux.h
--- openssh-7.4p1/openbsd-compat/port-linux.h.keycat 2017-02-08 14:32:33.009581453 +0100
+++ openssh-7.4p1/openbsd-compat/port-linux.h 2017-02-08 14:32:33.015581448 +0100
@@ -23,8 +23,10 @@ void ssh_selinux_setup_pty(char *, const
void ssh_selinux_change_context(const char *);
void ssh_selinux_setfscreatecon(const char *);
SSHDLIBS="$SSHDLIBS -lpam"
+ KEYCATLIBS="$KEYCATLIBS -lpam"
AC_DEFINE([USE_PAM], [1],
[Define if you want to enable PAM support])
+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
@@ -3576,6 +3577,7 @@ AC_ARG_WITH([pam],
;;
*)
SSHDLIBS="$SSHDLIBS -ldl"
+ KEYCATLIBS="$KEYCATLIBS -ldl"
;;
esac
fi
@@ -4801,6 +4803,7 @@ AC_ARG_WITH([selinux],
fi ]
)
AC_SUBST([SSHDLIBS])
+AC_SUBST([KEYCATLIBS])
# Check whether user wants Kerberos 5 support
KRB5_MSG="no"
@@ -5812,6 +5815,9 @@ fi
if test ! -z "${SSHDLIBS}"; then
echo " +for sshd: ${SSHDLIBS}"
fi
+if test ! -z "${KEYCATLIBS}"; then
+echo " +for ssh-keycat: ${KEYCATLIBS}"
+fi
echo ""
diff --git a/misc.c b/misc.c
index c932f9bb..1e31acc9 100644
--- a/misc.c
+++ b/misc.c
@@ -2897,6 +2897,13 @@ subprocess(const char *tag, const char *command,
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
diff --git a/openbsd-compat/port-linux-sshd.c b/openbsd-compat/port-linux-sshd.c
index dfafc622..8c5fc1fe 100644
--- a/openbsd-compat/port-linux-sshd.c
+++ b/openbsd-compat/port-linux-sshd.c
@@ -52,6 +52,20 @@ extern ServerOptions options;
extern Authctxt *the_authctxt;
#ifdef LINUX_OOM_ADJUST
diff -up openssh-7.4p1/openbsd-compat/port-linux-sshd.c.keycat openssh-7.4p1/openbsd-compat/port-linux-sshd.c
--- openssh-7.4p1/openbsd-compat/port-linux-sshd.c.keycat 2017-02-08 14:32:33.008581454 +0100
+++ openssh-7.4p1/openbsd-compat/port-linux-sshd.c 2017-02-08 14:32:33.015581448 +0100
@@ -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
@ -162,7 +153,7 @@ index dfafc622..8c5fc1fe 100644
/* Send audit message */
static int
sshd_selinux_send_audit_message(int success, security_context_t default_context,
@@ -317,7 +331,7 @@ sshd_selinux_getctxbyname(char *pwname,
@@ -307,7 +321,7 @@ sshd_selinux_getctxbyname(char *pwname,
/* Setup environment variables for pam_selinux */
static int
@ -171,14 +162,14 @@ index dfafc622..8c5fc1fe 100644
{
const char *reqlvl;
char *role;
@@ -328,16 +342,16 @@ sshd_selinux_setup_pam_variables(void)
@@ -318,16 +332,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) {
if (inetd_flag && !rexeced_flag) {
use_current = "1";
} else {
use_current = "";
@ -191,7 +182,7 @@ index dfafc622..8c5fc1fe 100644
if (role != NULL)
free(role);
@@ -345,6 +359,24 @@ sshd_selinux_setup_pam_variables(void)
@@ -335,6 +349,24 @@ sshd_selinux_setup_pam_variables(void)
return rv;
}
@ -216,7 +207,7 @@ index dfafc622..8c5fc1fe 100644
/* Set the execution context to the default for the specified user */
void
sshd_selinux_setup_exec_context(char *pwname)
@@ -353,7 +385,7 @@ sshd_selinux_setup_exec_context(char *pwname)
@@ -343,7 +375,7 @@ sshd_selinux_setup_exec_context(char *pw
int r = 0;
security_context_t default_ctx = NULL;
@ -225,7 +216,7 @@ index dfafc622..8c5fc1fe 100644
return;
if (options.use_pam) {
@@ -420,7 +452,7 @@ sshd_selinux_copy_context(void)
@@ -414,7 +446,7 @@ sshd_selinux_copy_context(void)
{
security_context_t *ctx;
@ -234,26 +225,10 @@ index dfafc622..8c5fc1fe 100644
return;
if (getexeccon((security_context_t *)&ctx) != 0) {
diff --git a/openbsd-compat/port-linux.h b/openbsd-compat/port-linux.h
index 498d242a..1b745a76 100644
--- a/openbsd-compat/port-linux.h
+++ b/openbsd-compat/port-linux.h
@@ -23,8 +23,10 @@ void ssh_selinux_setup_pty(char *, const char *);
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
diff --git a/platform.c b/platform.c
index 1bfb4bea..0d12f311 100644
--- a/platform.c
+++ b/platform.c
@@ -55,7 +55,7 @@ platform_setusercontext(struct passwd *pw)
diff -up openssh-7.4p1/platform.c.keycat openssh-7.4p1/platform.c
--- openssh-7.4p1/platform.c.keycat 2017-02-08 14:32:33.007581455 +0100
+++ openssh-7.4p1/platform.c 2017-02-08 14:32:33.015581448 +0100
@@ -99,7 +99,7 @@ platform_setusercontext(struct passwd *p
{
#ifdef WITH_SELINUX
/* Cache selinux status for later use */
@ -262,12 +237,10 @@ index 1bfb4bea..0d12f311 100644
#endif
#ifdef USE_SOLARIS_PROJECTS
diff --git a/ssh-keycat.c b/ssh-keycat.c
new file mode 100644
index 00000000..5678be07
--- /dev/null
+++ b/ssh-keycat.c
@@ -0,0 +1,241 @@
diff -up openssh-7.4p1/ssh-keycat.c.keycat openssh-7.4p1/ssh-keycat.c
--- openssh-7.4p1/ssh-keycat.c.keycat 2017-02-08 14:32:33.015581448 +0100
+++ openssh-7.4p1/ssh-keycat.c 2017-02-08 14:32:33.015581448 +0100
@@ -0,0 +1,238 @@
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
@ -317,9 +290,6 @@ index 00000000..5678be07
+#include <pwd.h>
+#include <fcntl.h>
+#include <unistd.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#include <security/pam_appl.h>
+
@ -509,6 +479,3 @@ index 00000000..5678be07
+ }
+ return ev;
+}
--
2.49.0

View file

@ -0,0 +1,25 @@
diff -up openssh-6.6p1/authfile.c.keyperm openssh-6.6p1/authfile.c
--- openssh-6.6p1/authfile.c.keyperm 2014-02-04 01:20:15.000000000 +0100
+++ openssh-6.6p1/authfile.c 2014-05-05 15:20:43.075246776 +0200
@@ -54,6 +54,7 @@
#include <errno.h>
#include <fcntl.h>
+#include <grp.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
@@ -979,6 +980,13 @@ key_perm_ok(int fd, const char *filename
#ifdef HAVE_CYGWIN
if (check_ntsec(filename))
#endif
+ if (st.st_mode & 040) {
+ struct group *gr;
+
+ if ((gr = getgrnam("ssh_keys")) && (st.st_gid == gr->gr_gid))
+ st.st_mode &= ~040;
+ }
+
if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0) {
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @");

2719
openssh-6.6p1-ldap.patch Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,28 @@
diff --git a/sshd.c b/sshd.c
index a7b8b6a..24ab272 100644
--- a/sshd.c
+++ b/sshd.c
@@ -1620,6 +1620,10 @@ main(int ac, char **av)
parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name,
&cfg, NULL);
+ /* 'UsePAM no' is not supported in Red Hat Enterprise Linux */
+ if (! options.use_pam)
+ logit("WARNING: 'UsePAM no' is not supported in Red Hat Enterprise Linux and may cause several problems.");
+
seed_rng();
/* Fill in default values for those options not explicitly set. */
diff --git a/sshd_config b/sshd_config
index 36cb27a..c1b7c03 100644
--- a/sshd_config
+++ b/sshd_config
@@ -101,6 +101,8 @@ GSSAPICleanupCredentials no
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
+# WARNING: 'UsePAM no' is not supported in Red Hat Enterprise Linux and may cause several
+# problems.
UsePAM yes
#AllowAgentForwarding yes

View file

@ -0,0 +1,25 @@
diff -up openssh-7.4p1/servconf.c.memory-problems openssh-7.4p1/servconf.c
--- openssh-7.4p1/servconf.c.memory-problems 2017-02-09 10:41:42.483123417 +0100
+++ openssh-7.4p1/servconf.c 2017-02-09 10:42:16.392102462 +0100
@@ -2006,6 +2006,8 @@ copy_set_server_options(ServerOptions *d
dst->n = src->n; \
} while (0)
+ u_int i;
+
M_CP_INTOPT(password_authentication);
M_CP_INTOPT(gss_authentication);
M_CP_INTOPT(pubkey_authentication);
@@ -2058,8 +2060,10 @@ copy_set_server_options(ServerOptions *d
} while(0)
#define M_CP_STRARRAYOPT(n, num_n) do {\
if (src->num_n != 0) { \
+ for (i = 0; i < dst->num_n; i++) \
+ free(dst->n[i]); \
for (dst->num_n = 0; dst->num_n < src->num_n; dst->num_n++) \
- dst->n[dst->num_n] = xstrdup(src->n[dst->num_n]); \
+ dst->n[dst->num_n] = src->n[dst->num_n]; \
} \
} while(0)
diff -up openssh-7.4p1/sshd.c.memory-problems openssh-7.4p1/sshd.c

View file

@ -0,0 +1,108 @@
diff --git a/openbsd-compat/port-linux-sshd.c b/openbsd-compat/port-linux-sshd.c
index c18524e..d04f4ed 100644
--- a/openbsd-compat/port-linux-sshd.c
+++ b/openbsd-compat/port-linux-sshd.c
@@ -409,6 +409,25 @@ sshd_selinux_setup_exec_context(char *pwname)
debug3("%s: done", __func__);
}
+void
+sshd_selinux_copy_context(void)
+{
+ security_context_t *ctx;
+
+ if (!ssh_selinux_enabled())
+ return;
+
+ if (getexeccon((security_context_t *)&ctx) != 0) {
+ logit("%s: getcon failed with %s", __func__, strerror (errno));
+ return;
+ }
+ if (ctx != NULL) {
+ if (setcon(ctx) != 0)
+ logit("%s: setcon failed with %s", __func__, strerror (errno));
+ freecon(ctx);
+ }
+}
+
#endif
#endif
diff --git a/openbsd-compat/port-linux.h b/openbsd-compat/port-linux.h
index 8ef6cc4..b18893c 100644
--- a/openbsd-compat/port-linux.h
+++ b/openbsd-compat/port-linux.h
@@ -25,6 +25,7 @@ void ssh_selinux_setup_pty(char *, const char *);
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
diff --git a/session.c b/session.c
index 2bcf818..b5dc144 100644
--- a/session.c
+++ b/session.c
@@ -1538,6 +1538,9 @@ do_setusercontext(struct passwd *pw)
pw->pw_uid);
chroot_path = percent_expand(tmp, "h", pw->pw_dir,
"u", pw->pw_name, (char *)NULL);
+#ifdef WITH_SELINUX
+ sshd_selinux_copy_context();
+#endif
safely_chroot(chroot_path, pw->pw_uid);
free(tmp);
free(chroot_path);
@@ -1565,6 +1568,12 @@ do_setusercontext(struct passwd *pw)
/* Permanently switch to the desired uid. */
permanently_set_uid(pw);
#endif
+
+#ifdef WITH_SELINUX
+ if (options.chroot_directory == NULL ||
+ strcasecmp(options.chroot_directory, "none") == 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");
@@ -1826,9 +1835,6 @@ do_child(Session *s, const char *command)
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));
}
diff --git a/sshd.c b/sshd.c
index 07f9926..a97f8b7 100644
--- a/sshd.c
+++ b/sshd.c
@@ -632,6 +632,10 @@ privsep_preauth_child(void)
/* Demote the private keys to public keys. */
demote_sensitive_data();
+#ifdef WITH_SELINUX
+ ssh_selinux_change_context("sshd_net_t");
+#endif
+
/* Demote the child */
if (getuid() == 0 || geteuid() == 0) {
/* Change our root directory */
@@ -768,6 +772,13 @@ privsep_postauth(Authctxt *authctxt)
do_setusercontext(authctxt->pw);
skip:
+#ifdef WITH_SELINUX
+ /* switch SELinux content for root too */
+ if (authctxt->pw->pw_uid == 0) {
+ sshd_selinux_copy_context();
+ }
+#endif
+
/* It is safe now to apply the key state */
monitor_apply_keystate(pmonitor);

131
openssh-6.6p1-redhat.patch Normal file
View file

@ -0,0 +1,131 @@
diff -up openssh-7.4p1/ssh_config.redhat openssh-7.4p1/ssh_config
--- openssh-7.4p1/ssh_config.redhat 2017-02-08 15:22:30.811307915 +0100
+++ openssh-7.4p1/ssh_config 2017-02-08 15:22:30.812307915 +0100
@@ -52,3 +52,15 @@
# Uncomment this if you want to use .local domain
# Host *.local
# CheckHostIP no
+
+Host *
+ GSSAPIAuthentication yes
+# If this option is set to yes then remote X11 clients will have full access
+# to the original X11 display. As virtually no X11 client supports the untrusted
+# mode correctly we set this to yes.
+ ForwardX11Trusted yes
+# Send locale-related environment variables
+ SendEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
+ SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
+ SendEnv LC_IDENTIFICATION LC_ALL LANGUAGE
+ SendEnv XMODIFIERS
diff -up openssh-7.4p1/sshd_config.0.redhat openssh-7.4p1/sshd_config.0
--- openssh-7.4p1/sshd_config.0.redhat 2016-12-19 06:21:22.000000000 +0100
+++ openssh-7.4p1/sshd_config.0 2017-02-08 15:22:30.813307914 +0100
@@ -837,9 +837,9 @@ DESCRIPTION
SyslogFacility
Gives the facility code that is used when logging messages from
- sshd(8). The possible values are: DAEMON, USER, AUTH, LOCAL0,
- LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The
- default is AUTH.
+ sshd(8). The possible values are: DAEMON, USER, AUTH, AUTHPRIV,
+ LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
+ The default is AUTH.
TCPKeepAlive
Specifies whether the system should send TCP keepalive messages
diff -up openssh-7.4p1/sshd_config.5.redhat openssh-7.4p1/sshd_config.5
--- openssh-7.4p1/sshd_config.5.redhat 2016-12-19 05:59:41.000000000 +0100
+++ openssh-7.4p1/sshd_config.5 2017-02-08 15:22:30.813307914 +0100
@@ -1393,7 +1393,7 @@ By default no subsystems are defined.
.It Cm SyslogFacility
Gives the facility code that is used when logging messages from
.Xr sshd 8 .
-The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2,
+The possible values are: DAEMON, USER, AUTH, AUTHPRIV, LOCAL0, LOCAL1, LOCAL2,
LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
The default is AUTH.
.It Cm TCPKeepAlive
diff -up openssh-7.4p1/sshd_config.redhat openssh-7.4p1/sshd_config
--- openssh-7.4p1/sshd_config.redhat 2016-12-19 05:59:41.000000000 +0100
+++ openssh-7.4p1/sshd_config 2017-02-08 15:33:24.705736576 +0100
@@ -10,21 +10,26 @@
# possible, but leave them commented. Uncommented options override the
# default value.
+# If you want to change the port on a SELinux system, you have to tell
+# SELinux about this change.
+# semanage port -a -t ssh_port_t -p tcp #PORTNUMBER
+#
#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
-#HostKey /etc/ssh/ssh_host_rsa_key
+HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_dsa_key
-#HostKey /etc/ssh/ssh_host_ecdsa_key
-#HostKey /etc/ssh/ssh_host_ed25519_key
+HostKey /etc/ssh/ssh_host_ecdsa_key
+HostKey /etc/ssh/ssh_host_ed25519_key
# Ciphers and keying
#RekeyLimit default none
# Logging
#SyslogFacility AUTH
+SyslogFacility AUTHPRIV
#LogLevel INFO
# Authentication:
@@ -57,9 +62,11 @@ AuthorizedKeysFile .ssh/authorized_keys
# To disable tunneled clear text passwords, change to no here!
#PasswordAuthentication yes
#PermitEmptyPasswords no
+PasswordAuthentication yes
# Change to no to disable s/key passwords
#ChallengeResponseAuthentication yes
+ChallengeResponseAuthentication no
# Kerberos options
#KerberosAuthentication no
@@ -68,8 +75,8 @@ AuthorizedKeysFile .ssh/authorized_keys
#KerberosGetAFSToken no
# GSSAPI options
-#GSSAPIAuthentication no
-#GSSAPICleanupCredentials yes
+GSSAPIAuthentication yes
+GSSAPICleanupCredentials no
# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
@@ -80,12 +87,12 @@ AuthorizedKeysFile .ssh/authorized_keys
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
-#UsePAM no
+UsePAM yes
#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
-#X11Forwarding no
+X11Forwarding yes
#X11DisplayOffset 10
#X11UseLocalhost yes
#PermitTTY yes
@@ -108,6 +115,12 @@ AuthorizedKeysFile .ssh/authorized_keys
# no default banner path
#Banner none
+# Accept locale-related environment variables
+AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
+AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
+AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
+AcceptEnv XMODIFIERS
+
# override default of no subsystems
Subsystem sftp /usr/libexec/sftp-server

View file

@ -1,17 +1,21 @@
From 9bb31b63142adaaf949e20c2d86c97f9b787217b Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:28 +0200
Subject: [PATCH 24/50] openssh-7.2p2-s390-closefrom
Zseries only: Leave the hardware filedescriptors open.
All filedescriptors above 2 are getting closed when a new
sshd process to handle a new client connection is
spawned. As the process also chroot into an empty filesystem
without any device nodes, there is no chance to reopen the
files. This patch filters out the reqired fds in the
closefrom function so these are skipped in the close loop.
Author: Harald Freudenberger <freude@de.ibm.com>
---
openbsd-compat/bsd-closefrom.c | 26 ++++++++++++++++++++++++++
openbsd-compat/bsd-closefrom.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/openbsd-compat/bsd-closefrom.c b/openbsd-compat/bsd-closefrom.c
index 49a4f35f..f6112458 100644
--- a/openbsd-compat/bsd-closefrom.c
+++ b/openbsd-compat/bsd-closefrom.c
@@ -140,7 +140,33 @@ closefrom(int lowfd)
@@ -82,7 +82,33 @@ closefrom(int lowfd)
fd = strtol(dent->d_name, &endp, 10);
if (dent->d_name != endp && *endp == '\0' &&
fd >= 0 && fd < INT_MAX && fd >= lowfd && fd != dirfd(dirp))
@ -44,7 +48,5 @@ index 49a4f35f..f6112458 100644
+#endif
}
(void) closedir(dirp);
return;
--
2.49.0
} else

View file

@ -1,43 +1,29 @@
From 34b196198018059bed294fa7a08e70606b4cbc36 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu, 15 May 2025 13:43:28 +0200
Subject: [PATCH 23/50] openssh-6.7p1-sftp-force-permission
---
sftp-server.8 | 7 +++++++
sftp-server.c | 24 ++++++++++++++++++++++--
2 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/sftp-server.8 b/sftp-server.8
index 5311bf92..5e6e3aa4 100644
--- a/sftp-server.8
+++ b/sftp-server.8
diff -up openssh-7.4p1/sftp-server.8.sftp-force-mode openssh-7.4p1/sftp-server.8
--- openssh-7.4p1/sftp-server.8.sftp-force-mode 2016-12-19 05:59:41.000000000 +0100
+++ openssh-7.4p1/sftp-server.8 2017-02-09 10:35:41.926475399 +0100
@@ -38,6 +38,7 @@
.Op Fl P Ar denied_requests
.Op Fl p Ar allowed_requests
.Op Fl P Ar blacklisted_requests
.Op Fl p Ar whitelisted_requests
.Op Fl u Ar umask
+.Op Fl m Ar force_file_perms
.Ek
.Nm
.Fl Q Ar protocol_feature
@@ -138,6 +139,12 @@ Sets an explicit
@@ -138,6 +139,10 @@ Sets an explicit
.Xr umask 2
to be applied to newly-created files and directories, instead of the
user's default mask.
+.It Fl m Ar force_file_perms
+Sets explicit file permissions to be applied to newly-created files instead
+of the default or client requested mode. Numeric values include:
+777, 755, 750, 666, 644, 640, etc. Using both -m and -u switches makes the
+umask (-u) effective only for newly created directories and explicit mode (-m)
+for newly created files.
+777, 755, 750, 666, 644, 640, etc. Option -u is ineffective if -m is set.
.El
.Pp
On some systems,
diff --git a/sftp-server.c b/sftp-server.c
index 4985da38..6ed1c27f 100644
--- a/sftp-server.c
+++ b/sftp-server.c
@@ -76,6 +76,10 @@ struct sshbuf *oqueue;
diff -up openssh-7.4p1/sftp-server.c.sftp-force-mode openssh-7.4p1/sftp-server.c
--- openssh-7.4p1/sftp-server.c.sftp-force-mode 2017-02-09 10:22:36.498019921 +0100
+++ openssh-7.4p1/sftp-server.c 2017-02-09 10:35:07.190520959 +0100
@@ -65,6 +65,10 @@ struct sshbuf *oqueue;
/* Version of client */
static u_int version;
@ -48,7 +34,7 @@ index 4985da38..6ed1c27f 100644
/* SSH2_FXP_INIT received */
static int init_done;
@@ -745,6 +749,7 @@ process_open(u_int32_t id)
@@ -679,6 +683,7 @@ process_open(u_int32_t id)
Attrib a;
char *name;
int r, handle, fd, flags, mode, status = SSH2_FX_FAILURE;
@ -56,18 +42,18 @@ index 4985da38..6ed1c27f 100644
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
(r = sshbuf_get_u32(iqueue, &pflags)) != 0 || /* portable flags */
@@ -754,6 +759,10 @@ process_open(u_int32_t id)
@@ -688,6 +693,10 @@ process_open(u_int32_t id)
debug3("request %u: open flags %d", id, pflags);
flags = flags_from_portable(pflags);
mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a.perm : 0666;
+ if (permforce == 1) { /* Force perm if -m is set */
+ mode = permforcemode;
+ old_umask = umask(0); /* so umask does not interfere */
+ }
+ }
logit("open \"%s\" flags %s mode 0%o",
name, string_from_portable(pflags), mode);
if (readonly &&
@@ -775,6 +784,8 @@ process_open(u_int32_t id)
@@ -709,6 +718,8 @@ process_open(u_int32_t id)
}
}
}
@ -76,16 +62,16 @@ index 4985da38..6ed1c27f 100644
if (status != SSH2_FX_OK)
send_status(id, status);
free(name);
@@ -1894,7 +1905,7 @@ sftp_server_usage(void)
@@ -1490,7 +1501,7 @@ sftp_server_usage(void)
fprintf(stderr,
"usage: %s [-ehR] [-d start_directory] [-f log_facility] "
"[-l log_level]\n\t[-P denied_requests] "
- "[-p allowed_requests] [-u umask]\n"
+ "[-p allowed_requests] [-u umask] [-m force_file_perms]\n"
"[-l log_level]\n\t[-P blacklisted_requests] "
- "[-p whitelisted_requests] [-u umask]\n"
+ "[-p whitelisted_requests] [-u umask] [-m force_file_perms]\n"
" %s -Q protocol_feature\n",
__progname, __progname);
exit(1);
@@ -1918,7 +1929,7 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw, int reset_handle
@@ -1516,7 +1527,7 @@ sftp_server_main(int argc, char **argv,
pw = pwcopy(user_pw);
while (!skipargs && (ch = getopt(argc, argv,
@ -94,7 +80,7 @@ index 4985da38..6ed1c27f 100644
switch (ch) {
case 'Q':
if (strcasecmp(optarg, "requests") != 0) {
@@ -1980,6 +1991,15 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw, int reset_handle
@@ -1576,6 +1587,15 @@ sftp_server_main(int argc, char **argv,
fatal("Invalid umask \"%s\"", optarg);
(void)umask((mode_t)mask);
break;
@ -110,6 +96,3 @@ index 4985da38..6ed1c27f 100644
case 'h':
default:
sftp_server_usage();
--
2.49.0

View file

@ -0,0 +1,98 @@
commit 0e22b79bfde45a7cf7a2e51a68ec11c4285f3b31
Author: Jakub Jelen <jjelen@redhat.com>
Date: Mon Nov 21 15:04:06 2016 +0100
systemd stuff
diff --git a/configure.ac b/configure.ac
index 2ffc369..162ce92 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4265,6 +4265,30 @@ AC_ARG_WITH([kerberos5],
AC_SUBST([GSSLIBS])
AC_SUBST([K5LIBS])
+# Check whether user wants systemd support
+SYSTEMD_MSG="no"
+AC_ARG_WITH(systemd,
+ [ --with-systemd Enable systemd support],
+ [ if test "x$withval" != "xno" ; then
+ AC_PATH_TOOL([PKGCONFIG], [pkg-config], [no])
+ if test "$PKGCONFIG" != "no"; then
+ AC_MSG_CHECKING([for libsystemd])
+ if $PKGCONFIG --exists libsystemd; then
+ SYSTEMD_CFLAGS=`$PKGCONFIG --cflags libsystemd`
+ SYSTEMD_LIBS=`$PKGCONFIG --libs libsystemd`
+ CPPFLAGS="$CPPFLAGS $SYSTEMD_CFLAGS"
+ SSHDLIBS="$SSHDLIBS $SYSTEMD_LIBS"
+ AC_MSG_RESULT([yes])
+ AC_DEFINE(HAVE_SYSTEMD, 1, [Define if you want systemd support.])
+ SYSTEMD_MSG="yes"
+ else
+ AC_MSG_RESULT([no])
+ fi
+ fi
+ fi ]
+)
+
+
# Looking for programs, paths and files
PRIVSEP_PATH=/var/empty
@@ -5097,6 +5121,7 @@ echo " libedit support: $LIBEDIT_MSG"
echo " Solaris process contract support: $SPC_MSG"
echo " Solaris project support: $SP_MSG"
echo " Solaris privilege support: $SPP_MSG"
+echo " systemd support: $SYSTEMD_MSG"
echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG"
echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG"
echo " BSD Auth support: $BSD_AUTH_MSG"
diff --git a/contrib/sshd.service b/contrib/sshd.service
new file mode 100644
index 0000000..e0d4923
--- /dev/null
+++ b/contrib/sshd.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=OpenSSH server daemon
+Documentation=man:sshd(8) man:sshd_config(5)
+After=network.target
+
+[Service]
+Type=notify
+ExecStart=/usr/sbin/sshd -D $OPTIONS
+ExecReload=/bin/kill -HUP $MAINPID
+KillMode=process
+Restart=on-failure
+RestartPreventExitStatus=255
+
+[Install]
+WantedBy=multi-user.target
+
diff --git a/sshd.c b/sshd.c
index 816611c..b8b9d13 100644
--- a/sshd.c
+++ b/sshd.c
@@ -85,6 +85,10 @@
#include <prot.h>
#endif
+#ifdef HAVE_SYSTEMD
+#include <systemd/sd-daemon.h>
+#endif
+
#include "xmalloc.h"
#include "ssh.h"
#include "ssh2.h"
@@ -1833,6 +1837,11 @@ main(int ac, char **av)
}
}
+#ifdef HAVE_SYSTEMD
+ /* Signal systemd that we are ready to accept connections */
+ sd_notify(0, "READY=1");
+#endif
+
/* Accept a connection and return in a forked child */
server_accept_loop(&sock_in, &sock_out,
&newsock, config_s);

View file

@ -0,0 +1,27 @@
diff -up openssh-7.4p1/servconf.c.sshd-t openssh-7.4p1/servconf.c
--- openssh-7.4p1/servconf.c.sshd-t 2017-02-09 10:19:56.859306131 +0100
+++ openssh-7.4p1/servconf.c 2017-02-09 10:22:07.895104402 +0100
@@ -2337,7 +2337,7 @@ dump_config(ServerOptions *o)
dump_cfg_string(sXAuthLocation, o->xauth_location);
dump_cfg_string(sCiphers, o->ciphers ? o->ciphers : KEX_SERVER_ENCRYPT);
dump_cfg_string(sMacs, o->macs ? o->macs : KEX_SERVER_MAC);
- dump_cfg_string(sBanner, o->banner);
+ dump_cfg_string(sBanner, o->banner == NULL ? "none" : o->banner);
dump_cfg_string(sForceCommand, o->adm_forced_command);
dump_cfg_string(sChrootDirectory, o->chroot_directory);
dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys);
diff -up openssh-7.4p1/ssh.1.sshd-t openssh-7.4p1/ssh.1
--- openssh-7.4p1/ssh.1.sshd-t 2017-02-09 10:19:56.823306172 +0100
+++ openssh-7.4p1/ssh.1 2017-02-09 10:19:56.859306131 +0100
@@ -512,7 +512,11 @@ For full details of the options listed b
.It GatewayPorts
.It GlobalKnownHostsFile
.It GSSAPIAuthentication
+.It GSSAPIKeyExchange
+.It GSSAPIClientIdentity
.It GSSAPIDelegateCredentials
+.It GSSAPIRenewalForcesRekey
+.It GSSAPITrustDns
.It HashKnownHosts
.It Host
.It HostbasedAuthentication

View file

@ -0,0 +1,214 @@
diff -up openssh-7.4p1/channels.c.x11max openssh-7.4p1/channels.c
--- openssh-7.4p1/channels.c.x11max 2017-02-09 12:49:04.690996627 +0100
+++ openssh-7.4p1/channels.c 2017-02-09 12:49:04.744996547 +0100
@@ -152,8 +152,8 @@ static int all_opens_permitted = 0;
/* -- X11 forwarding */
-/* Maximum number of fake X11 displays to try. */
-#define MAX_DISPLAYS 1000
+/* Minimum port number for X11 forwarding */
+#define X11_PORT_MIN 6000
/* Saved X11 local (client) display. */
static char *x11_saved_display = NULL;
@@ -4228,7 +4228,8 @@ channel_send_window_changes(void)
*/
int
x11_create_display_inet(int x11_display_offset, int x11_use_localhost,
- int single_connection, u_int *display_numberp, int **chanids)
+ int x11_max_displays, int single_connection, u_int *display_numberp,
+ int **chanids)
{
Channel *nc = NULL;
int display_number, sock;
@@ -4240,10 +4241,15 @@ x11_create_display_inet(int x11_display_
if (chanids == NULL)
return -1;
+ /* Try to bind ports starting at 6000+X11DisplayOffset */
+ x11_max_displays = x11_max_displays + x11_display_offset;
+
for (display_number = x11_display_offset;
- display_number < MAX_DISPLAYS;
+ display_number < x11_max_displays;
display_number++) {
- port = 6000 + display_number;
+ port = X11_PORT_MIN + display_number;
+ if (port < X11_PORT_MIN) /* overflow */
+ break;
memset(&hints, 0, sizeof(hints));
hints.ai_family = IPv4or6;
hints.ai_flags = x11_use_localhost ? 0: AI_PASSIVE;
@@ -4295,7 +4301,7 @@ x11_create_display_inet(int x11_display_
if (num_socks > 0)
break;
}
- if (display_number >= MAX_DISPLAYS) {
+ if (display_number >= x11_max_displays || port < X11_PORT_MIN ) {
error("Failed to allocate internet-domain X11 display socket.");
return -1;
}
@@ -4441,7 +4447,7 @@ x11_connect_display(void)
memset(&hints, 0, sizeof(hints));
hints.ai_family = IPv4or6;
hints.ai_socktype = SOCK_STREAM;
- snprintf(strport, sizeof strport, "%u", 6000 + display_number);
+ snprintf(strport, sizeof strport, "%u", X11_PORT_MIN + display_number);
if ((gaierr = getaddrinfo(buf, strport, &hints, &aitop)) != 0) {
error("%.100s: unknown host. (%s)", buf,
ssh_gai_strerror(gaierr));
@@ -4457,7 +4463,7 @@ x11_connect_display(void)
/* Connect it to the display. */
if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
debug2("connect %.100s port %u: %.100s", buf,
- 6000 + display_number, strerror(errno));
+ X11_PORT_MIN + display_number, strerror(errno));
close(sock);
continue;
}
@@ -4466,8 +4472,8 @@ x11_connect_display(void)
}
freeaddrinfo(aitop);
if (!ai) {
- error("connect %.100s port %u: %.100s", buf, 6000 + display_number,
- strerror(errno));
+ error("connect %.100s port %u: %.100s", buf,
+ X11_PORT_MIN + display_number, strerror(errno));
return -1;
}
set_nodelay(sock);
diff -up openssh-7.4p1/channels.h.x11max openssh-7.4p1/channels.h
--- openssh-7.4p1/channels.h.x11max 2017-02-09 12:49:04.744996547 +0100
+++ openssh-7.4p1/channels.h 2017-02-09 12:49:50.230929693 +0100
@@ -293,7 +293,7 @@ int permitopen_port(const char *);
void channel_set_x11_refuse_time(u_int);
int x11_connect_display(void);
-int x11_create_display_inet(int, int, int, u_int *, int **);
+int x11_create_display_inet(int, int, int, int, u_int *, int **);
int x11_input_open(int, u_int32_t, void *);
void x11_request_forwarding_with_spoofing(int, const char *, const char *,
const char *, int);
diff -up openssh-7.4p1/servconf.c.x11max openssh-7.4p1/servconf.c
--- openssh-7.4p1/servconf.c.x11max 2017-02-09 12:49:04.741996552 +0100
+++ openssh-7.4p1/servconf.c 2017-02-09 12:51:03.167822492 +0100
@@ -94,6 +94,7 @@ initialize_server_options(ServerOptions
options->print_lastlog = -1;
options->x11_forwarding = -1;
options->x11_display_offset = -1;
+ options->x11_max_displays = -1;
options->x11_use_localhost = -1;
options->permit_tty = -1;
options->permit_user_rc = -1;
@@ -242,6 +243,8 @@ fill_default_server_options(ServerOption
options->x11_forwarding = 0;
if (options->x11_display_offset == -1)
options->x11_display_offset = 10;
+ if (options->x11_max_displays == -1)
+ options->x11_max_displays = DEFAULT_MAX_DISPLAYS;
if (options->x11_use_localhost == -1)
options->x11_use_localhost = 1;
if (options->xauth_location == NULL)
@@ -416,7 +419,7 @@ typedef enum {
sPasswordAuthentication, sKbdInteractiveAuthentication,
sListenAddress, sAddressFamily,
sPrintMotd, sPrintLastLog, sIgnoreRhosts,
- sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
+ sX11Forwarding, sX11DisplayOffset, sX11MaxDisplays, sX11UseLocalhost,
sPermitTTY, sStrictModes, sEmptyPasswd, sTCPKeepAlive,
sPermitUserEnvironment, sAllowTcpForwarding, sCompression,
sRekeyLimit, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
@@ -537,6 +540,7 @@ static struct {
{ "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL },
{ "x11forwarding", sX11Forwarding, SSHCFG_ALL },
{ "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL },
+ { "x11maxdisplays", sX11MaxDisplays, SSHCFG_ALL },
{ "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL },
{ "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL },
{ "strictmodes", sStrictModes, SSHCFG_GLOBAL },
@@ -1313,6 +1317,10 @@ process_server_config_line(ServerOptions
*intptr = value;
break;
+ case sX11MaxDisplays:
+ intptr = &options->x11_max_displays;
+ goto parse_int;
+
case sX11UseLocalhost:
intptr = &options->x11_use_localhost;
goto parse_flag;
@@ -2060,6 +2068,7 @@ copy_set_server_options(ServerOptions *d
M_CP_INTOPT(fwd_opts.streamlocal_bind_unlink);
M_CP_INTOPT(x11_display_offset);
M_CP_INTOPT(x11_forwarding);
+ M_CP_INTOPT(x11_max_displays);
M_CP_INTOPT(x11_use_localhost);
M_CP_INTOPT(permit_tty);
M_CP_INTOPT(permit_user_rc);
@@ -2312,6 +2321,7 @@ dump_config(ServerOptions *o)
#endif
dump_cfg_int(sLoginGraceTime, o->login_grace_time);
dump_cfg_int(sX11DisplayOffset, o->x11_display_offset);
+ dump_cfg_int(sX11MaxDisplays, o->x11_max_displays);
dump_cfg_int(sMaxAuthTries, o->max_authtries);
dump_cfg_int(sMaxSessions, o->max_sessions);
dump_cfg_int(sClientAliveInterval, o->client_alive_interval);
diff -up openssh-7.4p1/servconf.h.x11max openssh-7.4p1/servconf.h
--- openssh-7.4p1/servconf.h.x11max 2017-02-09 12:49:04.741996552 +0100
+++ openssh-7.4p1/servconf.h 2017-02-09 12:49:04.744996547 +0100
@@ -55,6 +55,7 @@
#define DEFAULT_AUTH_FAIL_MAX 6 /* Default for MaxAuthTries */
#define DEFAULT_SESSIONS_MAX 10 /* Default for MaxSessions */
+#define DEFAULT_MAX_DISPLAYS 1000 /* Maximum number of fake X11 displays to try. */
/* Magic name for internal sftp-server */
#define INTERNAL_SFTP_NAME "internal-sftp"
@@ -85,6 +86,7 @@ typedef struct {
int x11_forwarding; /* If true, permit inet (spoofing) X11 fwd. */
int x11_display_offset; /* What DISPLAY number to start
* searching at */
+ int x11_max_displays; /* Number of displays to search */
int x11_use_localhost; /* If true, use localhost for fake X11 server. */
char *xauth_location; /* Location of xauth program */
int permit_tty; /* If false, deny pty allocation */
diff -up openssh-7.4p1/session.c.x11max openssh-7.4p1/session.c
--- openssh-7.4p1/session.c.x11max 2017-02-09 12:49:04.742996550 +0100
+++ openssh-7.4p1/session.c 2017-02-09 12:49:04.745996546 +0100
@@ -2502,8 +2502,9 @@ session_setup_x11fwd(Session *s)
return 0;
}
if (x11_create_display_inet(options.x11_display_offset,
- options.x11_use_localhost, s->single_connection,
- &s->display_number, &s->x11_chanids) == -1) {
+ options.x11_use_localhost, options.x11_max_displays,
+ s->single_connection, &s->display_number,
+ &s->x11_chanids) == -1) {
debug("x11_create_display_inet failed.");
return 0;
}
diff -up openssh-7.4p1/sshd_config.5.x11max openssh-7.4p1/sshd_config.5
--- openssh-7.4p1/sshd_config.5.x11max 2017-02-09 12:49:04.742996550 +0100
+++ openssh-7.4p1/sshd_config.5 2017-02-09 12:51:24.656790909 +0100
@@ -1137,6 +1137,7 @@ Available keywords are
.Cm StreamLocalBindUnlink ,
.Cm TrustedUserCAKeys ,
.Cm X11DisplayOffset ,
+.Cm X11MaxDisplays ,
.Cm X11Forwarding
and
.Cm X11UseLocalHost .
@@ -1563,6 +1564,12 @@ Specifies the first display number avail
X11 forwarding.
This prevents sshd from interfering with real X11 servers.
The default is 10.
+.It Cm X11MaxDisplays
+Specifies the maximum number of displays available for
+.Xr sshd 8 Ns 's
+X11 forwarding.
+This prevents sshd from exhausting local ports.
+The default is 1000.
.It Cm X11Forwarding
Specifies whether X11 forwarding is permitted.
The argument must be

View file

@ -0,0 +1,145 @@
From 74287f5df9966a0648b4a68417451dd18f079ab8 Mon Sep 17 00:00:00 2001
From: "djm@openbsd.org" <djm@openbsd.org>
Date: Tue, 31 Jul 2018 03:10:27 +0000
Subject: [PATCH] upstream: delay bailout for invalid authentic
=?UTF-8?q?ating=20user=20until=20after=20the=20packet=20containing=20the?=
=?UTF-8?q?=20request=20has=20been=20fully=20parsed.=20Reported=20by=20Dar?=
=?UTF-8?q?iusz=20Tytko=20and=20Micha=C5=82=20Sajdak;=20ok=20deraadt?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
OpenBSD-Commit-ID: b4891882fbe413f230fe8ac8a37349b03bd0b70d
---
auth2-gss.c | 11 +++++++----
auth2-hostbased.c | 11 ++++++-----
auth2-pubkey.c | 25 +++++++++++++++----------
3 files changed, 28 insertions(+), 19 deletions(-)
diff --git a/auth2-gss.c b/auth2-gss.c
index 47308c5ce..9351e0428 100644
--- a/auth2-gss.c
+++ b/auth2-gss.c
@@ -70,9 +70,6 @@ userauth_gssapi(struct ssh *ssh)
u_int len;
u_char *doid = NULL;
- if (!authctxt->valid || authctxt->user == NULL)
- return (0);
-
mechs = packet_get_int();
if (mechs == 0) {
debug("Mechanism negotiation is not supported");
@@ -106,6 +103,12 @@ userauth_gssapi(struct ssh *ssh)
return (0);
}
+ if (!authctxt->valid || authctxt->user == NULL) {
+ debug2("%s: disabled because of invalid user", __func__);
+ free(doid);
+ return (0);
+ }
+
if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, &goid)))) {
if (ctxt != NULL)
ssh_gssapi_delete_ctx(&ctxt);
diff --git a/auth2-hostbased.c b/auth2-hostbased.c
index 60159a56c..359393291 100644
--- a/auth2-hostbased.c
+++ b/auth2-hostbased.c
@@ -67,10 +67,6 @@ userauth_hostbased(struct ssh *ssh)
int pktype;
int authenticated = 0;
- if (!authctxt->valid) {
- debug2("userauth_hostbased: disabled because of invalid user");
- return 0;
- }
pkalg = packet_get_string(&alen);
pkblob = packet_get_string(&blen);
chost = packet_get_string(NULL);
@@ -117,6 +113,11 @@ userauth_hostbased(struct ssh *ssh)
goto done;
}
+ if (!authctxt->valid || authctxt->user == NULL) {
+ debug2("%s: disabled because of invalid user", __func__);
+ goto done;
+ }
+
service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
authctxt->service;
buffer_init(&b);
diff --git a/auth2-pubkey.c b/auth2-pubkey.c
index c4d0f7908..e1c150401 100644
--- a/auth2-pubkey.c
+++ b/auth2-pubkey.c
@@ -89,16 +89,12 @@ userauth_pubkey(struct ssh *ssh)
{
Buffer b;
Key *key = NULL;
- char *pkalg, *userstyle, *pubkey, *fp = NULL;
- u_char *pkblob, *sig;
+ char *pkalg = NULL, *userstyle = NULL, *pubkey = NULL, *fp = NULL;
+ u_char *pkblob = NULL, *sig = NULL;
u_int alen, blen, slen;
int have_sig, pktype;
int authenticated = 0;
- if (!authctxt->valid) {
- debug2("%s: disabled because of invalid user", __func__);
- return 0;
- }
have_sig = packet_get_char();
if (datafellows & SSH_BUG_PKAUTH) {
debug2("%s: SSH_BUG_PKAUTH", __func__);
@@ -167,6 +163,12 @@ userauth_pubkey(struct ssh *ssh)
} else {
buffer_put_string(&b, session_id2, session_id2_len);
}
+ if (!authctxt->valid || authctxt->user == NULL) {
+ buffer_free(&b);
+ debug2("%s: disabled because of invalid user",
+ __func__);
+ goto done;
+ }
/* reconstruct packet */
buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
xasprintf(&userstyle, "%s%s%s%s%s", authctxt->user,
@@ -183,7 +184,6 @@ userauth_pubkey(struct ssh *ssh)
#endif
pubkey = sshkey_format_oneline(key, options.fingerprint_hash);
auth_info(authctxt, "%s", pubkey);
-
/* test for correct signature */
authenticated = 0;
if (PRIVSEP(user_key_allowed(authctxt->pw, key, 1)) &&
@@ -194,7 +194,6 @@ userauth_pubkey(struct ssh *ssh)
free(pubkey);
}
buffer_free(&b);
- free(sig);
} else {
debug("%s: test whether pkalg/pkblob are acceptable for %s %s",
__func__, sshkey_type(key), fp);
@@ -205,6 +204,11 @@ userauth_pubkey(struct ssh *ssh)
__func__, sshkey_type(key), fp);
packet_check_eom();
+ if (!authctxt->valid || authctxt->user == NULL) {
+ debug2("%s: disabled because of invalid user",
+ __func__);
+ goto done;
+ }
/* XXX fake reply and always send PK_OK ? */
/*
* XXX this allows testing whether a user is allowed
@@ -238,6 +242,7 @@ userauth_pubkey(struct ssh *ssh)
free(pkalg);
free(pkblob);
free(fp);
+ free(sig);
return authenticated;
}

View file

@ -0,0 +1,16 @@
diff -up openssh-7.4p1/mux.c.controlPath openssh-7.4p1/mux.c
--- openssh-7.4p1/mux.c.controlPath 2017-05-04 14:49:44.629247946 +0200
+++ openssh-7.4p1/mux.c 2017-05-04 14:52:54.955109022 +0200
@@ -1290,6 +1290,12 @@ muxserver_listen(void)
oerrno = errno;
umask(old_umask);
if (muxserver_sock < 0) {
+ if (oerrno == ENAMETOOLONG) {
+ /* the error is already logged from unix_listener() */
+ error("ControlPath %s too long, "
+ "disabling multiplexing", options.control_path);
+ goto disable_mux_master;
+ }
if (oerrno == EINVAL || oerrno == EADDRINUSE) {
error("ControlSocket %s already exists, "
"disabling multiplexing", options.control_path);

2182
openssh-7.4p1-audit.patch Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,38 @@
From ddd3d34e5c7979ca6f4a3a98a7d219a4ed3d98c2 Mon Sep 17 00:00:00 2001
From: "djm@openbsd.org" <djm@openbsd.org>
Date: Fri, 30 Dec 2016 22:08:02 +0000
Subject: [PATCH] upstream commit
fix deadlock when keys/principals command produces a lot of
output and a key is matched early; bz#2655, patch from jboning AT gmail.com
Upstream-ID: e19456429bf99087ea994432c16d00a642060afe
---
auth2-pubkey.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/auth2-pubkey.c b/auth2-pubkey.c
index 20f3309e1..70c021589 100644
--- a/auth2-pubkey.c
+++ b/auth2-pubkey.c
@@ -727,6 +727,9 @@ match_principals_command(struct passwd *user_pw, const struct sshkey *key)
ok = process_principals(f, NULL, pw, cert);
+ fclose(f);
+ f = NULL;
+
if (exited_cleanly(pid, "AuthorizedPrincipalsCommand", command) != 0)
goto out;
@@ -1050,6 +1053,9 @@ user_key_command_allowed2(struct passwd *user_pw, Key *key)
ok = check_authkeys_file(f, options.authorized_keys_command, key, pw);
+ fclose(f);
+ f = NULL;
+
if (exited_cleanly(pid, "AuthorizedKeysCommand", command) != 0)
goto out;

View file

@ -0,0 +1,50 @@
diff --git a/ssh-agent.c b/ssh-agent.c
index 1320cda..2441329 100644
--- a/ssh-agent.c
+++ b/ssh-agent.c
@@ -821,7 +821,7 @@ send:
static void
process_remove_smartcard_key(SocketEntry *e)
{
- char *provider = NULL, *pin = NULL;
+ char *provider = NULL, *pin = NULL, canonical_provider[PATH_MAX];
int r, version, success = 0;
Identity *id, *nxt;
Idtab *tab;
@@ -831,6 +831,13 @@ process_remove_smartcard_key(SocketEntry *e)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
free(pin);
+ if (realpath(provider, canonical_provider) == NULL) {
+ verbose("failed PKCS#11 add of \"%.100s\": realpath: %s",
+ provider, strerror(errno));
+ goto send;
+ }
+
+ debug("%s: remove %.100s", __func__, canonical_provider);
for (version = 1; version < 3; version++) {
tab = idtab_lookup(version);
for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) {
@@ -838,18 +845,19 @@ process_remove_smartcard_key(SocketEntry *e)
/* Skip file--based keys */
if (id->provider == NULL)
continue;
- if (!strcmp(provider, id->provider)) {
+ if (!strcmp(canonical_provider, id->provider)) {
TAILQ_REMOVE(&tab->idlist, id, next);
free_identity(id);
tab->nentries--;
}
}
}
- if (pkcs11_del_provider(provider) == 0)
+ if (pkcs11_del_provider(canonical_provider) == 0)
success = 1;
else
error("process_remove_smartcard_key:"
" pkcs11_del_provider failed");
+send:
free(provider);
send_status(e, success);
}

View file

@ -0,0 +1,30 @@
commit 0fb1a617a07b8df5de188dd5a0c8bf293d4bfc0e
Author: markus@openbsd.org <markus@openbsd.org>
Date: Sat Mar 11 13:07:35 2017 +0000
upstream commit
Don't count the initial block twice when computing how
many bytes to discard for the work around for the attacks against CBC-mode.
ok djm@; report from Jean Paul, Kenny, Martin and Torben @ RHUL
Upstream-ID: f445f509a4e0a7ba3b9c0dae7311cb42458dc1e2
diff --git a/packet.c b/packet.c
index 01e2d45..2f3a2ec 100644
--- a/packet.c
+++ b/packet.c
@@ -1850,11 +1850,11 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
if (r != SSH_ERR_MAC_INVALID)
goto out;
logit("Corrupted MAC on input.");
- if (need > PACKET_MAX_SIZE)
+ if (need + block_size > PACKET_MAX_SIZE)
return SSH_ERR_INTERNAL_ERROR;
return ssh_packet_start_discard(ssh, enc, mac,
sshbuf_len(state->incoming_packet),
- PACKET_MAX_SIZE - need);
+ PACKET_MAX_SIZE - need - block_size);
}
/* Remove MAC from input buffer */
DBG(debug("MAC #%d ok", state->p_read.seqnr));

View file

@ -0,0 +1,574 @@
diff -up openssh-7.4p1/auth-pam.c.coverity openssh-7.4p1/auth-pam.c
diff -up openssh-7.4p1/channels.c.coverity openssh-7.4p1/channels.c
--- openssh-7.4p1/channels.c.coverity 2017-02-09 14:58:32.786064600 +0100
+++ openssh-7.4p1/channels.c 2017-02-09 15:01:28.869890219 +0100
@@ -266,11 +266,11 @@ channel_register_fds(Channel *c, int rfd
channel_max_fd = MAXIMUM(channel_max_fd, wfd);
channel_max_fd = MAXIMUM(channel_max_fd, efd);
- if (rfd != -1)
+ if (rfd >= 0)
fcntl(rfd, F_SETFD, FD_CLOEXEC);
- if (wfd != -1 && wfd != rfd)
+ if (wfd >= 0 && wfd != rfd)
fcntl(wfd, F_SETFD, FD_CLOEXEC);
- if (efd != -1 && efd != rfd && efd != wfd)
+ if (efd >= 0 && efd != rfd && efd != wfd)
fcntl(efd, F_SETFD, FD_CLOEXEC);
c->rfd = rfd;
@@ -288,11 +288,11 @@ channel_register_fds(Channel *c, int rfd
/* enable nonblocking mode */
if (nonblock) {
- if (rfd != -1)
+ if (rfd >= 0)
set_nonblock(rfd);
- if (wfd != -1)
+ if (wfd >= 0)
set_nonblock(wfd);
- if (efd != -1)
+ if (efd >= 0)
set_nonblock(efd);
}
}
diff -up openssh-7.4p1/clientloop.c.coverity openssh-7.4p1/clientloop.c
diff -up openssh-7.4p1/key.c.coverity openssh-7.4p1/key.c
diff -up openssh-7.4p1/monitor.c.coverity openssh-7.4p1/monitor.c
--- openssh-7.4p1/monitor.c.coverity 2017-02-09 14:58:32.793064593 +0100
+++ openssh-7.4p1/monitor.c 2017-02-09 14:58:32.805064581 +0100
@@ -411,7 +411,7 @@ monitor_child_preauth(Authctxt *_authctx
mm_get_keystate(pmonitor);
/* Drain any buffered messages from the child */
- while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0)
+ while (pmonitor->m_log_recvfd >= 0 && monitor_read_log(pmonitor) == 0)
;
close(pmonitor->m_sendfd);
diff -up openssh-7.4p1/monitor_wrap.c.coverity openssh-7.4p1/monitor_wrap.c
--- openssh-7.4p1/monitor_wrap.c.coverity 2017-02-09 14:58:32.797064589 +0100
+++ openssh-7.4p1/monitor_wrap.c 2017-02-09 14:58:32.805064581 +0100
@@ -525,10 +525,10 @@ mm_pty_allocate(int *ptyfd, int *ttyfd,
if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 ||
(tmp2 = dup(pmonitor->m_recvfd)) == -1) {
error("%s: cannot allocate fds for pty", __func__);
- if (tmp1 > 0)
+ if (tmp1 >= 0)
close(tmp1);
- if (tmp2 > 0)
- close(tmp2);
+ /*DEAD CODE if (tmp2 >= 0)
+ close(tmp2);*/
return 0;
}
close(tmp1);
diff -up openssh-7.4p1/openbsd-compat/bindresvport.c.coverity openssh-7.4p1/openbsd-compat/bindresvport.c
--- openssh-7.4p1/openbsd-compat/bindresvport.c.coverity 2016-12-19 05:59:41.000000000 +0100
+++ openssh-7.4p1/openbsd-compat/bindresvport.c 2017-02-09 14:58:32.805064581 +0100
@@ -58,7 +58,7 @@ bindresvport_sa(int sd, struct sockaddr
struct sockaddr_in6 *in6;
u_int16_t *portp;
u_int16_t port;
- socklen_t salen;
+ socklen_t salen = sizeof(struct sockaddr_storage);
int i;
if (sa == NULL) {
diff -up openssh-7.4p1/packet.c.coverity openssh-7.4p1/packet.c
diff -up openssh-7.4p1/progressmeter.c.coverity openssh-7.4p1/progressmeter.c
diff -up openssh-7.4p1/scp.c.coverity openssh-7.4p1/scp.c
--- openssh-7.4p1/scp.c.coverity 2017-02-09 14:58:32.761064625 +0100
+++ openssh-7.4p1/scp.c 2017-02-09 14:58:38.590058852 +0100
@@ -157,7 +157,7 @@ killchild(int signo)
{
if (do_cmd_pid > 1) {
kill(do_cmd_pid, signo ? signo : SIGTERM);
- waitpid(do_cmd_pid, NULL, 0);
+ (void) waitpid(do_cmd_pid, NULL, 0);
}
if (signo)
diff -up openssh-7.4p1/servconf.c.coverity openssh-7.4p1/servconf.c
--- openssh-7.4p1/servconf.c.coverity 2017-02-09 14:58:32.801064585 +0100
+++ openssh-7.4p1/servconf.c 2017-02-09 14:58:38.591058851 +0100
@@ -1544,7 +1544,7 @@ process_server_config_line(ServerOptions
fatal("%s line %d: Missing subsystem name.",
filename, linenum);
if (!*activep) {
- arg = strdelim(&cp);
+ /*arg =*/ (void) strdelim(&cp);
break;
}
for (i = 0; i < options->num_subsystems; i++)
@@ -1635,8 +1635,9 @@ process_server_config_line(ServerOptions
if (*activep && *charptr == NULL) {
*charptr = tilde_expand_filename(arg, getuid());
/* increase optional counter */
- if (intptr != NULL)
- *intptr = *intptr + 1;
+ /* DEAD CODE intptr is still NULL ;)
+ if (intptr != NULL)
+ *intptr = *intptr + 1; */
}
break;
diff -up openssh-7.4p1/serverloop.c.coverity openssh-7.4p1/serverloop.c
--- openssh-7.4p1/serverloop.c.coverity 2016-12-19 05:59:41.000000000 +0100
+++ openssh-7.4p1/serverloop.c 2017-02-09 14:58:38.592058850 +0100
@@ -125,13 +125,13 @@ notify_setup(void)
static void
notify_parent(void)
{
- if (notify_pipe[1] != -1)
+ if (notify_pipe[1] >= 0)
(void)write(notify_pipe[1], "", 1);
}
static void
notify_prepare(fd_set *readset)
{
- if (notify_pipe[0] != -1)
+ if (notify_pipe[0] >= 0)
FD_SET(notify_pipe[0], readset);
}
static void
@@ -139,8 +139,8 @@ notify_done(fd_set *readset)
{
char c;
- if (notify_pipe[0] != -1 && FD_ISSET(notify_pipe[0], readset))
- while (read(notify_pipe[0], &c, 1) != -1)
+ if (notify_pipe[0] >= 0 && FD_ISSET(notify_pipe[0], readset))
+ while (read(notify_pipe[0], &c, 1) >= 0)
debug2("notify_done: reading");
}
@@ -518,7 +518,7 @@ server_request_tun(void)
}
tun = packet_get_int();
- if (forced_tun_device != -1) {
+ if (forced_tun_device >= 0) {
if (tun != SSH_TUNID_ANY && forced_tun_device != tun)
goto done;
tun = forced_tun_device;
diff -up openssh-7.4p1/sftp.c.coverity openssh-7.4p1/sftp.c
--- openssh-7.4p1/sftp.c.coverity 2016-12-19 05:59:41.000000000 +0100
+++ openssh-7.4p1/sftp.c 2017-02-09 14:58:38.598058844 +0100
@@ -224,7 +224,7 @@ killchild(int signo)
{
if (sshpid > 1) {
kill(sshpid, SIGTERM);
- waitpid(sshpid, NULL, 0);
+ (void) waitpid(sshpid, NULL, 0);
}
_exit(1);
diff -up openssh-7.4p1/sftp-client.c.coverity openssh-7.4p1/sftp-client.c
--- openssh-7.4p1/sftp-client.c.coverity 2017-02-09 14:58:38.596058846 +0100
+++ openssh-7.4p1/sftp-client.c 2017-02-09 15:20:18.893624636 +0100
@@ -973,7 +973,7 @@ do_symlink(struct sftp_conn *conn, const
}
int
-do_fsync(struct sftp_conn *conn, u_char *handle, u_int handle_len)
+do_fsync(struct sftp_conn *conn, const u_char *handle, u_int handle_len)
{
struct sshbuf *msg;
u_int status, id;
--- openssh-7.4p1/sftp-client.h.coverity 2017-02-10 09:28:10.951155129 +0100
+++ openssh-7.4p1/sftp-client.h 2017-02-10 09:27:28.685069870 +0100
@@ -107,7 +107,7 @@ int do_hardlink(struct sftp_conn *, cons
int do_symlink(struct sftp_conn *, const char *, const char *);
/* Call fsync() on open file 'handle' */
-int do_fsync(struct sftp_conn *conn, u_char *, u_int);
+int do_fsync(struct sftp_conn *conn, const u_char *, u_int);
/*
* Download 'remote_path' to 'local_path'. Preserve permissions and times
diff -up openssh-7.4p1/ssh-agent.c.coverity openssh-7.4p1/ssh-agent.c
--- openssh-7.4p1/ssh-agent.c.coverity 2017-02-09 14:58:38.599058843 +0100
+++ openssh-7.4p1/ssh-agent.c 2017-02-09 15:29:21.938917065 +0100
@@ -1220,8 +1220,8 @@ main(int ac, char **av)
sanitise_stdfd();
/* drop */
- setegid(getgid());
- setgid(getgid());
+ (void) setegid(getgid());
+ (void) setgid(getgid());
platform_disable_tracing(0); /* strict=no */
diff -up openssh-7.4p1/sshd.c.coverity openssh-7.4p1/sshd.c
--- openssh-7.4p1/sshd.c.coverity 2017-02-09 14:58:38.600058842 +0100
+++ openssh-7.4p1/sshd.c 2017-02-09 15:30:33.403800831 +0100
@@ -679,8 +679,10 @@ privsep_preauth(Authctxt *authctxt)
privsep_preauth_child();
setproctitle("%s", "[net]");
- if (box != NULL)
+ if (box != NULL) {
ssh_sandbox_child(box);
+ free(box);
+ }
return 0;
}
@@ -1382,6 +1384,9 @@ server_accept_loop(int *sock_in, int *so
if (num_listen_socks < 0)
break;
}
+
+ if (fdset != NULL)
+ free(fdset);
}
/*
diff --git a/auth-pam.c b/auth-pam.c
index e554ec4..bd16d80 100644
--- a/auth-pam.c
+++ b/auth-pam.c
@@ -834,6 +834,8 @@ fake_password(const char *wire_password)
fatal("%s: password length too long: %zu", __func__, l);
ret = malloc(l + 1);
+ if (ret == NULL)
+ return NULL;
for (i = 0; i < l; i++)
ret[i] = junk[i % (sizeof(junk) - 1)];
ret[i] = '\0';
diff --git a/clientloop.c b/clientloop.c
index c6a4138..9b00e12 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -2290,7 +2290,7 @@ update_known_hosts(struct hostkeys_update_ctx *ctx)
free(response);
response = read_passphrase("Accept updated hostkeys? "
"(yes/no): ", RP_ECHO);
- if (strcasecmp(response, "yes") == 0)
+ if (response != NULL && strcasecmp(response, "yes") == 0)
break;
else if (quit_pending || response == NULL ||
strcasecmp(response, "no") == 0) {
diff --git a/digest-openssl.c b/digest-openssl.c
index 13b63c2..dfa9b8d 100644
--- a/digest-openssl.c
+++ b/digest-openssl.c
@@ -158,7 +158,7 @@ ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen)
const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg);
u_int l = dlen;
- if (dlen > UINT_MAX)
+ if (digest == NULL || dlen > UINT_MAX)
return SSH_ERR_INVALID_ARGUMENT;
if (dlen < digest->digest_len) /* No truncation allowed */
return SSH_ERR_INVALID_ARGUMENT;
diff --git a/kex.c b/kex.c
index a30dabe..a8ac91f 100644
--- a/kex.c
+++ b/kex.c
@@ -178,7 +178,7 @@ kex_names_valid(const char *names)
char *
kex_names_cat(const char *a, const char *b)
{
- char *ret = NULL, *tmp = NULL, *cp, *p;
+ char *ret = NULL, *tmp = NULL, *cp, *p, *m;
size_t len;
if (a == NULL || *a == '\0')
@@ -195,8 +195,10 @@ kex_names_cat(const char *a, const char *b)
}
strlcpy(ret, a, len);
for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) {
- if (match_list(ret, p, NULL) != NULL)
+ if ((m = match_list(ret, p, NULL)) != NULL) {
+ free(m);
continue; /* Algorithm already present */
+ }
if (strlcat(ret, ",", len) >= len ||
strlcat(ret, p, len) >= len) {
free(tmp);
@@ -651,8 +653,10 @@ choose_enc(struct sshenc *enc, char *client, char *server)
#endif
return SSH_ERR_NO_CIPHER_ALG_MATCH;
}
- if ((enc->cipher = cipher_by_name(name)) == NULL)
+ if ((enc->cipher = cipher_by_name(name)) == NULL) {
+ free(name);
return SSH_ERR_INTERNAL_ERROR;
+ }
enc->name = name;
enc->enabled = 0;
enc->iv = NULL;
@@ -670,8 +674,10 @@ choose_mac(struct ssh *ssh, struct sshmac *mac, char *client, char *server)
#endif
return SSH_ERR_NO_MAC_ALG_MATCH;
}
- if (mac_setup(mac, name) < 0)
+ if (mac_setup(mac, name) < 0) {
+ free(name);
return SSH_ERR_INTERNAL_ERROR;
+ }
/* truncate the key */
if (ssh->compat & SSH_BUG_HMAC)
mac->key_len = 16;
@@ -695,6 +701,7 @@ choose_comp(struct sshcomp *comp, char *client, char *server)
} else if (strcmp(name, "none") == 0) {
comp->type = COMP_NONE;
} else {
+ free(name);
return SSH_ERR_INTERNAL_ERROR;
}
comp->name = name;
diff --git a/readconf.c b/readconf.c
index 3e7a5d8..acc1391 100644
--- a/readconf.c
+++ b/readconf.c
@@ -1500,6 +1500,7 @@ parse_keytypes:
if (r == GLOB_NOMATCH) {
debug("%.200s line %d: include %s matched no "
"files",filename, linenum, arg2);
+ free(arg2);
continue;
} else if (r != 0 || gl.gl_pathc < 0)
fatal("%.200s line %d: glob failed for %s.",
diff --git a/servconf.c b/servconf.c
index 6ab1cb4..5f2464a 100644
--- a/servconf.c
+++ b/servconf.c
@@ -2284,8 +2284,6 @@ dump_cfg_fmtint(ServerOpCodes code, int val)
static void
dump_cfg_string(ServerOpCodes code, const char *val)
{
- if (val == NULL)
- return;
printf("%s %s\n", lookup_opcode_name(code),
val == NULL ? "none" : val);
}
diff --git a/sshconnect.c b/sshconnect.c
index 07f80cd..5d4b41b 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -1533,6 +1533,7 @@ maybe_add_key_to_agent(char *authfile, Key *private, char *comment,
if (options.add_keys_to_agent == 2 &&
!ask_permission("Add key %s (%s) to agent?", authfile, comment)) {
debug3("user denied adding this key");
+ close(auth_sock);
return;
}
@@ -1541,4 +1542,5 @@ maybe_add_key_to_agent(char *authfile, Key *private, char *comment,
debug("identity added to agent: %s", authfile);
else
debug("could not add identity to agent: %s (%d)", authfile, r);
+ close(auth_sock);
}
diff --git a/sshconnect2.c b/sshconnect2.c
index f31c24c..aecf765 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -1061,6 +1061,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
if (key_to_blob(id->key, &blob, &bloblen) == 0) {
/* we cannot handle this key */
+ free(blob);
debug3("sign_and_send_pubkey: cannot handle key");
return 0;
}
@@ -1170,6 +1171,7 @@ send_pubkey_test(Authctxt *authctxt, Identity *id)
if (key_to_blob(id->key, &blob, &bloblen) == 0) {
/* we cannot handle this key */
+ free(blob);
debug3("send_pubkey_test: cannot handle key");
return 0;
}
diff --git a/sshkey.c b/sshkey.c
index 85fd1bd..58c1051 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -1375,8 +1375,6 @@ sshkey_read(struct sshkey *ret, char **cpp)
retval = 0;
/*XXXX*/
sshkey_free(k);
- if (retval != 0)
- break;
break;
default:
return SSH_ERR_INVALID_ARGUMENT;
diff --git a/krl.c b/krl.c
index e271a19..69bec99 100644
--- a/krl.c
+++ b/krl.c
@@ -1089,7 +1089,7 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp,
break;
case KRL_SECTION_SIGNATURE:
/* Handled above, but still need to stay in synch */
- sshbuf_reset(sect);
+ sshbuf_free(sect);
sect = NULL;
if ((r = sshbuf_skip_string(copy)) != 0)
goto out;
@@ -1288,7 +1288,8 @@ ssh_krl_file_contains_key(const char *path, const struct sshkey *key)
debug2("%s: checking KRL %s", __func__, path);
r = ssh_krl_check_key(krl, key);
out:
- close(fd);
+ if (fd != -1)
+ close(fd);
sshbuf_free(krlbuf);
ssh_krl_free(krl);
if (r != 0)
diff --git a/readconf.c b/readconf.c
index acc1391..c4dff15 100644
--- a/readconf.c
+++ b/readconf.c
@@ -1185,7 +1185,7 @@ parse_int:
value = cipher_number(arg);
if (value == -1)
fatal("%.200s line %d: Bad cipher '%s'.",
- filename, linenum, arg ? arg : "<NONE>");
+ filename, linenum, arg);
if (*activep && *intptr == -1)
*intptr = value;
break;
@@ -1196,7 +1196,7 @@ parse_int:
fatal("%.200s line %d: Missing argument.", filename, linenum);
if (!ciphers_valid(*arg == '+' ? arg + 1 : arg))
fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
- filename, linenum, arg ? arg : "<NONE>");
+ filename, linenum, arg);
if (*activep && options->ciphers == NULL)
options->ciphers = xstrdup(arg);
break;
@@ -1207,7 +1207,7 @@ parse_int:
fatal("%.200s line %d: Missing argument.", filename, linenum);
if (!mac_valid(*arg == '+' ? arg + 1 : arg))
fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
- filename, linenum, arg ? arg : "<NONE>");
+ filename, linenum, arg);
if (*activep && options->macs == NULL)
options->macs = xstrdup(arg);
break;
@@ -1220,7 +1220,7 @@ parse_int:
filename, linenum);
if (!kex_names_valid(*arg == '+' ? arg + 1 : arg))
fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
- filename, linenum, arg ? arg : "<NONE>");
+ filename, linenum, arg);
if (*activep && options->kex_algorithms == NULL)
options->kex_algorithms = xstrdup(arg);
break;
@@ -1235,7 +1235,7 @@ parse_keytypes:
filename, linenum);
if (!sshkey_names_valid2(*arg == '+' ? arg + 1 : arg, 1))
fatal("%s line %d: Bad key types '%s'.",
- filename, linenum, arg ? arg : "<NONE>");
+ filename, linenum, arg);
if (*activep && *charptr == NULL)
*charptr = xstrdup(arg);
break;
@@ -1248,7 +1248,7 @@ parse_keytypes:
value = proto_spec(arg);
if (value == SSH_PROTO_UNKNOWN)
fatal("%.200s line %d: Bad protocol spec '%s'.",
- filename, linenum, arg ? arg : "<NONE>");
+ filename, linenum, arg);
if (*activep && *intptr == SSH_PROTO_UNKNOWN)
*intptr = value;
break;
diff --git a/servconf.c b/servconf.c
index 5f2464a..4564494 100644
--- a/servconf.c
+++ b/servconf.c
@@ -1217,7 +1217,7 @@ process_server_config_line_depth(ServerOptions *options, char *line,
filename, linenum);
if (!sshkey_names_valid2(*arg == '+' ? arg + 1 : arg, 1))
fatal("%s line %d: Bad key types '%s'.",
- filename, linenum, arg ? arg : "<NONE>");
+ filename, linenum, arg);
if (*activep && *charptr == NULL)
*charptr = xstrdup(arg);
break;
@@ -1476,7 +1476,7 @@ process_server_config_line_depth(ServerOptions *options, char *line,
fatal("%s line %d: Missing argument.", filename, linenum);
if (!ciphers_valid(*arg == '+' ? arg + 1 : arg))
fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
- filename, linenum, arg ? arg : "<NONE>");
+ filename, linenum, arg);
if (options->ciphers == NULL)
options->ciphers = xstrdup(arg);
break;
@@ -1487,7 +1487,7 @@ process_server_config_line_depth(ServerOptions *options, char *line,
fatal("%s line %d: Missing argument.", filename, linenum);
if (!mac_valid(*arg == '+' ? arg + 1 : arg))
fatal("%s line %d: Bad SSH2 mac spec '%s'.",
- filename, linenum, arg ? arg : "<NONE>");
+ filename, linenum, arg);
if (options->macs == NULL)
options->macs = xstrdup(arg);
break;
@@ -1500,7 +1500,7 @@ process_server_config_line_depth(ServerOptions *options, char *line,
filename, linenum);
if (!kex_names_valid(*arg == '+' ? arg + 1 : arg))
fatal("%s line %d: Bad SSH2 KexAlgorithms '%s'.",
- filename, linenum, arg ? arg : "<NONE>");
+ filename, linenum, arg);
if (options->kex_algorithms == NULL)
options->kex_algorithms = xstrdup(arg);
break;
diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c
index aaf712d..62a76b3 100644
--- a/ssh-pkcs11.c
+++ b/ssh-pkcs11.c
@@ -536,8 +536,8 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx,
X509_free(x509);
}
if (rsa && rsa->n && rsa->e &&
- pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) {
- key = sshkey_new(KEY_UNSPEC);
+ pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0 &&
+ (key = sshkey_new(KEY_UNSPEC)) != NULL) {
key->rsa = rsa;
key->type = KEY_RSA;
key->flags |= SSHKEY_FLAG_EXT;
diff --git a/sshconnect1.c b/sshconnect1.c
index a045361..0e1a506 100644
--- a/sshconnect1.c
+++ b/sshconnect1.c
@@ -520,7 +520,8 @@ ssh_kex(char *host, struct sockaddr *hostaddr)
cookie[i] = packet_get_char();
/* Get the public key. */
- server_key = key_new(KEY_RSA1);
+ if ((server_key = key_new(KEY_RSA1)) == NULL)
+ fatal("%s: key_new(KEY_RSA1) failed", __func__);
bits = packet_get_int();
packet_get_bignum(server_key->rsa->e);
packet_get_bignum(server_key->rsa->n);
@@ -532,7 +533,8 @@ ssh_kex(char *host, struct sockaddr *hostaddr)
logit("Warning: This may be due to an old implementation of ssh.");
}
/* Get the host key. */
- host_key = key_new(KEY_RSA1);
+ if ((host_key = key_new(KEY_RSA1)) == NULL)
+ fatal("%s: key_new(KEY_RSA1) failed", __func__);
bits = packet_get_int();
packet_get_bignum(host_key->rsa->e);
packet_get_bignum(host_key->rsa->n);
diff --git a/sshkey.c b/sshkey.c
index 58c1051..6afacb5 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -1239,6 +1239,9 @@ sshkey_read(struct sshkey *ret, char **cpp)
u_long bits;
#endif /* WITH_SSH1 */
+ if (ret == NULL)
+ return SSH_ERR_INVALID_ARGUMENT;
+
cp = *cpp;
switch (ret->type) {

View file

@ -0,0 +1,250 @@
diff -up openssh-6.8p1/Makefile.in.ctr-cavs openssh-6.8p1/Makefile.in
--- openssh-6.8p1/Makefile.in.ctr-cavs 2015-03-18 11:22:05.493289018 +0100
+++ openssh-6.8p1/Makefile.in 2015-03-18 11:22:44.504196316 +0100
@@ -28,6 +28,7 @@ SSH_KEYSIGN=$(libexecdir)/ssh-keysign
SSH_LDAP_HELPER=$(libexecdir)/ssh-ldap-helper
SSH_LDAP_WRAPPER=$(libexecdir)/ssh-ldap-wrapper
SSH_KEYCAT=$(libexecdir)/ssh-keycat
+CTR_CAVSTEST=$(libexecdir)/ctr-cavstest
SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
PRIVSEP_PATH=@PRIVSEP_PATH@
SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@
@@ -66,7 +67,7 @@ EXEEXT=@EXEEXT@
MANFMT=@MANFMT@
INSTALL_SSH_LDAP_HELPER=@INSTALL_SSH_LDAP_HELPER@
-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-ldap-helper$(EXEEXT) ssh-keycat$(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-ldap-helper$(EXEEXT) ssh-keycat$(EXEEXT) ctr-cavstest$(EXEEXT)
LIBOPENSSH_OBJS=\
ssh_api.o \
@@ -194,6 +195,9 @@ ssh-ldap-helper$(EXEEXT): $(LIBCOMPAT) l
ssh-keycat$(EXEEXT): $(LIBCOMPAT) $(SSHDOBJS) libssh.a ssh-keycat.o
$(LD) -o $@ ssh-keycat.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(KEYCATLIBS) $(SSHLIBS)
+ctr-cavstest$(EXEEXT): $(LIBCOMPAT) libssh.a ctr-cavstest.o
+ $(LD) -o $@ ctr-cavstest.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS)
+
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o
$(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
@@ -326,6 +330,7 @@ install-files:
$(INSTALL) -m 0700 ssh-ldap-wrapper $(DESTDIR)$(SSH_LDAP_WRAPPER) ; \
fi
$(INSTALL) -m 0755 $(STRIP_OPT) ssh-keycat$(EXEEXT) $(DESTDIR)$(libexecdir)/ssh-keycat$(EXEEXT)
+ $(INSTALL) -m 0755 $(STRIP_OPT) ctr-cavstest$(EXEEXT) $(DESTDIR)$(libexecdir)/ctr-cavstest$(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 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
diff -up openssh-6.8p1/ctr-cavstest.c.ctr-cavs openssh-6.8p1/ctr-cavstest.c
--- openssh-6.8p1/ctr-cavstest.c.ctr-cavs 2015-03-18 11:22:05.521288952 +0100
+++ openssh-6.8p1/ctr-cavstest.c 2015-03-18 11:22:05.521288952 +0100
@@ -0,0 +1,208 @@
+/*
+ *
+ * invocation (all of the following are equal):
+ * ./ctr-cavstest --algo aes128-ctr --key 987212980144b6a632e864031f52dacc --mode encrypt --data a6deca405eef2e8e4609abf3c3ccf4a6
+ * ./ctr-cavstest --algo aes128-ctr --key 987212980144b6a632e864031f52dacc --mode encrypt --data a6deca405eef2e8e4609abf3c3ccf4a6 --iv 00000000000000000000000000000000
+ * echo -n a6deca405eef2e8e4609abf3c3ccf4a6 | ./ctr-cavstest --algo aes128-ctr --key 987212980144b6a632e864031f52dacc --mode encrypt
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "xmalloc.h"
+#include "log.h"
+#include "cipher.h"
+
+/* compatibility with old or broken OpenSSL versions */
+#include "openbsd-compat/openssl-compat.h"
+
+void usage(void) {
+ fprintf(stderr, "Usage: ctr-cavstest --algo <ssh-crypto-algorithm>\n"
+ " --key <hexadecimal-key> --mode <encrypt|decrypt>\n"
+ " [--iv <hexadecimal-iv>] --data <hexadecimal-data>\n\n"
+ "Hexadecimal output is printed to stdout.\n"
+ "Hexadecimal input data can be alternatively read from stdin.\n");
+ exit(1);
+}
+
+void *fromhex(char *hex, size_t *len)
+{
+ unsigned char *bin;
+ char *p;
+ size_t n = 0;
+ int shift = 4;
+ unsigned char out = 0;
+ unsigned char *optr;
+
+ bin = xmalloc(strlen(hex)/2);
+ optr = bin;
+
+ for (p = hex; *p != '\0'; ++p) {
+ unsigned char c;
+
+ c = *p;
+ if (isspace(c))
+ continue;
+
+ if (c >= '0' && c <= '9') {
+ c = c - '0';
+ } else if (c >= 'A' && c <= 'F') {
+ c = c - 'A' + 10;
+ } else if (c >= 'a' && c <= 'f') {
+ c = c - 'a' + 10;
+ } else {
+ /* truncate on nonhex cipher */
+ break;
+ }
+
+ out |= c << shift;
+ shift = (shift + 4) % 8;
+
+ if (shift) {
+ *(optr++) = out;
+ out = 0;
+ ++n;
+ }
+ }
+
+ *len = n;
+ return bin;
+}
+
+#define READ_CHUNK 4096
+#define MAX_READ_SIZE 1024*1024*100
+char *read_stdin(void)
+{
+ char *buf;
+ size_t n, total = 0;
+
+ buf = xmalloc(READ_CHUNK);
+
+ do {
+ n = fread(buf + total, 1, READ_CHUNK, stdin);
+ if (n < READ_CHUNK) /* terminate on short read */
+ break;
+
+ total += n;
+ buf = xreallocarray(buf, total + READ_CHUNK, 1);
+ } while(total < MAX_READ_SIZE);
+ return buf;
+}
+
+int main (int argc, char *argv[])
+{
+
+ const struct sshcipher *c;
+ struct sshcipher_ctx *cc;
+ char *algo = "aes128-ctr";
+ char *hexkey = NULL;
+ char *hexiv = "00000000000000000000000000000000";
+ char *hexdata = NULL;
+ char *p;
+ int i;
+ int encrypt = 1;
+ void *key;
+ size_t keylen;
+ void *iv;
+ size_t ivlen;
+ void *data;
+ size_t datalen;
+ void *outdata;
+
+ for (i = 1; i < argc; ++i) {
+ if (strcmp(argv[i], "--algo") == 0) {
+ algo = argv[++i];
+ } else if (strcmp(argv[i], "--key") == 0) {
+ hexkey = argv[++i];
+ } else if (strcmp(argv[i], "--mode") == 0) {
+ ++i;
+ if (argv[i] == NULL) {
+ usage();
+ }
+ if (strncmp(argv[i], "enc", 3) == 0) {
+ encrypt = 1;
+ } else if (strncmp(argv[i], "dec", 3) == 0) {
+ encrypt = 0;
+ } else {
+ usage();
+ }
+ } else if (strcmp(argv[i], "--iv") == 0) {
+ hexiv = argv[++i];
+ } else if (strcmp(argv[i], "--data") == 0) {
+ hexdata = argv[++i];
+ }
+ }
+
+ if (hexkey == NULL || algo == NULL) {
+ usage();
+ }
+
+ SSLeay_add_all_algorithms();
+
+ c = cipher_by_name(algo);
+ if (c == NULL) {
+ fprintf(stderr, "Error: unknown algorithm\n");
+ return 2;
+ }
+
+ if (hexdata == NULL) {
+ hexdata = read_stdin();
+ } else {
+ hexdata = xstrdup(hexdata);
+ }
+
+ key = fromhex(hexkey, &keylen);
+
+ if (keylen != 16 && keylen != 24 && keylen == 32) {
+ fprintf(stderr, "Error: unsupported key length\n");
+ return 2;
+ }
+
+ iv = fromhex(hexiv, &ivlen);
+
+ if (ivlen != 16) {
+ fprintf(stderr, "Error: unsupported iv length\n");
+ return 2;
+ }
+
+ data = fromhex(hexdata, &datalen);
+
+ if (data == NULL || datalen == 0) {
+ fprintf(stderr, "Error: no data to encrypt/decrypt\n");
+ return 2;
+ }
+
+ cipher_init(&cc, c, key, keylen, iv, ivlen, encrypt);
+
+ free(key);
+ free(iv);
+
+ outdata = malloc(datalen);
+ if(outdata == NULL) {
+ fprintf(stderr, "Error: memory allocation failure\n");
+ return 2;
+ }
+
+ cipher_crypt(cc, 0, outdata, data, datalen, 0, 0);
+
+ free(data);
+
+ cipher_free(cc);
+
+ for (p = outdata; datalen > 0; ++p, --datalen) {
+ printf("%02X", (unsigned char)*p);
+ }
+
+ free(outdata);
+
+ printf("\n");
+ return 0;
+}
+

View file

@ -0,0 +1,140 @@
diff -up openssh-7.4p1/configure.ac.tcp_wrappers openssh-7.4p1/configure.ac
--- openssh-7.4p1/configure.ac.tcp_wrappers 2016-12-23 15:36:38.745411192 +0100
+++ openssh-7.4p1/configure.ac 2016-12-23 15:36:38.777411197 +0100
@@ -1491,6 +1491,62 @@ AC_ARG_WITH([skey],
]
)
+# Check whether user wants TCP wrappers support
+TCPW_MSG="no"
+AC_ARG_WITH([tcp-wrappers],
+ [ --with-tcp-wrappers[[=PATH]] Enable tcpwrappers support (optionally in PATH)],
+ [
+ if test "x$withval" != "xno" ; then
+ saved_LIBS="$LIBS"
+ saved_LDFLAGS="$LDFLAGS"
+ saved_CPPFLAGS="$CPPFLAGS"
+ if test -n "${withval}" && \
+ test "x${withval}" != "xyes"; then
+ if test -d "${withval}/lib"; then
+ if test -n "${need_dash_r}"; then
+ LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}"
+ else
+ LDFLAGS="-L${withval}/lib ${LDFLAGS}"
+ fi
+ else
+ if test -n "${need_dash_r}"; then
+ LDFLAGS="-L${withval} -R${withval} ${LDFLAGS}"
+ else
+ LDFLAGS="-L${withval} ${LDFLAGS}"
+ fi
+ fi
+ if test -d "${withval}/include"; then
+ CPPFLAGS="-I${withval}/include ${CPPFLAGS}"
+ else
+ CPPFLAGS="-I${withval} ${CPPFLAGS}"
+ fi
+ fi
+ LIBS="-lwrap $LIBS"
+ AC_MSG_CHECKING([for libwrap])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <tcpd.h>
+int deny_severity = 0, allow_severity = 0;
+ ]], [[
+ hosts_access(0);
+ ]])], [
+ AC_MSG_RESULT([yes])
+ AC_DEFINE([LIBWRAP], [1],
+ [Define if you want
+ TCP Wrappers support])
+ SSHDLIBS="$SSHDLIBS -lwrap"
+ TCPW_MSG="yes"
+ ], [
+ AC_MSG_ERROR([*** libwrap missing])
+
+ ])
+ LIBS="$saved_LIBS"
+ fi
+ ]
+)
+
# Check whether user wants to use ldns
LDNS_MSG="no"
AC_ARG_WITH(ldns,
@@ -5214,6 +5270,7 @@ echo " KerberosV support
echo " SELinux support: $SELINUX_MSG"
echo " Smartcard support: $SCARD_MSG"
echo " S/KEY support: $SKEY_MSG"
+echo " TCP Wrappers support: $TCPW_MSG"
echo " MD5 password support: $MD5_MSG"
echo " libedit support: $LIBEDIT_MSG"
echo " Solaris process contract support: $SPC_MSG"
diff -up openssh-7.4p1/sshd.8.tcp_wrappers openssh-7.4p1/sshd.8
--- openssh-7.4p1/sshd.8.tcp_wrappers 2016-12-23 15:36:38.759411194 +0100
+++ openssh-7.4p1/sshd.8 2016-12-23 15:36:38.778411197 +0100
@@ -836,6 +836,12 @@ the user's home directory becomes access
This file should be writable only by the user, and need not be
readable by anyone else.
.Pp
+.It Pa /etc/hosts.allow
+.It Pa /etc/hosts.deny
+Access controls that should be enforced by tcp-wrappers are defined here.
+Further details are described in
+.Xr hosts_access 5 .
+.Pp
.It Pa /etc/hosts.equiv
This file is for host-based authentication (see
.Xr ssh 1 ) .
@@ -960,6 +966,7 @@ IPv6 address can be used everywhere wher
.Xr ssh-keygen 1 ,
.Xr ssh-keyscan 1 ,
.Xr chroot 2 ,
+.Xr hosts_access 5 ,
.Xr login.conf 5 ,
.Xr moduli 5 ,
.Xr sshd_config 5 ,
diff -up openssh-7.4p1/sshd.c.tcp_wrappers openssh-7.4p1/sshd.c
--- openssh-7.4p1/sshd.c.tcp_wrappers 2016-12-23 15:36:38.772411196 +0100
+++ openssh-7.4p1/sshd.c 2016-12-23 15:37:15.032417028 +0100
@@ -123,6 +123,13 @@
#include "version.h"
#include "ssherr.h"
+#ifdef LIBWRAP
+#include <tcpd.h>
+#include <syslog.h>
+int allow_severity;
+int deny_severity;
+#endif /* LIBWRAP */
+
/* Re-exec fds */
#define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1)
#define REEXEC_STARTUP_PIPE_FD (STDERR_FILENO + 2)
@@ -2012,6 +2019,24 @@ main(int ac, char **av)
#ifdef SSH_AUDIT_EVENTS
audit_connection_from(remote_ip, remote_port);
#endif
+#ifdef LIBWRAP
+ allow_severity = options.log_facility|LOG_INFO;
+ deny_severity = options.log_facility|LOG_WARNING;
+ /* Check whether logins are denied from this host. */
+ if (packet_connection_is_on_socket()) {
+ struct request_info req;
+
+ request_init(&req, RQ_DAEMON, __progname, RQ_FILE, sock_in, 0);
+ fromhost(&req);
+
+ if (!hosts_access(&req)) {
+ debug("Connection refused by tcp wrapper");
+ refuse(&req);
+ /* NOTREACHED */
+ fatal("libwrap refuse returns");
+ }
+ }
+#endif /* LIBWRAP */
/* Log the connection. */
laddr = get_local_ipaddr(sock_in);

Some files were not shown because too many files have changed in this diff Show more