commit
9338977782
@ -0,0 +1,2 @@
|
|||||||
|
SOURCES/gpgkey-736060BA.gpg
|
||||||
|
SOURCES/openssh-9.9p1.tar.gz
|
@ -0,0 +1,2 @@
|
|||||||
|
dbb35b4e9ae3f72b930a82c6fd5e83e9dcd7b193 SOURCES/gpgkey-736060BA.gpg
|
||||||
|
5ded7eb0add0b02b5d1a1c4bf5cb2c89d2117b53 SOURCES/openssh-9.9p1.tar.gz
|
@ -0,0 +1,18 @@
|
|||||||
|
diff -up openssh-8.6p1/contrib/gnome-ssh-askpass2.c.grab-info openssh-8.6p1/contrib/gnome-ssh-askpass2.c
|
||||||
|
--- openssh-8.6p1/contrib/gnome-ssh-askpass2.c.grab-info 2021-04-19 13:57:11.720113536 +0200
|
||||||
|
+++ openssh-8.6p1/contrib/gnome-ssh-askpass2.c 2021-04-19 13:59:29.842163204 +0200
|
||||||
|
@@ -70,8 +70,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));
|
@ -0,0 +1,83 @@
|
|||||||
|
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 <unistd.h>
|
||||||
|
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
+#include <glib.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include <gdk/gdkx.h>
|
||||||
|
#include <gdk/gdkkeysyms.h>
|
||||||
|
@@ -81,14 +82,25 @@ ok_dialog(GtkWidget *entry, gpointer dia
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
const char *failed;
|
||||||
|
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;
|
||||||
|
@@ -104,14 +116,19 @@ passphrase_dialog(char *message)
|
||||||
|
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) {
|
||||||
|
@@ -130,6 +145,22 @@ passphrase_dialog(char *message)
|
||||||
|
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 */
|
@ -0,0 +1,14 @@
|
|||||||
|
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,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;
|
||||||
|
|
@ -0,0 +1,24 @@
|
|||||||
|
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.
|
||||||
|
+.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
|
||||||
|
.Xr scp 1 ,
|
||||||
|
.Xr sftp 1 ,
|
||||||
|
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
|
||||||
|
+.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
|
||||||
|
.Xr scp 1 ,
|
||||||
|
.Xr sftp 1 ,
|
@ -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]);
|
@ -0,0 +1,263 @@
|
|||||||
|
diff -up openssh-8.6p1/log.c.log-in-chroot openssh-8.6p1/log.c
|
||||||
|
--- openssh-8.6p1/log.c.log-in-chroot 2021-04-16 05:55:25.000000000 +0200
|
||||||
|
+++ openssh-8.6p1/log.c 2021-04-19 14:43:08.544843434 +0200
|
||||||
|
@@ -194,6 +194,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
|
||||||
|
@@ -206,8 +211,10 @@ log_init(const char *av0, LogLevel level
|
||||||
|
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 -up openssh-8.6p1/log.h.log-in-chroot openssh-8.6p1/log.h
|
||||||
|
--- openssh-8.6p1/log.h.log-in-chroot 2021-04-19 14:43:08.544843434 +0200
|
||||||
|
+++ openssh-8.6p1/log.h 2021-04-19 14:56:46.931042176 +0200
|
||||||
|
@@ -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 -up openssh-8.6p1/monitor.c.log-in-chroot openssh-8.6p1/monitor.c
|
||||||
|
--- openssh-8.6p1/monitor.c.log-in-chroot 2021-04-19 14:43:08.526843298 +0200
|
||||||
|
+++ openssh-8.6p1/monitor.c 2021-04-19 14:55:25.286424043 +0200
|
||||||
|
@@ -297,6 +297,8 @@ monitor_child_preauth(struct ssh *ssh, s
|
||||||
|
close(pmonitor->m_log_sendfd);
|
||||||
|
pmonitor->m_log_sendfd = pmonitor->m_recvfd = -1;
|
||||||
|
|
||||||
|
+ pmonitor->m_state = "preauth";
|
||||||
|
+
|
||||||
|
authctxt = (Authctxt *)ssh->authctxt;
|
||||||
|
memset(authctxt, 0, sizeof(*authctxt));
|
||||||
|
ssh->authctxt = authctxt;
|
||||||
|
@@ -408,6 +410,8 @@ monitor_child_postauth(struct ssh *ssh,
|
||||||
|
close(pmonitor->m_recvfd);
|
||||||
|
pmonitor->m_recvfd = -1;
|
||||||
|
|
||||||
|
+ pmonitor->m_state = "postauth";
|
||||||
|
+
|
||||||
|
monitor_set_child_handler(pmonitor->m_pid);
|
||||||
|
ssh_signal(SIGHUP, &monitor_child_handler);
|
||||||
|
ssh_signal(SIGTERM, &monitor_child_handler);
|
||||||
|
@@ -480,7 +484,7 @@ monitor_read_log(struct monitor *pmonito
|
||||||
|
/* Log it */
|
||||||
|
if (log_level_name(level) == NULL)
|
||||||
|
fatal_f("invalid log level %u (corrupted message?)", level);
|
||||||
|
- sshlogdirect(level, forced, "%s [preauth]", msg);
|
||||||
|
+ sshlogdirect(level, forced, "%s [%s]", msg, pmonitor->m_state);
|
||||||
|
|
||||||
|
sshbuf_free(logmsg);
|
||||||
|
free(msg);
|
||||||
|
@@ -1868,13 +1872,28 @@ monitor_init(void)
|
||||||
|
mon = xcalloc(1, sizeof(*mon));
|
||||||
|
monitor_openfds(mon, 1);
|
||||||
|
|
||||||
|
+ mon->m_state = "";
|
||||||
|
+
|
||||||
|
return mon;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 -up openssh-8.6p1/monitor.h.log-in-chroot openssh-8.6p1/monitor.h
|
||||||
|
--- openssh-8.6p1/monitor.h.log-in-chroot 2021-04-19 14:43:08.527843305 +0200
|
||||||
|
+++ openssh-8.6p1/monitor.h 2021-04-19 14:43:08.545843441 +0200
|
||||||
|
@@ -80,10 +80,11 @@ struct monitor {
|
||||||
|
int m_log_sendfd;
|
||||||
|
struct kex **m_pkex;
|
||||||
|
pid_t m_pid;
|
||||||
|
+ char *m_state;
|
||||||
|
};
|
||||||
|
|
||||||
|
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 -up openssh-8.6p1/session.c.log-in-chroot openssh-8.6p1/session.c
|
||||||
|
--- openssh-8.6p1/session.c.log-in-chroot 2021-04-19 14:43:08.534843358 +0200
|
||||||
|
+++ openssh-8.6p1/session.c 2021-04-19 14:43:08.545843441 +0200
|
||||||
|
@@ -160,6 +160,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;
|
||||||
|
@@ -661,6 +662,7 @@ do_exec(struct ssh *ssh, Session *s, con
|
||||||
|
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;
|
||||||
|
@@ -720,6 +722,10 @@ do_exec(struct ssh *ssh, Session *s, con
|
||||||
|
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 ",
|
||||||
|
@@ -1524,14 +1530,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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -1665,8 +1663,6 @@ do_child(struct ssh *ssh, Session *s, co
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
- closefrom(STDERR_FILENO + 1);
|
||||||
|
-
|
||||||
|
do_rc_files(ssh, s, shell);
|
||||||
|
|
||||||
|
/* restore SIGPIPE for child */
|
||||||
|
@@ -1691,9 +1687,17 @@ do_child(struct ssh *ssh, Session *s, co
|
||||||
|
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 -up openssh-8.6p1/sftp.h.log-in-chroot openssh-8.6p1/sftp.h
|
||||||
|
--- openssh-8.6p1/sftp.h.log-in-chroot 2021-04-16 05:55:25.000000000 +0200
|
||||||
|
+++ openssh-8.6p1/sftp.h 2021-04-19 14:43:08.545843441 +0200
|
||||||
|
@@ -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 -up openssh-8.6p1/sftp-server.c.log-in-chroot openssh-8.6p1/sftp-server.c
|
||||||
|
--- openssh-8.6p1/sftp-server.c.log-in-chroot 2021-04-16 05:55:25.000000000 +0200
|
||||||
|
+++ openssh-8.6p1/sftp-server.c 2021-04-19 14:43:08.545843441 +0200
|
||||||
|
@@ -1644,7 +1644,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;
|
||||||
|
@@ -1657,7 +1657,7 @@ sftp_server_main(int argc, char **argv,
|
||||||
|
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);
|
||||||
|
|
||||||
|
@@ -1730,7 +1730,7 @@ sftp_server_main(int argc, char **argv,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- 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 -up openssh-8.6p1/sftp-server-main.c.log-in-chroot openssh-8.6p1/sftp-server-main.c
|
||||||
|
--- openssh-8.6p1/sftp-server-main.c.log-in-chroot 2021-04-16 05:55:25.000000000 +0200
|
||||||
|
+++ openssh-8.6p1/sftp-server-main.c 2021-04-19 14:43:08.545843441 +0200
|
||||||
|
@@ -50,5 +50,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 -up openssh-8.6p1/sshd-session.c.log-in-chroot openssh-8.6p1/sshd-session.c
|
||||||
|
--- openssh-8.6p1/sshd-session.c.log-in-chroot 2021-04-19 14:43:08.543843426 +0200
|
||||||
|
+++ openssh-8.6p1/sshd-session.c 2021-04-19 14:43:08.545843441 +0200
|
||||||
|
@@ -559,7 +559,7 @@ privsep_postauth(struct ssh *ssh, Authct
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* New socket pair */
|
||||||
|
- monitor_reinit(pmonitor);
|
||||||
|
+ monitor_reinit(pmonitor, options.chroot_directory);
|
||||||
|
|
||||||
|
pmonitor->m_pid = fork();
|
||||||
|
if (pmonitor->m_pid == -1)
|
||||||
|
@@ -578,6 +578,11 @@ privsep_postauth(struct ssh *ssh, Authct
|
||||||
|
|
||||||
|
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();
|
@ -0,0 +1,14 @@
|
|||||||
|
--- a/scp.c
|
||||||
|
+++ a/scp.c
|
||||||
|
@@ -1084,6 +1084,10 @@ sink(int argc, char **argv)
|
||||||
|
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) {
|
||||||
|
--
|
@ -0,0 +1,131 @@
|
|||||||
|
diff --git a/openbsd-compat/port-linux-sshd.c b/openbsd-compat/port-linux-sshd.c
|
||||||
|
index 8f32464..18a2ca4 100644
|
||||||
|
--- a/openbsd-compat/port-linux-sshd.c
|
||||||
|
+++ b/openbsd-compat/port-linux-sshd.c
|
||||||
|
@@ -32,6 +32,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"
|
||||||
|
@@ -445,7 +446,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;
|
||||||
|
@@ -461,6 +462,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
|
||||||
|
--- a/openbsd-compat/port-linux.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99)
|
||||||
|
+++ b/openbsd-compat/port-linux.c (date 1703108053912)
|
||||||
|
@@ -207,7 +207,7 @@
|
||||||
|
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 cb51f99..8b7cda2 100644
|
||||||
|
--- a/openbsd-compat/port-linux.h
|
||||||
|
+++ b/openbsd-compat/port-linux.h
|
||||||
|
@@ -29,6 +29,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-session.c b/sshd-session.c
|
||||||
|
index 2871fe9..39b9c08 100644
|
||||||
|
--- a/sshd-session.c
|
||||||
|
+++ b/sshd-session.c
|
||||||
|
@@ -629,7 +629,7 @@ privsep_preauth_child(void)
|
||||||
|
demote_sensitive_data();
|
||||||
|
|
||||||
|
#ifdef WITH_SELINUX
|
||||||
|
- ssh_selinux_change_context("sshd_net_t");
|
||||||
|
+ sshd_selinux_change_privsep_preauth_context();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Demote the child */
|
@ -0,0 +1,134 @@
|
|||||||
|
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 2016-12-23 15:18:40.615216100 +0100
|
||||||
|
+++ openssh-7.4p1/gss-serv-krb5.c 2016-12-23 15:18:40.628216102 +0100
|
||||||
|
@@ -279,7 +279,6 @@ ssh_gssapi_krb5_cmdok(krb5_principal pri
|
||||||
|
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 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 2016-12-23 15:18:40.615216100 +0100
|
||||||
|
+++ openssh-7.4p1/servconf.c 2016-12-23 15:35:36.354401156 +0100
|
||||||
|
@@ -168,6 +168,7 @@ initialize_server_options(ServerOptions
|
||||||
|
options->gss_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;
|
||||||
|
@@ -345,6 +346,8 @@ fill_default_server_options(ServerOption
|
||||||
|
#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)
|
||||||
|
@@ -578,7 +578,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,
|
||||||
|
@@ -600,14 +600,16 @@ static struct {
|
||||||
|
{ "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL },
|
||||||
|
{ "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL },
|
||||||
|
{ "gssapikexalgorithms", sGssKexAlgorithms, SSHCFG_GLOBAL },
|
||||||
|
+ { "gssapienablek5users", sGssEnablek5users, SSHCFG_ALL },
|
||||||
|
#else
|
||||||
|
{ "gssapiauthentication", sUnsupported, SSHCFG_ALL },
|
||||||
|
{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
|
||||||
|
{ "gssapicleanupcreds", sUnsupported, SSHCFG_GLOBAL },
|
||||||
|
{ "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },
|
||||||
|
{ "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL },
|
||||||
|
{ "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL },
|
||||||
|
{ "gssapikexalgorithms", sUnsupported, SSHCFG_GLOBAL },
|
||||||
|
+ { "gssapienablek5users", sUnsupported, SSHCFG_ALL },
|
||||||
|
#endif
|
||||||
|
{ "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL },
|
||||||
|
{ "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 sMatch:
|
||||||
|
if (cmdline)
|
||||||
|
fatal("Match directive not supported as a command-line "
|
||||||
|
@@ -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);
|
||||||
|
M_CP_INTOPT(log_level);
|
||||||
|
@@ -2320,6 +2330,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 -up openssh-7.4p1/servconf.h.GSSAPIEnablek5users openssh-7.4p1/servconf.h
|
||||||
|
--- openssh-7.4p1/servconf.h.GSSAPIEnablek5users 2016-12-23 15:18:40.616216100 +0100
|
||||||
|
+++ openssh-7.4p1/servconf.h 2016-12-23 15:18:40.629216102 +0100
|
||||||
|
@@ -174,6 +174,7 @@ typedef struct {
|
||||||
|
int kerberos_unique_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 -up openssh-7.4p1/sshd_config.5.GSSAPIEnablek5users openssh-7.4p1/sshd_config.5
|
||||||
|
--- openssh-7.4p1/sshd_config.5.GSSAPIEnablek5users 2016-12-23 15:18:40.630216103 +0100
|
||||||
|
+++ openssh-7.4p1/sshd_config.5 2016-12-23 15:36:21.607408435 +0100
|
||||||
|
@@ -628,6 +628,12 @@ Specifies whether to automatically destr
|
||||||
|
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.
|
||||||
|
diff -up openssh-7.4p1/sshd_config.GSSAPIEnablek5users openssh-7.4p1/sshd_config
|
||||||
|
--- openssh-7.4p1/sshd_config.GSSAPIEnablek5users 2016-12-23 15:18:40.616216100 +0100
|
||||||
|
+++ openssh-7.4p1/sshd_config 2016-12-23 15:18:40.631216103 +0100
|
||||||
|
@@ -80,6 +80,7 @@ GSSAPIAuthentication yes
|
||||||
|
#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 -up openssh-9.8p1/servconf.c.xxx openssh-9.8p1/servconf.c
|
||||||
|
--- openssh-9.8p1/servconf.c.xxx 2024-07-11 13:51:19.969960781 +0200
|
||||||
|
+++ openssh-9.8p1/servconf.c 2024-07-11 13:51:30.938231250 +0200
|
@ -0,0 +1,42 @@
|
|||||||
|
diff -up openssh/sshd.c.ip-opts openssh/sshd.c
|
||||||
|
--- openssh/sshd-session.c.ip-opts 2016-07-25 13:58:48.998507834 +0200
|
||||||
|
+++ openssh/sshd-session.c 2016-07-25 14:01:28.346469878 +0200
|
||||||
|
@@ -1507,12 +1507,32 @@ check_ip_options(struct ssh *ssh)
|
||||||
|
|
||||||
|
if (getsockopt(sock_in, IPPROTO_IP, IP_OPTIONS, opts,
|
||||||
|
&option_size) >= 0 && option_size != 0) {
|
||||||
|
- text[0] = '\0';
|
||||||
|
- for (i = 0; i < option_size; i++)
|
||||||
|
- snprintf(text + i*3, sizeof(text) - i*3,
|
||||||
|
- " %2.2x", opts[i]);
|
||||||
|
- fatal("Connection from %.100s port %d with IP opts: %.800s",
|
||||||
|
- ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), text);
|
||||||
|
+ i = 0;
|
||||||
|
+ do {
|
||||||
|
+ switch (opts[i]) {
|
||||||
|
+ case 0:
|
||||||
|
+ case 1:
|
||||||
|
+ ++i;
|
||||||
|
+ break;
|
||||||
|
+ case 130:
|
||||||
|
+ case 133:
|
||||||
|
+ case 134:
|
||||||
|
+ if (i + 1 < option_size && opts[i + 1] >= 2) {
|
||||||
|
+ i += opts[i + 1];
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ /* FALLTHROUGH */
|
||||||
|
+ default:
|
||||||
|
+ /* Fail, fatally, if we detect either loose or strict
|
||||||
|
+ * or incorrect source routing options. */
|
||||||
|
+ text[0] = '\0';
|
||||||
|
+ for (i = 0; i < option_size; i++)
|
||||||
|
+ snprintf(text + i*3, sizeof(text) - i*3,
|
||||||
|
+ " %2.2x", opts[i]);
|
||||||
|
+ fatal("Connection from %.100s port %d with IP options:%.800s",
|
||||||
|
+ ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), text);
|
||||||
|
+ }
|
||||||
|
+ } while (i < option_size);
|
||||||
|
}
|
||||||
|
#endif /* IP_OPTIONS */
|
||||||
|
}
|
@ -0,0 +1,280 @@
|
|||||||
|
diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c
|
||||||
|
index 413b845..54dd383 100644
|
||||||
|
--- a/gss-serv-krb5.c
|
||||||
|
+++ b/gss-serv-krb5.c
|
||||||
|
@@ -32,7 +32,9 @@
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
+#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
+#include <unistd.h>
|
||||||
|
|
||||||
|
#include "xmalloc.h"
|
||||||
|
#include "sshkey.h"
|
||||||
|
@@ -45,6 +47,7 @@
|
||||||
|
|
||||||
|
#include "ssh-gss.h"
|
||||||
|
|
||||||
|
+extern Authctxt *the_authctxt;
|
||||||
|
extern ServerOptions options;
|
||||||
|
|
||||||
|
#ifdef HEIMDAL
|
||||||
|
@@ -56,6 +59,13 @@ extern ServerOptions options;
|
||||||
|
# include <gssapi/gssapi_krb5.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+/* all commands are allowed by default */
|
||||||
|
+char **k5users_allowed_cmds = NULL;
|
||||||
|
+
|
||||||
|
+static int ssh_gssapi_k5login_exists();
|
||||||
|
+static int ssh_gssapi_krb5_cmdok(krb5_principal, const char *, const char *,
|
||||||
|
+ int);
|
||||||
|
+
|
||||||
|
static krb5_context krb_context = NULL;
|
||||||
|
|
||||||
|
/* Initialise the krb5 library, for the stuff that GSSAPI won't do */
|
||||||
|
@@ -88,6 +98,7 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name)
|
||||||
|
krb5_principal princ;
|
||||||
|
int retval;
|
||||||
|
const char *errmsg;
|
||||||
|
+ int k5login_exists;
|
||||||
|
|
||||||
|
if (ssh_gssapi_krb5_init() == 0)
|
||||||
|
return 0;
|
||||||
|
@@ -99,10 +110,22 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name)
|
||||||
|
krb5_free_error_message(krb_context, errmsg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
- if (krb5_kuserok(krb_context, princ, name)) {
|
||||||
|
+ /* krb5_kuserok() returns 1 if .k5login DNE and this is self-login.
|
||||||
|
+ * We have to make sure to check .k5users in that case. */
|
||||||
|
+ k5login_exists = ssh_gssapi_k5login_exists();
|
||||||
|
+ /* NOTE: .k5login and .k5users must opened as root, not the user,
|
||||||
|
+ * because if they are on a krb5-protected filesystem, user credentials
|
||||||
|
+ * to access these files aren't available yet. */
|
||||||
|
+ if (krb5_kuserok(krb_context, princ, name) && k5login_exists) {
|
||||||
|
retval = 1;
|
||||||
|
logit("Authorized to %s, krb5 principal %s (krb5_kuserok)",
|
||||||
|
name, (char *)client->displayname.value);
|
||||||
|
+ } 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);
|
||||||
|
} else
|
||||||
|
retval = 0;
|
||||||
|
|
||||||
|
@@ -110,6 +133,137 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name)
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Test for existence of .k5login.
|
||||||
|
+ * We need this as part of our .k5users check, because krb5_kuserok()
|
||||||
|
+ * returns success if .k5login DNE and user is logging in as himself.
|
||||||
|
+ * With .k5login absent and .k5users present, we don't want absence
|
||||||
|
+ * of .k5login to authorize self-login. (absence of both is required)
|
||||||
|
+ * Returns 1 if .k5login is available, 0 otherwise.
|
||||||
|
+ */
|
||||||
|
+static int
|
||||||
|
+ssh_gssapi_k5login_exists()
|
||||||
|
+{
|
||||||
|
+ char file[MAXPATHLEN];
|
||||||
|
+ struct passwd *pw = the_authctxt->pw;
|
||||||
|
+
|
||||||
|
+ snprintf(file, sizeof(file), "%s/.k5login", pw->pw_dir);
|
||||||
|
+ return access(file, F_OK) == 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* check .k5users for login or command authorization
|
||||||
|
+ * Returns 1 if principal is authorized, 0 otherwise.
|
||||||
|
+ * If principal is authorized, (global) k5users_allowed_cmds may be populated.
|
||||||
|
+ */
|
||||||
|
+static int
|
||||||
|
+ssh_gssapi_krb5_cmdok(krb5_principal principal, const char *name,
|
||||||
|
+ const char *luser, int k5login_exists)
|
||||||
|
+{
|
||||||
|
+ 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;
|
||||||
|
+ int ncommands = 0, allcommands = 0;
|
||||||
|
+ u_long linenum = 0;
|
||||||
|
+ size_t linesize = 0;
|
||||||
|
+
|
||||||
|
+ 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)) {
|
||||||
|
+ return (krb5_aname_to_localname(krb_context, principal,
|
||||||
|
+ sizeof(kuser), kuser) == 0) &&
|
||||||
|
+ (strcmp(kuser, luser) == 0);
|
||||||
|
+ }
|
||||||
|
+ if ((fp = fopen(file, "r")) == NULL) {
|
||||||
|
+ int saved_errno = errno;
|
||||||
|
+ /* 2nd access check to ease debugging if file perms are wrong.
|
||||||
|
+ * But we don't want to report this if .k5users simply DNE. */
|
||||||
|
+ if (access(file, F_OK) == 0) {
|
||||||
|
+ logit("User %s fopen %s failed: %s",
|
||||||
|
+ pw->pw_name, file, strerror(saved_errno));
|
||||||
|
+ }
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ /* .k5users must be owned either by the user or by root */
|
||||||
|
+ if (fstat(fileno(fp), &st) == -1) {
|
||||||
|
+ /* can happen, but very wierd error so report it */
|
||||||
|
+ logit("User %s fstat %s failed: %s",
|
||||||
|
+ pw->pw_name, file, strerror(errno));
|
||||||
|
+ fclose(fp);
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ if (!(st.st_uid == pw->pw_uid || st.st_uid == 0)) {
|
||||||
|
+ logit("User %s %s is not owned by root or user",
|
||||||
|
+ pw->pw_name, file);
|
||||||
|
+ fclose(fp);
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ /* .k5users must be a regular file. krb5_kuserok() doesn't do this
|
||||||
|
+ * check, but we don't want to be deficient if they add a check. */
|
||||||
|
+ if (!S_ISREG(st.st_mode)) {
|
||||||
|
+ logit("User %s %s is not a regular file", pw->pw_name, file);
|
||||||
|
+ fclose(fp);
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ /* file exists; initialize k5users_allowed_cmds (to none!) */
|
||||||
|
+ 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++;
|
||||||
|
+ char *token;
|
||||||
|
+
|
||||||
|
+ /* we parse just like ksu, even though we could do better */
|
||||||
|
+ if ((token = strtok(line, " \t\n")) == NULL)
|
||||||
|
+ continue;
|
||||||
|
+ if (strcmp(name, token) == 0) {
|
||||||
|
+ /* we matched on client principal */
|
||||||
|
+ found_principal = 1;
|
||||||
|
+ if ((token = strtok(NULL, " \t\n")) == NULL) {
|
||||||
|
+ /* only shell is allowed */
|
||||||
|
+ k5users_allowed_cmds[ncommands-1] =
|
||||||
|
+ xstrdup(pw->pw_shell);
|
||||||
|
+ k5users_allowed_cmds =
|
||||||
|
+ xreallocarray(k5users_allowed_cmds, ++ncommands,
|
||||||
|
+ sizeof(*k5users_allowed_cmds));
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ /* process the allowed commands */
|
||||||
|
+ while (token) {
|
||||||
|
+ if (strcmp(token, "*") == 0) {
|
||||||
|
+ allcommands = 1;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ k5users_allowed_cmds[ncommands-1] =
|
||||||
|
+ xstrdup(token);
|
||||||
|
+ k5users_allowed_cmds =
|
||||||
|
+ xreallocarray(k5users_allowed_cmds, ++ncommands,
|
||||||
|
+ sizeof(*k5users_allowed_cmds));
|
||||||
|
+ token = strtok(NULL, " \t\n");
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ free(line);
|
||||||
|
+ if (k5users_allowed_cmds) {
|
||||||
|
+ /* terminate vector */
|
||||||
|
+ k5users_allowed_cmds[ncommands-1] = NULL;
|
||||||
|
+ /* if all commands are allowed, free vector */
|
||||||
|
+ if (allcommands) {
|
||||||
|
+ int i;
|
||||||
|
+ for (i = 0; i < ncommands; i++) {
|
||||||
|
+ free(k5users_allowed_cmds[i]);
|
||||||
|
+ }
|
||||||
|
+ free(k5users_allowed_cmds);
|
||||||
|
+ k5users_allowed_cmds = NULL;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ fclose(fp);
|
||||||
|
+ return found_principal;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
|
||||||
|
/* 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 28659ec..9c94d8e 100644
|
||||||
|
--- a/session.c
|
||||||
|
+++ b/session.c
|
||||||
|
@@ -789,6 +789,29 @@ do_exec(Session *s, const char *command)
|
||||||
|
command = auth_opts->force_command;
|
||||||
|
forced = "(key-option)";
|
||||||
|
}
|
||||||
|
+#ifdef GSSAPI
|
||||||
|
+#ifdef KRB5 /* k5users_allowed_cmds only available w/ GSSAPI+KRB5 */
|
||||||
|
+ else if (k5users_allowed_cmds) {
|
||||||
|
+ const char *match = command;
|
||||||
|
+ int allowed = 0, i = 0;
|
||||||
|
+
|
||||||
|
+ if (!match)
|
||||||
|
+ match = s->pw->pw_shell;
|
||||||
|
+ while (k5users_allowed_cmds[i]) {
|
||||||
|
+ if (strcmp(match, k5users_allowed_cmds[i++]) == 0) {
|
||||||
|
+ debug("Allowed command '%.900s'", match);
|
||||||
|
+ allowed = 1;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ if (!allowed) {
|
||||||
|
+ debug("command '%.900s' not allowed", match);
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
s->forced = 0;
|
||||||
|
if (forced != NULL) {
|
||||||
|
s->forced = 1;
|
||||||
|
diff --git a/ssh-gss.h b/ssh-gss.h
|
||||||
|
index 0374c88..509109a 100644
|
||||||
|
--- a/ssh-gss.h
|
||||||
|
+++ b/ssh-gss.h
|
||||||
|
@@ -49,6 +49,10 @@
|
||||||
|
# endif /* !HAVE_DECL_GSS_C_NT_... */
|
||||||
|
|
||||||
|
# endif /* !HEIMDAL */
|
||||||
|
+
|
||||||
|
+/* .k5users support */
|
||||||
|
+extern char **k5users_allowed_cmds;
|
||||||
|
+
|
||||||
|
#endif /* KRB5 */
|
||||||
|
|
||||||
|
/* draft-ietf-secsh-gsskeyex-06 */
|
||||||
|
diff --git a/sshd.8 b/sshd.8
|
||||||
|
index adcaaf9..824163b 100644
|
||||||
|
--- a/sshd.8
|
||||||
|
+++ b/sshd.8
|
||||||
|
@@ -324,6 +324,7 @@ Finally, the server and the client enter an authentication dialog.
|
||||||
|
The client tries to authenticate itself using
|
||||||
|
host-based authentication,
|
||||||
|
public key authentication,
|
||||||
|
+GSSAPI authentication,
|
||||||
|
challenge-response authentication,
|
||||||
|
or password authentication.
|
||||||
|
.Pp
|
||||||
|
@@ -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
|
||||||
|
+.It Pa ~/.k5login
|
||||||
|
+.It Pa ~/.k5users
|
||||||
|
+These files enforce GSSAPI/Kerberos authentication access control.
|
||||||
|
+Further details are described in
|
||||||
|
+.Xr ksu 1 .
|
||||||
|
+.Pp
|
||||||
|
.It Pa ~/.ssh/
|
||||||
|
This directory is the default location for all user-specific configuration
|
||||||
|
and authentication information.
|
@ -0,0 +1,484 @@
|
|||||||
|
diff -up openssh/misc.c.keycat openssh/misc.c
|
||||||
|
--- openssh/misc.c.keycat 2015-06-24 10:57:50.158849606 +0200
|
||||||
|
+++ openssh/misc.c 2015-06-24 11:04:23.989868638 +0200
|
||||||
|
@@ -966,6 +966,13 @@ subprocess(const char *tag, struct passw
|
||||||
|
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 -up openssh/HOWTO.ssh-keycat.keycat openssh/HOWTO.ssh-keycat
|
||||||
|
--- openssh/HOWTO.ssh-keycat.keycat 2015-06-24 10:57:50.157849608 +0200
|
||||||
|
+++ openssh/HOWTO.ssh-keycat 2015-06-24 10:57:50.157849608 +0200
|
||||||
|
@@ -0,0 +1,12 @@
|
||||||
|
+The ssh-keycat retrieves the content of the ~/.ssh/authorized_keys
|
||||||
|
+of an user in any environment. This includes environments with
|
||||||
|
+polyinstantiation of home directories and SELinux MLS policy enabled.
|
||||||
|
+
|
||||||
|
+To use ssh-keycat, set these options in /etc/ssh/sshd_config file:
|
||||||
|
+ AuthorizedKeysCommand /usr/libexec/openssh/ssh-keycat
|
||||||
|
+ AuthorizedKeysCommandUser root
|
||||||
|
+
|
||||||
|
+Do not forget to enable public key authentication:
|
||||||
|
+ PubkeyAuthentication yes
|
||||||
|
+
|
||||||
|
+
|
||||||
|
diff -up openssh/Makefile.in.keycat openssh/Makefile.in
|
||||||
|
--- openssh/Makefile.in.keycat 2015-06-24 10:57:50.152849621 +0200
|
||||||
|
+++ openssh/Makefile.in 2015-06-24 10:57:50.157849608 +0200
|
||||||
|
@@ -27,6 +27,7 @@ SFTP_SERVER=$(libexecdir)/sftp-server
|
||||||
|
ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass
|
||||||
|
SFTP_SERVER=$(libexecdir)/sftp-server
|
||||||
|
SSH_KEYSIGN=$(libexecdir)/ssh-keysign
|
||||||
|
+SSH_KEYCAT=$(libexecdir)/ssh-keycat
|
||||||
|
SSHD_SESSION=$(libexecdir)/sshd-session
|
||||||
|
SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
|
||||||
|
SSH_SK_HELPER=$(libexecdir)/ssh-sk-helper
|
||||||
|
@@ -52,6 +52,7 @@ K5LIBS=@K5LIBS@
|
||||||
|
K5LIBS=@K5LIBS@
|
||||||
|
GSSLIBS=@GSSLIBS@
|
||||||
|
SSHDLIBS=@SSHDLIBS@
|
||||||
|
+KEYCATLIBS=@KEYCATLIBS@
|
||||||
|
LIBEDIT=@LIBEDIT@
|
||||||
|
LIBFIDO2=@LIBFIDO2@
|
||||||
|
AR=@AR@
|
||||||
|
@@ -65,7 +66,7 @@ EXEEXT=@EXEEXT@
|
||||||
|
|
||||||
|
.SUFFIXES: .lo
|
||||||
|
|
||||||
|
-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) sshd-session$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT)
|
||||||
|
+TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) sshd-session$(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)
|
||||||
|
|
||||||
|
XMSS_OBJS=\
|
||||||
|
ssh-xmss.o \
|
||||||
|
@@ -190,6 +191,9 @@ ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT)
|
||||||
|
ssh-sk-helper$(EXEEXT): $(LIBCOMPAT) libssh.a $(SKHELPER_OBJS)
|
||||||
|
$(LD) -o $@ $(SKHELPER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) $(LIBFIDO2) $(CHANNELLIBS)
|
||||||
|
|
||||||
|
+ssh-keycat$(EXEEXT): $(LIBCOMPAT) $(SSHDOBJS) libssh.a ssh-keycat.o uidswap.o
|
||||||
|
+ $(LD) -o $@ ssh-keycat.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat $(KEYCATLIBS) $(LIBS)
|
||||||
|
+
|
||||||
|
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYSCAN_OBJS)
|
||||||
|
$(LD) -o $@ $(SSHKEYSCAN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) $(CHANNELLIBS)
|
||||||
|
|
||||||
|
@@ -321,6 +325,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)
|
||||||
|
+ $(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 -up openssh/openbsd-compat/port-linux.h.keycat openssh/openbsd-compat/port-linux.h
|
||||||
|
--- openssh/openbsd-compat/port-linux.h.keycat 2015-06-24 10:57:50.150849626 +0200
|
||||||
|
+++ openssh/openbsd-compat/port-linux.h 2015-06-24 10:57:50.160849601 +0200
|
||||||
|
@@ -25,8 +25,10 @@ void ssh_selinux_setup_pty(char *, const
|
||||||
|
void ssh_selinux_change_context(const char *);
|
||||||
|
void ssh_selinux_setfscreatecon(const char *);
|
||||||
|
|
||||||
|
+int sshd_selinux_enabled(void);
|
||||||
|
void sshd_selinux_copy_context(void);
|
||||||
|
void sshd_selinux_setup_exec_context(char *);
|
||||||
|
+int sshd_selinux_setup_env_variables(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LINUX_OOM_ADJUST
|
||||||
|
diff -up openssh/openbsd-compat/port-linux-sshd.c.keycat openssh/openbsd-compat/port-linux-sshd.c
|
||||||
|
--- openssh/openbsd-compat/port-linux-sshd.c.keycat 2015-06-24 10:57:50.150849626 +0200
|
||||||
|
+++ openssh/openbsd-compat/port-linux-sshd.c 2015-06-24 10:57:50.159849603 +0200
|
||||||
|
@@ -54,6 +54,20 @@ extern Authctxt *the_authctxt;
|
||||||
|
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)
|
||||||
|
+{
|
||||||
|
+ static int enabled = -1;
|
||||||
|
+
|
||||||
|
+ if (enabled == -1) {
|
||||||
|
+ enabled = (is_selinux_enabled() == 1);
|
||||||
|
+ debug("SELinux support %s", enabled ? "enabled" : "disabled");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return (enabled);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Send audit message */
|
||||||
|
static int
|
||||||
|
sshd_selinux_send_audit_message(int success, security_context_t default_context,
|
||||||
|
@@ -308,7 +322,7 @@ sshd_selinux_getctxbyname(char *pwname,
|
||||||
|
|
||||||
|
/* Setup environment variables for pam_selinux */
|
||||||
|
static int
|
||||||
|
-sshd_selinux_setup_pam_variables(void)
|
||||||
|
+sshd_selinux_setup_variables(int(*set_it)(char *, const char *))
|
||||||
|
{
|
||||||
|
const char *reqlvl;
|
||||||
|
char *role;
|
||||||
|
@@ -319,16 +333,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) {
|
||||||
|
use_current = "1";
|
||||||
|
} else {
|
||||||
|
use_current = "";
|
||||||
|
- rv = rv || do_pam_putenv("SELINUX_LEVEL_REQUESTED", reqlvl ? reqlvl: "");
|
||||||
|
+ rv = rv || set_it("SELINUX_LEVEL_REQUESTED", reqlvl ? reqlvl: "");
|
||||||
|
}
|
||||||
|
|
||||||
|
- rv = rv || do_pam_putenv("SELINUX_USE_CURRENT_RANGE", use_current);
|
||||||
|
+ rv = rv || set_it("SELINUX_USE_CURRENT_RANGE", use_current);
|
||||||
|
|
||||||
|
if (role != NULL)
|
||||||
|
free(role);
|
||||||
|
@@ -336,6 +350,24 @@ sshd_selinux_setup_pam_variables(void)
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int
|
||||||
|
+sshd_selinux_setup_pam_variables(void)
|
||||||
|
+{
|
||||||
|
+ return sshd_selinux_setup_variables(do_pam_putenv);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+do_setenv(char *name, const char *value)
|
||||||
|
+{
|
||||||
|
+ return setenv(name, value, 1);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+sshd_selinux_setup_env_variables(void)
|
||||||
|
+{
|
||||||
|
+ return sshd_selinux_setup_variables(do_setenv);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Set the execution context to the default for the specified user */
|
||||||
|
void
|
||||||
|
sshd_selinux_setup_exec_context(char *pwname)
|
||||||
|
@@ -344,7 +376,7 @@ sshd_selinux_setup_exec_context(char *pw
|
||||||
|
int r = 0;
|
||||||
|
security_context_t default_ctx = NULL;
|
||||||
|
|
||||||
|
- if (!ssh_selinux_enabled())
|
||||||
|
+ if (!sshd_selinux_enabled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (options.use_pam) {
|
||||||
|
@@ -415,7 +447,7 @@ sshd_selinux_copy_context(void)
|
||||||
|
{
|
||||||
|
security_context_t *ctx;
|
||||||
|
|
||||||
|
- if (!ssh_selinux_enabled())
|
||||||
|
+ if (!sshd_selinux_enabled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (getexeccon((security_context_t *)&ctx) != 0) {
|
||||||
|
diff -up openssh/platform.c.keycat openssh/platform.c
|
||||||
|
--- openssh/platform.c.keycat 2015-06-24 10:57:50.147849633 +0200
|
||||||
|
+++ openssh/platform.c 2015-06-24 10:57:50.160849601 +0200
|
||||||
|
@@ -103,7 +103,7 @@ platform_setusercontext(struct passwd *p
|
||||||
|
{
|
||||||
|
#ifdef WITH_SELINUX
|
||||||
|
/* Cache selinux status for later use */
|
||||||
|
- (void)ssh_selinux_enabled();
|
||||||
|
+ (void)sshd_selinux_enabled();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_SOLARIS_PROJECTS
|
||||||
|
diff -up openssh/ssh-keycat.c.keycat openssh/ssh-keycat.c
|
||||||
|
--- openssh/ssh-keycat.c.keycat 2015-06-24 10:57:50.161849599 +0200
|
||||||
|
+++ openssh/ssh-keycat.c 2015-06-24 10:57:50.161849599 +0200
|
||||||
|
@@ -0,0 +1,241 @@
|
||||||
|
+/*
|
||||||
|
+ * Redistribution and use in source and binary forms, with or without
|
||||||
|
+ * modification, are permitted provided that the following conditions
|
||||||
|
+ * are met:
|
||||||
|
+ * 1. Redistributions of source code must retain the above copyright
|
||||||
|
+ * notice, and the entire permission notice in its entirety,
|
||||||
|
+ * including the disclaimer of warranties.
|
||||||
|
+ * 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
+ * notice, this list of conditions and the following disclaimer in the
|
||||||
|
+ * documentation and/or other materials provided with the distribution.
|
||||||
|
+ * 3. The name of the author may not be used to endorse or promote
|
||||||
|
+ * products derived from this software without specific prior
|
||||||
|
+ * written permission.
|
||||||
|
+ *
|
||||||
|
+ * ALTERNATIVELY, this product may be distributed under the terms of
|
||||||
|
+ * the GNU Public License, in which case the provisions of the GPL are
|
||||||
|
+ * required INSTEAD OF the above restrictions. (This clause is
|
||||||
|
+ * necessary due to a potential bad interaction between the GPL and
|
||||||
|
+ * the restrictions contained in a BSD-style copyright.)
|
||||||
|
+ *
|
||||||
|
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||||
|
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Copyright (c) 2011 Red Hat, Inc.
|
||||||
|
+ * Written by Tomas Mraz <tmraz@redhat.com>
|
||||||
|
+*/
|
||||||
|
+
|
||||||
|
+#define _GNU_SOURCE
|
||||||
|
+
|
||||||
|
+#include "config.h"
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+#include <sys/types.h>
|
||||||
|
+#include <sys/stat.h>
|
||||||
|
+#include <pwd.h>
|
||||||
|
+#include <fcntl.h>
|
||||||
|
+#include <unistd.h>
|
||||||
|
+#ifdef HAVE_STDINT_H
|
||||||
|
+#include <stdint.h>
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#include <security/pam_appl.h>
|
||||||
|
+
|
||||||
|
+#include "uidswap.h"
|
||||||
|
+#include "misc.h"
|
||||||
|
+
|
||||||
|
+#define ERR_USAGE 1
|
||||||
|
+#define ERR_PAM_START 2
|
||||||
|
+#define ERR_OPEN_SESSION 3
|
||||||
|
+#define ERR_CLOSE_SESSION 4
|
||||||
|
+#define ERR_PAM_END 5
|
||||||
|
+#define ERR_GETPWNAM 6
|
||||||
|
+#define ERR_MEMORY 7
|
||||||
|
+#define ERR_OPEN 8
|
||||||
|
+#define ERR_FILE_MODE 9
|
||||||
|
+#define ERR_FDOPEN 10
|
||||||
|
+#define ERR_STAT 11
|
||||||
|
+#define ERR_WRITE 12
|
||||||
|
+#define ERR_PAM_PUTENV 13
|
||||||
|
+#define BUFLEN 4096
|
||||||
|
+
|
||||||
|
+/* Just ignore the messages in the conversation function */
|
||||||
|
+static int
|
||||||
|
+dummy_conv(int num_msg, const struct pam_message **msgm,
|
||||||
|
+ struct pam_response **response, void *appdata_ptr)
|
||||||
|
+{
|
||||||
|
+ struct pam_response *rsp;
|
||||||
|
+
|
||||||
|
+ (void)msgm;
|
||||||
|
+ (void)appdata_ptr;
|
||||||
|
+
|
||||||
|
+ if (num_msg <= 0)
|
||||||
|
+ return PAM_CONV_ERR;
|
||||||
|
+
|
||||||
|
+ /* Just allocate the array as empty responses */
|
||||||
|
+ rsp = calloc (num_msg, sizeof (struct pam_response));
|
||||||
|
+ if (rsp == NULL)
|
||||||
|
+ return PAM_CONV_ERR;
|
||||||
|
+
|
||||||
|
+ *response = rsp;
|
||||||
|
+ return PAM_SUCCESS;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct pam_conv conv = {
|
||||||
|
+ dummy_conv,
|
||||||
|
+ NULL
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+char *
|
||||||
|
+make_auth_keys_name(const struct passwd *pwd)
|
||||||
|
+{
|
||||||
|
+ char *fname;
|
||||||
|
+
|
||||||
|
+ if (asprintf(&fname, "%s/.ssh/authorized_keys", pwd->pw_dir) < 0)
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ return fname;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+dump_keys(const char *user)
|
||||||
|
+{
|
||||||
|
+ struct passwd *pwd;
|
||||||
|
+ int fd = -1;
|
||||||
|
+ FILE *f = NULL;
|
||||||
|
+ char *fname = NULL;
|
||||||
|
+ int rv = 0;
|
||||||
|
+ char buf[BUFLEN];
|
||||||
|
+ size_t len;
|
||||||
|
+ struct stat st;
|
||||||
|
+
|
||||||
|
+ if ((pwd = getpwnam(user)) == NULL) {
|
||||||
|
+ return ERR_GETPWNAM;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if ((fname = make_auth_keys_name(pwd)) == NULL) {
|
||||||
|
+ return ERR_MEMORY;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ temporarily_use_uid(pwd);
|
||||||
|
+
|
||||||
|
+ if ((fd = open(fname, O_RDONLY|O_NONBLOCK|O_NOFOLLOW, 0)) < 0) {
|
||||||
|
+ rv = ERR_OPEN;
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (fstat(fd, &st) < 0) {
|
||||||
|
+ rv = ERR_STAT;
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!S_ISREG(st.st_mode) ||
|
||||||
|
+ (st.st_uid != pwd->pw_uid && st.st_uid != 0)) {
|
||||||
|
+ rv = ERR_FILE_MODE;
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ unset_nonblock(fd);
|
||||||
|
+
|
||||||
|
+ if ((f = fdopen(fd, "r")) == NULL) {
|
||||||
|
+ rv = ERR_FDOPEN;
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ fd = -1;
|
||||||
|
+
|
||||||
|
+ while ((len = fread(buf, 1, sizeof(buf), f)) > 0) {
|
||||||
|
+ rv = fwrite(buf, 1, len, stdout) != len ? ERR_WRITE : 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+fail:
|
||||||
|
+ if (fd != -1)
|
||||||
|
+ close(fd);
|
||||||
|
+ if (f != NULL)
|
||||||
|
+ fclose(f);
|
||||||
|
+ free(fname);
|
||||||
|
+ restore_uid();
|
||||||
|
+ return rv;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static const char *env_names[] = { "SELINUX_ROLE_REQUESTED",
|
||||||
|
+ "SELINUX_LEVEL_REQUESTED",
|
||||||
|
+ "SELINUX_USE_CURRENT_RANGE"
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+extern char **environ;
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+set_pam_environment(pam_handle_t *pamh)
|
||||||
|
+{
|
||||||
|
+ int i;
|
||||||
|
+ size_t j;
|
||||||
|
+
|
||||||
|
+ for (j = 0; j < sizeof(env_names)/sizeof(env_names[0]); ++j) {
|
||||||
|
+ int len = strlen(env_names[j]);
|
||||||
|
+
|
||||||
|
+ for (i = 0; environ[i] != NULL; ++i) {
|
||||||
|
+ if (strncmp(env_names[j], environ[i], len) == 0 &&
|
||||||
|
+ environ[i][len] == '=') {
|
||||||
|
+ if (pam_putenv(pamh, environ[i]) != PAM_SUCCESS)
|
||||||
|
+ return ERR_PAM_PUTENV;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+main(int argc, char *argv[])
|
||||||
|
+{
|
||||||
|
+ pam_handle_t *pamh = NULL;
|
||||||
|
+ int retval;
|
||||||
|
+ int ev = 0;
|
||||||
|
+
|
||||||
|
+ if (argc != 2) {
|
||||||
|
+ fprintf(stderr, "Usage: %s <user-name>\n", argv[0]);
|
||||||
|
+ return ERR_USAGE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ retval = pam_start("ssh-keycat", argv[1], &conv, &pamh);
|
||||||
|
+ if (retval != PAM_SUCCESS) {
|
||||||
|
+ return ERR_PAM_START;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ev = set_pam_environment(pamh);
|
||||||
|
+ if (ev != 0)
|
||||||
|
+ goto finish;
|
||||||
|
+
|
||||||
|
+ retval = pam_open_session(pamh, PAM_SILENT);
|
||||||
|
+ if (retval != PAM_SUCCESS) {
|
||||||
|
+ ev = ERR_OPEN_SESSION;
|
||||||
|
+ goto finish;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ev = dump_keys(argv[1]);
|
||||||
|
+
|
||||||
|
+ retval = pam_close_session(pamh, PAM_SILENT);
|
||||||
|
+ if (retval != PAM_SUCCESS) {
|
||||||
|
+ ev = ERR_CLOSE_SESSION;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+finish:
|
||||||
|
+ retval = pam_end (pamh,retval);
|
||||||
|
+ if (retval != PAM_SUCCESS) {
|
||||||
|
+ ev = ERR_PAM_END;
|
||||||
|
+ }
|
||||||
|
+ return ev;
|
||||||
|
+}
|
||||||
|
diff --git a/configure.ac b/configure.ac
|
||||||
|
index 3bbccfd..6481f1f 100644
|
||||||
|
--- a/configure.ac
|
||||||
|
+++ b/configure.ac
|
||||||
|
@@ -2952,6 +2952,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])
|
||||||
|
|
||||||
|
@@ -3105,6 +3106,7 @@
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
SSHDLIBS="$SSHDLIBS -ldl"
|
||||||
|
+ KEYCATLIBS="$KEYCATLIBS -ldl"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
@@ -4042,6 +4044,7 @@ AC_ARG_WITH([selinux],
|
||||||
|
fi ]
|
||||||
|
)
|
||||||
|
AC_SUBST([SSHDLIBS])
|
||||||
|
+AC_SUBST([KEYCATLIBS])
|
||||||
|
|
||||||
|
# Check whether user wants Kerberos 5 support
|
||||||
|
KRB5_MSG="no"
|
||||||
|
@@ -5031,6 +5034,9 @@ fi
|
||||||
|
if test ! -z "${SSHDLIBS}"; then
|
||||||
|
echo " +for sshd: ${SSHDLIBS}"
|
||||||
|
fi
|
||||||
|
+if test ! -z "${KEYCATLIBS}"; then
|
||||||
|
+echo " +for ssh-keycat: ${KEYCATLIBS}"
|
||||||
|
+fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
@ -0,0 +1,289 @@
|
|||||||
|
diff -up openssh-7.4p1/auth-krb5.c.kuserok openssh-7.4p1/auth-krb5.c
|
||||||
|
--- openssh-7.4p1/auth-krb5.c.kuserok 2016-12-23 14:36:07.640465939 +0100
|
||||||
|
+++ openssh-7.4p1/auth-krb5.c 2016-12-23 14:36:07.644465936 +0100
|
||||||
|
@@ -56,6 +56,21 @@
|
||||||
|
|
||||||
|
extern ServerOptions options;
|
||||||
|
|
||||||
|
+int
|
||||||
|
+ssh_krb5_kuserok(krb5_context krb5_ctx, krb5_principal krb5_user, const char *client,
|
||||||
|
+ int k5login_exists)
|
||||||
|
+{
|
||||||
|
+ if (options.use_kuserok || !k5login_exists)
|
||||||
|
+ return krb5_kuserok(krb5_ctx, krb5_user, client);
|
||||||
|
+ else {
|
||||||
|
+ char kuser[65];
|
||||||
|
+
|
||||||
|
+ if (krb5_aname_to_localname(krb5_ctx, krb5_user, sizeof(kuser), kuser))
|
||||||
|
+ return 0;
|
||||||
|
+ return strcmp(kuser, client) == 0;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
krb5_init(void *context)
|
||||||
|
{
|
||||||
|
@@ -160,8 +175,9 @@ auth_krb5_password(Authctxt *authctxt, c
|
||||||
|
if (problem)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
- if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user,
|
||||||
|
- authctxt->pw->pw_name)) {
|
||||||
|
+ /* Use !options.use_kuserok here to make ssh_krb5_kuserok() not
|
||||||
|
+ * depend on the existance of .k5login */
|
||||||
|
+ if (!ssh_krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, authctxt->pw->pw_name, !options.use_kuserok)) {
|
||||||
|
problem = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
diff -up openssh-7.4p1/gss-serv-krb5.c.kuserok openssh-7.4p1/gss-serv-krb5.c
|
||||||
|
--- openssh-7.4p1/gss-serv-krb5.c.kuserok 2016-12-23 14:36:07.640465939 +0100
|
||||||
|
+++ openssh-7.4p1/gss-serv-krb5.c 2016-12-23 14:36:07.644465936 +0100
|
||||||
|
@@ -67,6 +67,7 @@ static int ssh_gssapi_krb5_cmdok(krb5_pr
|
||||||
|
int);
|
||||||
|
|
||||||
|
static krb5_context krb_context = NULL;
|
||||||
|
+extern int ssh_krb5_kuserok(krb5_context, krb5_principal, const char *, int);
|
||||||
|
|
||||||
|
/* Initialise the krb5 library, for the stuff that GSSAPI won't do */
|
||||||
|
|
||||||
|
@@ -92,6 +93,103 @@ ssh_gssapi_krb5_init(void)
|
||||||
|
* Returns true if the user is OK to log in, otherwise returns 0
|
||||||
|
*/
|
||||||
|
|
||||||
|
+/* The purpose of the function is to find out if a Kerberos principal is
|
||||||
|
+ * allowed to log in as the given local user. This is a general problem with
|
||||||
|
+ * Kerberized services because by design the Kerberos principals are
|
||||||
|
+ * completely independent from the local user names. This is one of the
|
||||||
|
+ * reasons why Kerberos is working well on different operating systems like
|
||||||
|
+ * Windows and UNIX/Linux. Nevertheless a relationship between a Kerberos
|
||||||
|
+ * principal and a local user name must be established because otherwise every
|
||||||
|
+ * access would be granted for every principal with a valid ticket.
|
||||||
|
+ *
|
||||||
|
+ * Since it is a general issue libkrb5 provides some functions for
|
||||||
|
+ * applications to find out about the relationship between the Kerberos
|
||||||
|
+ * principal and a local user name. They are krb5_kuserok() and
|
||||||
|
+ * krb5_aname_to_localname().
|
||||||
|
+ *
|
||||||
|
+ * krb5_kuserok() can be used to "Determine if a principal is authorized to
|
||||||
|
+ * log in as a local user" (from the MIT Kerberos documentation of this
|
||||||
|
+ * function). Which is exactly what we are looking for and should be the
|
||||||
|
+ * preferred choice. It accepts the Kerberos principal and a local user name
|
||||||
|
+ * and let libkrb5 or its plugins determine if they relate to each other or
|
||||||
|
+ * not.
|
||||||
|
+ *
|
||||||
|
+ * krb5_aname_to_localname() can use used to "Convert a principal name to a
|
||||||
|
+ * local name" (from the MIT Kerberos documentation of this function). It
|
||||||
|
+ * accepts a Kerberos principle and returns a local name and it is up to the
|
||||||
|
+ * application to do any additional checks. There are two issues using
|
||||||
|
+ * krb5_aname_to_localname(). First, since POSIX user names are case
|
||||||
|
+ * sensitive, the calling application in general has no other choice than
|
||||||
|
+ * doing a case-sensitive string comparison between the name returned by
|
||||||
|
+ * krb5_aname_to_localname() and the name used at the login prompt. When the
|
||||||
|
+ * users are provided by a case in-sensitive server, e.g. Active Directory,
|
||||||
|
+ * this might lead to login failures because the user typing the name at the
|
||||||
|
+ * login prompt might not be aware of the right case. Another issue might be
|
||||||
|
+ * caused if there are multiple alias names available for a single user. E.g.
|
||||||
|
+ * the canonical name of a user is user@group.department.example.com but there
|
||||||
|
+ * exists a shorter login name, e.g. user@example.com, to safe typing at the
|
||||||
|
+ * login prompt. Here krb5_aname_to_localname() can only return the canonical
|
||||||
|
+ * name, but if the short alias is used at the login prompt authentication
|
||||||
|
+ * will fail as well. All this can be avoided by using krb5_kuserok() and
|
||||||
|
+ * configuring krb5.conf or using a suitable plugin to meet the needs of the
|
||||||
|
+ * given environment.
|
||||||
|
+ *
|
||||||
|
+ * The Fedora and RHEL version of openssh contain two patches which modify the
|
||||||
|
+ * access control behavior:
|
||||||
|
+ * - openssh-6.6p1-kuserok.patch
|
||||||
|
+ * - openssh-6.6p1-force_krb.patch
|
||||||
|
+ *
|
||||||
|
+ * openssh-6.6p1-kuserok.patch adds a new option KerberosUseKuserok for
|
||||||
|
+ * sshd_config which controls if krb5_kuserok() is used to check if the
|
||||||
|
+ * principle is authorized or if krb5_aname_to_localname() should be used.
|
||||||
|
+ * The reason to add this patch was that krb5_kuserok() by default checks if
|
||||||
|
+ * a .k5login file exits in the users home-directory. With this the user can
|
||||||
|
+ * give access to his account for any given principal which might be
|
||||||
|
+ * in violation with company policies and it would be useful if this can be
|
||||||
|
+ * rejected. Nevertheless the patch ignores the fact that krb5_kuserok() does
|
||||||
|
+ * no only check .k5login but other sources as well and checking .k5login can
|
||||||
|
+ * be disabled for all applications in krb5.conf as well. With this new
|
||||||
|
+ * option KerberosUseKuserok set to 'no' (and this is the default for RHEL7
|
||||||
|
+ * and Fedora 21) openssh can only use krb5_aname_to_localname() with the
|
||||||
|
+ * restrictions mentioned above.
|
||||||
|
+ *
|
||||||
|
+ * openssh-6.6p1-force_krb.patch adds a ksu like behaviour to ssh, i.e. when
|
||||||
|
+ * using GSSAPI authentication only commands configured in the .k5user can be
|
||||||
|
+ * executed. Here the wrong assumption that krb5_kuserok() only checks
|
||||||
|
+ * .k5login is made as well. In contrast ksu checks .k5login directly and
|
||||||
|
+ * does not use krb5_kuserok() which might be more useful for the given
|
||||||
|
+ * purpose. Additionally this patch is not synced with
|
||||||
|
+ * openssh-6.6p1-kuserok.patch.
|
||||||
|
+ *
|
||||||
|
+ * The current patch tries to restore the usage of krb5_kuserok() so that e.g.
|
||||||
|
+ * localauth plugins can be used. It does so by adding a forth parameter to
|
||||||
|
+ * ssh_krb5_kuserok() which indicates whether .k5login exists or not. If it
|
||||||
|
+ * does not exists krb5_kuserok() is called even if KerberosUseKuserok is set
|
||||||
|
+ * to 'no' because the intent of the option is to not check .k5login and if it
|
||||||
|
+ * does not exists krb5_kuserok() returns a result without checking .k5login.
|
||||||
|
+ * If .k5login does exists and KerberosUseKuserok is 'no' we fall back to
|
||||||
|
+ * krb5_aname_to_localname(). This is in my point of view an acceptable
|
||||||
|
+ * limitation and does not break the current behaviour.
|
||||||
|
+ *
|
||||||
|
+ * Additionally with this patch ssh_krb5_kuserok() is called in
|
||||||
|
+ * ssh_gssapi_krb5_cmdok() instead of only krb5_aname_to_localname() is
|
||||||
|
+ * neither .k5login nor .k5users exists to allow plugin evaluation via
|
||||||
|
+ * krb5_kuserok() as well.
|
||||||
|
+ *
|
||||||
|
+ * I tried to keep the patch as minimal as possible, nevertheless I see some
|
||||||
|
+ * areas for improvement which, if they make sense, have to be evaluated
|
||||||
|
+ * carefully because they might change existing behaviour and cause breaks
|
||||||
|
+ * during upgrade:
|
||||||
|
+ * - I wonder if disabling .k5login usage make sense in sshd or if it should
|
||||||
|
+ * be better disabled globally in krb5.conf
|
||||||
|
+ * - if really needed openssh-6.6p1-kuserok.patch should be fixed to really
|
||||||
|
+ * only disable checking .k5login and maybe .k5users
|
||||||
|
+ * - the ksu behaviour should be configurable and maybe check the .k5login and
|
||||||
|
+ * .k5users files directly like ksu itself does
|
||||||
|
+ * - to make krb5_aname_to_localname() more useful an option for sshd to use
|
||||||
|
+ * the canonical name (the one returned by getpwnam()) instead of the name
|
||||||
|
+ * given at the login prompt might be useful */
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name)
|
||||||
|
{
|
||||||
|
@@ -116,7 +214,8 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client
|
||||||
|
/* NOTE: .k5login and .k5users must opened as root, not the user,
|
||||||
|
* because if they are on a krb5-protected filesystem, user credentials
|
||||||
|
* to access these files aren't available yet. */
|
||||||
|
- if (krb5_kuserok(krb_context, princ, name) && k5login_exists) {
|
||||||
|
+ 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);
|
||||||
|
@@ -190,9 +289,8 @@ 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)) {
|
||||||
|
- return (krb5_aname_to_localname(krb_context, principal,
|
||||||
|
- sizeof(kuser), kuser) == 0) &&
|
||||||
|
- (strcmp(kuser, luser) == 0);
|
||||||
|
+ return ssh_krb5_kuserok(krb_context, principal, luser,
|
||||||
|
+ k5login_exists);
|
||||||
|
}
|
||||||
|
if ((fp = fopen(file, "r")) == NULL) {
|
||||||
|
int saved_errno = errno;
|
||||||
|
diff -up openssh-7.4p1/servconf.c.kuserok openssh-7.4p1/servconf.c
|
||||||
|
--- openssh-7.4p1/servconf.c.kuserok 2016-12-23 14:36:07.630465944 +0100
|
||||||
|
+++ openssh-7.4p1/servconf.c 2016-12-23 15:11:52.278133344 +0100
|
||||||
|
@@ -116,6 +116,7 @@ initialize_server_options(ServerOptions
|
||||||
|
options->gss_strict_acceptor = -1;
|
||||||
|
options->gss_store_rekey = -1;
|
||||||
|
options->gss_kex_algorithms = NULL;
|
||||||
|
+ options->use_kuserok = -1;
|
||||||
|
options->password_authentication = -1;
|
||||||
|
options->kbd_interactive_authentication = -1;
|
||||||
|
options->permit_empty_passwd = -1;
|
||||||
|
@@ -278,6 +279,8 @@ fill_default_server_options(ServerOption
|
||||||
|
if (options->gss_kex_algorithms == NULL)
|
||||||
|
options->gss_kex_algorithms = strdup(GSS_KEX_DEFAULT_KEX);
|
||||||
|
#endif
|
||||||
|
+ if (options->use_kuserok == -1)
|
||||||
|
+ options->use_kuserok = 1;
|
||||||
|
if (options->password_authentication == -1)
|
||||||
|
options->password_authentication = 1;
|
||||||
|
if (options->kbd_interactive_authentication == -1)
|
||||||
|
@@ -399,7 +402,7 @@ typedef enum {
|
||||||
|
sPort, sHostKeyFile, sLoginGraceTime,
|
||||||
|
sPermitRootLogin, sLogFacility, sLogLevel, sLogVerbose,
|
||||||
|
sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
|
||||||
|
- sKerberosGetAFSToken, sKerberosUniqueCCache, sPasswordAuthentication,
|
||||||
|
+ sKerberosGetAFSToken, sKerberosUniqueCCache, sKerberosUseKuserok, sPasswordAuthentication,
|
||||||
|
sKbdInteractiveAuthentication, sListenAddress, sAddressFamily,
|
||||||
|
sPrintMotd, sPrintLastLog, sIgnoreRhosts,
|
||||||
|
sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
|
||||||
|
@@ -478,12 +481,14 @@ static struct {
|
||||||
|
{ "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
|
||||||
|
#endif
|
||||||
|
{ "kerberosuniqueccache", sKerberosUniqueCCache, SSHCFG_GLOBAL },
|
||||||
|
+ { "kerberosusekuserok", sKerberosUseKuserok, SSHCFG_ALL },
|
||||||
|
#else
|
||||||
|
{ "kerberosauthentication", sUnsupported, SSHCFG_ALL },
|
||||||
|
{ "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL },
|
||||||
|
{ "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
|
||||||
|
{ "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
|
||||||
|
{ "kerberosuniqueccache", sUnsupported, SSHCFG_GLOBAL },
|
||||||
|
+ { "kerberosusekuserok", sUnsupported, SSHCFG_ALL },
|
||||||
|
#endif
|
||||||
|
{ "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
|
||||||
|
{ "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
|
||||||
|
@@ -1644,6 +1649,10 @@ process_server_config_line(ServerOptions
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
+ case sKerberosUseKuserok:
|
||||||
|
+ intptr = &options->use_kuserok;
|
||||||
|
+ goto parse_flag;
|
||||||
|
+
|
||||||
|
case sMatch:
|
||||||
|
if (cmdline)
|
||||||
|
fatal("Match directive not supported as a command-line "
|
||||||
|
@@ -2016,6 +2025,7 @@ copy_set_server_options(ServerOptions *d
|
||||||
|
M_CP_INTOPT(client_alive_interval);
|
||||||
|
M_CP_INTOPT(ip_qos_interactive);
|
||||||
|
M_CP_INTOPT(ip_qos_bulk);
|
||||||
|
+ M_CP_INTOPT(use_kuserok);
|
||||||
|
M_CP_INTOPT(rekey_limit);
|
||||||
|
M_CP_INTOPT(rekey_interval);
|
||||||
|
M_CP_INTOPT(log_level);
|
||||||
|
@@ -2309,6 +2319,7 @@ dump_config(ServerOptions *o)
|
||||||
|
dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token);
|
||||||
|
# endif
|
||||||
|
dump_cfg_fmtint(sKerberosUniqueCCache, o->kerberos_unique_ccache);
|
||||||
|
+ dump_cfg_fmtint(sKerberosUseKuserok, o->use_kuserok);
|
||||||
|
#endif
|
||||||
|
#ifdef GSSAPI
|
||||||
|
dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
|
||||||
|
diff -up openssh-7.4p1/servconf.h.kuserok openssh-7.4p1/servconf.h
|
||||||
|
--- openssh-7.4p1/servconf.h.kuserok 2016-12-23 14:36:07.630465944 +0100
|
||||||
|
+++ openssh-7.4p1/servconf.h 2016-12-23 14:36:07.645465936 +0100
|
||||||
|
@@ -118,6 +118,7 @@ typedef struct {
|
||||||
|
* authenticated with Kerberos. */
|
||||||
|
int kerberos_unique_ccache; /* If true, the acquired ticket will
|
||||||
|
* be stored in per-session ccache */
|
||||||
|
+ int use_kuserok;
|
||||||
|
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 -up openssh-7.4p1/sshd_config.5.kuserok openssh-7.4p1/sshd_config.5
|
||||||
|
--- openssh-7.4p1/sshd_config.5.kuserok 2016-12-23 14:36:07.637465940 +0100
|
||||||
|
+++ openssh-7.4p1/sshd_config.5 2016-12-23 15:14:03.117162222 +0100
|
||||||
|
@@ -850,6 +850,10 @@ Specifies whether to automatically destr
|
||||||
|
.Cm no
|
||||||
|
can lead to overwriting previous tickets by subseqent connections to the same
|
||||||
|
user account.
|
||||||
|
+.It Cm KerberosUseKuserok
|
||||||
|
+Specifies whether to look at .k5login file for user's aliases.
|
||||||
|
+The default is
|
||||||
|
+.Cm yes .
|
||||||
|
.It Cm KexAlgorithms
|
||||||
|
Specifies the permitted KEX (Key Exchange) algorithms that the server will
|
||||||
|
offer to clients.
|
||||||
|
@@ -1078,6 +1082,7 @@ Available keywords are
|
||||||
|
.Cm IPQoS ,
|
||||||
|
.Cm KbdInteractiveAuthentication ,
|
||||||
|
.Cm KerberosAuthentication ,
|
||||||
|
+.Cm KerberosUseKuserok ,
|
||||||
|
.Cm LogLevel ,
|
||||||
|
.Cm MaxAuthTries ,
|
||||||
|
.Cm MaxSessions ,
|
||||||
|
diff -up openssh-7.4p1/sshd_config.kuserok openssh-7.4p1/sshd_config
|
||||||
|
--- openssh-7.4p1/sshd_config.kuserok 2016-12-23 14:36:07.631465943 +0100
|
||||||
|
+++ openssh-7.4p1/sshd_config 2016-12-23 14:36:07.646465935 +0100
|
||||||
|
@@ -73,6 +73,7 @@ ChallengeResponseAuthentication no
|
||||||
|
#KerberosOrLocalPasswd yes
|
||||||
|
#KerberosTicketCleanup yes
|
||||||
|
#KerberosGetAFSToken no
|
||||||
|
+#KerberosUseKuserok yes
|
||||||
|
|
||||||
|
# GSSAPI options
|
||||||
|
#GSSAPIAuthentication no
|
@ -0,0 +1,120 @@
|
|||||||
|
diff -up openssh-7.4p1/openbsd-compat/port-linux.h.privsep-selinux openssh-7.4p1/openbsd-compat/port-linux.h
|
||||||
|
--- openssh-7.4p1/openbsd-compat/port-linux.h.privsep-selinux 2016-12-23 18:58:52.972122201 +0100
|
||||||
|
+++ openssh-7.4p1/openbsd-compat/port-linux.h 2016-12-23 18:58:52.974122201 +0100
|
||||||
|
@@ -23,6 +23,7 @@ void ssh_selinux_setup_pty(char *, const
|
||||||
|
void ssh_selinux_change_context(const char *);
|
||||||
|
void ssh_selinux_setfscreatecon(const char *);
|
||||||
|
|
||||||
|
+void sshd_selinux_copy_context(void);
|
||||||
|
void sshd_selinux_setup_exec_context(char *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
diff -up openssh-7.4p1/openbsd-compat/port-linux-sshd.c.privsep-selinux openssh-7.4p1/openbsd-compat/port-linux-sshd.c
|
||||||
|
--- openssh-7.4p1/openbsd-compat/port-linux-sshd.c.privsep-selinux 2016-12-23 18:58:52.973122201 +0100
|
||||||
|
+++ openssh-7.4p1/openbsd-compat/port-linux-sshd.c 2016-12-23 18:58:52.974122201 +0100
|
||||||
|
@@ -419,6 +419,28 @@ sshd_selinux_setup_exec_context(char *pw
|
||||||
|
debug3_f("done");
|
||||||
|
}
|
||||||
|
|
||||||
|
+void
|
||||||
|
+sshd_selinux_copy_context(void)
|
||||||
|
+{
|
||||||
|
+ security_context_t *ctx;
|
||||||
|
+
|
||||||
|
+ if (!ssh_selinux_enabled())
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ if (getexeccon((security_context_t *)&ctx) != 0) {
|
||||||
|
+ logit_f("getexeccon failed with %s", strerror(errno));
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ if (ctx != NULL) {
|
||||||
|
+ /* unset exec context before we will lose this capabililty */
|
||||||
|
+ if (setexeccon(NULL) != 0)
|
||||||
|
+ fatal_f("setexeccon failed with %s", strerror(errno));
|
||||||
|
+ if (setcon(ctx) != 0)
|
||||||
|
+ fatal_f("setcon failed with %s", strerror(errno));
|
||||||
|
+ freecon(ctx);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
diff -up openssh-7.4p1/session.c.privsep-selinux openssh-7.4p1/session.c
|
||||||
|
--- openssh-7.4p1/session.c.privsep-selinux 2016-12-19 05:59:41.000000000 +0100
|
||||||
|
+++ openssh-7.4p1/session.c 2016-12-23 18:58:52.974122201 +0100
|
||||||
|
@@ -1331,7 +1331,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) {
|
||||||
|
@@ -1361,6 +1361,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);
|
||||||
|
@@ -1396,6 +1399,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");
|
||||||
|
@@ -1413,9 +1421,6 @@ do_pwchange(Session *s)
|
||||||
|
if (s->ttyfd != -1) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"You must change your password now and login again!\n");
|
||||||
|
-#ifdef WITH_SELINUX
|
||||||
|
- setexeccon(NULL);
|
||||||
|
-#endif
|
||||||
|
#ifdef PASSWD_NEEDS_USERNAME
|
||||||
|
execl(_PATH_PASSWD_PROG, "passwd", s->pw->pw_name,
|
||||||
|
(char *)NULL);
|
||||||
|
@@ -1625,9 +1630,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 -up openssh-7.4p1/sshd.c.privsep-selinux openssh-7.4p1/sshd.c
|
||||||
|
--- openssh-7.4p1/sshd-session.c.privsep-selinux 2016-12-23 18:58:52.973122201 +0100
|
||||||
|
+++ openssh-7.4p1/sshd-session.c 2016-12-23 18:59:13.808124269 +0100
|
||||||
|
@@ -540,6 +540,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 (privsep_chroot) {
|
||||||
|
/* Change our root directory */
|
||||||
|
@@ -403,7 +403,7 @@ privsep_postauth(struct ssh *ssh, Authct
|
||||||
|
* 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
|
||||||
|
|
@ -0,0 +1,248 @@
|
|||||||
|
diff -up openssh-8.5p1/auth-krb5.c.coverity openssh-8.5p1/auth-krb5.c
|
||||||
|
--- openssh-8.5p1/auth-krb5.c.coverity 2021-03-24 12:03:33.724967756 +0100
|
||||||
|
+++ openssh-8.5p1/auth-krb5.c 2021-03-24 12:03:33.782968159 +0100
|
||||||
|
@@ -426,6 +426,7 @@ ssh_krb5_cc_new_unique(krb5_context ctx,
|
||||||
|
umask(old_umask);
|
||||||
|
if (tmpfd == -1) {
|
||||||
|
logit("mkstemp(): %.100s", strerror(oerrno));
|
||||||
|
+ free(ccname);
|
||||||
|
return oerrno;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -433,6 +434,7 @@ ssh_krb5_cc_new_unique(krb5_context ctx,
|
||||||
|
oerrno = errno;
|
||||||
|
logit("fchmod(): %.100s", strerror(oerrno));
|
||||||
|
close(tmpfd);
|
||||||
|
+ free(ccname);
|
||||||
|
return oerrno;
|
||||||
|
}
|
||||||
|
/* make sure the KRB5CCNAME is set for non-standard location */
|
||||||
|
diff -up openssh-8.5p1/gss-genr.c.coverity openssh-8.5p1/gss-genr.c
|
||||||
|
--- openssh-8.5p1/gss-genr.c.coverity 2021-03-26 11:52:46.613942552 +0100
|
||||||
|
+++ openssh-8.5p1/gss-genr.c 2021-03-26 11:54:37.881726318 +0100
|
||||||
|
@@ -167,8 +167,9 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_sup
|
||||||
|
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 -up openssh-8.5p1/krl.c.coverity openssh-8.5p1/krl.c
|
||||||
|
--- openssh-8.5p1/krl.c.coverity 2021-03-02 11:31:47.000000000 +0100
|
||||||
|
+++ openssh-8.5p1/krl.c 2021-03-24 12:03:33.783968166 +0100
|
||||||
|
@@ -1261,6 +1262,7 @@ is_key_revoked(struct ssh_krl *krl, cons
|
||||||
|
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;
|
||||||
|
@@ -1271,6 +1273,7 @@ is_key_revoked(struct ssh_krl *krl, cons
|
||||||
|
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;
|
||||||
|
@@ -1282,6 +1285,7 @@ is_key_revoked(struct ssh_krl *krl, cons
|
||||||
|
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 -up openssh-8.5p1/loginrec.c.coverity openssh-8.5p1/loginrec.c
|
||||||
|
--- openssh-8.5p1/loginrec.c.coverity 2021-03-24 13:18:53.793225885 +0100
|
||||||
|
+++ openssh-8.5p1/loginrec.c 2021-03-24 13:21:27.948404751 +0100
|
||||||
|
@@ -690,9 +690,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 -up openssh-8.5p1/misc.c.coverity openssh-8.5p1/misc.c
|
||||||
|
--- openssh-8.5p1/misc.c.coverity 2021-03-24 12:03:33.745967902 +0100
|
||||||
|
+++ openssh-8.5p1/misc.c 2021-03-24 13:31:47.037079617 +0100
|
||||||
|
@@ -1425,6 +1425,8 @@ sanitise_stdfd(void)
|
||||||
|
}
|
||||||
|
if (nullfd > STDERR_FILENO)
|
||||||
|
close(nullfd);
|
||||||
|
+ /* coverity[leaked_handle : FALSE]*/
|
||||||
|
+ /* coverity[leaked_handle : FALSE]*/
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
@@ -2511,6 +2513,7 @@ stdfd_devnull(int do_stdin, int do_stdou
|
||||||
|
}
|
||||||
|
if (devnull > STDERR_FILENO)
|
||||||
|
close(devnull);
|
||||||
|
+ /* coverity[leaked_handle : FALSE]*/
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff -up openssh-7.4p1/monitor.c.coverity openssh-7.4p1/monitor.c
|
||||||
|
--- openssh-7.4p1/monitor.c.coverity 2016-12-23 16:40:26.888788688 +0100
|
||||||
|
+++ openssh-7.4p1/monitor.c 2016-12-23 16:40:26.900788691 +0100
|
||||||
|
@@ -411,7 +411,7 @@ monitor_child_preauth(Authctxt *_authctx
|
||||||
|
mm_get_keystate(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)
|
||||||
|
@@ -1678,7 +1678,7 @@ mm_answer_pty(struct ssh *ssh, int sock,
|
||||||
|
s->ptymaster = s->ptyfd;
|
||||||
|
|
||||||
|
debug3_f("tty %s ptyfd %d", s->tty, s->ttyfd);
|
||||||
|
-
|
||||||
|
+ /* coverity[leaked_handle : FALSE] */
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
error:
|
||||||
|
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 2016-12-23 16:40:26.901788691 +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-8.7p1/openbsd-compat/bsd-pselect.c.coverity openssh-8.7p1/openbsd-compat/bsd-pselect.c
|
||||||
|
--- openssh-8.7p1/openbsd-compat/bsd-pselect.c.coverity 2021-08-30 16:36:11.357288009 +0200
|
||||||
|
+++ openssh-8.7p1/openbsd-compat/bsd-pselect.c 2021-08-30 16:37:21.791897976 +0200
|
||||||
|
@@ -113,13 +113,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
|
||||||
|
@@ -127,8 +127,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 -up openssh-8.5p1/readconf.c.coverity openssh-8.5p1/readconf.c
|
||||||
|
--- openssh-8.5p1/readconf.c.coverity 2021-03-24 12:03:33.778968131 +0100
|
||||||
|
+++ openssh-8.5p1/readconf.c 2021-03-24 12:03:33.785968180 +0100
|
||||||
|
@@ -1847,6 +1847,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 -up openssh-7.4p1/servconf.c.coverity openssh-7.4p1/servconf.c
|
||||||
|
--- openssh-7.4p1/servconf.c.coverity 2016-12-23 16:40:26.896788690 +0100
|
||||||
|
+++ openssh-7.4p1/servconf.c 2016-12-23 16:40:26.901788691 +0100
|
||||||
|
@@ -1638,8 +1638,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-8.7p1/serverloop.c.coverity openssh-8.7p1/serverloop.c
|
||||||
|
--- openssh-8.7p1/serverloop.c.coverity 2021-08-20 06:03:49.000000000 +0200
|
||||||
|
+++ openssh-8.7p1/serverloop.c 2021-08-30 16:28:22.416226981 +0200
|
||||||
|
@@ -547,7 +547,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 -up openssh-7.4p1/ssh-agent.c.coverity openssh-7.4p1/ssh-agent.c
|
||||||
|
--- openssh-7.4p1/ssh-agent.c.coverity 2016-12-19 05:59:41.000000000 +0100
|
||||||
|
+++ openssh-7.4p1/ssh-agent.c 2016-12-23 16:40:26.903788691 +0100
|
||||||
|
@@ -869,6 +869,7 @@ sanitize_pkcs11_provider(const char *pro
|
||||||
|
|
||||||
|
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 -up openssh-7.4p1/sshd-session.c.coverity openssh-7.4p1/sshd-session.c
|
||||||
|
--- openssh-7.4p1/sshd-session.c.coverity 2016-12-23 16:40:26.897788690 +0100
|
||||||
|
+++ openssh-7.4p1/sshd-session.c 2016-12-23 16:40:26.904788692 +0100
|
||||||
|
@@ -691,8 +691,10 @@ privsep_preauth(Authctxt *authctxt)
|
||||||
|
|
||||||
|
privsep_preauth_child(ssh);
|
||||||
|
setproctitle("%s", "[net]");
|
||||||
|
- if (box != NULL)
|
||||||
|
+ if (box != NULL) {
|
||||||
|
ssh_sandbox_child(box);
|
||||||
|
+ free(box);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@@ -2519,8 +2524,11 @@ do_ssh2_kex(struct ssh *ssh)
|
||||||
|
|
||||||
|
if (newstr)
|
||||||
|
myproposal[PROPOSAL_KEX_ALGS] = newstr;
|
||||||
|
- else
|
||||||
|
+ else {
|
||||||
|
fatal("No supported key exchange algorithms");
|
||||||
|
+ free(gss);
|
||||||
|
+ }
|
||||||
|
+ /* coverity[leaked_storage: FALSE]*/
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
diff -up openssh-8.5p1/ssh-keygen.c.coverity openssh-8.5p1/ssh-keygen.c
|
||||||
|
--- openssh-8.5p1/ssh-keygen.c.coverity 2021-03-24 12:03:33.780968145 +0100
|
||||||
|
+++ openssh-8.5p1/ssh-keygen.c 2021-03-24 12:03:33.787968194 +0100
|
||||||
|
@@ -2332,6 +2332,9 @@ update_krl_from_file(struct passwd *pw,
|
||||||
|
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;
|
@ -0,0 +1,100 @@
|
|||||||
|
diff -up openssh-7.2p2/sftp-server.8.sftp-force-mode openssh-7.2p2/sftp-server.8
|
||||||
|
--- openssh-7.2p2/sftp-server.8.sftp-force-mode 2016-03-09 19:04:48.000000000 +0100
|
||||||
|
+++ openssh-7.2p2/sftp-server.8 2016-06-23 16:18:20.463854117 +0200
|
||||||
|
@@ -38,6 +38,7 @@
|
||||||
|
.Op Fl P Ar denied_requests
|
||||||
|
.Op Fl p Ar allowed_requests
|
||||||
|
.Op Fl u Ar umask
|
||||||
|
+.Op Fl m Ar force_file_perms
|
||||||
|
.Ek
|
||||||
|
.Nm
|
||||||
|
.Fl Q Ar protocol_feature
|
||||||
|
@@ -138,6 +139,12 @@ 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.
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
On some systems,
|
||||||
|
diff -up openssh-7.2p2/sftp-server.c.sftp-force-mode openssh-7.2p2/sftp-server.c
|
||||||
|
--- openssh-7.2p2/sftp-server.c.sftp-force-mode 2016-06-23 16:18:20.446854128 +0200
|
||||||
|
+++ openssh-7.2p2/sftp-server.c 2016-06-23 16:20:37.950766082 +0200
|
||||||
|
@@ -69,6 +69,10 @@ struct sshbuf *oqueue;
|
||||||
|
/* Version of client */
|
||||||
|
static u_int version;
|
||||||
|
|
||||||
|
+/* Force file permissions */
|
||||||
|
+int permforce = 0;
|
||||||
|
+long permforcemode;
|
||||||
|
+
|
||||||
|
/* SSH2_FXP_INIT received */
|
||||||
|
static int init_done;
|
||||||
|
|
||||||
|
@@ -683,6 +687,7 @@ process_open(u_int32_t id)
|
||||||
|
Attrib a;
|
||||||
|
char *name;
|
||||||
|
int r, handle, fd, flags, mode, status = SSH2_FX_FAILURE;
|
||||||
|
+ mode_t old_umask = 0;
|
||||||
|
|
||||||
|
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
|
||||||
|
(r = sshbuf_get_u32(iqueue, &pflags)) != 0 || /* portable flags */
|
||||||
|
@@ -692,6 +697,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 &&
|
||||||
|
@@ -713,6 +722,8 @@ process_open(u_int32_t id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ if (permforce == 1)
|
||||||
|
+ (void) umask(old_umask); /* restore umask to something sane */
|
||||||
|
if (status != SSH2_FX_OK)
|
||||||
|
send_status(id, status);
|
||||||
|
free(name);
|
||||||
|
@@ -1494,7 +1505,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"
|
||||||
|
" %s -Q protocol_feature\n",
|
||||||
|
__progname, __progname);
|
||||||
|
exit(1);
|
||||||
|
@@ -1520,7 +1531,7 @@ sftp_server_main(int argc, char **argv,
|
||||||
|
pw = pwcopy(user_pw);
|
||||||
|
|
||||||
|
while (!skipargs && (ch = getopt(argc, argv,
|
||||||
|
- "d:f:l:P:p:Q:u:cehR")) != -1) {
|
||||||
|
+ "d:f:l:P:p:Q:u:m:cehR")) != -1) {
|
||||||
|
switch (ch) {
|
||||||
|
case 'Q':
|
||||||
|
if (strcasecmp(optarg, "requests") != 0) {
|
||||||
|
@@ -1580,6 +1591,15 @@ sftp_server_main(int argc, char **argv,
|
||||||
|
fatal("Invalid umask \"%s\"", optarg);
|
||||||
|
(void)umask((mode_t)mask);
|
||||||
|
break;
|
||||||
|
+ case 'm':
|
||||||
|
+ /* Force permissions on file received via sftp */
|
||||||
|
+ permforce = 1;
|
||||||
|
+ permforcemode = strtol(optarg, &cp, 8);
|
||||||
|
+ if (permforcemode < 0 || permforcemode > 0777 ||
|
||||||
|
+ *cp != '\0' || (permforcemode == 0 &&
|
||||||
|
+ errno != 0))
|
||||||
|
+ fatal("Invalid file mode \"%s\"", optarg);
|
||||||
|
+ break;
|
||||||
|
case 'h':
|
||||||
|
default:
|
||||||
|
sftp_server_usage();
|
@ -0,0 +1,12 @@
|
|||||||
|
diff -up openssh/servconf.c.sshdt openssh/servconf.c
|
||||||
|
--- openssh/servconf.c.sshdt 2015-06-24 11:42:29.041078704 +0200
|
||||||
|
+++ openssh/servconf.c 2015-06-24 11:44:39.734745802 +0200
|
||||||
|
@@ -2317,7 +2317,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);
|
@ -0,0 +1,186 @@
|
|||||||
|
diff -up openssh-7.4p1/monitor_wrap.c.audit-race openssh-7.4p1/monitor_wrap.c
|
||||||
|
--- openssh-7.4p1/monitor_wrap.c.audit-race 2016-12-23 16:35:52.694685771 +0100
|
||||||
|
+++ openssh-7.4p1/monitor_wrap.c 2016-12-23 16:35:52.697685772 +0100
|
||||||
|
@@ -1107,4 +1107,50 @@ mm_audit_destroy_sensitive_data(const ch
|
||||||
|
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 -up openssh-7.4p1/monitor_wrap.h.audit-race openssh-7.4p1/monitor_wrap.h
|
||||||
|
--- openssh-7.4p1/monitor_wrap.h.audit-race 2016-12-23 16:35:52.694685771 +0100
|
||||||
|
+++ openssh-7.4p1/monitor_wrap.h 2016-12-23 16:35:52.698685772 +0100
|
||||||
|
@@ -83,6 +83,8 @@ void mm_audit_unsupported_body(int);
|
||||||
|
void mm_audit_kex_body(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 -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c
|
||||||
|
--- openssh-7.4p1/session.c.audit-race 2016-12-23 16:35:52.695685771 +0100
|
||||||
|
+++ openssh-7.4p1/session.c 2016-12-23 16:37:26.339730596 +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(struct ssh *ssh);
|
||||||
|
+
|
||||||
|
#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
|
||||||
|
close(err[0]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+ child_destory_sensitive_data(ssh);
|
||||||
|
+
|
||||||
|
/* Do processing for the child (exec command etc). */
|
||||||
|
do_child(ssh, 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(ssh);
|
||||||
|
+
|
||||||
|
/* record login, etc. similar to login(1) */
|
||||||
|
#ifndef HAVE_OSF_SIA
|
||||||
|
do_login(ssh, s, command);
|
||||||
|
@@ -717,6 +728,8 @@ do_exec(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);
|
||||||
|
@@ -732,6 +745,20 @@ do_exec(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1538,6 +1565,33 @@ child_close_fds(void)
|
||||||
|
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 */
|
||||||
|
+ 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
|
||||||
|
@@ -1554,13 +1608,6 @@ do_child(Session *s, const char *command
|
||||||
|
|
||||||
|
sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id));
|
||||||
|
|
||||||
|
- /* remove hostkey from the child's 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);
|
@ -0,0 +1,87 @@
|
|||||||
|
diff --git a/auth-krb5.c b/auth-krb5.c
|
||||||
|
index 2b02a04..19b9364 100644
|
||||||
|
--- a/auth-krb5.c
|
||||||
|
+++ b/auth-krb5.c
|
||||||
|
@@ -375,5 +375,21 @@ cleanup:
|
||||||
|
return (krb5_cc_resolve(ctx, ccname, ccache));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Reads k5login_directory option from the krb5.conf
|
||||||
|
+ */
|
||||||
|
+krb5_error_code
|
||||||
|
+ssh_krb5_get_k5login_directory(krb5_context ctx, char **k5login_directory) {
|
||||||
|
+ profile_t p;
|
||||||
|
+ int ret = 0;
|
||||||
|
+
|
||||||
|
+ ret = krb5_get_profile(ctx, &p);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ return profile_get_string(p, "libdefaults", "k5login_directory", NULL, NULL,
|
||||||
|
+ k5login_directory);
|
||||||
|
+}
|
||||||
|
#endif /* !HEIMDAL */
|
||||||
|
#endif /* KRB5 */
|
||||||
|
diff --git a/auth.h b/auth.h
|
||||||
|
index f9d191c..c432d2f 100644
|
||||||
|
--- a/auth.h
|
||||||
|
+++ b/auth.h
|
||||||
|
@@ -222,6 +222,8 @@ 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 *);
|
||||||
|
+krb5_error_code ssh_krb5_get_k5login_directory(krb5_context ctx,
|
||||||
|
+ char **k5login_directory);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* AUTH_H */
|
||||||
|
diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c
|
||||||
|
index a7c0c5f..df8cc9a 100644
|
||||||
|
--- a/gss-serv-krb5.c
|
||||||
|
+++ b/gss-serv-krb5.c
|
||||||
|
@@ -244,8 +244,27 @@ ssh_gssapi_k5login_exists()
|
||||||
|
{
|
||||||
|
char file[MAXPATHLEN];
|
||||||
|
struct passwd *pw = the_authctxt->pw;
|
||||||
|
+ char *k5login_directory = NULL;
|
||||||
|
+ int ret = 0;
|
||||||
|
+
|
||||||
|
+ ret = ssh_krb5_get_k5login_directory(krb_context, &k5login_directory);
|
||||||
|
+ debug3_f("k5login_directory = %s (rv=%d)", 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.
|
||||||
|
+ */
|
||||||
|
+ snprintf(file, sizeof(file), "%s/.k5login", pw->pw_dir);
|
||||||
|
+ } else {
|
||||||
|
+ /* If set, the library will look for a local user's k5login file
|
||||||
|
+ * within the named directory, with a filename corresponding to the
|
||||||
|
+ * local username.
|
||||||
|
+ */
|
||||||
|
+ snprintf(file, sizeof(file), "%s%s%s", k5login_directory,
|
||||||
|
+ k5login_directory[strlen(k5login_directory)-1] != '/' ? "/" : "",
|
||||||
|
+ pw->pw_name);
|
||||||
|
+ }
|
||||||
|
+ debug_f("Checking existence of file %s", 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 5c4f15b..135e290 100644
|
||||||
|
--- a/sshd.8
|
||||||
|
+++ b/sshd.8
|
||||||
|
@@ -806,6 +806,10 @@ rlogin/rsh.
|
||||||
|
These files enforce GSSAPI/Kerberos authentication access control.
|
||||||
|
Further details are described in
|
||||||
|
.Xr ksu 1 .
|
||||||
|
+The location of the k5login file depends on the configuration option
|
||||||
|
+.Cm k5login_directory
|
||||||
|
+in the
|
||||||
|
+.Xr krb5.conf 5 .
|
||||||
|
.Pp
|
||||||
|
.It Pa ~/.ssh/
|
||||||
|
This directory is the default location for all user-specific configuration
|
@ -0,0 +1,52 @@
|
|||||||
|
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 ++++++++++++++++++++++++++
|
||||||
|
1 file changed, 26 insertions(+)
|
||||||
|
|
||||||
|
--- a/openbsd-compat/bsd-closefrom.c
|
||||||
|
+++ b/openbsd-compat/bsd-closefrom.c
|
||||||
|
@@ -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))
|
||||||
|
+#ifdef __s390__
|
||||||
|
+ {
|
||||||
|
+ /*
|
||||||
|
+ * the filedescriptors used to communicate with
|
||||||
|
+ * the device drivers to provide hardware support
|
||||||
|
+ * should survive. HF <freude@de.ibm.com>
|
||||||
|
+ */
|
||||||
|
+ char fpath[PATH_MAX], lpath[PATH_MAX];
|
||||||
|
+ len = snprintf(fpath, sizeof(fpath), "%s/%s",
|
||||||
|
+ fdpath, dent->d_name);
|
||||||
|
+ if (len > 0 && (size_t)len <= sizeof(fpath)) {
|
||||||
|
+ len = readlink(fpath, lpath, sizeof(lpath));
|
||||||
|
+ if (len > 0) {
|
||||||
|
+ lpath[len] = 0;
|
||||||
|
+ if (strstr(lpath, "dev/z90crypt")
|
||||||
|
+ || strstr(lpath, "dev/zcrypt")
|
||||||
|
+ || strstr(lpath, "dev/prandom")
|
||||||
|
+ || strstr(lpath, "dev/shm/icastats"))
|
||||||
|
+ fd = -1;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ if (fd >= 0)
|
||||||
|
+ (void) close((int) fd);
|
||||||
|
+ }
|
||||||
|
+#else
|
||||||
|
(void) close((int) fd);
|
||||||
|
+#endif
|
||||||
|
}
|
||||||
|
(void) closedir(dirp);
|
||||||
|
return;
|
||||||
|
|
@ -0,0 +1,55 @@
|
|||||||
|
diff --git a/channels.c b/channels.c
|
||||||
|
--- a/channels.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99)
|
||||||
|
+++ b/channels.c (date 1703026069921)
|
||||||
|
@@ -5075,11 +5075,13 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-connect_local_xsocket_path(const char *pathname)
|
||||||
|
+connect_local_xsocket_path(const char *pathname, int len)
|
||||||
|
{
|
||||||
|
int sock;
|
||||||
|
struct sockaddr_un addr;
|
||||||
|
|
||||||
|
+ if (len <= 0)
|
||||||
|
+ return -1;
|
||||||
|
sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
if (sock == -1) {
|
||||||
|
error("socket: %.100s", strerror(errno));
|
||||||
|
@@ -5087,11 +5089,12 @@
|
||||||
|
}
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.sun_family = AF_UNIX;
|
||||||
|
- strlcpy(addr.sun_path, pathname, sizeof addr.sun_path);
|
||||||
|
- if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0)
|
||||||
|
+ if (len > sizeof addr.sun_path)
|
||||||
|
+ len = sizeof addr.sun_path;
|
||||||
|
+ memcpy(addr.sun_path, pathname, len);
|
||||||
|
+ if (connect(sock, (struct sockaddr *)&addr, sizeof addr - (sizeof addr.sun_path - len) ) == 0)
|
||||||
|
return sock;
|
||||||
|
close(sock);
|
||||||
|
- error("connect %.100s: %.100s", addr.sun_path, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -5099,8 +5102,18 @@
|
||||||
|
connect_local_xsocket(u_int dnr)
|
||||||
|
{
|
||||||
|
char buf[1024];
|
||||||
|
- snprintf(buf, sizeof buf, _PATH_UNIX_X, dnr);
|
||||||
|
- return connect_local_xsocket_path(buf);
|
||||||
|
+ int len, ret;
|
||||||
|
+ len = snprintf(buf + 1, sizeof (buf) - 1, _PATH_UNIX_X, dnr);
|
||||||
|
+#ifdef linux
|
||||||
|
+ /* try abstract socket first */
|
||||||
|
+ buf[0] = '\0';
|
||||||
|
+ if ((ret = connect_local_xsocket_path(buf, len + 1)) >= 0)
|
||||||
|
+ return ret;
|
||||||
|
+#endif
|
||||||
|
+ if ((ret = connect_local_xsocket_path(buf + 1, len)) >= 0)
|
||||||
|
+ return ret;
|
||||||
|
+ error("connect %.100s: %.100s", buf + 1, strerror(errno));
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
@ -0,0 +1,213 @@
|
|||||||
|
diff -up openssh-7.4p1/channels.c.x11max openssh-7.4p1/channels.c
|
||||||
|
--- openssh-7.4p1/channels.c.x11max 2016-12-23 15:46:32.071506625 +0100
|
||||||
|
+++ openssh-7.4p1/channels.c 2016-12-23 15:46:32.139506636 +0100
|
||||||
|
@@ -152,8 +152,8 @@ static int all_opens_permitted = 0;
|
||||||
|
#define NUM_SOCKS 10
|
||||||
|
|
||||||
|
/* -- 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
|
||||||
|
|
||||||
|
/* Per-channel callback for pre/post IO actions */
|
||||||
|
typedef void chan_fn(struct ssh *, Channel *c);
|
||||||
|
@@ -4228,7 +4228,7 @@ channel_send_window_changes(void)
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
@@ -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 = ssh->chanctxt->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 = ssh->chanctxt->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) == -1) {
|
||||||
|
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 2016-12-19 05:59:41.000000000 +0100
|
||||||
|
+++ openssh-7.4p1/channels.h 2016-12-23 15:46:32.139506636 +0100
|
||||||
|
@@ -293,7 +293,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);
|
||||||
|
|
||||||
|
diff -up openssh-7.4p1/servconf.c.x11max openssh-7.4p1/servconf.c
|
||||||
|
--- openssh-7.4p1/servconf.c.x11max 2016-12-23 15:46:32.133506635 +0100
|
||||||
|
+++ openssh-7.4p1/servconf.c 2016-12-23 15:47:27.320519121 +0100
|
||||||
|
@@ -95,6 +95,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;
|
||||||
|
@@ -243,6 +244,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)
|
||||||
|
@@ -419,7 +422,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,
|
||||||
|
@@ -540,6 +543,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 },
|
||||||
|
@@ -1316,6 +1320,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;
|
||||||
|
@@ -2063,6 +2071,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);
|
||||||
|
@@ -2315,6 +2324,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 2016-12-23 15:46:32.133506635 +0100
|
||||||
|
+++ openssh-7.4p1/servconf.h 2016-12-23 15:46:32.140506636 +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 2016-12-23 15:46:32.136506636 +0100
|
||||||
|
+++ openssh-7.4p1/session.c 2016-12-23 15:46:32.141506636 +0100
|
||||||
|
@@ -2518,8 +2518,9 @@ session_setup_x11fwd(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 -up openssh-7.4p1/sshd_config.5.x11max openssh-7.4p1/sshd_config.5
|
||||||
|
--- openssh-7.4p1/sshd_config.5.x11max 2016-12-23 15:46:32.134506635 +0100
|
||||||
|
+++ openssh-7.4p1/sshd_config.5 2016-12-23 15:46:32.141506636 +0100
|
||||||
|
@@ -1133,6 +1133,7 @@ Available keywords are
|
||||||
|
.Cm TrustedUserCAKeys ,
|
||||||
|
.Cm UnusedConnectionTimeout ,
|
||||||
|
.Cm X11DisplayOffset ,
|
||||||
|
+.Cm X11MaxDisplays ,
|
||||||
|
.Cm X11Forwarding
|
||||||
|
and
|
||||||
|
.Cm X11UseLocalhost .
|
||||||
|
@@ -1566,6 +1567,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
|
@ -0,0 +1,86 @@
|
|||||||
|
In order to use the OpenSSL-ibmpkcs11 engine it is needed to allow flock
|
||||||
|
and ipc calls, because this engine calls OpenCryptoki (a PKCS#11
|
||||||
|
implementation) which calls the libraries that will communicate with the
|
||||||
|
crypto cards. OpenCryptoki makes use of flock and ipc and, as of now,
|
||||||
|
this is only need on s390 architecture.
|
||||||
|
|
||||||
|
Signed-off-by: Eduardo Barretto <ebarretto@xxxxxxxxxxxxxxxxxx>
|
||||||
|
---
|
||||||
|
sandbox-seccomp-filter.c | 6 ++++++
|
||||||
|
1 file changed, 6 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/sandbox-seccomp-filter.c b/sandbox-seccomp-filter.c
|
||||||
|
index ca75cc7..6e7de31 100644
|
||||||
|
--- a/sandbox-seccomp-filter.c
|
||||||
|
+++ b/sandbox-seccomp-filter.c
|
||||||
|
@@ -166,6 +166,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
|
||||||
|
@@ -178,6 +181,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
|
||||||
|
--
|
||||||
|
1.9.1
|
||||||
|
|
||||||
|
getuid and geteuid are needed when using an openssl engine that calls a
|
||||||
|
crypto card, e.g. ICA (libica).
|
||||||
|
Those syscalls are also needed by the distros for audit code.
|
||||||
|
|
||||||
|
Signed-off-by: Eduardo Barretto <ebarretto@xxxxxxxxxxxxxxxxxx>
|
||||||
|
---
|
||||||
|
sandbox-seccomp-filter.c | 12 ++++++++++++
|
||||||
|
1 file changed, 12 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/sandbox-seccomp-filter.c b/sandbox-seccomp-filter.c
|
||||||
|
index 6e7de31..e86aa2c 100644
|
||||||
|
--- a/sandbox-seccomp-filter.c
|
||||||
|
+++ b/sandbox-seccomp-filter.c
|
||||||
|
@@ -175,6 +175,18 @@ 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_getrandom
|
||||||
|
SC_ALLOW(__NR_getrandom),
|
||||||
|
#endif
|
||||||
|
-- 1.9.1
|
||||||
|
1.9.1
|
||||||
|
diff -up openssh-7.6p1/sandbox-seccomp-filter.c.sandbox openssh-7.6p1/sandbox-seccomp-filter.c
|
||||||
|
--- openssh-7.6p1/sandbox-seccomp-filter.c.sandbox 2017-12-12 13:59:30.563874059 +0100
|
||||||
|
+++ openssh-7.6p1/sandbox-seccomp-filter.c 2017-12-12 13:59:14.842784083 +0100
|
||||||
|
@@ -190,6 +190,9 @@ static const struct sock_filter preauth_
|
||||||
|
#ifdef __NR_geteuid32
|
||||||
|
SC_ALLOW(__NR_geteuid32),
|
||||||
|
#endif
|
||||||
|
+#ifdef __NR_gettid
|
||||||
|
+ SC_ALLOW(__NR_gettid),
|
||||||
|
+#endif
|
||||||
|
#ifdef __NR_getrandom
|
||||||
|
SC_ALLOW(__NR_getrandom),
|
||||||
|
#endif
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,271 @@
|
|||||||
|
diff -up openssh/auth2-pubkey.c.refactor openssh/auth2-pubkey.c
|
||||||
|
--- openssh/auth2-pubkey.c.refactor 2019-04-04 13:19:12.188821236 +0200
|
||||||
|
+++ openssh/auth2-pubkey.c 2019-04-04 13:19:12.276822078 +0200
|
||||||
|
@@ -72,6 +72,8 @@
|
||||||
|
|
||||||
|
/* import */
|
||||||
|
extern ServerOptions options;
|
||||||
|
+extern int inetd_flag;
|
||||||
|
+extern Authctxt *the_authctxt;
|
||||||
|
extern struct authmethod_cfg methodcfg_pubkey;
|
||||||
|
|
||||||
|
static char *
|
||||||
|
@@ -511,7 +514,8 @@ match_principals_command(struct ssh *ssh
|
||||||
|
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;
|
||||||
|
@@ -981,7 +985,8 @@ user_key_command_allowed2(struct ssh *ss
|
||||||
|
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 -up openssh/misc.c.refactor openssh/misc.c
|
||||||
|
--- openssh/misc.c.refactor 2019-04-04 13:19:12.235821686 +0200
|
||||||
|
+++ openssh/misc.c 2019-04-04 13:19:12.276822078 +0200
|
||||||
|
@@ -756,7 +756,8 @@ auth_get_canonical_hostname(struct ssh *
|
||||||
|
pid_t
|
||||||
|
subprocess(const char *tag, 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;
|
||||||
|
@@ -872,7 +873,7 @@ subprocess(const char *tag, struct passw
|
||||||
|
_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 -up openssh/misc.h.refactor openssh/misc.h
|
||||||
|
--- openssh/misc.h.refactor 2019-04-04 13:19:12.251821839 +0200
|
||||||
|
+++ openssh/misc.h 2019-04-04 13:19:12.276822078 +0200
|
||||||
|
@@ -235,7 +235,7 @@ struct passwd *fakepw(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 -up openssh/openbsd-compat/port-linux.h.refactor openssh/openbsd-compat/port-linux.h
|
||||||
|
--- openssh/openbsd-compat/port-linux.h.refactor 2019-04-04 13:19:12.256821887 +0200
|
||||||
|
+++ openssh/openbsd-compat/port-linux.h 2019-04-04 13:19:12.276822078 +0200
|
||||||
|
@@ -26,8 +26,8 @@ void ssh_selinux_setfscreatecon(const ch
|
||||||
|
|
||||||
|
int sshd_selinux_enabled(void);
|
||||||
|
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 -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compat/port-linux-sshd.c
|
||||||
|
--- openssh/openbsd-compat/port-linux-sshd.c.refactor 2019-04-04 13:19:12.256821887 +0200
|
||||||
|
+++ openssh/openbsd-compat/port-linux-sshd.c 2019-04-04 13:19:12.276822078 +0200
|
||||||
|
@@ -49,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)
|
||||||
|
@@ -223,7 +218,8 @@ get_user_context(const char *sename, con
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
-ssh_selinux_get_role_level(char **role, const char **level)
|
||||||
|
+ssh_selinux_get_role_level(char **role, const char **level,
|
||||||
|
+ Authctxt *the_authctxt)
|
||||||
|
{
|
||||||
|
*role = NULL;
|
||||||
|
*level = NULL;
|
||||||
|
@@ -241,8 +237,8 @@ ssh_selinux_get_role_level(char **role,
|
||||||
|
|
||||||
|
/* Return the default security context for the given username */
|
||||||
|
static int
|
||||||
|
-sshd_selinux_getctxbyname(char *pwname,
|
||||||
|
- security_context_t *default_sc, security_context_t *user_sc)
|
||||||
|
+sshd_selinux_getctxbyname(char *pwname, security_context_t *default_sc,
|
||||||
|
+ security_context_t *user_sc, int inetd, Authctxt *the_authctxt)
|
||||||
|
{
|
||||||
|
char *sename, *lvl;
|
||||||
|
char *role;
|
||||||
|
@@ -250,7 +246,7 @@ sshd_selinux_getctxbyname(char *pwname,
|
||||||
|
int r = 0;
|
||||||
|
context_t con = NULL;
|
||||||
|
|
||||||
|
- ssh_selinux_get_role_level(&role, &reqlvl);
|
||||||
|
+ ssh_selinux_get_role_level(&role, &reqlvl, the_authctxt);
|
||||||
|
|
||||||
|
#ifdef HAVE_GETSEUSERBYNAME
|
||||||
|
if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) {
|
||||||
|
@@ -272,7 +268,7 @@ sshd_selinux_getctxbyname(char *pwname,
|
||||||
|
|
||||||
|
if (r == 0) {
|
||||||
|
/* If launched from xinetd, we must use current level */
|
||||||
|
- if (inetd_flag) {
|
||||||
|
+ if (inetd) {
|
||||||
|
security_context_t sshdsc=NULL;
|
||||||
|
|
||||||
|
if (getcon_raw(&sshdsc) < 0)
|
||||||
|
@@ -333,7 +329,8 @@ sshd_selinux_getctxbyname(char *pwname,
|
||||||
|
|
||||||
|
/* Setup environment variables for pam_selinux */
|
||||||
|
static int
|
||||||
|
-sshd_selinux_setup_variables(int(*set_it)(char *, const char *))
|
||||||
|
+sshd_selinux_setup_variables(int(*set_it)(char *, const char *), int inetd,
|
||||||
|
+ Authctxt *the_authctxt)
|
||||||
|
{
|
||||||
|
const char *reqlvl;
|
||||||
|
char *role;
|
||||||
|
@@ -342,11 +339,11 @@ sshd_selinux_setup_variables(int(*set_it
|
||||||
|
|
||||||
|
debug3_f("setting execution context");
|
||||||
|
|
||||||
|
- ssh_selinux_get_role_level(&role, &reqlvl);
|
||||||
|
+ ssh_selinux_get_role_level(&role, &reqlvl, the_authctxt);
|
||||||
|
|
||||||
|
rv = set_it("SELINUX_ROLE_REQUESTED", role ? role : "");
|
||||||
|
|
||||||
|
- if (inetd_flag) {
|
||||||
|
+ if (inetd) {
|
||||||
|
use_current = "1";
|
||||||
|
} else {
|
||||||
|
use_current = "";
|
||||||
|
@@ -362,9 +359,10 @@ sshd_selinux_setup_variables(int(*set_it
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-sshd_selinux_setup_pam_variables(void)
|
||||||
|
+sshd_selinux_setup_pam_variables(int inetd,
|
||||||
|
+ int(pam_setenv)(char *, const char *), Authctxt *the_authctxt)
|
||||||
|
{
|
||||||
|
- return sshd_selinux_setup_variables(do_pam_putenv);
|
||||||
|
+ return sshd_selinux_setup_variables(pam_setenv, inetd, the_authctxt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
@@ -374,25 +372,28 @@ do_setenv(char *name, const char *value)
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
-sshd_selinux_setup_env_variables(void)
|
||||||
|
+sshd_selinux_setup_env_variables(int inetd, void *the_authctxt)
|
||||||
|
{
|
||||||
|
- return sshd_selinux_setup_variables(do_setenv);
|
||||||
|
+ Authctxt *authctxt = (Authctxt *) the_authctxt;
|
||||||
|
+ return sshd_selinux_setup_variables(do_setenv, inetd, authctxt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the execution context to the default for the specified user */
|
||||||
|
void
|
||||||
|
-sshd_selinux_setup_exec_context(char *pwname)
|
||||||
|
+sshd_selinux_setup_exec_context(char *pwname, int inetd,
|
||||||
|
+ int(pam_setenv)(char *, const char *), void *the_authctxt, int use_pam)
|
||||||
|
{
|
||||||
|
security_context_t user_ctx = NULL;
|
||||||
|
int r = 0;
|
||||||
|
security_context_t default_ctx = NULL;
|
||||||
|
+ Authctxt *authctxt = (Authctxt *) the_authctxt;
|
||||||
|
|
||||||
|
if (!sshd_selinux_enabled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
- if (options.use_pam) {
|
||||||
|
+ if (use_pam) {
|
||||||
|
/* do not compute context, just setup environment for pam_selinux */
|
||||||
|
- if (sshd_selinux_setup_pam_variables()) {
|
||||||
|
+ if (sshd_selinux_setup_pam_variables(inetd, pam_setenv, authctxt)) {
|
||||||
|
switch (security_getenforce()) {
|
||||||
|
case -1:
|
||||||
|
fatal_f("security_getenforce() failed");
|
||||||
|
@@ -410,7 +411,7 @@ sshd_selinux_setup_exec_context(char *pw
|
||||||
|
|
||||||
|
debug3_f("setting execution context");
|
||||||
|
|
||||||
|
- r = sshd_selinux_getctxbyname(pwname, &default_ctx, &user_ctx);
|
||||||
|
+ r = sshd_selinux_getctxbyname(pwname, &default_ctx, &user_ctx, inetd, authctxt);
|
||||||
|
if (r >= 0) {
|
||||||
|
r = setexeccon(user_ctx);
|
||||||
|
if (r < 0) {
|
||||||
|
diff -up openssh/platform.c.refactor openssh/platform.c
|
||||||
|
--- openssh/platform.c.refactor 2019-04-04 13:19:12.204821389 +0200
|
||||||
|
+++ openssh/platform.c 2019-04-04 13:19:12.277822088 +0200
|
||||||
|
@@ -32,6 +32,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
|
||||||
|
@@ -183,7 +186,9 @@ platform_setusercontext_post_groups(stru
|
||||||
|
}
|
||||||
|
#endif /* HAVE_SETPCRED */
|
||||||
|
#ifdef WITH_SELINUX
|
||||||
|
- sshd_selinux_setup_exec_context(pw->pw_name);
|
||||||
|
+ sshd_selinux_setup_exec_context(pw->pw_name,
|
||||||
|
+ inetd_flag, do_pam_putenv, the_authctxt,
|
||||||
|
+ options.use_pam);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
diff -up openssh/sshd-session.c.refactor openssh/sshd-session.c
|
||||||
|
--- openssh/sshd-session.c.refactor 2019-04-04 13:19:12.275822068 +0200
|
||||||
|
+++ openssh/sshd-session.c 2019-04-04 13:19:51.270195262 +0200
|
||||||
|
@@ -158,7 +158,7 @@ int debug_flag = 0;
|
||||||
|
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;
|
||||||
|
@@ -2192,7 +2192,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) {
|
||||||
|
diff -up openssh/sshconnect.c.refactor openssh/sshconnect.c
|
||||||
|
--- openssh/sshconnect.c.refactor 2021-02-24 00:12:03.065325046 +0100
|
||||||
|
+++ openssh/sshconnect.c 2021-02-24 00:12:12.126449544 +0100
|
||||||
|
@@ -892,7 +892,7 @@ load_hostkeys_command(struct hostkeys *h
|
||||||
|
|
||||||
|
if ((pid = subprocess(tag, command, ac, av, &f,
|
||||||
|
SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_UNSAFE_PATH|
|
||||||
|
- SSH_SUBPROCESS_PRESERVE_ENV, NULL, NULL, NULL)) == 0)
|
||||||
|
+ SSH_SUBPROCESS_PRESERVE_ENV, NULL, NULL, NULL, 0, NULL)) == 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
load_hostkeys_file(hostkeys, hostfile_hostname, tag, f, 1);
|
@ -0,0 +1,766 @@
|
|||||||
|
diff -up openssh-8.6p1/dh.c.fips openssh-8.6p1/dh.c
|
||||||
|
--- openssh-8.6p1/dh.c.fips 2021-04-16 05:55:25.000000000 +0200
|
||||||
|
+++ openssh-8.6p1/dh.c 2021-05-06 12:12:10.107634472 +0200
|
||||||
|
@@ -36,6 +36,7 @@
|
||||||
|
|
||||||
|
#include <openssl/bn.h>
|
||||||
|
#include <openssl/dh.h>
|
||||||
|
+#include <openssl/fips.h>
|
||||||
|
|
||||||
|
#include "dh.h"
|
||||||
|
#include "pathnames.h"
|
||||||
|
@@ -164,6 +164,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 +508,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 -up openssh-8.6p1/dh.h.fips openssh-8.6p1/dh.h
|
||||||
|
--- openssh-8.6p1/dh.h.fips 2021-05-06 12:08:36.498926877 +0200
|
||||||
|
+++ openssh-8.6p1/dh.h 2021-05-06 12:11:28.393298005 +0200
|
||||||
|
@@ -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 -up openssh-8.6p1/kex-names.c.fips openssh-8.6p1/kex-names.c
|
||||||
|
--- openssh-8.6p1/kex-names.c.fips 2021-05-06 12:08:36.489926807 +0200
|
||||||
|
+++ openssh-8.6p1/kex-names.c 2021-05-06 12:08:36.498926877 +0200
|
||||||
|
@@ -39,6 +39,7 @@
|
||||||
|
|
||||||
|
#ifdef WITH_OPENSSL
|
||||||
|
#include <openssl/crypto.h>
|
||||||
|
+#include <openssl/fips.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@@ -203,7 +203,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 -up openssh-8.6p1/kexgexc.c.fips openssh-8.6p1/kexgexc.c
|
||||||
|
--- openssh-8.6p1/kexgexc.c.fips 2021-04-16 05:55:25.000000000 +0200
|
||||||
|
+++ openssh-8.6p1/kexgexc.c 2021-05-06 12:08:36.498926877 +0200
|
||||||
|
@@ -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
|
||||||
|
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 -up openssh-8.6p1/myproposal.h.fips openssh-8.6p1/myproposal.h
|
||||||
|
--- openssh-8.6p1/myproposal.h.fips 2021-04-16 05:55:25.000000000 +0200
|
||||||
|
+++ openssh-8.6p1/myproposal.h 2021-05-06 12:08:36.498926877 +0200
|
||||||
|
@@ -57,6 +57,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-ctr,aes192-ctr,aes256-ctr," \
|
||||||
|
@@ -78,6 +92,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 -up openssh-8.6p1/readconf.c.fips openssh-8.6p1/readconf.c
|
||||||
|
--- openssh-8.6p1/readconf.c.fips 2021-05-06 12:08:36.428926336 +0200
|
||||||
|
+++ openssh-8.6p1/readconf.c 2021-05-06 12:08:36.499926885 +0200
|
||||||
|
@@ -39,6 +39,7 @@
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
+#include <openssl/fips.h>
|
||||||
|
#ifdef USE_SYSTEM_GLOB
|
||||||
|
# include <glob.h>
|
||||||
|
#else
|
||||||
|
@@ -2538,11 +2538,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 -up openssh-8.6p1/sandbox-seccomp-filter.c.fips openssh-8.6p1/sandbox-seccomp-filter.c
|
||||||
|
--- openssh-8.6p1/sandbox-seccomp-filter.c.fips 2021-05-06 12:08:36.463926606 +0200
|
||||||
|
+++ openssh-8.6p1/sandbox-seccomp-filter.c 2021-05-06 12:08:36.499926885 +0200
|
||||||
|
@@ -160,6 +160,9 @@ static const struct sock_filter preauth_
|
||||||
|
#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 -up openssh-8.6p1/servconf.c.fips openssh-8.6p1/servconf.c
|
||||||
|
--- openssh-8.6p1/servconf.c.fips 2021-05-06 12:08:36.455926545 +0200
|
||||||
|
+++ openssh-8.6p1/servconf.c 2021-05-06 12:08:36.500926893 +0200
|
||||||
|
@@ -38,6 +38,7 @@
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <errno.h>
|
||||||
|
+#include <openssl/fips.h>
|
||||||
|
#ifdef HAVE_UTIL_H
|
||||||
|
#include <util.h>
|
||||||
|
#endif
|
||||||
|
@@ -226,11 +226,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 -up openssh-8.6p1/ssh.c.fips openssh-8.6p1/ssh.c
|
||||||
|
--- openssh-8.6p1/ssh.c.fips 2021-05-06 12:08:36.467926637 +0200
|
||||||
|
+++ openssh-8.6p1/ssh.c 2021-05-06 12:08:36.500926893 +0200
|
||||||
|
@@ -77,6 +77,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"
|
||||||
|
|
||||||
|
@@ -1516,6 +1517,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 -up openssh-8.6p1/sshconnect2.c.fips openssh-8.6p1/sshconnect2.c
|
||||||
|
--- openssh-8.6p1/sshconnect2.c.fips 2021-05-06 12:08:36.485926777 +0200
|
||||||
|
+++ openssh-8.6p1/sshconnect2.c 2021-05-06 12:08:36.501926900 +0200
|
||||||
|
@@ -45,6 +45,8 @@
|
||||||
|
#include <vis.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+#include <openssl/fips.h>
|
||||||
|
+
|
||||||
|
#include "openbsd-compat/sys-queue.h"
|
||||||
|
|
||||||
|
#include "xmalloc.h"
|
||||||
|
@@ -269,36 +271,41 @@ ssh_kex2(struct ssh *ssh, char *host, st
|
||||||
|
|
||||||
|
#if defined(GSSAPI) && defined(WITH_OPENSSL)
|
||||||
|
if (options.gss_keyex) {
|
||||||
|
- /* Add the GSSAPI mechanisms currently supported on this
|
||||||
|
- * client to the key exchange algorithm proposal */
|
||||||
|
- orig = myproposal[PROPOSAL_KEX_ALGS];
|
||||||
|
-
|
||||||
|
- if (options.gss_server_identity) {
|
||||||
|
- gss_host = xstrdup(options.gss_server_identity);
|
||||||
|
- } else if (options.gss_trust_dns) {
|
||||||
|
- gss_host = remote_hostname(ssh);
|
||||||
|
- /* Fall back to specified host if we are using proxy command
|
||||||
|
- * and can not use DNS on that socket */
|
||||||
|
- if (strcmp(gss_host, "UNKNOWN") == 0) {
|
||||||
|
- free(gss_host);
|
||||||
|
+ if (FIPS_mode()) {
|
||||||
|
+ logit("Disabling GSSAPIKeyExchange. Not usable in FIPS mode");
|
||||||
|
+ options.gss_keyex = 0;
|
||||||
|
+ } else {
|
||||||
|
+ /* Add the GSSAPI mechanisms currently supported on this
|
||||||
|
+ * client to the key exchange algorithm proposal */
|
||||||
|
+ orig = myproposal[PROPOSAL_KEX_ALGS];
|
||||||
|
+
|
||||||
|
+ if (options.gss_server_identity) {
|
||||||
|
+ gss_host = xstrdup(options.gss_server_identity);
|
||||||
|
+ } else if (options.gss_trust_dns) {
|
||||||
|
+ gss_host = remote_hostname(ssh);
|
||||||
|
+ /* Fall back to specified host if we are using proxy command
|
||||||
|
+ * and can not use DNS on that socket */
|
||||||
|
+ if (strcmp(gss_host, "UNKNOWN") == 0) {
|
||||||
|
+ free(gss_host);
|
||||||
|
+ gss_host = xstrdup(host);
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
gss_host = xstrdup(host);
|
||||||
|
}
|
||||||
|
- } else {
|
||||||
|
- gss_host = xstrdup(host);
|
||||||
|
- }
|
||||||
|
|
||||||
|
- gss = ssh_gssapi_client_mechanisms(gss_host,
|
||||||
|
- options.gss_client_identity, options.gss_kex_algorithms);
|
||||||
|
- if (gss) {
|
||||||
|
- debug("Offering GSSAPI proposal: %s", gss);
|
||||||
|
- xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
|
||||||
|
- "%s,%s", gss, orig);
|
||||||
|
-
|
||||||
|
- /* If we've got GSSAPI algorithms, then we also support the
|
||||||
|
- * 'null' hostkey, as a last resort */
|
||||||
|
- orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
|
||||||
|
- xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
|
||||||
|
- "%s,null", orig);
|
||||||
|
+ gss = ssh_gssapi_client_mechanisms(gss_host,
|
||||||
|
+ options.gss_client_identity, options.gss_kex_algorithms);
|
||||||
|
+ if (gss) {
|
||||||
|
+ debug("Offering GSSAPI proposal: %s", gss);
|
||||||
|
+ xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
|
||||||
|
+ "%s,%s", gss, orig);
|
||||||
|
+
|
||||||
|
+ /* If we've got GSSAPI algorithms, then we also support the
|
||||||
|
+ * 'null' hostkey, as a last resort */
|
||||||
|
+ orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
|
||||||
|
+ xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
|
||||||
|
+ "%s,null", orig);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
diff -up openssh-8.6p1/sshd.c.fips openssh-8.6p1/sshd.c
|
||||||
|
--- openssh-8.6p1/sshd.c.fips 2021-05-06 12:08:36.493926838 +0200
|
||||||
|
+++ openssh-8.6p1/sshd.c 2021-05-06 12:13:56.501492639 +0200
|
||||||
|
@@ -66,6 +66,7 @@
|
||||||
|
#endif
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <signal.h>
|
||||||
|
+#include <syslog.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
@@ -77,6 +78,7 @@
|
||||||
|
#ifdef WITH_OPENSSL
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/rand.h>
|
||||||
|
+#include <openssl/fips.h>
|
||||||
|
#include "openbsd-compat/openssl-compat.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@@ -1931,6 +1931,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",
|
||||||
|
@@ -2110,6 +2113,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 -up openssh-8.6p1/sshd-session.c.fips openssh-8.6p1/sshd-session.c
|
||||||
|
--- a/sshd-session.c.fips 2021-05-06 12:08:36.493926838 +0200
|
||||||
|
+++ b/sshd-session.c 2021-05-06 12:13:56.501492639 +0200
|
||||||
|
@@ -78,6 +79,7 @@
|
||||||
|
#include <openssl/bn.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/rand.h>
|
||||||
|
+#include <openssl/fips.h>
|
||||||
|
#include "openbsd-compat/openssl-compat.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@@ -2506,10 +2513,14 @@ do_ssh2_kex(struct ssh *ssh)
|
||||||
|
if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0)
|
||||||
|
orig = NULL;
|
||||||
|
|
||||||
|
- if (options.gss_keyex)
|
||||||
|
- gss = ssh_gssapi_server_mechanisms();
|
||||||
|
- else
|
||||||
|
- gss = NULL;
|
||||||
|
+ if (options.gss_keyex) {
|
||||||
|
+ if (FIPS_mode()) {
|
||||||
|
+ logit("Disabling GSSAPIKeyExchange. Not usable in FIPS mode");
|
||||||
|
+ options.gss_keyex = 0;
|
||||||
|
+ } else {
|
||||||
|
+ gss = ssh_gssapi_server_mechanisms();
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
|
||||||
|
if (gss && orig)
|
||||||
|
xasprintf(&newstr, "%s,%s", gss, orig);
|
||||||
|
diff -up openssh-8.6p1/sshkey.c.fips openssh-8.6p1/sshkey.c
|
||||||
|
--- openssh-8.6p1/sshkey.c.fips 2021-05-06 12:08:36.493926838 +0200
|
||||||
|
+++ openssh-8.6p1/sshkey.c 2021-05-06 12:08:36.502926908 +0200
|
||||||
|
@@ -36,6 +36,7 @@
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
+#include <openssl/fips.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "crypto_api.h"
|
||||||
|
@@ -57,6 +58,7 @@
|
||||||
|
#define SSHKEY_INTERNAL
|
||||||
|
#include "sshkey.h"
|
||||||
|
#include "match.h"
|
||||||
|
+#include "log.h"
|
||||||
|
#include "ssh-sk.h"
|
||||||
|
|
||||||
|
#ifdef WITH_XMSS
|
||||||
|
@@ -285,6 +285,18 @@ sshkey_alg_list(int certs_only, int plai
|
||||||
|
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))
|
||||||
|
@@ -1503,6 +1503,20 @@ sshkey_read(struct sshkey *ret, char **c
|
||||||
|
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;
|
||||||
|
@@ -2916,6 +2916,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)
|
||||||
|
@@ -2973,6 +2978,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,
|
||||||
|
diff -up openssh-8.6p1/ssh-keygen.c.fips openssh-8.6p1/ssh-keygen.c
|
||||||
|
--- openssh-8.6p1/ssh-keygen.c.fips 2021-05-06 12:08:36.467926637 +0200
|
||||||
|
+++ openssh-8.6p1/ssh-keygen.c 2021-05-06 12:08:36.503926916 +0200
|
||||||
|
@@ -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
|
||||||
|
@@ -69,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
|
||||||
|
@@ -205,6 +205,12 @@ type_bits_valid(int type, const char *na
|
||||||
|
#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)
|
||||||
|
@@ -266,7 +267,7 @@ ask_filename(struct passwd *pw, const ch
|
||||||
|
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
|
||||||
|
@@ -1098,9 +1104,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));
|
||||||
|
@@ -3830,7 +3831,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 -up openssh-9.3p1/ssh-rsa.c.evpgenrsa openssh-9.3p1/ssh-rsa.c
|
||||||
|
--- openssh-9.3p1/ssh-rsa.c.evpgenrsa 2022-06-30 15:14:58.200518353 +0200
|
||||||
|
+++ openssh-9.3p1/ssh-rsa.c 2022-06-30 15:24:31.499641196 +0200
|
||||||
|
@@ -33,6 +33,7 @@
|
||||||
|
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
+#include <openssl/fips.h>
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
@@ -1705,6 +1707,8 @@ ssh_rsa_generate(u_int bits, RSA
|
||||||
|
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 -up openssh-9.9p1/kexgen.c.xxx openssh-9.9p1/kexgen.c
|
||||||
|
--- openssh-9.9p1/kexgen.c.xxx 2024-10-09 10:35:56.285946080 +0200
|
||||||
|
+++ openssh-9.9p1/kexgen.c 2024-10-09 10:41:52.792597194 +0200
|
||||||
|
@@ -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
|
||||||
|
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 s
|
||||||
|
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 -up openssh-8.7p1/ssh-ed25519.c.fips3 openssh-8.7p1/ssh-ed25519.c
|
||||||
|
--- openssh-8.7p1/ssh-ed25519.c.fips3 2022-07-11 16:53:41.428343304 +0200
|
||||||
|
+++ openssh-8.7p1/ssh-ed25519.c 2022-07-11 16:56:09.284663661 +0200
|
||||||
|
@@ -24,6 +24,7 @@
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
+#include <openssl/fips.h>
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
#include "sshbuf.h"
|
||||||
|
@@ -52,6 +53,10 @@ ssh_ed25519_sign(const struct sshkey *ke
|
||||||
|
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;
|
||||||
|
@@ -108,6 +113,10 @@ ssh_ed25519_verify(const struct sshkey *
|
||||||
|
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 -up openssh-9.9p1/kex.c.xxx openssh-9.9p1/kex.c
|
||||||
|
--- openssh-9.9p1/kex.c.xxx 2024-10-11 12:44:08.087426597 +0200
|
||||||
|
+++ openssh-9.9p1/kex.c 2024-10-11 14:00:10.404714521 +0200
|
||||||
|
@@ -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
|
||||||
|
|
||||||
|
/* 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)
|
@ -0,0 +1,632 @@
|
|||||||
|
diff -up openssh-8.6p1/auth.h.ccache_name openssh-8.6p1/auth.h
|
||||||
|
--- openssh-8.6p1/auth.h.ccache_name 2021-04-19 14:05:10.820744325 +0200
|
||||||
|
+++ openssh-8.6p1/auth.h 2021-04-19 14:05:10.853744569 +0200
|
||||||
|
@@ -83,6 +83,7 @@ struct Authctxt {
|
||||||
|
krb5_principal krb5_user;
|
||||||
|
char *krb5_ticket_file;
|
||||||
|
char *krb5_ccname;
|
||||||
|
+ int krb5_set_env;
|
||||||
|
#endif
|
||||||
|
struct sshbuf *loginmsg;
|
||||||
|
|
||||||
|
@@ -231,7 +232,7 @@ struct passwd *fakepw(void);
|
||||||
|
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 -up openssh-8.6p1/auth-krb5.c.ccache_name openssh-8.6p1/auth-krb5.c
|
||||||
|
--- openssh-8.6p1/auth-krb5.c.ccache_name 2021-04-16 05:55:25.000000000 +0200
|
||||||
|
+++ openssh-8.6p1/auth-krb5.c 2021-04-19 14:40:55.142832954 +0200
|
||||||
|
@@ -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, c
|
||||||
|
#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, c
|
||||||
|
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, c
|
||||||
|
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, 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);
|
||||||
|
+ 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,188 @@ krb5_cleanup_proc(Authctxt *authctxt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-#ifndef HEIMDAL
|
||||||
|
+
|
||||||
|
+#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 || 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;
|
||||||
|
+
|
||||||
|
+ 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 (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_gen(krb5_context ctx, krb5_ccache *ccache) {
|
||||||
|
- int tmpfd, ret, oerrno;
|
||||||
|
- char ccname[40];
|
||||||
|
+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;
|
||||||
|
|
||||||
|
- ret = snprintf(ccname, sizeof(ccname),
|
||||||
|
- "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
|
||||||
|
- if (ret < 0 || (size_t)ret >= sizeof(ccname))
|
||||||
|
- return ENOMEM;
|
||||||
|
-
|
||||||
|
- old_umask = umask(0177);
|
||||||
|
- tmpfd = mkstemp(ccname + strlen("FILE:"));
|
||||||
|
- oerrno = errno;
|
||||||
|
- umask(old_umask);
|
||||||
|
- if (tmpfd == -1) {
|
||||||
|
- logit("mkstemp(): %.100s", strerror(oerrno));
|
||||||
|
- return oerrno;
|
||||||
|
- }
|
||||||
|
+ debug3_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;
|
||||||
|
|
||||||
|
- if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) {
|
||||||
|
+ 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 -up openssh-8.6p1/gss-serv.c.ccache_name openssh-8.6p1/gss-serv.c
|
||||||
|
--- openssh-8.6p1/gss-serv.c.ccache_name 2021-04-19 14:05:10.844744503 +0200
|
||||||
|
+++ openssh-8.6p1/gss-serv.c 2021-04-19 14:05:10.854744577 +0200
|
||||||
|
@@ -413,13 +413,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
|
||||||
|
@@ -499,9 +501,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 -up openssh-8.6p1/gss-serv-krb5.c.ccache_name openssh-8.6p1/gss-serv-krb5.c
|
||||||
|
--- openssh-8.6p1/gss-serv-krb5.c.ccache_name 2021-04-19 14:05:10.852744562 +0200
|
||||||
|
+++ openssh-8.6p1/gss-serv-krb5.c 2021-04-19 14:05:10.854744577 +0200
|
||||||
|
@@ -267,7 +267,7 @@ ssh_gssapi_krb5_cmdok(krb5_principal pri
|
||||||
|
/* This writes out any forwarded credentials from the structure populated
|
||||||
|
* during userauth. Called after we have setuid to the user */
|
||||||
|
|
||||||
|
-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_cl
|
||||||
|
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_cl
|
||||||
|
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_cl
|
||||||
|
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_cl
|
||||||
|
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_cl
|
||||||
|
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_cl
|
||||||
|
|
||||||
|
client->store.data = krb_context;
|
||||||
|
|
||||||
|
- return;
|
||||||
|
+ return set_env;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
diff -up openssh-8.6p1/servconf.c.ccache_name openssh-8.6p1/servconf.c
|
||||||
|
--- openssh-8.6p1/servconf.c.ccache_name 2021-04-19 14:05:10.848744532 +0200
|
||||||
|
+++ openssh-8.6p1/servconf.c 2021-04-19 14:05:10.854744577 +0200
|
||||||
|
@@ -136,6 +136,7 @@ initialize_server_options(ServerOptions
|
||||||
|
options->kerberos_or_local_passwd = -1;
|
||||||
|
options->kerberos_ticket_cleanup = -1;
|
||||||
|
options->kerberos_get_afs_token = -1;
|
||||||
|
+ options->kerberos_unique_ccache = -1;
|
||||||
|
options->gss_authentication=-1;
|
||||||
|
options->gss_keyex = -1;
|
||||||
|
options->gss_cleanup_creds = -1;
|
||||||
|
@@ -359,6 +360,8 @@ fill_default_server_options(ServerOption
|
||||||
|
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)
|
||||||
|
@@ -506,7 +509,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,
|
||||||
|
@@ -593,11 +597,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 },
|
||||||
|
@@ -1573,6 +1579,10 @@ process_server_config_line_depth(ServerO
|
||||||
|
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;
|
||||||
|
@@ -2891,6 +2901,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 -up openssh-8.6p1/servconf.h.ccache_name openssh-8.6p1/servconf.h
|
||||||
|
--- openssh-8.6p1/servconf.h.ccache_name 2021-04-19 14:05:10.848744532 +0200
|
||||||
|
+++ openssh-8.6p1/servconf.h 2021-04-19 14:05:10.855744584 +0200
|
||||||
|
@@ -140,6 +140,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 -up openssh-8.6p1/session.c.ccache_name openssh-8.6p1/session.c
|
||||||
|
--- openssh-8.6p1/session.c.ccache_name 2021-04-19 14:05:10.852744562 +0200
|
||||||
|
+++ openssh-8.6p1/session.c 2021-04-19 14:05:10.855744584 +0200
|
||||||
|
@@ -1038,7 +1038,8 @@ do_setup_env(struct ssh *ssh, Session *s
|
||||||
|
/* 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. */
|
||||||
|
@@ -1114,7 +1115,7 @@ do_setup_env(struct ssh *ssh, Session *s
|
||||||
|
}
|
||||||
|
#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 -up openssh-8.6p1/sshd-session.c.ccache_name openssh-8.6p1/sshd-session.c
|
||||||
|
--- openssh-8.6p1/sshd-session.c.ccache_name 2021-04-19 14:05:10.849744540 +0200
|
||||||
|
+++ openssh-8.6p1/sshd-session.c 2021-04-19 14:05:10.855744584 +0200
|
||||||
|
@@ -2284,7 +2284,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 -up openssh-8.6p1/sshd_config.5.ccache_name openssh-8.6p1/sshd_config.5
|
||||||
|
--- openssh-8.6p1/sshd_config.5.ccache_name 2021-04-19 14:05:10.849744540 +0200
|
||||||
|
+++ openssh-8.6p1/sshd_config.5 2021-04-19 14:05:10.856744592 +0200
|
||||||
|
@@ -939,6 +939,14 @@ Specifies whether to automatically destr
|
||||||
|
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.
|
||||||
|
diff -up openssh-8.6p1/ssh-gss.h.ccache_name openssh-8.6p1/ssh-gss.h
|
||||||
|
--- openssh-8.6p1/ssh-gss.h.ccache_name 2021-04-19 14:05:10.852744562 +0200
|
||||||
|
+++ openssh-8.6p1/ssh-gss.h 2021-04-19 14:05:10.855744584 +0200
|
||||||
|
@@ -114,7 +114,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;
|
||||||
|
|
||||||
|
@@ -175,7 +175,7 @@ int ssh_gssapi_userok(char *name, struct
|
||||||
|
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);
|
@ -0,0 +1,109 @@
|
|||||||
|
diff -up openssh/ssh_config.redhat openssh/ssh_config
|
||||||
|
--- openssh/ssh_config.redhat 2020-02-11 23:28:35.000000000 +0100
|
||||||
|
+++ openssh/ssh_config 2020-02-13 18:13:39.180641839 +0100
|
||||||
|
@@ -43,3 +43,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 -up openssh/ssh_config_redhat.redhat openssh/ssh_config_redhat
|
||||||
|
--- openssh/ssh_config_redhat.redhat 2020-02-13 18:13:39.180641839 +0100
|
||||||
|
+++ openssh/ssh_config_redhat 2020-02-13 18:13:39.180641839 +0100
|
||||||
|
@@ -0,0 +1,15 @@
|
||||||
|
+# 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
|
||||||
|
+
|
||||||
|
+# Uncomment this if you want to use .local domain
|
||||||
|
+# Host *.local
|
||||||
|
diff -up openssh/sshd_config.0.redhat openssh/sshd_config.0
|
||||||
|
--- openssh/sshd_config.0.redhat 2020-02-12 14:30:04.000000000 +0100
|
||||||
|
+++ openssh/sshd_config.0 2020-02-13 18:13:39.181641855 +0100
|
||||||
|
@@ -970,9 +970,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/sshd_config.5.redhat openssh/sshd_config.5
|
||||||
|
--- openssh/sshd_config.5.redhat 2020-02-11 23:28:35.000000000 +0100
|
||||||
|
+++ openssh/sshd_config.5 2020-02-13 18:13:39.181641855 +0100
|
||||||
|
@@ -1614,7 +1614,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/sshd_config.redhat openssh/sshd_config
|
||||||
|
--- openssh/sshd_config.redhat 2020-02-11 23:28:35.000000000 +0100
|
||||||
|
+++ openssh/sshd_config 2020-02-13 18:20:16.349913681 +0100
|
||||||
|
@@ -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 -up openssh/sshd_config_redhat.redhat openssh/sshd_config_redhat
|
||||||
|
--- openssh/sshd_config_redhat.redhat 2020-02-13 18:14:02.268006439 +0100
|
||||||
|
+++ openssh/sshd_config_redhat 2020-02-13 18:19:20.765035947 +0100
|
||||||
|
@@ -0,0 +1,15 @@
|
||||||
|
+SyslogFacility AUTHPRIV
|
||||||
|
+
|
||||||
|
+ChallengeResponseAuthentication no
|
||||||
|
+
|
||||||
|
+GSSAPIAuthentication yes
|
||||||
|
+GSSAPICleanupCredentials no
|
||||||
|
+
|
||||||
|
+UsePAM yes
|
||||||
|
+
|
||||||
|
+X11Forwarding yes
|
||||||
|
+
|
||||||
|
+# 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 -up openssh/sshd_config_redhat.redhat openssh/sshd_config_redhat
|
||||||
|
--- openssh/sshd_config_redhat_cp.redhat 2020-02-13 18:14:02.268006439 +0100
|
||||||
|
+++ openssh/sshd_config_redhat_cp 2020-02-13 18:19:20.765035947 +0100
|
||||||
|
@@ -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
|
||||||
|
+
|
@ -0,0 +1,26 @@
|
|||||||
|
diff -up openssh-8.6p1/sshd.c.log-usepam-no openssh-8.6p1/sshd.c
|
||||||
|
--- openssh-8.6p1/sshd-session.c.log-usepam-no 2021-04-19 14:00:45.099735129 +0200
|
||||||
|
+++ openssh-8.6p1/sshd-session.c 2021-04-19 14:03:21.140920974 +0200
|
||||||
|
@@ -1749,6 +1749,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 -up openssh-8.6p1/sshd_config.log-usepam-no openssh-8.6p1/sshd_config
|
||||||
|
--- openssh-8.6p1/sshd_config.log-usepam-no 2021-04-19 14:00:45.098735121 +0200
|
||||||
|
+++ openssh-8.6p1/sshd_config 2021-04-19 14:00:45.099735129 +0200
|
||||||
|
@@ -87,6 +87,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
|
@ -0,0 +1,863 @@
|
|||||||
|
diff -up openssh/auth2.c.role-mls openssh/auth2.c
|
||||||
|
--- openssh/auth2.c.role-mls 2018-08-20 07:57:29.000000000 +0200
|
||||||
|
+++ openssh/auth2.c 2018-08-22 11:14:56.815430916 +0200
|
||||||
|
@@ -256,6 +256,9 @@ input_userauth_request(int type, u_int32
|
||||||
|
Authctxt *authctxt = ssh->authctxt;
|
||||||
|
Authmethod *m = NULL;
|
||||||
|
char *user = NULL, *service = NULL, *method = NULL, *style = NULL;
|
||||||
|
+#ifdef WITH_SELINUX
|
||||||
|
+ char *role = NULL;
|
||||||
|
+#endif
|
||||||
|
int r, authenticated = 0;
|
||||||
|
double tstart = monotime_double();
|
||||||
|
|
||||||
|
@@ -268,6 +271,11 @@ input_userauth_request(int type, u_int32
|
||||||
|
debug("userauth-request for user %s service %s method %s", user, service, method);
|
||||||
|
debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
|
||||||
|
|
||||||
|
+#ifdef WITH_SELINUX
|
||||||
|
+ if ((role = strchr(user, '/')) != NULL)
|
||||||
|
+ *role++ = 0;
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
if ((style = strchr(user, ':')) != NULL)
|
||||||
|
*style++ = 0;
|
||||||
|
|
||||||
|
@@ -314,7 +314,13 @@ input_userauth_request(int type, u_int32
|
||||||
|
setproctitle("%s [net]", authctxt->valid ? user : "unknown");
|
||||||
|
authctxt->service = xstrdup(service);
|
||||||
|
authctxt->style = style ? xstrdup(style) : NULL;
|
||||||
|
+#ifdef WITH_SELINUX
|
||||||
|
+ authctxt->role = role ? xstrdup(role) : NULL;
|
||||||
|
+#endif
|
||||||
|
mm_inform_authserv(service, style);
|
||||||
|
+#ifdef WITH_SELINUX
|
||||||
|
+ mm_inform_authrole(role);
|
||||||
|
+#endif
|
||||||
|
userauth_banner(ssh);
|
||||||
|
if ((r = kex_server_update_ext_info(ssh)) != 0)
|
||||||
|
fatal_fr(r, "kex_server_update_ext_info failed");
|
||||||
|
diff -up openssh/auth2-gss.c.role-mls openssh/auth2-gss.c
|
||||||
|
--- openssh/auth2-gss.c.role-mls 2018-08-20 07:57:29.000000000 +0200
|
||||||
|
+++ openssh/auth2-gss.c 2018-08-22 11:15:42.459799171 +0200
|
||||||
|
@@ -281,6 +281,7 @@ input_gssapi_mic(int type, u_int32_t ple
|
||||||
|
Authctxt *authctxt = ssh->authctxt;
|
||||||
|
Gssctxt *gssctxt;
|
||||||
|
int r, authenticated = 0;
|
||||||
|
+ char *micuser;
|
||||||
|
struct sshbuf *b;
|
||||||
|
gss_buffer_desc mic, gssbuf;
|
||||||
|
u_char *p;
|
||||||
|
@@ -298,7 +299,13 @@ input_gssapi_mic(int type, u_int32_t ple
|
||||||
|
fatal_f("sshbuf_new failed");
|
||||||
|
mic.value = p;
|
||||||
|
mic.length = len;
|
||||||
|
- ssh_gssapi_buildmic(b, authctxt->user, authctxt->service,
|
||||||
|
+#ifdef WITH_SELINUX
|
||||||
|
+ if (authctxt->role && authctxt->role[0] != 0)
|
||||||
|
+ xasprintf(&micuser, "%s/%s", authctxt->user, authctxt->role);
|
||||||
|
+ else
|
||||||
|
+#endif
|
||||||
|
+ micuser = authctxt->user;
|
||||||
|
+ ssh_gssapi_buildmic(b, micuser, authctxt->service,
|
||||||
|
"gssapi-with-mic", ssh->kex->session_id);
|
||||||
|
|
||||||
|
if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL)
|
||||||
|
@@ -311,6 +318,8 @@ input_gssapi_mic(int type, u_int32_t ple
|
||||||
|
logit("GSSAPI MIC check failed");
|
||||||
|
|
||||||
|
sshbuf_free(b);
|
||||||
|
+ if (micuser != authctxt->user)
|
||||||
|
+ free(micuser);
|
||||||
|
free(mic.value);
|
||||||
|
|
||||||
|
authctxt->postponed = 0;
|
||||||
|
diff -up openssh/auth2-hostbased.c.role-mls openssh/auth2-hostbased.c
|
||||||
|
--- openssh/auth2-hostbased.c.role-mls 2018-08-20 07:57:29.000000000 +0200
|
||||||
|
+++ openssh/auth2-hostbased.c 2018-08-22 11:14:56.816430924 +0200
|
||||||
|
@@ -123,7 +123,16 @@ userauth_hostbased(struct ssh *ssh)
|
||||||
|
/* reconstruct packet */
|
||||||
|
if ((r = sshbuf_put_stringb(b, ssh->kex->session_id)) != 0 ||
|
||||||
|
(r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
|
||||||
|
+#ifdef WITH_SELINUX
|
||||||
|
+ (authctxt->role
|
||||||
|
+ ? ( (r = sshbuf_put_u32(b, strlen(authctxt->user)+strlen(authctxt->role)+1)) != 0 ||
|
||||||
|
+ (r = sshbuf_put(b, authctxt->user, strlen(authctxt->user))) != 0 ||
|
||||||
|
+ (r = sshbuf_put_u8(b, '/') != 0) ||
|
||||||
|
+ (r = sshbuf_put(b, authctxt->role, strlen(authctxt->role))) != 0)
|
||||||
|
+ : (r = sshbuf_put_cstring(b, authctxt->user)) != 0) ||
|
||||||
|
+#else
|
||||||
|
(r = sshbuf_put_cstring(b, authctxt->user)) != 0 ||
|
||||||
|
+#endif
|
||||||
|
(r = sshbuf_put_cstring(b, authctxt->service)) != 0 ||
|
||||||
|
(r = sshbuf_put_cstring(b, method)) != 0 ||
|
||||||
|
(r = sshbuf_put_string(b, pkalg, alen)) != 0 ||
|
||||||
|
diff -up openssh/auth2-pubkey.c.role-mls openssh/auth2-pubkey.c
|
||||||
|
--- openssh/auth2-pubkey.c.role-mls 2018-08-22 11:14:56.816430924 +0200
|
||||||
|
+++ openssh/auth2-pubkey.c 2018-08-22 11:17:07.331483958 +0200
|
||||||
|
@@ -169,9 +169,16 @@ userauth_pubkey(struct ssh *ssh)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
/* reconstruct packet */
|
||||||
|
- xasprintf(&userstyle, "%s%s%s", authctxt->user,
|
||||||
|
+ xasprintf(&userstyle, "%s%s%s%s%s", authctxt->user,
|
||||||
|
authctxt->style ? ":" : "",
|
||||||
|
- authctxt->style ? authctxt->style : "");
|
||||||
|
+ authctxt->style ? authctxt->style : "",
|
||||||
|
+#ifdef WITH_SELINUX
|
||||||
|
+ authctxt->role ? "/" : "",
|
||||||
|
+ authctxt->role ? authctxt->role : ""
|
||||||
|
+#else
|
||||||
|
+ "", ""
|
||||||
|
+#endif
|
||||||
|
+ );
|
||||||
|
if ((r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
|
||||||
|
(r = sshbuf_put_cstring(b, userstyle)) != 0 ||
|
||||||
|
(r = sshbuf_put_cstring(b, authctxt->service)) != 0 ||
|
||||||
|
diff -up openssh/auth.h.role-mls openssh/auth.h
|
||||||
|
--- openssh/auth.h.role-mls 2018-08-20 07:57:29.000000000 +0200
|
||||||
|
+++ openssh/auth.h 2018-08-22 11:14:56.816430924 +0200
|
||||||
|
@@ -65,6 +65,9 @@ struct Authctxt {
|
||||||
|
char *service;
|
||||||
|
struct passwd *pw; /* set if 'valid' */
|
||||||
|
char *style;
|
||||||
|
+#ifdef WITH_SELINUX
|
||||||
|
+ char *role;
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
/* Method lists for multiple authentication */
|
||||||
|
char **auth_methods; /* modified from server config */
|
||||||
|
diff -up openssh/auth-pam.c.role-mls openssh/auth-pam.c
|
||||||
|
--- openssh/auth-pam.c.role-mls 2018-08-20 07:57:29.000000000 +0200
|
||||||
|
+++ openssh/auth-pam.c 2018-08-22 11:14:56.816430924 +0200
|
||||||
|
@@ -1172,7 +1172,7 @@ is_pam_session_open(void)
|
||||||
|
* during the ssh authentication process.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
-do_pam_putenv(char *name, char *value)
|
||||||
|
+do_pam_putenv(char *name, const char *value)
|
||||||
|
{
|
||||||
|
int ret = 1;
|
||||||
|
char *compound;
|
||||||
|
diff -up openssh/auth-pam.h.role-mls openssh/auth-pam.h
|
||||||
|
--- openssh/auth-pam.h.role-mls 2018-08-20 07:57:29.000000000 +0200
|
||||||
|
+++ openssh/auth-pam.h 2018-08-22 11:14:56.817430932 +0200
|
||||||
|
@@ -33,7 +33,7 @@ u_int do_pam_account(void);
|
||||||
|
void do_pam_session(struct ssh *);
|
||||||
|
void do_pam_setcred(void);
|
||||||
|
void do_pam_chauthtok(void);
|
||||||
|
-int do_pam_putenv(char *, char *);
|
||||||
|
+int do_pam_putenv(char *, const char *);
|
||||||
|
char ** fetch_pam_environment(void);
|
||||||
|
char ** fetch_pam_child_environment(void);
|
||||||
|
void free_pam_environment(char **);
|
||||||
|
diff -up openssh/misc.c.role-mls openssh/misc.c
|
||||||
|
--- openssh/misc.c.role-mls 2018-08-20 07:57:29.000000000 +0200
|
||||||
|
+++ openssh/misc.c 2018-08-22 11:14:56.817430932 +0200
|
||||||
|
@@ -542,6 +542,7 @@ char *
|
||||||
|
colon(char *cp)
|
||||||
|
{
|
||||||
|
int flag = 0;
|
||||||
|
+ int start = 1;
|
||||||
|
|
||||||
|
if (*cp == ':') /* Leading colon is part of file name. */
|
||||||
|
return NULL;
|
||||||
|
@@ -557,6 +558,13 @@ colon(char *cp)
|
||||||
|
return (cp);
|
||||||
|
if (*cp == '/')
|
||||||
|
return NULL;
|
||||||
|
+ if (start) {
|
||||||
|
+ /* Slash on beginning or after dots only denotes file name. */
|
||||||
|
+ if (*cp == '/')
|
||||||
|
+ return (0);
|
||||||
|
+ if (*cp != '.')
|
||||||
|
+ start = 0;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
diff -up openssh-8.6p1/monitor.c.role-mls openssh-8.6p1/monitor.c
|
||||||
|
--- openssh-8.6p1/monitor.c.role-mls 2021-04-16 05:55:25.000000000 +0200
|
||||||
|
+++ openssh-8.6p1/monitor.c 2021-05-21 14:21:56.719414087 +0200
|
||||||
|
@@ -117,6 +117,9 @@ int mm_answer_sign(struct ssh *, int, st
|
||||||
|
int mm_answer_pwnamallow(struct ssh *, int, struct sshbuf *);
|
||||||
|
int mm_answer_auth2_read_banner(struct ssh *, int, struct sshbuf *);
|
||||||
|
int mm_answer_authserv(struct ssh *, int, struct sshbuf *);
|
||||||
|
+#ifdef WITH_SELINUX
|
||||||
|
+int mm_answer_authrole(struct ssh *, int, struct sshbuf *);
|
||||||
|
+#endif
|
||||||
|
int mm_answer_authpassword(struct ssh *, int, struct sshbuf *);
|
||||||
|
int mm_answer_bsdauthquery(struct ssh *, int, struct sshbuf *);
|
||||||
|
int mm_answer_bsdauthrespond(struct ssh *, int, struct sshbuf *);
|
||||||
|
@@ -195,6 +198,9 @@ struct mon_table mon_dispatch_proto20[]
|
||||||
|
{MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
|
||||||
|
{MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
|
||||||
|
{MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
|
||||||
|
+#ifdef WITH_SELINUX
|
||||||
|
+ {MONITOR_REQ_AUTHROLE, MON_ONCE, mm_answer_authrole},
|
||||||
|
+#endif
|
||||||
|
{MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner},
|
||||||
|
{MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
|
||||||
|
#ifdef USE_PAM
|
||||||
|
@@ -803,6 +809,9 @@ mm_answer_pwnamallow(struct ssh *ssh, in
|
||||||
|
|
||||||
|
/* Allow service/style information on the auth context */
|
||||||
|
monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
|
||||||
|
+#ifdef WITH_SELINUX
|
||||||
|
+ monitor_permit(mon_dispatch, MONITOR_REQ_AUTHROLE, 1);
|
||||||
|
+#endif
|
||||||
|
monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1);
|
||||||
|
|
||||||
|
#ifdef USE_PAM
|
||||||
|
@@ -877,6 +886,26 @@ key_base_type_match(const char *method,
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
+#ifdef WITH_SELINUX
|
||||||
|
+int
|
||||||
|
+mm_answer_authrole(struct ssh *ssh, int sock, struct sshbuf *m)
|
||||||
|
+{
|
||||||
|
+ int r;
|
||||||
|
+ monitor_permit_authentications(1);
|
||||||
|
+
|
||||||
|
+ if ((r = sshbuf_get_cstring(m, &authctxt->role, NULL)) != 0)
|
||||||
|
+ fatal_f("buffer error: %s", ssh_err(r));
|
||||||
|
+ debug3_f("role=%s", authctxt->role);
|
||||||
|
+
|
||||||
|
+ if (strlen(authctxt->role) == 0) {
|
||||||
|
+ free(authctxt->role);
|
||||||
|
+ authctxt->role = NULL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return (0);
|
||||||
|
+}
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
int
|
||||||
|
mm_answer_authpassword(struct ssh *ssh, int sock, struct sshbuf *m)
|
||||||
|
{
|
||||||
|
@@ -1251,7 +1280,7 @@ monitor_valid_userblob(struct ssh *ssh,
|
||||||
|
struct sshbuf *b;
|
||||||
|
struct sshkey *hostkey = NULL;
|
||||||
|
const u_char *p;
|
||||||
|
- char *userstyle, *cp;
|
||||||
|
+ char *userstyle, *s, *cp;
|
||||||
|
size_t len;
|
||||||
|
u_char type;
|
||||||
|
int hostbound = 0, r, fail = 0;
|
||||||
|
@@ -1282,6 +1311,8 @@ monitor_valid_userblob(struct ssh *ssh,
|
||||||
|
fail++;
|
||||||
|
if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0)
|
||||||
|
fatal_fr(r, "parse userstyle");
|
||||||
|
+ if ((s = strchr(cp, '/')) != NULL)
|
||||||
|
+ *s = '\0';
|
||||||
|
xasprintf(&userstyle, "%s%s%s", authctxt->user,
|
||||||
|
authctxt->style ? ":" : "",
|
||||||
|
authctxt->style ? authctxt->style : "");
|
||||||
|
@@ -1317,7 +1348,7 @@ monitor_valid_hostbasedblob(const u_char
|
||||||
|
{
|
||||||
|
struct sshbuf *b;
|
||||||
|
const u_char *p;
|
||||||
|
- char *cp, *userstyle;
|
||||||
|
+ char *cp, *s, *userstyle;
|
||||||
|
size_t len;
|
||||||
|
int r, fail = 0;
|
||||||
|
u_char type;
|
||||||
|
@@ -1338,6 +1370,8 @@ monitor_valid_hostbasedblob(const u_char
|
||||||
|
fail++;
|
||||||
|
if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0)
|
||||||
|
fatal_fr(r, "parse userstyle");
|
||||||
|
+ if ((s = strchr(cp, '/')) != NULL)
|
||||||
|
+ *s = '\0';
|
||||||
|
xasprintf(&userstyle, "%s%s%s", authctxt->user,
|
||||||
|
authctxt->style ? ":" : "",
|
||||||
|
authctxt->style ? authctxt->style : "");
|
||||||
|
diff -up openssh/monitor.h.role-mls openssh/monitor.h
|
||||||
|
--- openssh/monitor.h.role-mls 2018-08-20 07:57:29.000000000 +0200
|
||||||
|
+++ openssh/monitor.h 2018-08-22 11:14:56.818430941 +0200
|
||||||
|
@@ -55,6 +55,10 @@ enum monitor_reqtype {
|
||||||
|
MONITOR_REQ_GSSCHECKMIC = 48, MONITOR_ANS_GSSCHECKMIC = 49,
|
||||||
|
MONITOR_REQ_TERM = 50,
|
||||||
|
|
||||||
|
+#ifdef WITH_SELINUX
|
||||||
|
+ MONITOR_REQ_AUTHROLE = 80,
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
MONITOR_REQ_PAM_START = 100,
|
||||||
|
MONITOR_REQ_PAM_ACCOUNT = 102, MONITOR_ANS_PAM_ACCOUNT = 103,
|
||||||
|
MONITOR_REQ_PAM_INIT_CTX = 104, MONITOR_ANS_PAM_INIT_CTX = 105,
|
||||||
|
diff -up openssh/monitor_wrap.c.role-mls openssh/monitor_wrap.c
|
||||||
|
--- openssh/monitor_wrap.c.role-mls 2018-08-22 11:14:56.818430941 +0200
|
||||||
|
+++ openssh/monitor_wrap.c 2018-08-22 11:21:47.938747968 +0200
|
||||||
|
@@ -390,6 +390,27 @@ mm_inform_authserv(char *service, char *
|
||||||
|
sshbuf_free(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Inform the privileged process about role */
|
||||||
|
+
|
||||||
|
+#ifdef WITH_SELINUX
|
||||||
|
+void
|
||||||
|
+mm_inform_authrole(char *role)
|
||||||
|
+{
|
||||||
|
+ int r;
|
||||||
|
+ struct sshbuf *m;
|
||||||
|
+
|
||||||
|
+ debug3_f("entering");
|
||||||
|
+
|
||||||
|
+ if ((m = sshbuf_new()) == NULL)
|
||||||
|
+ fatal_f("sshbuf_new failed");
|
||||||
|
+ if ((r = sshbuf_put_cstring(m, role ? role : "")) != 0)
|
||||||
|
+ fatal_f("buffer error: %s", ssh_err(r));
|
||||||
|
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHROLE, m);
|
||||||
|
+
|
||||||
|
+ sshbuf_free(m);
|
||||||
|
+}
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
/* Do the password authentication */
|
||||||
|
int
|
||||||
|
mm_auth_password(struct ssh *ssh, char *password)
|
||||||
|
diff -up openssh/monitor_wrap.h.role-mls openssh/monitor_wrap.h
|
||||||
|
--- openssh/monitor_wrap.h.role-mls 2018-08-22 11:14:56.818430941 +0200
|
||||||
|
+++ openssh/monitor_wrap.h 2018-08-22 11:22:10.439929513 +0200
|
||||||
|
@@ -44,6 +44,9 @@ DH *mm_choose_dh(int, int, int);
|
||||||
|
const u_char *, size_t, const char *, const char *,
|
||||||
|
const char *, u_int compat);
|
||||||
|
void mm_inform_authserv(char *, char *);
|
||||||
|
+#ifdef WITH_SELINUX
|
||||||
|
+void mm_inform_authrole(char *);
|
||||||
|
+#endif
|
||||||
|
struct passwd *mm_getpwnamallow(struct ssh *, const char *);
|
||||||
|
char *mm_auth2_read_banner(void);
|
||||||
|
int mm_auth_password(struct ssh *, char *);
|
||||||
|
diff -up openssh/openbsd-compat/Makefile.in.role-mls openssh/openbsd-compat/Makefile.in
|
||||||
|
--- openssh/openbsd-compat/Makefile.in.role-mls 2018-08-20 07:57:29.000000000 +0200
|
||||||
|
+++ openssh/openbsd-compat/Makefile.in 2018-08-22 11:14:56.819430949 +0200
|
||||||
|
@@ -92,7 +92,8 @@ PORTS= port-aix.o \
|
||||||
|
port-prngd.o \
|
||||||
|
port-solaris.o \
|
||||||
|
port-net.o \
|
||||||
|
- port-uw.o
|
||||||
|
+ port-uw.o \
|
||||||
|
+ port-linux-sshd.o
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
$(CC) $(CFLAGS_NOPIE) $(PICFLAG) $(CPPFLAGS) -c $<
|
||||||
|
diff -up openssh/openbsd-compat/port-linux.c.role-mls openssh/openbsd-compat/port-linux.c
|
||||||
|
--- openssh/openbsd-compat/port-linux.c.role-mls 2018-08-20 07:57:29.000000000 +0200
|
||||||
|
+++ openssh/openbsd-compat/port-linux.c 2018-08-22 11:14:56.819430949 +0200
|
||||||
|
@@ -100,37 +100,6 @@ ssh_selinux_getctxbyname(char *pwname)
|
||||||
|
return sc;
|
||||||
|
}
|
||||||
|
|
||||||
|
-/* Set the execution context to the default for the specified user */
|
||||||
|
-void
|
||||||
|
-ssh_selinux_setup_exec_context(char *pwname)
|
||||||
|
-{
|
||||||
|
- char *user_ctx = NULL;
|
||||||
|
-
|
||||||
|
- if (!ssh_selinux_enabled())
|
||||||
|
- return;
|
||||||
|
-
|
||||||
|
- debug3("%s: setting execution context", __func__);
|
||||||
|
-
|
||||||
|
- user_ctx = ssh_selinux_getctxbyname(pwname);
|
||||||
|
- if (setexeccon(user_ctx) != 0) {
|
||||||
|
- switch (security_getenforce()) {
|
||||||
|
- case -1:
|
||||||
|
- fatal("%s: security_getenforce() failed", __func__);
|
||||||
|
- case 0:
|
||||||
|
- error("%s: Failed to set SELinux execution "
|
||||||
|
- "context for %s", __func__, pwname);
|
||||||
|
- break;
|
||||||
|
- default:
|
||||||
|
- fatal("%s: Failed to set SELinux execution context "
|
||||||
|
- "for %s (in enforcing mode)", __func__, pwname);
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- if (user_ctx != NULL)
|
||||||
|
- freecon(user_ctx);
|
||||||
|
-
|
||||||
|
- debug3("%s: done", __func__);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
/* Set the TTY context for the specified user */
|
||||||
|
void
|
||||||
|
ssh_selinux_setup_pty(char *pwname, const char *tty)
|
||||||
|
@@ -145,7 +114,11 @@ ssh_selinux_setup_pty(char *pwname, cons
|
||||||
|
|
||||||
|
debug3("%s: setting TTY context on %s", __func__, tty);
|
||||||
|
|
||||||
|
- user_ctx = ssh_selinux_getctxbyname(pwname);
|
||||||
|
+ if (getexeccon(&user_ctx) != 0) {
|
||||||
|
+ error_f("getexeccon: %s", strerror(errno));
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
|
||||||
|
/* XXX: should these calls fatal() upon failure in enforcing mode? */
|
||||||
|
|
||||||
|
diff -up openssh/openbsd-compat/port-linux.h.role-mls openssh/openbsd-compat/port-linux.h
|
||||||
|
--- openssh/openbsd-compat/port-linux.h.role-mls 2018-08-20 07:57:29.000000000 +0200
|
||||||
|
+++ openssh/openbsd-compat/port-linux.h 2018-08-22 11:14:56.819430949 +0200
|
||||||
|
@@ -20,9 +20,10 @@
|
||||||
|
#ifdef WITH_SELINUX
|
||||||
|
int ssh_selinux_enabled(void);
|
||||||
|
void ssh_selinux_setup_pty(char *, const char *);
|
||||||
|
-void ssh_selinux_setup_exec_context(char *);
|
||||||
|
void ssh_selinux_change_context(const char *);
|
||||||
|
void ssh_selinux_setfscreatecon(const char *);
|
||||||
|
+
|
||||||
|
+void sshd_selinux_setup_exec_context(char *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LINUX_OOM_ADJUST
|
||||||
|
diff -up openssh/openbsd-compat/port-linux-sshd.c.role-mls openssh/openbsd-compat/port-linux-sshd.c
|
||||||
|
--- openssh/openbsd-compat/port-linux-sshd.c.role-mls 2018-08-22 11:14:56.819430949 +0200
|
||||||
|
+++ openssh/openbsd-compat/port-linux-sshd.c 2018-08-22 11:14:56.819430949 +0200
|
||||||
|
@@ -0,0 +1,420 @@
|
||||||
|
+/*
|
||||||
|
+ * Copyright (c) 2005 Daniel Walsh <dwalsh@redhat.com>
|
||||||
|
+ * Copyright (c) 2014 Petr Lautrbach <plautrba@redhat.com>
|
||||||
|
+ *
|
||||||
|
+ * Permission to use, copy, modify, and distribute this software for any
|
||||||
|
+ * purpose with or without fee is hereby granted, provided that the above
|
||||||
|
+ * copyright notice and this permission notice appear in all copies.
|
||||||
|
+ *
|
||||||
|
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Linux-specific portability code - just SELinux support for sshd at present
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include "includes.h"
|
||||||
|
+
|
||||||
|
+#if defined(WITH_SELINUX) || defined(LINUX_OOM_ADJUST)
|
||||||
|
+#include <errno.h>
|
||||||
|
+#include <stdarg.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+
|
||||||
|
+#include "log.h"
|
||||||
|
+#include "xmalloc.h"
|
||||||
|
+#include "misc.h" /* servconf.h needs misc.h for struct ForwardOptions */
|
||||||
|
+#include "servconf.h"
|
||||||
|
+#include "port-linux.h"
|
||||||
|
+#include "sshkey.h"
|
||||||
|
+#include "hostfile.h"
|
||||||
|
+#include "auth.h"
|
||||||
|
+
|
||||||
|
+#ifdef WITH_SELINUX
|
||||||
|
+#include <selinux/selinux.h>
|
||||||
|
+#include <selinux/context.h>
|
||||||
|
+#include <selinux/get_context_list.h>
|
||||||
|
+#include <selinux/get_default_type.h>
|
||||||
|
+
|
||||||
|
+#ifdef HAVE_LINUX_AUDIT
|
||||||
|
+#include <libaudit.h>
|
||||||
|
+#include <unistd.h>
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+extern ServerOptions options;
|
||||||
|
+extern Authctxt *the_authctxt;
|
||||||
|
+extern int inetd_flag;
|
||||||
|
+
|
||||||
|
+/* Send audit message */
|
||||||
|
+static int
|
||||||
|
+sshd_selinux_send_audit_message(int success, security_context_t default_context,
|
||||||
|
+ security_context_t selected_context)
|
||||||
|
+{
|
||||||
|
+ int rc=0;
|
||||||
|
+#ifdef HAVE_LINUX_AUDIT
|
||||||
|
+ char *msg = NULL;
|
||||||
|
+ int audit_fd = audit_open();
|
||||||
|
+ security_context_t default_raw=NULL;
|
||||||
|
+ security_context_t selected_raw=NULL;
|
||||||
|
+ rc = -1;
|
||||||
|
+ if (audit_fd < 0) {
|
||||||
|
+ if (errno == EINVAL || errno == EPROTONOSUPPORT ||
|
||||||
|
+ errno == EAFNOSUPPORT)
|
||||||
|
+ return 0; /* No audit support in kernel */
|
||||||
|
+ error("Error connecting to audit system.");
|
||||||
|
+ return rc;
|
||||||
|
+ }
|
||||||
|
+ if (selinux_trans_to_raw_context(default_context, &default_raw) < 0) {
|
||||||
|
+ error("Error translating default context.");
|
||||||
|
+ default_raw = NULL;
|
||||||
|
+ }
|
||||||
|
+ if (selinux_trans_to_raw_context(selected_context, &selected_raw) < 0) {
|
||||||
|
+ error("Error translating selected context.");
|
||||||
|
+ selected_raw = NULL;
|
||||||
|
+ }
|
||||||
|
+ if (asprintf(&msg, "sshd: default-context=%s selected-context=%s",
|
||||||
|
+ default_raw ? default_raw : (default_context ? default_context: "?"),
|
||||||
|
+ selected_context ? selected_raw : (selected_context ? selected_context :"?")) < 0) {
|
||||||
|
+ error("Error allocating memory.");
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ if (audit_log_user_message(audit_fd, AUDIT_USER_ROLE_CHANGE,
|
||||||
|
+ msg, NULL, NULL, NULL, success) <= 0) {
|
||||||
|
+ error("Error sending audit message.");
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ rc = 0;
|
||||||
|
+ out:
|
||||||
|
+ free(msg);
|
||||||
|
+ freecon(default_raw);
|
||||||
|
+ freecon(selected_raw);
|
||||||
|
+ close(audit_fd);
|
||||||
|
+#endif
|
||||||
|
+ return rc;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+mls_range_allowed(security_context_t src, security_context_t dst)
|
||||||
|
+{
|
||||||
|
+ struct av_decision avd;
|
||||||
|
+ int retval;
|
||||||
|
+ access_vector_t bit;
|
||||||
|
+ security_class_t class;
|
||||||
|
+
|
||||||
|
+ debug_f("src:%s dst:%s", src, dst);
|
||||||
|
+ class = string_to_security_class("context");
|
||||||
|
+ if (!class) {
|
||||||
|
+ error("string_to_security_class failed to translate security class context");
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ bit = string_to_av_perm(class, "contains");
|
||||||
|
+ if (!bit) {
|
||||||
|
+ error("string_to_av_perm failed to translate av perm contains");
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ retval = security_compute_av(src, dst, class, bit, &avd);
|
||||||
|
+ if (retval || ((bit & avd.allowed) != bit))
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ return 1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+get_user_context(const char *sename, const char *role, const char *lvl,
|
||||||
|
+ security_context_t *sc) {
|
||||||
|
+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
|
||||||
|
+ if (lvl == NULL || lvl[0] == '\0' || get_default_context_with_level(sename, lvl, NULL, sc) != 0) {
|
||||||
|
+ /* User may have requested a level completely outside of his
|
||||||
|
+ allowed range. We get a context just for auditing as the
|
||||||
|
+ range check below will certainly fail for default context. */
|
||||||
|
+#endif
|
||||||
|
+ if (get_default_context(sename, NULL, sc) != 0) {
|
||||||
|
+ *sc = NULL;
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+ if (role != NULL && role[0]) {
|
||||||
|
+ context_t con;
|
||||||
|
+ char *type=NULL;
|
||||||
|
+ if (get_default_type(role, &type) != 0) {
|
||||||
|
+ error("get_default_type: failed to get default type for '%s'",
|
||||||
|
+ role);
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ con = context_new(*sc);
|
||||||
|
+ if (!con) {
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ context_role_set(con, role);
|
||||||
|
+ context_type_set(con, type);
|
||||||
|
+ freecon(*sc);
|
||||||
|
+ *sc = strdup(context_str(con));
|
||||||
|
+ context_free(con);
|
||||||
|
+ if (!*sc)
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
|
||||||
|
+ if (lvl != NULL && lvl[0]) {
|
||||||
|
+ /* verify that the requested range is obtained */
|
||||||
|
+ context_t con;
|
||||||
|
+ security_context_t obtained_raw;
|
||||||
|
+ security_context_t requested_raw;
|
||||||
|
+ con = context_new(*sc);
|
||||||
|
+ if (!con) {
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ context_range_set(con, lvl);
|
||||||
|
+ if (selinux_trans_to_raw_context(*sc, &obtained_raw) < 0) {
|
||||||
|
+ context_free(con);
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ if (selinux_trans_to_raw_context(context_str(con), &requested_raw) < 0) {
|
||||||
|
+ freecon(obtained_raw);
|
||||||
|
+ context_free(con);
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ debug("get_user_context: obtained context '%s' requested context '%s'",
|
||||||
|
+ obtained_raw, requested_raw);
|
||||||
|
+ if (strcmp(obtained_raw, requested_raw)) {
|
||||||
|
+ /* set the context to the real requested one but fail */
|
||||||
|
+ freecon(requested_raw);
|
||||||
|
+ freecon(obtained_raw);
|
||||||
|
+ freecon(*sc);
|
||||||
|
+ *sc = strdup(context_str(con));
|
||||||
|
+ context_free(con);
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+ freecon(requested_raw);
|
||||||
|
+ freecon(obtained_raw);
|
||||||
|
+ context_free(con);
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+ return 0;
|
||||||
|
+ out:
|
||||||
|
+ freecon(*sc);
|
||||||
|
+ *sc = NULL;
|
||||||
|
+ return -1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+ssh_selinux_get_role_level(char **role, const char **level)
|
||||||
|
+{
|
||||||
|
+ *role = NULL;
|
||||||
|
+ *level = NULL;
|
||||||
|
+ if (the_authctxt) {
|
||||||
|
+ if (the_authctxt->role != NULL) {
|
||||||
|
+ char *slash;
|
||||||
|
+ *role = xstrdup(the_authctxt->role);
|
||||||
|
+ if ((slash = strchr(*role, '/')) != NULL) {
|
||||||
|
+ *slash = '\0';
|
||||||
|
+ *level = slash + 1;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Return the default security context for the given username */
|
||||||
|
+static int
|
||||||
|
+sshd_selinux_getctxbyname(char *pwname,
|
||||||
|
+ security_context_t *default_sc, security_context_t *user_sc)
|
||||||
|
+{
|
||||||
|
+ char *sename, *lvl;
|
||||||
|
+ char *role;
|
||||||
|
+ const char *reqlvl;
|
||||||
|
+ int r = 0;
|
||||||
|
+ context_t con = NULL;
|
||||||
|
+
|
||||||
|
+ ssh_selinux_get_role_level(&role, &reqlvl);
|
||||||
|
+
|
||||||
|
+#ifdef HAVE_GETSEUSERBYNAME
|
||||||
|
+ if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) {
|
||||||
|
+ sename = NULL;
|
||||||
|
+ lvl = NULL;
|
||||||
|
+ }
|
||||||
|
+#else
|
||||||
|
+ sename = pwname;
|
||||||
|
+ lvl = "";
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ if (r == 0) {
|
||||||
|
+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
|
||||||
|
+ r = get_default_context_with_level(sename, lvl, NULL, default_sc);
|
||||||
|
+#else
|
||||||
|
+ r = get_default_context(sename, NULL, default_sc);
|
||||||
|
+#endif
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (r == 0) {
|
||||||
|
+ /* If launched from xinetd, we must use current level */
|
||||||
|
+ if (inetd_flag) {
|
||||||
|
+ security_context_t sshdsc=NULL;
|
||||||
|
+
|
||||||
|
+ if (getcon_raw(&sshdsc) < 0)
|
||||||
|
+ fatal("failed to allocate security context");
|
||||||
|
+
|
||||||
|
+ if ((con=context_new(sshdsc)) == NULL)
|
||||||
|
+ fatal("failed to allocate selinux context");
|
||||||
|
+ reqlvl = context_range_get(con);
|
||||||
|
+ freecon(sshdsc);
|
||||||
|
+ if (reqlvl !=NULL && lvl != NULL && strcmp(reqlvl, lvl) == 0)
|
||||||
|
+ /* we actually don't change level */
|
||||||
|
+ reqlvl = "";
|
||||||
|
+
|
||||||
|
+ debug_f("current connection level '%s'", reqlvl);
|
||||||
|
+
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if ((reqlvl != NULL && reqlvl[0]) || (role != NULL && role[0])) {
|
||||||
|
+ r = get_user_context(sename, role, reqlvl, user_sc);
|
||||||
|
+
|
||||||
|
+ if (r == 0 && reqlvl != NULL && reqlvl[0]) {
|
||||||
|
+ security_context_t default_level_sc = *default_sc;
|
||||||
|
+ if (role != NULL && role[0]) {
|
||||||
|
+ if (get_user_context(sename, role, lvl, &default_level_sc) < 0)
|
||||||
|
+ default_level_sc = *default_sc;
|
||||||
|
+ }
|
||||||
|
+ /* verify that the requested range is contained in the user range */
|
||||||
|
+ if (mls_range_allowed(default_level_sc, *user_sc)) {
|
||||||
|
+ logit("permit MLS level %s (user range %s)", reqlvl, lvl);
|
||||||
|
+ } else {
|
||||||
|
+ r = -1;
|
||||||
|
+ error("deny MLS level %s (user range %s)", reqlvl, lvl);
|
||||||
|
+ }
|
||||||
|
+ if (default_level_sc != *default_sc)
|
||||||
|
+ freecon(default_level_sc);
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ *user_sc = *default_sc;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ if (r != 0) {
|
||||||
|
+ error_f("Failed to get default SELinux security "
|
||||||
|
+ "context for %s", pwname);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+#ifdef HAVE_GETSEUSERBYNAME
|
||||||
|
+ free(sename);
|
||||||
|
+ free(lvl);
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ if (role != NULL)
|
||||||
|
+ free(role);
|
||||||
|
+ if (con)
|
||||||
|
+ context_free(con);
|
||||||
|
+
|
||||||
|
+ return (r);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Setup environment variables for pam_selinux */
|
||||||
|
+static int
|
||||||
|
+sshd_selinux_setup_pam_variables(void)
|
||||||
|
+{
|
||||||
|
+ const char *reqlvl;
|
||||||
|
+ char *role;
|
||||||
|
+ char *use_current;
|
||||||
|
+ int rv;
|
||||||
|
+
|
||||||
|
+ debug3_f("setting execution context");
|
||||||
|
+
|
||||||
|
+ ssh_selinux_get_role_level(&role, &reqlvl);
|
||||||
|
+
|
||||||
|
+ rv = do_pam_putenv("SELINUX_ROLE_REQUESTED", role ? role : "");
|
||||||
|
+
|
||||||
|
+ if (inetd_flag) {
|
||||||
|
+ use_current = "1";
|
||||||
|
+ } else {
|
||||||
|
+ use_current = "";
|
||||||
|
+ rv = rv || do_pam_putenv("SELINUX_LEVEL_REQUESTED", reqlvl ? reqlvl: "");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ rv = rv || do_pam_putenv("SELINUX_USE_CURRENT_RANGE", use_current);
|
||||||
|
+
|
||||||
|
+ if (role != NULL)
|
||||||
|
+ free(role);
|
||||||
|
+
|
||||||
|
+ return rv;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Set the execution context to the default for the specified user */
|
||||||
|
+void
|
||||||
|
+sshd_selinux_setup_exec_context(char *pwname)
|
||||||
|
+{
|
||||||
|
+ security_context_t user_ctx = NULL;
|
||||||
|
+ int r = 0;
|
||||||
|
+ security_context_t default_ctx = NULL;
|
||||||
|
+
|
||||||
|
+ if (!ssh_selinux_enabled())
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ if (options.use_pam) {
|
||||||
|
+ /* do not compute context, just setup environment for pam_selinux */
|
||||||
|
+ if (sshd_selinux_setup_pam_variables()) {
|
||||||
|
+ switch (security_getenforce()) {
|
||||||
|
+ case -1:
|
||||||
|
+ fatal_f("security_getenforce() failed");
|
||||||
|
+ case 0:
|
||||||
|
+ error_f("SELinux PAM variable setup failure. Continuing in permissive mode.");
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ fatal_f("SELinux PAM variable setup failure. Aborting connection.");
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ debug3_f("setting execution context");
|
||||||
|
+
|
||||||
|
+ r = sshd_selinux_getctxbyname(pwname, &default_ctx, &user_ctx);
|
||||||
|
+ if (r >= 0) {
|
||||||
|
+ r = setexeccon(user_ctx);
|
||||||
|
+ if (r < 0) {
|
||||||
|
+ error_f("Failed to set SELinux execution context %s for %s",
|
||||||
|
+ user_ctx, pwname);
|
||||||
|
+ }
|
||||||
|
+#ifdef HAVE_SETKEYCREATECON
|
||||||
|
+ else if (setkeycreatecon(user_ctx) < 0) {
|
||||||
|
+ error_f("Failed to set SELinux keyring creation context %s for %s",
|
||||||
|
+ user_ctx, pwname);
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+ }
|
||||||
|
+ if (user_ctx == NULL) {
|
||||||
|
+ user_ctx = default_ctx;
|
||||||
|
+ }
|
||||||
|
+ if (r < 0 || user_ctx != default_ctx) {
|
||||||
|
+ /* audit just the case when user changed a role or there was
|
||||||
|
+ a failure */
|
||||||
|
+ sshd_selinux_send_audit_message(r >= 0, default_ctx, user_ctx);
|
||||||
|
+ }
|
||||||
|
+ if (r < 0) {
|
||||||
|
+ switch (security_getenforce()) {
|
||||||
|
+ case -1:
|
||||||
|
+ fatal_f("security_getenforce() failed");
|
||||||
|
+ case 0:
|
||||||
|
+ error_f("ELinux failure. Continuing in permissive mode.");
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ fatal_f("SELinux failure. Aborting connection.");
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ if (user_ctx != NULL && user_ctx != default_ctx)
|
||||||
|
+ freecon(user_ctx);
|
||||||
|
+ if (default_ctx != NULL)
|
||||||
|
+ freecon(default_ctx);
|
||||||
|
+
|
||||||
|
+ debug3_f("done");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#endif
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
diff -up openssh/platform.c.role-mls openssh/platform.c
|
||||||
|
--- openssh/platform.c.role-mls 2018-08-20 07:57:29.000000000 +0200
|
||||||
|
+++ openssh/platform.c 2018-08-22 11:14:56.819430949 +0200
|
||||||
|
@@ -183,7 +183,7 @@ platform_setusercontext_post_groups(stru
|
||||||
|
}
|
||||||
|
#endif /* HAVE_SETPCRED */
|
||||||
|
#ifdef WITH_SELINUX
|
||||||
|
- ssh_selinux_setup_exec_context(pw->pw_name);
|
||||||
|
+ sshd_selinux_setup_exec_context(pw->pw_name);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
diff -up openssh/sshd.c.role-mls openssh/sshd.c
|
||||||
|
--- openssh/sshd-session.c.role-mls 2018-08-20 07:57:29.000000000 +0200
|
||||||
|
+++ openssh/sshd-session.c 2018-08-22 11:14:56.820430957 +0200
|
||||||
|
@@ -2186,6 +2186,9 @@ main(int ac, char **av)
|
||||||
|
restore_uid();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
+#ifdef WITH_SELINUX
|
||||||
|
+ sshd_selinux_setup_exec_context(authctxt->pw->pw_name);
|
||||||
|
+#endif
|
||||||
|
#ifdef USE_PAM
|
||||||
|
if (options.use_pam) {
|
||||||
|
do_pam_setcred();
|
@ -0,0 +1,16 @@
|
|||||||
|
diff --git a/scp.c b/scp.c
|
||||||
|
index 60682c68..9344806e 100644
|
||||||
|
--- a/scp.c
|
||||||
|
+++ b/scp.c
|
||||||
|
@@ -714,7 +714,9 @@ toremote(int argc, char **argv)
|
||||||
|
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)
|
||||||
|
|
@ -0,0 +1,642 @@
|
|||||||
|
diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.3p1/ssh_config.5 openssh-9.3p1-patched/ssh_config.5
|
||||||
|
--- openssh-9.3p1/ssh_config.5 2023-06-07 10:26:48.284590156 +0200
|
||||||
|
+++ openssh-9.3p1-patched/ssh_config.5 2023-06-07 10:26:00.623052194 +0200
|
||||||
|
@@ -378,17 +378,13 @@
|
||||||
|
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
|
||||||
|
@@ -450,20 +446,25 @@
|
||||||
|
(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
|
||||||
|
@@ -479,13 +480,6 @@
|
||||||
|
chacha20-poly1305@openssh.com
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
-The default is:
|
||||||
|
-.Bd -literal -offset indent
|
||||||
|
-chacha20-poly1305@openssh.com,
|
||||||
|
-aes128-ctr,aes192-ctr,aes256-ctr,
|
||||||
|
-aes128-gcm@openssh.com,aes256-gcm@openssh.com
|
||||||
|
-.Ed
|
||||||
|
-.Pp
|
||||||
|
The list of available ciphers may also be obtained using
|
||||||
|
.Qq ssh -Q cipher .
|
||||||
|
.It Cm ClearAllForwardings
|
||||||
|
@@ -885,6 +879,11 @@
|
||||||
|
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
|
||||||
|
@@ -897,10 +896,8 @@
|
||||||
|
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
|
||||||
|
@@ -919,36 +916,25 @@
|
||||||
|
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
|
||||||
|
@@ -1001,6 +987,17 @@
|
||||||
|
.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
|
||||||
|
@@ -1330,6 +1330,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
|
||||||
|
@@ -1338,29 +1343,17 @@ Multiple algorithms must be comma-separa
|
||||||
|
.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
|
||||||
|
-sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com,
|
||||||
|
-mlkem768x25519-sha256,
|
||||||
|
-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
|
||||||
|
@@ -1365,37 +1357,33 @@
|
||||||
|
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
|
||||||
|
@@ -1567,39 +1555,31 @@
|
||||||
|
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
|
||||||
|
@@ -2265,7 +2245,9 @@
|
||||||
|
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 --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.3p1/sshd_config.5 openssh-9.3p1-patched/sshd_config.5
|
||||||
|
--- openssh-9.3p1/sshd_config.5 2023-06-07 10:26:48.277590077 +0200
|
||||||
|
+++ openssh-9.3p1-patched/sshd_config.5 2023-06-07 10:26:00.592051845 +0200
|
||||||
|
@@ -379,17 +379,13 @@
|
||||||
|
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
|
||||||
|
@@ -525,20 +521,25 @@
|
||||||
|
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
|
||||||
|
@@ -565,13 +566,6 @@
|
||||||
|
chacha20-poly1305@openssh.com
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
-The default is:
|
||||||
|
-.Bd -literal -offset indent
|
||||||
|
-chacha20-poly1305@openssh.com,
|
||||||
|
-aes128-ctr,aes192-ctr,aes256-ctr,
|
||||||
|
-aes128-gcm@openssh.com,aes256-gcm@openssh.com
|
||||||
|
-.Ed
|
||||||
|
-.Pp
|
||||||
|
The list of available ciphers may also be obtained using
|
||||||
|
.Qq ssh -Q cipher .
|
||||||
|
.It Cm ClientAliveCountMax
|
||||||
|
@@ -766,53 +760,43 @@
|
||||||
|
.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 .
|
||||||
|
@@ -879,25 +863,14 @@
|
||||||
|
.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
|
||||||
|
@@ -1025,6 +1025,11 @@ Specifies whether to look at .k5login fi
|
||||||
|
The default is
|
||||||
|
.Cm yes .
|
||||||
|
.It Cm KexAlgorithms
|
||||||
|
+The default is handled system-wide by
|
||||||
|
+.Xr crypto-policies 7 .
|
||||||
|
+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
|
||||||
|
@@ -1033,16 +1038,16 @@ Multiple algorithms must be comma-separa
|
||||||
|
.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
|
||||||
|
@@ -1075,17 +1080,6 @@ ecdh-sha2-nistp521
|
||||||
|
sntrup761x25519-sha512@openssh.com
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
-The default is:
|
||||||
|
-.Bd -literal -offset indent
|
||||||
|
-sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com,
|
||||||
|
-mlkem768x25519-sha256,
|
||||||
|
-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
|
||||||
|
The list of supported key exchange algorithms may also be obtained using
|
||||||
|
.Qq ssh -Q KexAlgorithms .
|
||||||
|
.It Cm ListenAddress
|
||||||
|
@@ -1184,21 +1152,26 @@
|
||||||
|
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
|
||||||
|
@@ -1241,15 +1214,6 @@
|
||||||
|
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
|
||||||
|
@@ -1633,36 +1597,25 @@
|
||||||
|
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 .
|
||||||
|
@@ -2131,7 +2084,9 @@
|
||||||
|
.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
|
@ -0,0 +1,12 @@
|
|||||||
|
diff -up openssh-8.0p1/ssh-keygen.c.strip-doseol openssh-8.0p1/ssh-keygen.c
|
||||||
|
--- openssh-8.0p1/ssh-keygen.c.strip-doseol 2021-03-18 17:41:34.472404994 +0100
|
||||||
|
+++ openssh-8.0p1/ssh-keygen.c 2021-03-18 17:41:55.255538761 +0100
|
||||||
|
@@ -901,7 +901,7 @@ do_fingerprint(struct passwd *pw)
|
||||||
|
while (getline(&line, &linesize, f) != -1) {
|
||||||
|
lnum++;
|
||||||
|
cp = line;
|
||||||
|
- cp[strcspn(cp, "\n")] = '\0';
|
||||||
|
+ cp[strcspn(cp, "\r\n")] = '\0';
|
||||||
|
/* Trim leading space and comments */
|
||||||
|
cp = line + strspn(line, " \t");
|
||||||
|
if (*cp == '#' || *cp == '\0')
|
@ -0,0 +1,151 @@
|
|||||||
|
commit 2c3ef499bfffce3cfd315edeebf202850ba4e00a
|
||||||
|
Author: Jakub Jelen <jjelen@redhat.com>
|
||||||
|
Date: Tue Apr 16 15:35:18 2019 +0200
|
||||||
|
|
||||||
|
Use the new OpenSSL KDF
|
||||||
|
|
||||||
|
diff --git a/configure.ac b/configure.ac
|
||||||
|
index 2a455e4e..e01c3d43 100644
|
||||||
|
--- a/configure.ac
|
||||||
|
+++ b/configure.ac
|
||||||
|
@@ -2712,6 +2712,7 @@ if test "x$openssl" = "xyes" ; then
|
||||||
|
HMAC_CTX_init \
|
||||||
|
RSA_generate_key_ex \
|
||||||
|
RSA_get_default_method \
|
||||||
|
+ EVP_KDF_CTX_new \
|
||||||
|
])
|
||||||
|
|
||||||
|
# OpenSSL_add_all_algorithms may be a macro.
|
||||||
|
diff --git a/kex.c b/kex.c
|
||||||
|
index b6f041f4..1fbce2bb 100644
|
||||||
|
--- a/kex.c
|
||||||
|
+++ b/kex.c
|
||||||
|
@@ -38,6 +38,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"
|
||||||
|
@@ -942,6 +945,107 @@ kex_choose_conf(struct ssh *ssh)
|
||||||
|
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)
|
||||||
|
@@ -1004,6 +1096,7 @@ derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen,
|
||||||
|
ssh_digest_free(hashctx);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
+#endif /* HAVE_OPENSSL_EVP_KDF_CTX_NEW */
|
||||||
|
|
||||||
|
#define NKEYS 6
|
||||||
|
int
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,43 @@
|
|||||||
|
diff -up openssh-8.0p1/auth-pam.c.preserve-pam-errors openssh-8.0p1/auth-pam.c
|
||||||
|
--- openssh-8.0p1/auth-pam.c.preserve-pam-errors 2021-03-31 17:03:15.618592347 +0200
|
||||||
|
+++ openssh-8.0p1/auth-pam.c 2021-03-31 17:06:58.115220014 +0200
|
||||||
|
@@ -511,7 +511,11 @@ sshpam_thread(void *ctxtp)
|
||||||
|
goto auth_fail;
|
||||||
|
|
||||||
|
if (!do_pam_account()) {
|
||||||
|
- sshpam_err = PAM_ACCT_EXPIRED;
|
||||||
|
+ /* Preserve PAM_PERM_DENIED and PAM_USER_UNKNOWN.
|
||||||
|
+ * Backward compatibility for other errors. */
|
||||||
|
+ if (sshpam_err != PAM_PERM_DENIED
|
||||||
|
+ && sshpam_err != PAM_USER_UNKNOWN)
|
||||||
|
+ sshpam_err = PAM_ACCT_EXPIRED;
|
||||||
|
goto auth_fail;
|
||||||
|
}
|
||||||
|
if (sshpam_authctxt->force_pwchange) {
|
||||||
|
@@ -568,8 +572,10 @@ sshpam_thread(void *ctxtp)
|
||||||
|
pam_strerror(sshpam_handle, sshpam_err))) != 0)
|
||||||
|
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
/* XXX - can't do much about an error here */
|
||||||
|
- if (sshpam_err == PAM_ACCT_EXPIRED)
|
||||||
|
- ssh_msg_send(ctxt->pam_csock, PAM_ACCT_EXPIRED, buffer);
|
||||||
|
+ if (sshpam_err == PAM_PERM_DENIED
|
||||||
|
+ || sshpam_err == PAM_USER_UNKNOWN
|
||||||
|
+ || sshpam_err == PAM_ACCT_EXPIRED)
|
||||||
|
+ ssh_msg_send(ctxt->pam_csock, sshpam_err, buffer);
|
||||||
|
else if (sshpam_maxtries_reached)
|
||||||
|
ssh_msg_send(ctxt->pam_csock, PAM_MAXTRIES, buffer);
|
||||||
|
else
|
||||||
|
@@ -856,9 +862,11 @@ sshpam_query(void *ctx, char **name, cha
|
||||||
|
free(msg);
|
||||||
|
break;
|
||||||
|
case PAM_ACCT_EXPIRED:
|
||||||
|
+ sshpam_account_status = 0;
|
||||||
|
+ /* FALLTHROUGH */
|
||||||
|
case PAM_MAXTRIES:
|
||||||
|
+ case PAM_USER_UNKNOWN:
|
||||||
|
+ case PAM_PERM_DENIED:
|
||||||
|
- if (type == PAM_ACCT_EXPIRED)
|
||||||
|
- sshpam_account_status = 0;
|
||||||
|
if (type == PAM_MAXTRIES)
|
||||||
|
sshpam_set_maxtries_reached(1);
|
||||||
|
/* FALLTHROUGH */
|
@ -0,0 +1,40 @@
|
|||||||
|
diff --git a/regress/misc/sk-dummy/sk-dummy.c b/regress/misc/sk-dummy/sk-dummy.c
|
||||||
|
index dca158de..afdcb1d2 100644
|
||||||
|
--- a/regress/misc/sk-dummy/sk-dummy.c
|
||||||
|
+++ b/regress/misc/sk-dummy/sk-dummy.c
|
||||||
|
@@ -71,7 +71,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;
|
||||||
|
@@ -220,7 +220,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)
|
||||||
|
@@ -467,7 +467,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,
|
||||||
|
@@ -518,7 +518,7 @@ sk_sign(uint32_t alg, const uint8_t *message, size_t message_len,
|
||||||
|
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)
|
||||||
|
{
|
@ -0,0 +1,30 @@
|
|||||||
|
diff --git a/channels.c b/channels.c
|
||||||
|
--- a/channels.c
|
||||||
|
+++ b/channels.c
|
||||||
|
@@ -3933,16 +3933,26 @@ x11_create_display_inet(int x11_display_
|
||||||
|
if (ai->ai_family == AF_INET6)
|
||||||
|
sock_set_v6only(sock);
|
||||||
|
if (x11_use_localhost)
|
||||||
|
set_reuseaddr(sock);
|
||||||
|
if (bind(sock, ai->ai_addr, ai->ai_addrlen) == -1) {
|
||||||
|
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;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
socks[num_socks++] = sock;
|
||||||
|
if (num_socks == NUM_SOCKS)
|
||||||
|
break;
|
@ -0,0 +1,11 @@
|
|||||||
|
--- openssh-8.7p1/openbsd-compat/bsd-closefrom.c.orig 2022-04-12 15:47:03.815044607 +0200
|
||||||
|
+++ openssh-8.7p1/openbsd-compat/bsd-closefrom.c 2022-04-12 15:48:12.464963511 +0200
|
||||||
|
@@ -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>
|
@ -0,0 +1,22 @@
|
|||||||
|
diff --git a/readconf.c b/readconf.c
|
||||||
|
--- a/readconf.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99)
|
||||||
|
+++ b/readconf.c (date 1703169891147)
|
||||||
|
@@ -326,6 +326,7 @@
|
||||||
|
{ "securitykeyprovider", oSecurityKeyProvider },
|
||||||
|
{ "knownhostscommand", oKnownHostsCommand },
|
||||||
|
{ "requiredrsasize", oRequiredRSASize },
|
||||||
|
+ { "rsaminsize", oRequiredRSASize }, /* alias */
|
||||||
|
{ "enableescapecommandline", oEnableEscapeCommandline },
|
||||||
|
{ "obscurekeystroketiming", oObscureKeystrokeTiming },
|
||||||
|
{ "channeltimeout", oChannelTimeout },
|
||||||
|
diff --git a/servconf.c b/servconf.c
|
||||||
|
--- a/servconf.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99)
|
||||||
|
+++ b/servconf.c (date 1703169891148)
|
||||||
|
@@ -691,6 +691,7 @@
|
||||||
|
{ "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 },
|
@ -0,0 +1,118 @@
|
|||||||
|
diff -up openssh-9.3p1/regress/hostkey-agent.sh.xxx openssh-9.3p1/regress/hostkey-agent.sh
|
||||||
|
--- openssh-9.3p1/regress/hostkey-agent.sh.xxx 2023-05-29 18:15:56.311236887 +0200
|
||||||
|
+++ openssh-9.3p1/regress/hostkey-agent.sh 2023-05-29 18:16:07.598503551 +0200
|
||||||
|
@@ -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 +48,16 @@ rm $OBJ/agent-ca # Don't need CA private
|
||||||
|
|
||||||
|
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 +70,16 @@ for k in $SSH_KEYTYPES ; do
|
||||||
|
done
|
||||||
|
|
||||||
|
SSH_CERTTYPES=`ssh -Q key-sig | grep 'cert-v01@openssh.com'`
|
||||||
|
+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 +93,7 @@ echo "HostKeyAlgorithms $HOSTKEYALGS" >>
|
||||||
|
( 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 -up openssh-9.3p1/sshconnect2.c.xxx openssh-9.3p1/sshconnect2.c
|
||||||
|
--- openssh-9.3p1/sshconnect2.c.xxx 2023-04-26 17:37:35.100827792 +0200
|
||||||
|
+++ openssh-9.3p1/sshconnect2.c 2023-04-26 17:50:31.860748877 +0200
|
||||||
|
@@ -221,7 +221,7 @@ ssh_kex2(struct ssh *ssh, char *host, st
|
||||||
|
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)
|
||||||
|
@@ -260,10 +260,22 @@ ssh_kex2(struct ssh *ssh, char *host, st
|
||||||
|
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) {
|
||||||
|
@@ -303,6 +315,7 @@ ssh_kex2(struct ssh *ssh, char *host, st
|
||||||
|
#endif
|
||||||
|
|
||||||
|
free(hkalgs);
|
||||||
|
+ free(filtered_algs);
|
||||||
|
|
||||||
|
/* start key exchange */
|
||||||
|
if ((r = kex_setup(ssh, myproposal)) != 0)
|
@ -0,0 +1,297 @@
|
|||||||
|
diff -up openssh-8.7p1/compat.c.sshrsacheck openssh-8.7p1/compat.c
|
||||||
|
--- openssh-8.7p1/compat.c.sshrsacheck 2023-01-12 13:29:06.338710923 +0100
|
||||||
|
+++ openssh-8.7p1/compat.c 2023-01-12 13:29:06.357711165 +0100
|
||||||
|
@@ -43,6 +43,7 @@ void
|
||||||
|
compat_banner(struct ssh *ssh, const char *version)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
+ int forbid_ssh_rsa = 0;
|
||||||
|
static struct {
|
||||||
|
char *pat;
|
||||||
|
int bugs;
|
||||||
|
@@ -145,16 +146,21 @@ compat_banner(struct ssh *ssh, const cha
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 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 -up openssh-8.7p1/compat.h.sshrsacheck openssh-8.7p1/compat.h
|
||||||
|
--- openssh-8.7p1/compat.h.sshrsacheck 2021-08-20 06:03:49.000000000 +0200
|
||||||
|
+++ openssh-8.7p1/compat.h 2023-01-12 13:29:06.358711178 +0100
|
||||||
|
@@ -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 -up openssh-8.7p1/monitor.c.sshrsacheck openssh-8.7p1/monitor.c
|
||||||
|
--- openssh-8.7p1/monitor.c.sshrsacheck 2023-01-20 13:07:54.279676981 +0100
|
||||||
|
+++ openssh-8.7p1/monitor.c 2023-01-20 15:01:07.007821379 +0100
|
||||||
|
@@ -660,11 +660,12 @@ mm_answer_sign(struct ssh *ssh, int sock
|
||||||
|
struct sshkey *key;
|
||||||
|
struct sshbuf *sigbuf = NULL;
|
||||||
|
u_char *p = NULL, *signature = NULL;
|
||||||
|
- char *alg = NULL;
|
||||||
|
+ 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");
|
||||||
|
|
||||||
|
@@ -719,18 +720,30 @@ mm_answer_sign(struct ssh *ssh, int sock
|
||||||
|
}
|
||||||
|
|
||||||
|
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 -up openssh-8.7p1/regress/unittests/kex/test_kex.c.sshrsacheck openssh-8.7p1/regress/unittests/kex/test_kex.c
|
||||||
|
--- openssh-8.7p1/regress/unittests/kex/test_kex.c.sshrsacheck 2023-01-26 13:34:52.645743677 +0100
|
||||||
|
+++ openssh-8.7p1/regress/unittests/kex/test_kex.c 2023-01-26 13:36:56.220745823 +0100
|
||||||
|
@@ -97,7 +97,8 @@ do_kex_with_key(char *kex, int keytype,
|
||||||
|
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 -up openssh-8.7p1/regress/unittests/sshkey/test_file.c.sshrsacheck openssh-8.7p1/regress/unittests/sshkey/test_file.c
|
||||||
|
--- openssh-8.7p1/regress/unittests/sshkey/test_file.c.sshrsacheck 2023-01-26 12:04:55.946343408 +0100
|
||||||
|
+++ openssh-8.7p1/regress/unittests/sshkey/test_file.c 2023-01-26 12:06:35.235164432 +0100
|
||||||
|
@@ -110,6 +110,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);
|
||||||
|
@@ -117,7 +118,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 -up openssh-8.7p1/regress/unittests/sshkey/test_fuzz.c.sshrsacheck openssh-8.7p1/regress/unittests/sshkey/test_fuzz.c
|
||||||
|
--- openssh-8.7p1/regress/unittests/sshkey/test_fuzz.c.sshrsacheck 2023-01-26 12:10:37.533168013 +0100
|
||||||
|
+++ openssh-8.7p1/regress/unittests/sshkey/test_fuzz.c 2023-01-26 12:15:35.637631860 +0100
|
||||||
|
@@ -333,13 +333,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 -up openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c.sshrsacheck openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c
|
||||||
|
--- openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c.sshrsacheck 2023-01-26 11:02:52.339413463 +0100
|
||||||
|
+++ openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c 2023-01-26 11:58:42.324253896 +0100
|
||||||
|
@@ -60,6 +60,9 @@ build_cert(struct sshbuf *b, struct sshk
|
||||||
|
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);
|
||||||
|
@@ -101,8 +104,9 @@ build_cert(struct sshbuf *b, struct sshk
|
||||||
|
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);
|
||||||
|
@@ -119,16 +123,22 @@ signature_test(struct sshkey *k, struct
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -514,7 +524,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 -up openssh-8.7p1/serverloop.c.sshrsacheck openssh-8.7p1/serverloop.c
|
||||||
|
--- openssh-8.7p1/serverloop.c.sshrsacheck 2023-01-12 14:57:08.118400073 +0100
|
||||||
|
+++ openssh-8.7p1/serverloop.c 2023-01-12 14:59:17.330470518 +0100
|
||||||
|
@@ -80,6 +80,7 @@
|
||||||
|
#include "auth-options.h"
|
||||||
|
#include "serverloop.h"
|
||||||
|
#include "ssherr.h"
|
||||||
|
+#include "compat.h"
|
||||||
|
|
||||||
|
extern ServerOptions options;
|
||||||
|
|
||||||
|
@@ -737,6 +737,10 @@ server_input_hostkeys_prove(struct ssh *
|
||||||
|
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 -up openssh-8.7p1/sshconnect2.c.sshrsacheck openssh-8.7p1/sshconnect2.c
|
||||||
|
--- openssh-8.7p1/sshconnect2.c.sshrsacheck 2023-01-25 15:33:29.140353651 +0100
|
||||||
|
+++ openssh-8.7p1/sshconnect2.c 2023-01-25 15:59:34.225364883 +0100
|
||||||
|
@@ -1461,6 +1464,14 @@ identity_sign(struct identity *id, u_cha
|
||||||
|
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 -up openssh-8.7p1/ssh-rsa.c.sshrsacheck openssh-8.7p1/ssh-rsa.c
|
||||||
|
--- openssh-8.7p1/ssh-rsa.c.sshrsacheck 2023-01-20 13:07:54.180676144 +0100
|
||||||
|
+++ openssh-8.7p1/ssh-rsa.c 2023-01-20 13:07:54.290677074 +0100
|
||||||
|
@@ -254,7 +254,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 -up openssh-9.8p1/sshd-session.c.xxx openssh-9.8p1/sshd-session.c
|
||||||
|
--- openssh-9.8p1/sshd-session.c.xxx 2024-07-23 15:08:14.794350818 +0200
|
||||||
|
+++ openssh-9.8p1/sshd-session.c 2024-07-23 15:40:21.658456636 +0200
|
||||||
|
@@ -1305,6 +1305,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);
|
@ -0,0 +1,182 @@
|
|||||||
|
diff --git a/scp.c b/scp.c
|
||||||
|
--- a/scp.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99)
|
||||||
|
+++ b/scp.c (date 1703111453316)
|
||||||
|
@@ -1372,7 +1372,7 @@
|
||||||
|
|
||||||
|
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
|
||||||
|
--- a/sftp-client.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99)
|
||||||
|
+++ b/sftp-client.c (date 1703169614263)
|
||||||
|
@@ -1003,7 +1003,7 @@
|
||||||
|
|
||||||
|
/* 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 @@
|
||||||
|
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 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
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 @@
|
||||||
|
{
|
||||||
|
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 @@
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
@@ -2365,12 +2397,12 @@
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
@@ -2825,7 +2857,7 @@
|
||||||
|
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
|
||||||
|
--- a/sftp-client.h (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99)
|
||||||
|
+++ b/sftp-client.h (date 1703111691284)
|
||||||
|
@@ -111,7 +111,7 @@
|
||||||
|
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 @@
|
||||||
|
* 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
|
||||||
|
--- a/sftp.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99)
|
||||||
|
+++ b/sftp.c (date 1703168795365)
|
||||||
|
@@ -807,7 +807,7 @@
|
||||||
|
(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,
|
||||||
|
@@ -1642,7 +1642,7 @@
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
@@ -2247,7 +2247,7 @@
|
||||||
|
}
|
||||||
|
#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);
|
||||||
|
|
@ -0,0 +1,38 @@
|
|||||||
|
diff -up openssh-8.7p1/ssh.c.xxx openssh-8.7p1/ssh.c
|
||||||
|
--- openssh-8.7p1/ssh.c.xxx 2024-09-11 14:24:06.711088878 +0200
|
||||||
|
+++ openssh-8.7p1/ssh.c 2024-09-11 14:35:12.883765718 +0200
|
||||||
|
@@ -175,6 +175,14 @@ extern int muxserver_sock;
|
||||||
|
extern u_int muxclient_command;
|
||||||
|
|
||||||
|
/* Prints a help message to the user. This function never returns. */
|
||||||
|
+static void
|
||||||
|
+redhat_usage(void)
|
||||||
|
+{
|
||||||
|
+ fprintf(stderr,
|
||||||
|
+"\nYou can find some explanations for typical errors at this link:\n"
|
||||||
|
+" https://red.ht/support_rhel_ssh\n"
|
||||||
|
+ );
|
||||||
|
+}
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage(void)
|
||||||
|
@@ -188,6 +196,7 @@ usage(void)
|
||||||
|
" destination [command [argument ...]]\n"
|
||||||
|
" ssh [-Q query_option]\n"
|
||||||
|
);
|
||||||
|
+ redhat_usage();
|
||||||
|
exit(255);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1609,8 +1618,10 @@ main(int ac, char **av)
|
||||||
|
/* Open a connection to the remote host. */
|
||||||
|
if (ssh_connect(ssh, host, options.host_arg, addrs, &hostaddr,
|
||||||
|
options.port, options.connection_attempts,
|
||||||
|
- &timeout_ms, options.tcp_keep_alive) != 0)
|
||||||
|
+ &timeout_ms, options.tcp_keep_alive) != 0) {
|
||||||
|
+ redhat_usage();
|
||||||
|
exit(255);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
if (addrs != NULL)
|
||||||
|
freeaddrinfo(addrs);
|
@ -0,0 +1,46 @@
|
|||||||
|
diff -up openssh-8.7p1/pathnames.h.kill-scp openssh-8.7p1/pathnames.h
|
||||||
|
--- openssh-8.7p1/pathnames.h.kill-scp 2021-09-16 11:37:57.240171687 +0200
|
||||||
|
+++ openssh-8.7p1/pathnames.h 2021-09-16 11:42:29.183427917 +0200
|
||||||
|
@@ -42,6 +42,7 @@
|
||||||
|
#define _PATH_HOST_XMSS_KEY_FILE SSHDIR "/ssh_host_xmss_key"
|
||||||
|
#define _PATH_HOST_RSA_KEY_FILE SSHDIR "/ssh_host_rsa_key"
|
||||||
|
#define _PATH_DH_MODULI SSHDIR "/moduli"
|
||||||
|
+#define _PATH_SCP_KILL_SWITCH SSHDIR "/disable_scp"
|
||||||
|
|
||||||
|
#ifndef _PATH_SSH_PROGRAM
|
||||||
|
#define _PATH_SSH_PROGRAM "/usr/bin/ssh"
|
||||||
|
diff -up openssh-8.7p1/scp.1.kill-scp openssh-8.7p1/scp.1
|
||||||
|
--- openssh-8.7p1/scp.1.kill-scp 2021-09-16 12:09:02.646714578 +0200
|
||||||
|
+++ openssh-8.7p1/scp.1 2021-09-16 12:26:49.978628226 +0200
|
||||||
|
@@ -278,6 +278,13 @@ to print debugging messages about their
|
||||||
|
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 -up openssh-8.7p1/scp.c.kill-scp openssh-8.7p1/scp.c
|
||||||
|
--- openssh-8.7p1/scp.c.kill-scp 2021-09-16 11:42:56.013650519 +0200
|
||||||
|
+++ openssh-8.7p1/scp.c 2021-09-16 11:53:03.249713836 +0200
|
||||||
|
@@ -596,6 +596,14 @@ main(int argc, char **argv)
|
||||||
|
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);
|
||||||
|
|
@ -0,0 +1,53 @@
|
|||||||
|
diff --color -ru a/ssh.1 b/ssh.1
|
||||||
|
--- a/ssh.1 2022-07-12 11:47:51.307295880 +0200
|
||||||
|
+++ b/ssh.1 2022-07-12 11:50:28.793363263 +0200
|
||||||
|
@@ -493,6 +493,7 @@
|
||||||
|
.It AddressFamily
|
||||||
|
.It BatchMode
|
||||||
|
.It BindAddress
|
||||||
|
+.It BindInterface
|
||||||
|
.It CanonicalDomains
|
||||||
|
.It CanonicalizeFallbackLocal
|
||||||
|
.It CanonicalizeHostname
|
||||||
|
@@ -510,6 +511,7 @@
|
||||||
|
.It ControlPath
|
||||||
|
.It ControlPersist
|
||||||
|
.It DynamicForward
|
||||||
|
+.It EnableSSHKeysign
|
||||||
|
.It EnableEscapeCommandline
|
||||||
|
.It EscapeChar
|
||||||
|
.It ExitOnForwardFailure
|
||||||
|
@@ -538,6 +540,8 @@
|
||||||
|
.It IdentitiesOnly
|
||||||
|
.It IdentityAgent
|
||||||
|
.It IdentityFile
|
||||||
|
+.It IgnoreUnknown
|
||||||
|
+.It Include
|
||||||
|
.It IPQoS
|
||||||
|
.It KbdInteractiveAuthentication
|
||||||
|
.It KbdInteractiveDevices
|
||||||
|
@@ -546,6 +550,7 @@
|
||||||
|
.It LocalCommand
|
||||||
|
.It LocalForward
|
||||||
|
.It LogLevel
|
||||||
|
+.It LogVerbose
|
||||||
|
.It MACs
|
||||||
|
.It Match
|
||||||
|
.It NoHostAuthenticationForLocalhost
|
||||||
|
@@ -566,6 +571,8 @@
|
||||||
|
.It RemoteCommand
|
||||||
|
.It RemoteForward
|
||||||
|
.It RequestTTY
|
||||||
|
+.It RevokedHostKeys
|
||||||
|
+.It SecurityKeyProvider
|
||||||
|
.It RequiredRSASize
|
||||||
|
.It SendEnv
|
||||||
|
.It ServerAliveInterval
|
||||||
|
@@ -575,6 +582,7 @@
|
||||||
|
.It StreamLocalBindMask
|
||||||
|
.It StreamLocalBindUnlink
|
||||||
|
.It StrictHostKeyChecking
|
||||||
|
+.It SyslogFacility
|
||||||
|
.It TCPKeepAlive
|
||||||
|
.It Tunnel
|
||||||
|
.It TunnelDevice
|
@ -0,0 +1,246 @@
|
|||||||
|
diff -up openssh-9.0p1/audit-bsm.c.patch openssh-9.0p1/audit-bsm.c
|
||||||
|
--- openssh-9.0p1/audit-bsm.c.patch 2022-10-24 15:02:16.544858331 +0200
|
||||||
|
+++ openssh-9.0p1/audit-bsm.c 2022-10-24 14:51:43.685766639 +0200
|
||||||
|
@@ -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 -up openssh-9.0p1/audit.c.patch openssh-9.0p1/audit.c
|
||||||
|
--- openssh-9.0p1/audit.c.patch 2022-10-24 15:02:16.544858331 +0200
|
||||||
|
+++ openssh-9.0p1/audit.c 2022-10-24 15:20:38.854548226 +0200
|
||||||
|
@@ -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 -up openssh-9.0p1/audit.h.patch openssh-9.0p1/audit.h
|
||||||
|
--- openssh-9.0p1/audit.h.patch 2022-10-24 15:02:16.544858331 +0200
|
||||||
|
+++ openssh-9.0p1/audit.h 2022-10-24 14:58:20.887565518 +0200
|
||||||
|
@@ -64,7 +64,7 @@ void audit_session_close(struct logininf
|
||||||
|
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 *);
|
||||||
|
diff -up openssh-9.9p1/audit-linux.c.xxx openssh-9.9p1/audit-linux.c
|
||||||
|
--- openssh-9.9p1/audit-linux.c.xxx 2024-10-15 11:49:48.092151974 +0200
|
||||||
|
+++ openssh-9.9p1/audit-linux.c 2024-10-15 12:08:17.179158343 +0200
|
||||||
|
@@ -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 c
|
||||||
|
}
|
||||||
|
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
|
||||||
|
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
|
||||||
|
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_e
|
||||||
|
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_e
|
||||||
|
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
|
@ -0,0 +1,595 @@
|
|||||||
|
diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.0p1/dh.c openssh-9.0p1-patched/dh.c
|
||||||
|
--- openssh-9.0p1/dh.c 2023-05-25 09:24:28.730868316 +0200
|
||||||
|
+++ openssh-9.0p1-patched/dh.c 2023-05-25 09:23:44.841379532 +0200
|
||||||
|
@@ -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 @@
|
||||||
|
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 @@
|
||||||
|
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 --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.0p1/kex.c openssh-9.0p1-patched/kex.c
|
||||||
|
--- openssh-9.0p1/kex.c 2023-05-25 09:24:28.731868327 +0200
|
||||||
|
+++ openssh-9.0p1-patched/kex.c 2023-05-25 09:23:44.841379532 +0200
|
||||||
|
@@ -1623,3 +1623,142 @@
|
||||||
|
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 --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.0p1/kexdh.c openssh-9.0p1-patched/kexdh.c
|
||||||
|
--- openssh-9.0p1/kexdh.c 2023-05-25 09:24:28.674867692 +0200
|
||||||
|
+++ openssh-9.0p1-patched/kexdh.c 2023-05-25 09:25:28.494533889 +0200
|
||||||
|
@@ -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 @@
|
||||||
|
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 @@
|
||||||
|
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 --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.0p1/kex.h openssh-9.0p1-patched/kex.h
|
||||||
|
--- openssh-9.0p1/kex.h 2023-05-25 09:24:28.725868260 +0200
|
||||||
|
+++ openssh-9.0p1-patched/kex.h 2023-05-25 09:23:44.841379532 +0200
|
||||||
|
@@ -33,6 +33,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 */
|
||||||
|
@@ -283,6 +286,9@@
|
||||||
|
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 --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac ../openssh-8.7p1/kexecdh.c ./kexecdh.c
|
||||||
|
--- ../openssh-8.7p1/kexecdh.c 2021-08-20 06:03:49.000000000 +0200
|
||||||
|
+++ ./kexecdh.c 2023-04-13 14:30:14.882449593 +0200
|
||||||
|
@@ -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 @@
|
||||||
|
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 @@
|
||||||
|
*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 @@
|
||||||
|
{
|
||||||
|
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 @@
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,32 @@
|
|||||||
|
From 26f366e263e575c4e1a18e2e64ba418f58878b37 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Daan De Meyer <daan.j.demeyer@gmail.com>
|
||||||
|
Date: Mon, 20 Mar 2023 20:22:14 +0100
|
||||||
|
Subject: [PATCH] Only set PAM_RHOST if the remote host is not "UNKNOWN"
|
||||||
|
|
||||||
|
When using sshd's -i option with stdio that is not a AF_INET/AF_INET6
|
||||||
|
socket, auth_get_canonical_hostname() returns "UNKNOWN" which is then
|
||||||
|
set as the value of PAM_RHOST, causing pam to try to do a reverse DNS
|
||||||
|
query of "UNKNOWN", which times out multiple times, causing a
|
||||||
|
substantial slowdown when logging in.
|
||||||
|
|
||||||
|
To fix this, let's only set PAM_RHOST if the hostname is not "UNKNOWN".
|
||||||
|
---
|
||||||
|
auth-pam.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/auth-pam.c b/auth-pam.c
|
||||||
|
index e143304e3..39b4e4563 100644
|
||||||
|
--- a/auth-pam.c
|
||||||
|
+++ b/auth-pam.c
|
||||||
|
@@ -735,7 +735,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.44.0
|
||||||
|
|
@ -0,0 +1,12 @@
|
|||||||
|
diff -up openssh-9.9p1/ssh_config.5.xxx openssh-9.9p1/ssh_config.5
|
||||||
|
--- openssh-9.9p1/ssh_config.5.xxx 2024-10-11 12:01:14.260566303 +0200
|
||||||
|
+++ openssh-9.9p1/ssh_config.5 2024-10-11 12:01:59.725654775 +0200
|
||||||
|
@@ -759,7 +759,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 ~ ) .
|
@ -0,0 +1,16 @@
|
|||||||
|
-----BEGIN PGP SIGNATURE-----
|
||||||
|
|
||||||
|
iQIzBAABCgAdFiEEcWi5g4FaXu9ZpK39Kj9BTnNgYLoFAmbspccACgkQKj9BTnNg
|
||||||
|
YLppxRAAv7eU/Xd2w9MX9vWQdhugiPByEcKg7KuKXUUs9xJGy+HbLqPqUCvn1UW6
|
||||||
|
qodKoSAdeBuSB7AjzuIQ1lTVX7C67OmZaVPRq25ar5b+Wq4SSlv23KMRq0b4EVyw
|
||||||
|
pOW6R9tsxqYBwYaiXQ50APcYL8SpepnGU+b/iR15f7q3SU2XMVVtkVb149UdLOqK
|
||||||
|
smfurbDGwUKFb2Q009MUfEV/d9zq31tdSjphvkqAXCcmxc8siuOYWYcByuysie+m
|
||||||
|
NpaOpee0047L5JIxNSLsa2yZrJZhClP8LbTCH1Vfwr7l0KE5nvL2qAtPKI2XxGQC
|
||||||
|
3jXrDLzp10RFxV8sCym+QlY9pZyzGj9d3G7vCHtxWGQ1Y0Qt+xs18OeBpjiehRhl
|
||||||
|
WM3Y+cjoN35jBaGhOoHdh3ePZQdTUyZ16aSv0h/cUHOohiM7i/4XW+dQtkqsJsw4
|
||||||
|
a81O0E64WrL8ho3Ju9mwcVZ9A0aEaftJsmJPDB+qYBjF/i7xcnH32LginzP5pel7
|
||||||
|
/W0aS2C1ZNo3QKHezI6IA9MyENMZiAMy2ybvfmN0HgLBaBY1plJ8a5GvMwJc+Qwh
|
||||||
|
iCHLCQ6Qgf/1hh+F6liTXnhtedtFHneJdyqvd7XOoardDEipZjxcnGa4HthbDFU+
|
||||||
|
8XdHKnWWhn4BLA+y7KB3ZGURniQK+qibwkF6J63CuMU+LmG+bvQ=
|
||||||
|
=Ukrb
|
||||||
|
-----END PGP SIGNATURE-----
|
@ -0,0 +1,2 @@
|
|||||||
|
#Type Name ID GECOS Home directory Shell
|
||||||
|
u sshd 74 "Privilege-separated SSH" /usr/share/empty.sshd -
|
@ -0,0 +1,14 @@
|
|||||||
|
# just a Makefile parallel_test.sh uses to run stuff in parallel with make
|
||||||
|
%:
|
||||||
|
$(MAKE) -j1 -C .t/$* $*
|
||||||
|
|
||||||
|
t-exec-%:
|
||||||
|
$(MAKE) -j1 -C ".t/t-exec-$*" \
|
||||||
|
TEST_SSH_PORT=10$*0 \
|
||||||
|
SKIP_LTESTS="$(shell cat .ltests/not-in/$*)" \
|
||||||
|
BUILDDIR="$(shell pwd)/.t/t-exec-$*" \
|
||||||
|
TEST_SHELL=sh \
|
||||||
|
MAKE=make \
|
||||||
|
TEST_SSH_TRACE=yes \
|
||||||
|
TEST_SSH_FAIL_FATAL=yes \
|
||||||
|
t-exec \
|
@ -0,0 +1,91 @@
|
|||||||
|
#!/usr/bin/bash
|
||||||
|
set -uexo pipefail
|
||||||
|
|
||||||
|
# The custom %check script to run the OpenSSH upstream testsuite in parallel.
|
||||||
|
#
|
||||||
|
# The upstream testsuite is serial,
|
||||||
|
# so the idea here is to split the testsuite into several $PARTS:
|
||||||
|
# * file-tests
|
||||||
|
# * interop-tests
|
||||||
|
# * unit
|
||||||
|
# * ltests-00
|
||||||
|
# * ltests-01
|
||||||
|
# * ...
|
||||||
|
# * ltests-23
|
||||||
|
# and run them in parallel, using make, each in its own build subtree.
|
||||||
|
|
||||||
|
PARALLEL_MAKEFILE=$1
|
||||||
|
|
||||||
|
SPLIT=24
|
||||||
|
PARTS='file-tests interop-tests unit '
|
||||||
|
for ((i = 1; i < SPLIT; i++)); do ii=$(printf %02d $i);
|
||||||
|
PARTS+="t-exec-$ii "
|
||||||
|
done
|
||||||
|
|
||||||
|
# work around a selinux restriction:
|
||||||
|
#chcon -t unconfined_exec_t ssh-sk-helper || :
|
||||||
|
|
||||||
|
# work around something else that only crops up in brew
|
||||||
|
export TEST_SSH_UNSAFE_PERMISSIONS=1
|
||||||
|
|
||||||
|
# create a .test directory to store all our files in:
|
||||||
|
mkdir -p .t .ltests/{in,not-in}
|
||||||
|
|
||||||
|
# patch testsuite: use different ports to avoid port collisions
|
||||||
|
grep -REi 'port=[2-9][0-9]*' regress
|
||||||
|
sed -i 's|PORT=4242|PORT=$(expr $TEST_SSH_PORT + 1)|' \
|
||||||
|
regress/test-exec.sh*
|
||||||
|
sed -i 's|^P=3301 # test port|P=$(expr $TEST_SSH_PORT + 1)|' \
|
||||||
|
regress/multiplex.sh*
|
||||||
|
sed -i 's|^fwdport=3301|fwdport=$(expr $TEST_SSH_PORT + 1)|' \
|
||||||
|
regress/cfgmatch.sh* regress/cfgmatchlisten.sh*
|
||||||
|
sed -i 's|^LFWD_PORT=.*|LFWD_PORT=$(expr $TEST_SSH_PORT + 1)|' \
|
||||||
|
regress/forward-control.sh*
|
||||||
|
sed -i 's|^RFWD_PORT=.*|RFWD_PORT=$(expr $TEST_SSH_PORT + 2)|' \
|
||||||
|
regress/forward-control.sh*
|
||||||
|
( ! grep -REi 'port=[2-9][0-9]*' regress) # try to find more of those
|
||||||
|
|
||||||
|
# patch testsuite: speed up
|
||||||
|
sed -i 's|sleep 1$|sleep .25|' regress/forward-control.sh
|
||||||
|
|
||||||
|
# extract LTESTS list to .tests/ltests/all:
|
||||||
|
grep -Ex 'tests:[[:space:]]*file-tests t-exec interop-tests extra-tests unit' Makefile
|
||||||
|
echo -ne '\necho-ltests:\n\techo ${LTESTS}' >> regress/Makefile
|
||||||
|
make -s -C regress echo-ltests | tr ' ' '\n' > .ltests/all
|
||||||
|
|
||||||
|
# separate ltests into $SPLIT roughly equal .tests/ltests/in/$ii parts:
|
||||||
|
grep -qFx connect .ltests/all
|
||||||
|
( ! grep -qFx nonex .ltests/all )
|
||||||
|
split -d -a2 --number=l/$SPLIT .ltests/all .ltests/in/
|
||||||
|
wc -l .ltests/in/*
|
||||||
|
grep -qFx connect .ltests/in/*
|
||||||
|
|
||||||
|
# generate the inverses of them --- .ltests/not-in/$ii:
|
||||||
|
( ! grep -qFx nonex .ltests/in/* )
|
||||||
|
for ((i = 0; i < SPLIT; i++)); do ii=$(printf %02d $i);
|
||||||
|
while read -r tname; do
|
||||||
|
if ! grep -qFx "$tname" ".ltests/in/$ii"; then
|
||||||
|
echo -n "$tname " >> ".ltests/not-in/$ii"
|
||||||
|
fi
|
||||||
|
done < .ltests/all
|
||||||
|
done
|
||||||
|
grep . .ltests/not-in/*
|
||||||
|
( ! grep -q ^connect .ltests/not-in/0 )
|
||||||
|
for ((i = 1; i < SPLIT; i++)); do ii=$(printf %02d $i);
|
||||||
|
grep -q ^connect .ltests/not-in/$ii
|
||||||
|
done
|
||||||
|
|
||||||
|
# prepare several test directories:
|
||||||
|
for PART in $PARTS; do
|
||||||
|
mkdir .t/${PART}
|
||||||
|
cp -ra * .t/${PART}/
|
||||||
|
sed -i "s|abs_top_srcdir=.*|abs_top_srcdir=$(pwd)/.t/${PART}|" \
|
||||||
|
.t/${PART}/Makefile
|
||||||
|
sed -i "s|abs_top_builddir=.*|abs_top_builddir=$(pwd)/.t/${PART}|" \
|
||||||
|
.t/${PART}/Makefile
|
||||||
|
sed -i "s|^BUILDDIR=.*|BUILDDIR=$(pwd)/.t/${PART}|" \
|
||||||
|
.t/${PART}/Makefile
|
||||||
|
done
|
||||||
|
|
||||||
|
# finally, run tests $PARTS in parallel in their own subtrees:
|
||||||
|
time make -f "$PARALLEL_MAKEFILE" -j$(nproc) $PARTS
|
@ -0,0 +1,19 @@
|
|||||||
|
# Requires SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket"
|
||||||
|
# set in environment, handled for example in plasma via
|
||||||
|
# /etc/xdg/plasma-workspace/env/ssh-agent.sh
|
||||||
|
[Unit]
|
||||||
|
ConditionEnvironment=!SSH_AGENT_PID
|
||||||
|
Description=OpenSSH key agent
|
||||||
|
Documentation=man:ssh-agent(1) man:ssh-add(1) man:ssh(1)
|
||||||
|
Requires=ssh-agent.socket
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Environment=SSH_AUTH_SOCK=%t/ssh-agent.socket
|
||||||
|
ExecStartPre=/usr/bin/rm -f $SSH_AUTH_SOCK
|
||||||
|
ExecStart=/usr/bin/ssh-agent -D -a $SSH_AUTH_SOCK
|
||||||
|
PassEnvironment=SSH_AGENT_PID
|
||||||
|
SuccessExitStatus=2
|
||||||
|
Type=simple
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
Also=ssh-agent.socket
|
@ -0,0 +1,14 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=OpenSSH key agent
|
||||||
|
Documentation=man:ssh-agent(1) man:ssh-add(1) man:ssh(1)
|
||||||
|
|
||||||
|
[Socket]
|
||||||
|
ListenStream=%t/ssh-agent.socket
|
||||||
|
Service=ssh-agent.service
|
||||||
|
Priority=6
|
||||||
|
Backlog=5
|
||||||
|
SocketMode=0600
|
||||||
|
DirectoryMode=0700
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=sockets.target
|
@ -0,0 +1,15 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Update OpenSSH host key permissions
|
||||||
|
Documentation=https://fedoraproject.org/wiki/Changes/SSHKeySignSuidBit
|
||||||
|
Before=sshd.service
|
||||||
|
After=ssh-keygen.target
|
||||||
|
ConditionPathExists=!/var/lib/.ssh-host-keys-migration
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=-/usr/libexec/openssh/ssh-host-keys-migration.sh
|
||||||
|
ExecStart=touch /var/lib/.ssh-host-keys-migration
|
||||||
|
RemainAfterExit=yes
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=sshd.service
|
@ -0,0 +1,36 @@
|
|||||||
|
#!/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.
|
||||||
|
# sshd: no hostkeys available -- exiting.
|
||||||
|
#
|
||||||
|
output="$(sshd -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"
|
@ -0,0 +1,8 @@
|
|||||||
|
#%PAM-1.0
|
||||||
|
# pam_selinux.so close should be the first session rule
|
||||||
|
session required pam_selinux.so close
|
||||||
|
session required pam_loginuid.so
|
||||||
|
# pam_selinux.so open should only be followed by sessions to be executed in the user context
|
||||||
|
session required pam_selinux.so open env_params
|
||||||
|
session required pam_namespace.so
|
||||||
|
|
@ -0,0 +1,45 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Create the host keys for the OpenSSH 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/ssh/ssh_host_${KEYTYPE}_key
|
||||||
|
|
||||||
|
KEYGEN=/usr/bin/ssh-keygen
|
||||||
|
if [[ ! -x $KEYGEN ]]; then
|
||||||
|
exit 13
|
||||||
|
fi
|
||||||
|
|
||||||
|
# remove old keys
|
||||||
|
rm -f $KEY{,.pub}
|
||||||
|
|
||||||
|
# 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
|
@ -0,0 +1,5 @@
|
|||||||
|
[Unit]
|
||||||
|
Wants=sshd-keygen@rsa.service
|
||||||
|
Wants=sshd-keygen@ecdsa.service
|
||||||
|
Wants=sshd-keygen@ed25519.service
|
||||||
|
PartOf=sshd.service
|
@ -0,0 +1,11 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=OpenSSH %i Server Key Generation
|
||||||
|
ConditionFileNotEmpty=|!/etc/ssh/ssh_host_%i_key
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
EnvironmentFile=-/etc/sysconfig/sshd
|
||||||
|
ExecStart=/usr/libexec/openssh/sshd-keygen %i
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=sshd-keygen.target
|
@ -0,0 +1,17 @@
|
|||||||
|
#%PAM-1.0
|
||||||
|
auth substack password-auth
|
||||||
|
auth include postlogin
|
||||||
|
account required pam_sepermit.so
|
||||||
|
account required pam_nologin.so
|
||||||
|
account include password-auth
|
||||||
|
password include password-auth
|
||||||
|
# pam_selinux.so close should be the first session rule
|
||||||
|
session required pam_selinux.so close
|
||||||
|
session required pam_loginuid.so
|
||||||
|
# pam_selinux.so open should only be followed by sessions to be executed in the user context
|
||||||
|
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
|
@ -0,0 +1,20 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=OpenSSH server daemon
|
||||||
|
Documentation=man:sshd(8) man:sshd_config(5)
|
||||||
|
After=network.target sshd-keygen.target
|
||||||
|
Wants=sshd-keygen.target
|
||||||
|
# Migration for Fedora 38 change to remove group ownership for standard host keys
|
||||||
|
# See https://fedoraproject.org/wiki/Changes/SSHKeySignSuidBit
|
||||||
|
Wants=ssh-host-keys-migration.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=notify
|
||||||
|
EnvironmentFile=-/etc/sysconfig/sshd
|
||||||
|
ExecStart=/usr/sbin/sshd -D $OPTIONS
|
||||||
|
ExecReload=/bin/kill -HUP $MAINPID
|
||||||
|
KillMode=process
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=42s
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
@ -0,0 +1,11 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=OpenSSH Server Socket
|
||||||
|
Documentation=man:sshd(8) man:sshd_config(5)
|
||||||
|
Conflicts=sshd.service
|
||||||
|
|
||||||
|
[Socket]
|
||||||
|
ListenStream=22
|
||||||
|
Accept=yes
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=sockets.target
|
@ -0,0 +1,10 @@
|
|||||||
|
# Configuration file for the sshd service.
|
||||||
|
|
||||||
|
# The server keys are automatically generated if they are missing.
|
||||||
|
# To change the automatic creation, adjust sshd.service options for
|
||||||
|
# example using systemctl enable sshd-keygen@dsa.service to allow creation
|
||||||
|
# of DSA key or systemctl mask sshd-keygen@rsa.service to disable RSA key
|
||||||
|
# creation.
|
||||||
|
|
||||||
|
#SSH_RSA_BITS=3072
|
||||||
|
#SSH_ECDSA_BITS=256
|
@ -0,0 +1,13 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=OpenSSH per-connection server daemon
|
||||||
|
Documentation=man:sshd(8) man:sshd_config(5)
|
||||||
|
Wants=sshd-keygen.target
|
||||||
|
After=sshd-keygen.target
|
||||||
|
# Migration for Fedora 38 change to remove group ownership for standard host keys
|
||||||
|
# See https://fedoraproject.org/wiki/Changes/SSHKeySignSuidBit
|
||||||
|
Wants=ssh-host-keys-migration.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
EnvironmentFile=-/etc/sysconfig/sshd
|
||||||
|
ExecStart=-/usr/sbin/sshd -i $OPTIONS
|
||||||
|
StandardInput=socket
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue