import openssh-7.8p1-4.el8
This commit is contained in:
commit
b830398e18
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
SOURCES/DJM-GPG-KEY.gpg
|
||||||
|
SOURCES/openssh-7.8p1.tar.gz
|
||||||
|
SOURCES/pam_ssh_agent_auth-0.10.3.tar.bz2
|
3
.openssh.metadata
Normal file
3
.openssh.metadata
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
bed7240bb17840b451b8f8457791c33456814d93 SOURCES/DJM-GPG-KEY.gpg
|
||||||
|
27e267e370315561de96577fccae563bc2c37a60 SOURCES/openssh-7.8p1.tar.gz
|
||||||
|
a4482a050fdad1d012427e45799564136708cf6b SOURCES/pam_ssh_agent_auth-0.10.3.tar.bz2
|
19
SOURCES/openssh-4.3p2-askpass-grab-info.patch
Normal file
19
SOURCES/openssh-4.3p2-askpass-grab-info.patch
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
diff -up openssh-7.4p1/contrib/gnome-ssh-askpass2.c.grab-info openssh-7.4p1/contrib/gnome-ssh-askpass2.c
|
||||||
|
--- openssh-7.4p1/contrib/gnome-ssh-askpass2.c.grab-info 2016-12-23 13:31:22.645213115 +0100
|
||||||
|
+++ openssh-7.4p1/contrib/gnome-ssh-askpass2.c 2016-12-23 13:31:40.997216691 +0100
|
||||||
|
@@ -65,9 +65,12 @@ report_failed_grab (GtkWidget *parent_wi
|
||||||
|
err = gtk_message_dialog_new(GTK_WINDOW(parent_window), 0,
|
||||||
|
GTK_MESSAGE_ERROR,
|
||||||
|
GTK_BUTTONS_CLOSE,
|
||||||
|
- "Could not grab %s. "
|
||||||
|
- "A malicious client may be eavesdropping "
|
||||||
|
- "on your session.", what);
|
||||||
|
+ "SSH password dialog could not grab the %s input.\n"
|
||||||
|
+ "This might be caused by application such as screensaver, "
|
||||||
|
+ "however it could also mean that someone may be eavesdropping "
|
||||||
|
+ "on your session.\n"
|
||||||
|
+ "Either close the application which grabs the %s or "
|
||||||
|
+ "log out and log in again to prevent this from happening.", what, what);
|
||||||
|
gtk_window_set_position(GTK_WINDOW(err), GTK_WIN_POS_CENTER);
|
||||||
|
|
||||||
|
gtk_dialog_run(GTK_DIALOG(err));
|
81
SOURCES/openssh-5.1p1-askpass-progress.patch
Normal file
81
SOURCES/openssh-5.1p1-askpass-progress.patch
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
diff -up openssh-7.4p1/contrib/gnome-ssh-askpass2.c.progress openssh-7.4p1/contrib/gnome-ssh-askpass2.c
|
||||||
|
--- openssh-7.4p1/contrib/gnome-ssh-askpass2.c.progress 2016-12-19 05:59:41.000000000 +0100
|
||||||
|
+++ openssh-7.4p1/contrib/gnome-ssh-askpass2.c 2016-12-23 13:31:16.545211926 +0100
|
||||||
|
@@ -53,6 +53,7 @@
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
+#include <glib.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include <gdk/gdkx.h>
|
||||||
|
|
||||||
|
@@ -81,13 +82,24 @@ ok_dialog(GtkWidget *entry, gpointer dia
|
||||||
|
gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void
|
||||||
|
+move_progress(GtkWidget *entry, gpointer progress)
|
||||||
|
+{
|
||||||
|
+ gdouble step;
|
||||||
|
+ g_return_if_fail(GTK_IS_PROGRESS_BAR(progress));
|
||||||
|
+
|
||||||
|
+ step = g_random_double_range(0.03, 0.1);
|
||||||
|
+ gtk_progress_bar_set_pulse_step(GTK_PROGRESS_BAR(progress), step);
|
||||||
|
+ gtk_progress_bar_pulse(GTK_PROGRESS_BAR(progress));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
passphrase_dialog(char *message)
|
||||||
|
{
|
||||||
|
const char *failed;
|
||||||
|
char *passphrase, *local;
|
||||||
|
int result, grab_tries, grab_server, grab_pointer;
|
||||||
|
- GtkWidget *parent_window, *dialog, *entry;
|
||||||
|
+ GtkWidget *parent_window, *dialog, *entry, *progress, *hbox;
|
||||||
|
GdkGrabStatus status;
|
||||||
|
|
||||||
|
grab_server = (getenv("GNOME_SSH_ASKPASS_GRAB_SERVER") != NULL);
|
||||||
|
@@ -104,14 +116,32 @@ passphrase_dialog(char *message)
|
||||||
|
"%s",
|
||||||
|
message);
|
||||||
|
|
||||||
|
+ hbox = gtk_hbox_new(FALSE, 0);
|
||||||
|
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, FALSE,
|
||||||
|
+ FALSE, 0);
|
||||||
|
+ gtk_widget_show(hbox);
|
||||||
|
+
|
||||||
|
entry = gtk_entry_new();
|
||||||
|
gtk_box_pack_start(
|
||||||
|
- GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), entry,
|
||||||
|
- FALSE, FALSE, 0);
|
||||||
|
+ GTK_BOX(hbox), entry,
|
||||||
|
+ TRUE, FALSE, 0);
|
||||||
|
+ gtk_entry_set_width_chars(GTK_ENTRY(entry), 2);
|
||||||
|
gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE);
|
||||||
|
gtk_widget_grab_focus(entry);
|
||||||
|
gtk_widget_show(entry);
|
||||||
|
|
||||||
|
+ hbox = gtk_hbox_new(FALSE, 0);
|
||||||
|
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, FALSE,
|
||||||
|
+ FALSE, 8);
|
||||||
|
+ gtk_widget_show(hbox);
|
||||||
|
+
|
||||||
|
+ progress = gtk_progress_bar_new();
|
||||||
|
+
|
||||||
|
+ gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress), "Passphrase length hidden intentionally");
|
||||||
|
+ gtk_box_pack_start(GTK_BOX(hbox), progress, TRUE,
|
||||||
|
+ TRUE, 5);
|
||||||
|
+ gtk_widget_show(progress);
|
||||||
|
+
|
||||||
|
gtk_window_set_title(GTK_WINDOW(dialog), "OpenSSH");
|
||||||
|
gtk_window_set_position (GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
|
||||||
|
gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE);
|
||||||
|
@@ -120,6 +150,8 @@ passphrase_dialog(char *message)
|
||||||
|
gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
|
||||||
|
g_signal_connect(G_OBJECT(entry), "activate",
|
||||||
|
G_CALLBACK(ok_dialog), dialog);
|
||||||
|
+ g_signal_connect(G_OBJECT(entry), "changed",
|
||||||
|
+ G_CALLBACK(move_progress), progress);
|
||||||
|
|
||||||
|
gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE);
|
||||||
|
|
12
SOURCES/openssh-5.8p2-sigpipe.patch
Normal file
12
SOURCES/openssh-5.8p2-sigpipe.patch
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
diff -up openssh-5.8p2/ssh-keyscan.c.sigpipe openssh-5.8p2/ssh-keyscan.c
|
||||||
|
--- openssh-5.8p2/ssh-keyscan.c.sigpipe 2011-08-23 18:30:33.873025916 +0200
|
||||||
|
+++ openssh-5.8p2/ssh-keyscan.c 2011-08-23 18:32:24.574025362 +0200
|
||||||
|
@@ -715,6 +715,8 @@ main(int argc, char **argv)
|
||||||
|
fdlim_set(maxfd);
|
||||||
|
fdcon = xcalloc(maxfd, sizeof(con));
|
||||||
|
|
||||||
|
+ signal(SIGPIPE, SIG_IGN);
|
||||||
|
+
|
||||||
|
read_wait_nfdset = howmany(maxfd, NFDBITS);
|
||||||
|
read_wait = xcalloc(read_wait_nfdset, sizeof(fd_mask));
|
||||||
|
|
24
SOURCES/openssh-5.9p1-ipv6man.patch
Normal file
24
SOURCES/openssh-5.9p1-ipv6man.patch
Normal file
@ -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 ,
|
78
SOURCES/openssh-5.9p1-wIm.patch
Normal file
78
SOURCES/openssh-5.9p1-wIm.patch
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
diff -up openssh-5.9p1/Makefile.in.wIm openssh-5.9p1/Makefile.in
|
||||||
|
--- openssh-5.9p1/Makefile.in.wIm 2011-08-05 22:15:18.000000000 +0200
|
||||||
|
+++ openssh-5.9p1/Makefile.in 2011-09-12 16:24:18.643674014 +0200
|
||||||
|
@@ -66,7 +66,7 @@ LIBSSH_OBJS=acss.o authfd.o authfile.o b
|
||||||
|
cipher-bf1.o cipher-ctr.o cipher-3des1.o cleanup.o \
|
||||||
|
compat.o compress.o crc32.o deattack.o fatal.o hostfile.o \
|
||||||
|
log.o match.o md-sha256.o moduli.o nchan.o packet.o \
|
||||||
|
- readpass.o rsa.o ttymodes.o xmalloc.o addrmatch.o \
|
||||||
|
+ readpass.o rsa.o ttymodes.o whereIam.o xmalloc.o addrmatch.o \
|
||||||
|
atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \
|
||||||
|
monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \
|
||||||
|
kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \
|
||||||
|
diff -up openssh-5.9p1/log.h.wIm openssh-5.9p1/log.h
|
||||||
|
--- openssh-5.9p1/log.h.wIm 2011-06-20 06:42:23.000000000 +0200
|
||||||
|
+++ openssh-5.9p1/log.h 2011-09-12 16:34:52.984674326 +0200
|
||||||
|
@@ -65,6 +65,8 @@ void verbose(const char *, ...) __at
|
||||||
|
void debug(const char *, ...) __attribute__((format(printf, 1, 2)));
|
||||||
|
void debug2(const char *, ...) __attribute__((format(printf, 1, 2)));
|
||||||
|
void debug3(const char *, ...) __attribute__((format(printf, 1, 2)));
|
||||||
|
+void _debug_wIm_body(const char *, int, const char *, const char *, int);
|
||||||
|
+#define debug_wIm(a,b) _debug_wIm_body(a,b,__func__,__FILE__,__LINE__)
|
||||||
|
|
||||||
|
|
||||||
|
void set_log_handler(log_handler_fn *, void *);
|
||||||
|
diff -up openssh-5.9p1/sshd.c.wIm openssh-5.9p1/sshd.c
|
||||||
|
--- openssh-5.9p1/sshd.c.wIm 2011-06-23 11:45:51.000000000 +0200
|
||||||
|
+++ openssh-5.9p1/sshd.c 2011-09-12 16:38:35.787816490 +0200
|
||||||
|
@@ -140,6 +140,9 @@ int deny_severity;
|
||||||
|
|
||||||
|
extern char *__progname;
|
||||||
|
|
||||||
|
+/* trace of fork processes */
|
||||||
|
+extern int whereIam;
|
||||||
|
+
|
||||||
|
/* Server configuration options. */
|
||||||
|
ServerOptions options;
|
||||||
|
|
||||||
|
@@ -666,6 +669,7 @@ privsep_preauth(Authctxt *authctxt)
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
/* child */
|
||||||
|
+ whereIam = 1;
|
||||||
|
close(pmonitor->m_sendfd);
|
||||||
|
close(pmonitor->m_log_recvfd);
|
||||||
|
|
||||||
|
@@ -715,6 +719,7 @@ privsep_postauth(Authctxt *authctxt)
|
||||||
|
|
||||||
|
/* child */
|
||||||
|
|
||||||
|
+ whereIam = 2;
|
||||||
|
close(pmonitor->m_sendfd);
|
||||||
|
pmonitor->m_sendfd = -1;
|
||||||
|
|
||||||
|
@@ -1325,6 +1330,8 @@ main(int ac, char **av)
|
||||||
|
Key *key;
|
||||||
|
Authctxt *authctxt;
|
||||||
|
|
||||||
|
+ whereIam = 0;
|
||||||
|
+
|
||||||
|
#ifdef HAVE_SECUREWARE
|
||||||
|
(void)set_auth_parameters(ac, av);
|
||||||
|
#endif
|
||||||
|
diff -up openssh-5.9p1/whereIam.c.wIm openssh-5.9p1/whereIam.c
|
||||||
|
--- openssh-5.9p1/whereIam.c.wIm 2011-09-12 16:24:18.722674167 +0200
|
||||||
|
+++ openssh-5.9p1/whereIam.c 2011-09-12 16:24:18.724674418 +0200
|
||||||
|
@@ -0,0 +1,12 @@
|
||||||
|
+
|
||||||
|
+int whereIam = -1;
|
||||||
|
+
|
||||||
|
+void _debug_wIm_body(const char *txt, int val, const char *func, const char *file, int line)
|
||||||
|
+{
|
||||||
|
+ if (txt)
|
||||||
|
+ debug("%s=%d, %s(%s:%d) wIm = %d, uid=%d, euid=%d", txt, val, func, file, line, whereIam, getuid(), geteuid());
|
||||||
|
+ else
|
||||||
|
+ debug("%s(%s:%d) wIm = %d, uid=%d, euid=%d", func, file, line, whereIam, getuid(), geteuid());
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
21
SOURCES/openssh-6.1p1-gssapi-canohost.patch
Normal file
21
SOURCES/openssh-6.1p1-gssapi-canohost.patch
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
diff -up openssh-6.1p1/sshconnect2.c.canohost openssh-6.1p1/sshconnect2.c
|
||||||
|
--- openssh-6.1p1/sshconnect2.c.canohost 2012-10-30 10:52:59.593301692 +0100
|
||||||
|
+++ openssh-6.1p1/sshconnect2.c 2012-10-30 11:01:12.870301632 +0100
|
||||||
|
@@ -699,12 +699,15 @@ userauth_gssapi(Authctxt *authctxt)
|
||||||
|
static u_int mech = 0;
|
||||||
|
OM_uint32 min;
|
||||||
|
int r, ok = 0;
|
||||||
|
- const char *gss_host;
|
||||||
|
+ const char *gss_host = NULL;
|
||||||
|
|
||||||
|
if (options.gss_server_identity)
|
||||||
|
gss_host = options.gss_server_identity;
|
||||||
|
- else if (options.gss_trust_dns)
|
||||||
|
+ else if (options.gss_trust_dns) {
|
||||||
|
gss_host = get_canonical_hostname(active_state, 1);
|
||||||
|
+ if (strcmp(gss_host, "UNKNOWN") == 0)
|
||||||
|
+ gss_host = authctxt->host;
|
||||||
|
+ }
|
||||||
|
else
|
||||||
|
gss_host = authctxt->host;
|
||||||
|
|
142
SOURCES/openssh-6.2p1-vendor.patch
Normal file
142
SOURCES/openssh-6.2p1-vendor.patch
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
diff -up openssh-7.4p1/configure.ac.vendor openssh-7.4p1/configure.ac
|
||||||
|
--- openssh-7.4p1/configure.ac.vendor 2016-12-23 13:34:51.681253844 +0100
|
||||||
|
+++ openssh-7.4p1/configure.ac 2016-12-23 13:34:51.694253847 +0100
|
||||||
|
@@ -4930,6 +4930,12 @@ AC_ARG_WITH([lastlog],
|
||||||
|
fi
|
||||||
|
]
|
||||||
|
)
|
||||||
|
+AC_ARG_ENABLE(vendor-patchlevel,
|
||||||
|
+ [ --enable-vendor-patchlevel=TAG specify a vendor patch level],
|
||||||
|
+ [AC_DEFINE_UNQUOTED(SSH_VENDOR_PATCHLEVEL,[SSH_RELEASE "-" "$enableval"],[Define to your vendor patch level, if it has been modified from the upstream source release.])
|
||||||
|
+ SSH_VENDOR_PATCHLEVEL="$enableval"],
|
||||||
|
+ [AC_DEFINE(SSH_VENDOR_PATCHLEVEL,SSH_RELEASE,[Define to your vendor patch level, if it has been modified from the upstream source release.])
|
||||||
|
+ SSH_VENDOR_PATCHLEVEL=none])
|
||||||
|
|
||||||
|
dnl lastlog, [uw]tmpx? detection
|
||||||
|
dnl NOTE: set the paths in the platform section to avoid the
|
||||||
|
@@ -5194,6 +5200,7 @@ echo " Translate v4 in v6 hack
|
||||||
|
echo " BSD Auth support: $BSD_AUTH_MSG"
|
||||||
|
echo " Random number source: $RAND_MSG"
|
||||||
|
echo " Privsep sandbox style: $SANDBOX_STYLE"
|
||||||
|
+echo " Vendor patch level: $SSH_VENDOR_PATCHLEVEL"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
diff -up openssh-7.4p1/servconf.c.vendor openssh-7.4p1/servconf.c
|
||||||
|
--- openssh-7.4p1/servconf.c.vendor 2016-12-19 05:59:41.000000000 +0100
|
||||||
|
+++ openssh-7.4p1/servconf.c 2016-12-23 13:36:07.555268628 +0100
|
||||||
|
@@ -143,6 +143,7 @@ initialize_server_options(ServerOptions
|
||||||
|
options->max_authtries = -1;
|
||||||
|
options->max_sessions = -1;
|
||||||
|
options->banner = NULL;
|
||||||
|
+ options->show_patchlevel = -1;
|
||||||
|
options->use_dns = -1;
|
||||||
|
options->client_alive_interval = -1;
|
||||||
|
options->client_alive_count_max = -1;
|
||||||
|
@@ -325,6 +326,8 @@ fill_default_server_options(ServerOption
|
||||||
|
options->ip_qos_bulk = IPTOS_DSCP_CS1;
|
||||||
|
if (options->version_addendum == NULL)
|
||||||
|
options->version_addendum = xstrdup("");
|
||||||
|
+ if (options->show_patchlevel == -1)
|
||||||
|
+ options->show_patchlevel = 0;
|
||||||
|
if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
|
||||||
|
options->fwd_opts.streamlocal_bind_mask = 0177;
|
||||||
|
if (options->fwd_opts.streamlocal_bind_unlink == -1)
|
||||||
|
@@ -402,7 +405,7 @@ typedef enum {
|
||||||
|
sIgnoreUserKnownHosts, sCiphers, sMacs, sPidFile,
|
||||||
|
sGatewayPorts, sPubkeyAuthentication, sPubkeyAcceptedKeyTypes,
|
||||||
|
sXAuthLocation, sSubsystem, sMaxStartups, sMaxAuthTries, sMaxSessions,
|
||||||
|
- sBanner, sUseDNS, sHostbasedAuthentication,
|
||||||
|
+ sBanner, sShowPatchLevel, sUseDNS, sHostbasedAuthentication,
|
||||||
|
sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedKeyTypes,
|
||||||
|
sHostKeyAlgorithms,
|
||||||
|
sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
|
||||||
|
@@ -528,6 +531,7 @@ static struct {
|
||||||
|
{ "maxauthtries", sMaxAuthTries, SSHCFG_ALL },
|
||||||
|
{ "maxsessions", sMaxSessions, SSHCFG_ALL },
|
||||||
|
{ "banner", sBanner, SSHCFG_ALL },
|
||||||
|
+ { "showpatchlevel", sShowPatchLevel, SSHCFG_GLOBAL },
|
||||||
|
{ "usedns", sUseDNS, SSHCFG_GLOBAL },
|
||||||
|
{ "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
|
||||||
|
{ "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL },
|
||||||
|
@@ -1369,6 +1373,10 @@ process_server_config_line(ServerOptions
|
||||||
|
intptr = &options->disable_forwarding;
|
||||||
|
goto parse_flag;
|
||||||
|
|
||||||
|
+ case sShowPatchLevel:
|
||||||
|
+ intptr = &options->show_patchlevel;
|
||||||
|
+ goto parse_flag;
|
||||||
|
+
|
||||||
|
case sAllowUsers:
|
||||||
|
while ((arg = strdelim(&cp)) && *arg != '\0') {
|
||||||
|
if (match_user(NULL, NULL, NULL, arg) == -1)
|
||||||
|
@@ -2269,6 +2277,7 @@ dump_config(ServerOptions *o)
|
||||||
|
dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd);
|
||||||
|
dump_cfg_fmtint(sCompression, o->compression);
|
||||||
|
dump_cfg_fmtint(sGatewayPorts, o->fwd_opts.gateway_ports);
|
||||||
|
+ dump_cfg_fmtint(sShowPatchLevel, o->show_patchlevel);
|
||||||
|
dump_cfg_fmtint(sUseDNS, o->use_dns);
|
||||||
|
dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding);
|
||||||
|
dump_cfg_fmtint(sAllowAgentForwarding, o->allow_agent_forwarding);
|
||||||
|
diff -up openssh-7.4p1/servconf.h.vendor openssh-7.4p1/servconf.h
|
||||||
|
--- openssh-7.4p1/servconf.h.vendor 2016-12-19 05:59:41.000000000 +0100
|
||||||
|
+++ openssh-7.4p1/servconf.h 2016-12-23 13:34:51.694253847 +0100
|
||||||
|
@@ -149,6 +149,7 @@ typedef struct {
|
||||||
|
int max_authtries;
|
||||||
|
int max_sessions;
|
||||||
|
char *banner; /* SSH-2 banner message */
|
||||||
|
+ int show_patchlevel; /* Show vendor patch level to clients */
|
||||||
|
int use_dns;
|
||||||
|
int client_alive_interval; /*
|
||||||
|
* poke the client this often to
|
||||||
|
diff -up openssh-7.4p1/sshd_config.5.vendor openssh-7.4p1/sshd_config.5
|
||||||
|
--- openssh-7.4p1/sshd_config.5.vendor 2016-12-23 13:34:51.695253847 +0100
|
||||||
|
+++ openssh-7.4p1/sshd_config.5 2016-12-23 13:37:17.482282253 +0100
|
||||||
|
@@ -1334,6 +1334,13 @@ an OpenSSH Key Revocation List (KRL) as
|
||||||
|
.Cm AcceptEnv
|
||||||
|
or
|
||||||
|
.Cm PermitUserEnvironment .
|
||||||
|
+.It Cm ShowPatchLevel
|
||||||
|
+Specifies whether
|
||||||
|
+.Nm sshd
|
||||||
|
+will display the patch level of the binary in the identification string.
|
||||||
|
+The patch level is set at compile-time.
|
||||||
|
+The default is
|
||||||
|
+.Dq no .
|
||||||
|
.It Cm StreamLocalBindMask
|
||||||
|
Sets the octal file creation mode mask
|
||||||
|
.Pq umask
|
||||||
|
diff -up openssh-7.4p1/sshd_config.vendor openssh-7.4p1/sshd_config
|
||||||
|
--- openssh-7.4p1/sshd_config.vendor 2016-12-23 13:34:51.690253846 +0100
|
||||||
|
+++ openssh-7.4p1/sshd_config 2016-12-23 13:34:51.695253847 +0100
|
||||||
|
@@ -105,6 +105,7 @@ X11Forwarding yes
|
||||||
|
#Compression delayed
|
||||||
|
#ClientAliveInterval 0
|
||||||
|
#ClientAliveCountMax 3
|
||||||
|
+#ShowPatchLevel no
|
||||||
|
#UseDNS no
|
||||||
|
#PidFile /var/run/sshd.pid
|
||||||
|
#MaxStartups 10:30:100
|
||||||
|
diff -up openssh-7.4p1/sshd.c.vendor openssh-7.4p1/sshd.c
|
||||||
|
--- openssh-7.4p1/sshd.c.vendor 2016-12-23 13:34:51.682253844 +0100
|
||||||
|
+++ openssh-7.4p1/sshd.c 2016-12-23 13:38:32.434296856 +0100
|
||||||
|
@@ -367,7 +367,8 @@ sshd_exchange_identification(struct ssh
|
||||||
|
char remote_version[256]; /* Must be at least as big as buf. */
|
||||||
|
|
||||||
|
xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s\r\n",
|
||||||
|
- PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION,
|
||||||
|
+ PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2,
|
||||||
|
+ (options.show_patchlevel == 1) ? SSH_VENDOR_PATCHLEVEL : SSH_VERSION,
|
||||||
|
*options.version_addendum == '\0' ? "" : " ",
|
||||||
|
options.version_addendum);
|
||||||
|
|
||||||
|
@@ -1650,7 +1651,8 @@ main(int ac, char **av)
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
- debug("sshd version %s, %s", SSH_VERSION,
|
||||||
|
+ debug("sshd version %s, %s",
|
||||||
|
+ (options.show_patchlevel == 1) ? SSH_VENDOR_PATCHLEVEL : SSH_VERSION,
|
||||||
|
#ifdef WITH_OPENSSL
|
||||||
|
SSLeay_version(SSLEAY_VERSION)
|
||||||
|
#else
|
101
SOURCES/openssh-6.3p1-ctr-evp-fast.patch
Normal file
101
SOURCES/openssh-6.3p1-ctr-evp-fast.patch
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
diff -up openssh-5.9p1/cipher-ctr.c.ctr-evp openssh-5.9p1/cipher-ctr.c
|
||||||
|
--- openssh-5.9p1/cipher-ctr.c.ctr-evp 2012-01-11 09:24:06.000000000 +0100
|
||||||
|
+++ openssh-5.9p1/cipher-ctr.c 2012-01-11 15:54:04.675956600 +0100
|
||||||
|
@@ -38,7 +38,7 @@ void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, in
|
||||||
|
|
||||||
|
struct ssh_aes_ctr_ctx
|
||||||
|
{
|
||||||
|
- AES_KEY aes_ctx;
|
||||||
|
+ EVP_CIPHER_CTX ecbctx;
|
||||||
|
u_char aes_counter[AES_BLOCK_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -63,21 +63,42 @@ ssh_aes_ctr(EVP_CIPHER_CTX *ctx, u_char
|
||||||
|
{
|
||||||
|
struct ssh_aes_ctr_ctx *c;
|
||||||
|
size_t n = 0;
|
||||||
|
- u_char buf[AES_BLOCK_SIZE];
|
||||||
|
+ u_char ctrbuf[AES_BLOCK_SIZE*256];
|
||||||
|
+ u_char buf[AES_BLOCK_SIZE*256];
|
||||||
|
|
||||||
|
if (len == 0)
|
||||||
|
return (1);
|
||||||
|
if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
- while ((len--) > 0) {
|
||||||
|
+ for (; len > 0; len -= sizeof(u_int)) {
|
||||||
|
+ u_int r,a,b;
|
||||||
|
+
|
||||||
|
if (n == 0) {
|
||||||
|
- AES_encrypt(c->aes_counter, buf, &c->aes_ctx);
|
||||||
|
- ssh_ctr_inc(c->aes_counter, AES_BLOCK_SIZE);
|
||||||
|
+ int outl, i, buflen;
|
||||||
|
+
|
||||||
|
+ buflen = MIN(len, sizeof(ctrbuf));
|
||||||
|
+
|
||||||
|
+ for(i = 0; i < buflen; i += AES_BLOCK_SIZE) {
|
||||||
|
+ memcpy(&ctrbuf[i], c->aes_counter, AES_BLOCK_SIZE);
|
||||||
|
+ ssh_ctr_inc(c->aes_counter, AES_BLOCK_SIZE);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ EVP_EncryptUpdate(&c->ecbctx, buf, &outl,
|
||||||
|
+ ctrbuf, buflen);
|
||||||
|
}
|
||||||
|
- *(dest++) = *(src++) ^ buf[n];
|
||||||
|
- n = (n + 1) % AES_BLOCK_SIZE;
|
||||||
|
+
|
||||||
|
+ memcpy(&a, src, sizeof(a));
|
||||||
|
+ memcpy(&b, &buf[n], sizeof(b));
|
||||||
|
+ r = a ^ b;
|
||||||
|
+ memcpy(dest, &r, sizeof(r));
|
||||||
|
+ src += sizeof(a);
|
||||||
|
+ dest += sizeof(r);
|
||||||
|
+
|
||||||
|
+ n = (n + sizeof(b)) % sizeof(buf);
|
||||||
|
}
|
||||||
|
+ memset(ctrbuf, '\0', sizeof(ctrbuf));
|
||||||
|
+ memset(buf, '\0', sizeof(buf));
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -91,9 +112,28 @@ ssh_aes_ctr_init(EVP_CIPHER_CTX *ctx, co
|
||||||
|
c = xmalloc(sizeof(*c));
|
||||||
|
EVP_CIPHER_CTX_set_app_data(ctx, c);
|
||||||
|
}
|
||||||
|
- if (key != NULL)
|
||||||
|
- AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
|
||||||
|
- &c->aes_ctx);
|
||||||
|
+
|
||||||
|
+ EVP_CIPHER_CTX_init(&c->ecbctx);
|
||||||
|
+
|
||||||
|
+ if (key != NULL) {
|
||||||
|
+ const EVP_CIPHER *cipher;
|
||||||
|
+ switch(EVP_CIPHER_CTX_key_length(ctx)*8) {
|
||||||
|
+ case 128:
|
||||||
|
+ cipher = EVP_aes_128_ecb();
|
||||||
|
+ break;
|
||||||
|
+ case 192:
|
||||||
|
+ cipher = EVP_aes_192_ecb();
|
||||||
|
+ break;
|
||||||
|
+ case 256:
|
||||||
|
+ cipher = EVP_aes_256_ecb();
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ fatal("ssh_aes_ctr_init: wrong aes key length");
|
||||||
|
+ }
|
||||||
|
+ if(!EVP_EncryptInit_ex(&c->ecbctx, cipher, NULL, key, NULL))
|
||||||
|
+ fatal("ssh_aes_ctr_init: cannot initialize aes encryption");
|
||||||
|
+ EVP_CIPHER_CTX_set_padding(&c->ecbctx, 0);
|
||||||
|
+ }
|
||||||
|
if (iv != NULL)
|
||||||
|
memcpy(c->aes_counter, iv, AES_BLOCK_SIZE);
|
||||||
|
return (1);
|
||||||
|
@@ -105,6 +145,7 @@ ssh_aes_ctr_cleanup(EVP_CIPHER_CTX *ctx)
|
||||||
|
struct ssh_aes_ctr_ctx *c;
|
||||||
|
|
||||||
|
if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
|
||||||
|
+ EVP_CIPHER_CTX_cleanup(&c->ecbctx);
|
||||||
|
memset(c, 0, sizeof(*c));
|
||||||
|
free(c);
|
||||||
|
EVP_CIPHER_CTX_set_app_data(ctx, NULL);
|
16
SOURCES/openssh-6.4p1-fromto-remote.patch
Normal file
16
SOURCES/openssh-6.4p1-fromto-remote.patch
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
diff --git a/scp.c b/scp.c
|
||||||
|
index d98fa67..25d347b 100644
|
||||||
|
--- a/scp.c
|
||||||
|
+++ b/scp.c
|
||||||
|
@@ -638,7 +638,10 @@ toremote(char *targ, int argc, char **argv)
|
||||||
|
addargs(&alist, "%s", ssh_program);
|
||||||
|
addargs(&alist, "-x");
|
||||||
|
addargs(&alist, "-oClearAllForwardings=yes");
|
||||||
|
- addargs(&alist, "-n");
|
||||||
|
+ if (isatty(fileno(stdin)))
|
||||||
|
+ addargs(&alist, "-t");
|
||||||
|
+ else
|
||||||
|
+ addargs(&alist, "-n");
|
||||||
|
for (j = 0; j < remote_remote_args.num; j++) {
|
||||||
|
addargs(&alist, "%s",
|
||||||
|
remote_remote_args.list[j]);
|
263
SOURCES/openssh-6.6.1p1-log-in-chroot.patch
Normal file
263
SOURCES/openssh-6.6.1p1-log-in-chroot.patch
Normal file
@ -0,0 +1,263 @@
|
|||||||
|
diff -up openssh-7.4p1/log.c.log-in-chroot openssh-7.4p1/log.c
|
||||||
|
--- openssh-7.4p1/log.c.log-in-chroot 2016-12-19 05:59:41.000000000 +0100
|
||||||
|
+++ openssh-7.4p1/log.c 2016-12-23 15:14:33.330168088 +0100
|
||||||
|
@@ -250,6 +250,11 @@ debug3(const char *fmt,...)
|
||||||
|
void
|
||||||
|
log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr)
|
||||||
|
{
|
||||||
|
+ log_init_handler(av0, level, facility, on_stderr, 1);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+log_init_handler(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
|
||||||
|
@@ -273,8 +278,10 @@ log_init(char *av0, LogLevel level, Sysl
|
||||||
|
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-7.4p1/log.h.log-in-chroot openssh-7.4p1/log.h
|
||||||
|
--- openssh-7.4p1/log.h.log-in-chroot 2016-12-19 05:59:41.000000000 +0100
|
||||||
|
+++ openssh-7.4p1/log.h 2016-12-23 15:14:33.330168088 +0100
|
||||||
|
@@ -49,6 +49,7 @@ typedef enum {
|
||||||
|
typedef void (log_handler_fn)(LogLevel, const char *, void *);
|
||||||
|
|
||||||
|
void log_init(char *, LogLevel, SyslogFacility, int);
|
||||||
|
+void log_init_handler(char *, LogLevel, SyslogFacility, int, int);
|
||||||
|
LogLevel log_level_get(void);
|
||||||
|
int log_change_level(LogLevel);
|
||||||
|
int log_is_on_stderr(void);
|
||||||
|
diff -up openssh-7.4p1/monitor.c.log-in-chroot openssh-7.4p1/monitor.c
|
||||||
|
--- openssh-7.4p1/monitor.c.log-in-chroot 2016-12-23 15:14:33.311168085 +0100
|
||||||
|
+++ openssh-7.4p1/monitor.c 2016-12-23 15:16:42.154193100 +0100
|
||||||
|
@@ -307,6 +307,8 @@ monitor_child_preauth(Authctxt *_authctx
|
||||||
|
close(pmonitor->m_log_sendfd);
|
||||||
|
pmonitor->m_log_sendfd = pmonitor->m_recvfd = -1;
|
||||||
|
|
||||||
|
+ pmonitor->m_state = "preauth";
|
||||||
|
+
|
||||||
|
authctxt = _authctxt;
|
||||||
|
memset(authctxt, 0, sizeof(*authctxt));
|
||||||
|
ssh->authctxt = authctxt;
|
||||||
|
@@ -405,6 +407,8 @@ monitor_child_postauth(struct monitor *p
|
||||||
|
close(pmonitor->m_recvfd);
|
||||||
|
pmonitor->m_recvfd = -1;
|
||||||
|
|
||||||
|
+ pmonitor->m_state = "postauth";
|
||||||
|
+
|
||||||
|
monitor_set_child_handler(pmonitor->m_pid);
|
||||||
|
signal(SIGHUP, &monitor_child_handler);
|
||||||
|
signal(SIGTERM, &monitor_child_handler);
|
||||||
|
@@ -472,7 +476,7 @@ monitor_read_log(struct monitor *pmonito
|
||||||
|
if (log_level_name(level) == NULL)
|
||||||
|
fatal("%s: invalid log level %u (corrupted message?)",
|
||||||
|
__func__, level);
|
||||||
|
- do_log2(level, "%s [preauth]", msg);
|
||||||
|
+ do_log2(level, "%s [%s]", msg, pmonitor->m_state);
|
||||||
|
|
||||||
|
sshbuf_free(logmsg);
|
||||||
|
free(msg);
|
||||||
|
@@ -1719,13 +1723,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("%s: /dev/log doesn't exist in %s chroot - will try to log via monitor using [postauth] suffix", __func__, chroot_dir);
|
||||||
|
+ do_logfds = 1;
|
||||||
|
+ }
|
||||||
|
+ free(dev_log_path);
|
||||||
|
+ }
|
||||||
|
+ monitor_openfds(mon, do_logfds);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef GSSAPI
|
||||||
|
diff -up openssh-7.4p1/monitor.h.log-in-chroot openssh-7.4p1/monitor.h
|
||||||
|
--- openssh-7.4p1/monitor.h.log-in-chroot 2016-12-23 15:14:33.330168088 +0100
|
||||||
|
+++ openssh-7.4p1/monitor.h 2016-12-23 15:16:28.372190424 +0100
|
||||||
|
@@ -83,10 +83,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 Authctxt *, struct monitor *);
|
||||||
|
diff -up openssh-7.4p1/session.c.log-in-chroot openssh-7.4p1/session.c
|
||||||
|
--- openssh-7.4p1/session.c.log-in-chroot 2016-12-23 15:14:33.319168086 +0100
|
||||||
|
+++ openssh-7.4p1/session.c 2016-12-23 15:18:18.742211853 +0100
|
||||||
|
@@ -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;
|
||||||
|
@@ -619,6 +620,7 @@ do_exec(Session *s, const char *command)
|
||||||
|
int ret;
|
||||||
|
const char *forced = NULL, *tty = NULL;
|
||||||
|
char session_type[1024];
|
||||||
|
+ struct stat dev_log_stat;
|
||||||
|
|
||||||
|
if (options.adm_forced_command) {
|
||||||
|
original_command = command;
|
||||||
|
@@ -676,6 +678,10 @@ do_exec(Session *s, const char *command)
|
||||||
|
tty += 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (lstat("/dev/log", &dev_log_stat) != 0) {
|
||||||
|
+ have_dev_log = 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
verbose("Starting session: %s%s%s for %s from %.200s port %d id %d",
|
||||||
|
session_type,
|
||||||
|
tty == NULL ? "" : " on ",
|
||||||
|
@@ -1486,14 +1492,6 @@ child_close_fds(void)
|
||||||
|
* descriptors left by system functions. They will be closed later.
|
||||||
|
*/
|
||||||
|
endpwent();
|
||||||
|
-
|
||||||
|
- /*
|
||||||
|
- * 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -1629,8 +1627,6 @@ do_child(Session *s, const char *command
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
- closefrom(STDERR_FILENO + 1);
|
||||||
|
-
|
||||||
|
do_rc_files(ssh, s, shell);
|
||||||
|
|
||||||
|
/* restore SIGPIPE for child */
|
||||||
|
@@ -1653,9 +1649,17 @@ do_child(Session *s, const char *command
|
||||||
|
argv[i] = NULL;
|
||||||
|
optind = optreset = 1;
|
||||||
|
__progname = argv[0];
|
||||||
|
- exit(sftp_server_main(i, argv, s->pw));
|
||||||
|
+ exit(sftp_server_main(i, argv, s->pw, have_dev_log));
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * Close any extra open file descriptors so that we don't have them
|
||||||
|
+ * hanging around in clients. Note that we want to do this after
|
||||||
|
+ * initgroups, because at least on Solaris 2.3 it leaves file
|
||||||
|
+ * descriptors open.
|
||||||
|
+ */
|
||||||
|
+ closefrom(STDERR_FILENO + 1);
|
||||||
|
+
|
||||||
|
fflush(NULL);
|
||||||
|
|
||||||
|
/* Get the last component of the shell name. */
|
||||||
|
diff -up openssh-7.4p1/sftp.h.log-in-chroot openssh-7.4p1/sftp.h
|
||||||
|
--- openssh-7.4p1/sftp.h.log-in-chroot 2016-12-19 05:59:41.000000000 +0100
|
||||||
|
+++ openssh-7.4p1/sftp.h 2016-12-23 15:14:33.331168088 +0100
|
||||||
|
@@ -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-7.4p1/sftp-server.c.log-in-chroot openssh-7.4p1/sftp-server.c
|
||||||
|
--- openssh-7.4p1/sftp-server.c.log-in-chroot 2016-12-19 05:59:41.000000000 +0100
|
||||||
|
+++ openssh-7.4p1/sftp-server.c 2016-12-23 15:14:33.331168088 +0100
|
||||||
|
@@ -1497,7 +1497,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)
|
||||||
|
{
|
||||||
|
fd_set *rset, *wset;
|
||||||
|
int i, r, in, out, max, ch, skipargs = 0, log_stderr = 0;
|
||||||
|
@@ -1511,7 +1511,7 @@ sftp_server_main(int argc, char **argv,
|
||||||
|
|
||||||
|
ssh_malloc_init(); /* must be called before any mallocs */
|
||||||
|
__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);
|
||||||
|
|
||||||
|
@@ -1582,7 +1582,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-7.4p1/sftp-server-main.c.log-in-chroot openssh-7.4p1/sftp-server-main.c
|
||||||
|
--- openssh-7.4p1/sftp-server-main.c.log-in-chroot 2016-12-19 05:59:41.000000000 +0100
|
||||||
|
+++ openssh-7.4p1/sftp-server-main.c 2016-12-23 15:14:33.331168088 +0100
|
||||||
|
@@ -49,5 +49,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-7.4p1/sshd.c.log-in-chroot openssh-7.4p1/sshd.c
|
||||||
|
--- openssh-7.4p1/sshd.c.log-in-chroot 2016-12-23 15:14:33.328168088 +0100
|
||||||
|
+++ openssh-7.4p1/sshd.c 2016-12-23 15:14:33.332168088 +0100
|
||||||
|
@@ -650,7 +650,7 @@ privsep_postauth(Authctxt *authctxt)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* New socket pair */
|
||||||
|
- monitor_reinit(pmonitor);
|
||||||
|
+ monitor_reinit(pmonitor, options.chroot_directory);
|
||||||
|
|
||||||
|
pmonitor->m_pid = fork();
|
||||||
|
if (pmonitor->m_pid == -1)
|
||||||
|
@@ -668,6 +668,11 @@ privsep_postauth(Authctxt *authctxt)
|
||||||
|
|
||||||
|
close(pmonitor->m_sendfd);
|
||||||
|
pmonitor->m_sendfd = -1;
|
||||||
|
+ close(pmonitor->m_log_recvfd);
|
||||||
|
+ pmonitor->m_log_recvfd = -1;
|
||||||
|
+
|
||||||
|
+ if (pmonitor->m_log_sendfd != -1)
|
||||||
|
+ set_log_handler(mm_log_handler, pmonitor);
|
||||||
|
|
||||||
|
/* Demote the private keys to public keys. */
|
||||||
|
demote_sensitive_data();
|
14
SOURCES/openssh-6.6.1p1-scp-non-existing-directory.patch
Normal file
14
SOURCES/openssh-6.6.1p1-scp-non-existing-directory.patch
Normal file
@ -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)) < 0) {
|
||||||
|
--
|
126
SOURCES/openssh-6.6.1p1-selinux-contexts.patch
Normal file
126
SOURCES/openssh-6.6.1p1-selinux-contexts.patch
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
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,58 @@ 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;
|
||||||
|
+
|
||||||
|
+ contexts_path = selinux_openssh_contexts_path();
|
||||||
|
+ if (contexts_path != NULL) {
|
||||||
|
+ if ((contexts_file = fopen(contexts_path, "r")) != NULL) {
|
||||||
|
+ struct stat sb;
|
||||||
|
+
|
||||||
|
+ if (fstat(fileno(contexts_file), &sb) == 0 && ((sb.st_uid == 0) && ((sb.st_mode & 022) == 0))) {
|
||||||
|
+ 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("%s: privsep_preauth is empty", __func__);
|
||||||
|
+ fclose(contexts_file);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ preauth_context = xstrdup(arg);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ fclose(contexts_file);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (preauth_context == NULL)
|
||||||
|
+ preauth_context = xstrdup("sshd_net_t");
|
||||||
|
+
|
||||||
|
+ ssh_selinux_change_context(preauth_context);
|
||||||
|
+ free(preauth_context);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
diff --git a/openbsd-compat/port-linux.c b/openbsd-compat/port-linux.c
|
||||||
|
index 22ea8ef..1fc963d 100644
|
||||||
|
--- a/openbsd-compat/port-linux.c
|
||||||
|
+++ b/openbsd-compat/port-linux.c
|
||||||
|
@@ -26,6 +26,7 @@
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
#include "xmalloc.h"
|
||||||
|
@@ -179,7 +179,7 @@ ssh_selinux_change_context(const char *newname)
|
||||||
|
strlcpy(newctx + len, newname, newlen - len);
|
||||||
|
if ((cx = index(cx + 1, ':')))
|
||||||
|
strlcat(newctx, cx, newlen);
|
||||||
|
- debug3("%s: setting context from '%s' to '%s'", __func__,
|
||||||
|
+ debug("%s: setting context from '%s' to '%s'", __func__,
|
||||||
|
oldctx, newctx);
|
||||||
|
if (setcon(newctx) < 0)
|
||||||
|
switchlog("%s: setcon %s from %s failed with %s", __func__,
|
||||||
|
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.c b/sshd.c
|
||||||
|
index 2871fe9..39b9c08 100644
|
||||||
|
--- a/sshd.c
|
||||||
|
+++ b/sshd.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 */
|
129
SOURCES/openssh-6.6p1-GSSAPIEnablek5users.patch
Normal file
129
SOURCES/openssh-6.6p1-GSSAPIEnablek5users.patch
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
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_strict_acceptor = -1;
|
||||||
|
options->gss_store_rekey = -1;
|
||||||
|
options->use_kuserok = -1;
|
||||||
|
+ options->enable_k5users = -1;
|
||||||
|
options->password_authentication = -1;
|
||||||
|
options->kbd_interactive_authentication = -1;
|
||||||
|
options->challenge_response_authentication = -1;
|
||||||
|
@@ -345,6 +346,8 @@ fill_default_server_options(ServerOption
|
||||||
|
options->gss_store_rekey = 0;
|
||||||
|
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)
|
||||||
|
@@ -418,7 +421,7 @@ typedef enum {
|
||||||
|
sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedKeyTypes,
|
||||||
|
sHostKeyAlgorithms,
|
||||||
|
sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
|
||||||
|
- sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
|
||||||
|
+ sGssAuthentication, sGssCleanupCreds, sGssEnablek5users, sGssStrictAcceptor,
|
||||||
|
sGssKeyEx, sGssStoreRekey, sAcceptEnv, sSetEnv, sPermitTunnel,
|
||||||
|
sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory,
|
||||||
|
sUsePrivilegeSeparation, sAllowAgentForwarding,
|
||||||
|
@@ -497,12 +500,14 @@ static struct {
|
||||||
|
{ "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },
|
||||||
|
{ "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL },
|
||||||
|
{ "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL },
|
||||||
|
+ { "gssapienablek5users", sGssEnablek5users, SSHCFG_ALL },
|
||||||
|
#else
|
||||||
|
{ "gssapiauthentication", sUnsupported, SSHCFG_ALL },
|
||||||
|
{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
|
||||||
|
{ "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },
|
||||||
|
{ "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL },
|
||||||
|
{ "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL },
|
||||||
|
+ { "gssapienablek5users", sUnsupported, SSHCFG_ALL },
|
||||||
|
#endif
|
||||||
|
{ "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL },
|
||||||
|
{ "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL },
|
||||||
|
@@ -1653,6 +1658,10 @@ process_server_config_line(ServerOptions
|
||||||
|
intptr = &options->use_kuserok;
|
||||||
|
goto parse_flag;
|
||||||
|
|
||||||
|
+ case sGssEnablek5users:
|
||||||
|
+ intptr = &options->enable_k5users;
|
||||||
|
+ goto parse_flag;
|
||||||
|
+
|
||||||
|
case sPermitListen:
|
||||||
|
case sPermitOpen:
|
||||||
|
if (opcode == sPermitListen) {
|
||||||
|
@@ -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 no
|
||||||
|
#GSSAPIStrictAcceptorCheck yes
|
||||||
|
#GSSAPIKeyExchange no
|
||||||
|
+#GSSAPIEnablek5users no
|
||||||
|
|
||||||
|
# Set this to 'yes' to enable PAM authentication, account processing,
|
||||||
|
# and session processing. If this is enabled, PAM authentication will
|
39
SOURCES/openssh-6.6p1-allow-ip-opts.patch
Normal file
39
SOURCES/openssh-6.6p1-allow-ip-opts.patch
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
diff -up openssh/sshd.c.ip-opts openssh/sshd.c
|
||||||
|
--- openssh/sshd.c.ip-opts 2016-07-25 13:58:48.998507834 +0200
|
||||||
|
+++ openssh/sshd.c 2016-07-25 14:01:28.346469878 +0200
|
||||||
|
@@ -1507,12 +1507,29 @@ check_ip_options(struct ssh *ssh)
|
||||||
|
|
||||||
|
if (getsockopt(sock_in, IPPROTO_IP, IP_OPTIONS, opts,
|
||||||
|
&option_size) >= 0 && option_size != 0) {
|
||||||
|
- 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:
|
||||||
|
+ i += opts[i + 1];
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ /* Fail, fatally, if we detect either loose or strict
|
||||||
|
+ * 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);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
#endif /* IP_OPTIONS */
|
257
SOURCES/openssh-6.6p1-ctr-cavstest.patch
Normal file
257
SOURCES/openssh-6.6p1-ctr-cavstest.patch
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
diff -up openssh-6.8p1/Makefile.in.ctr-cavs openssh-6.8p1/Makefile.in
|
||||||
|
--- openssh-6.8p1/Makefile.in.ctr-cavs 2015-03-18 11:22:05.493289018 +0100
|
||||||
|
+++ openssh-6.8p1/Makefile.in 2015-03-18 11:22:44.504196316 +0100
|
||||||
|
@@ -28,6 +28,7 @@ SSH_KEYSIGN=$(libexecdir)/ssh-keysign
|
||||||
|
SSH_LDAP_HELPER=$(libexecdir)/ssh-ldap-helper
|
||||||
|
SSH_LDAP_WRAPPER=$(libexecdir)/ssh-ldap-wrapper
|
||||||
|
SSH_KEYCAT=$(libexecdir)/ssh-keycat
|
||||||
|
+CTR_CAVSTEST=$(libexecdir)/ctr-cavstest
|
||||||
|
SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
|
||||||
|
PRIVSEP_PATH=@PRIVSEP_PATH@
|
||||||
|
SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@
|
||||||
|
@@ -66,7 +67,7 @@ EXEEXT=@EXEEXT@
|
||||||
|
MKDIR_P=@MKDIR_P@
|
||||||
|
INSTALL_SSH_LDAP_HELPER=@INSTALL_SSH_LDAP_HELPER@
|
||||||
|
|
||||||
|
-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT) ssh-keycat$(EXEEXT)
|
||||||
|
+TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT) ssh-keycat$(EXEEXT) ctr-cavstest$(EXEEXT)
|
||||||
|
|
||||||
|
XMSS_OBJS=\
|
||||||
|
ssh-xmss.o \
|
||||||
|
@@ -194,6 +195,9 @@ ssh-ldap-helper$(EXEEXT): $(LIBCOMPAT) l
|
||||||
|
ssh-keycat$(EXEEXT): $(LIBCOMPAT) $(SSHDOBJS) libssh.a ssh-keycat.o uidswap.o
|
||||||
|
$(LD) -o $@ ssh-keycat.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(KEYCATLIBS) $(LIBS)
|
||||||
|
|
||||||
|
+ctr-cavstest$(EXEEXT): $(LIBCOMPAT) libssh.a ctr-cavstest.o
|
||||||
|
+ $(LD) -o $@ ctr-cavstest.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS)
|
||||||
|
+
|
||||||
|
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o
|
||||||
|
$(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
|
||||||
|
|
||||||
|
@@ -326,6 +330,7 @@ install-files:
|
||||||
|
$(INSTALL) -m 0700 ssh-ldap-wrapper $(DESTDIR)$(SSH_LDAP_WRAPPER) ; \
|
||||||
|
fi
|
||||||
|
$(INSTALL) -m 0755 $(STRIP_OPT) ssh-keycat$(EXEEXT) $(DESTDIR)$(libexecdir)/ssh-keycat$(EXEEXT)
|
||||||
|
+ $(INSTALL) -m 0755 $(STRIP_OPT) ctr-cavstest$(EXEEXT) $(DESTDIR)$(libexecdir)/ctr-cavstest$(EXEEXT)
|
||||||
|
$(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT)
|
||||||
|
$(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
|
||||||
|
$(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
|
||||||
|
diff -up openssh-6.8p1/ctr-cavstest.c.ctr-cavs openssh-6.8p1/ctr-cavstest.c
|
||||||
|
--- openssh-6.8p1/ctr-cavstest.c.ctr-cavs 2015-03-18 11:22:05.521288952 +0100
|
||||||
|
+++ openssh-6.8p1/ctr-cavstest.c 2015-03-18 11:22:05.521288952 +0100
|
||||||
|
@@ -0,0 +1,215 @@
|
||||||
|
+/*
|
||||||
|
+ *
|
||||||
|
+ * invocation (all of the following are equal):
|
||||||
|
+ * ./ctr-cavstest --algo aes128-ctr --key 987212980144b6a632e864031f52dacc --mode encrypt --data a6deca405eef2e8e4609abf3c3ccf4a6
|
||||||
|
+ * ./ctr-cavstest --algo aes128-ctr --key 987212980144b6a632e864031f52dacc --mode encrypt --data a6deca405eef2e8e4609abf3c3ccf4a6 --iv 00000000000000000000000000000000
|
||||||
|
+ * echo -n a6deca405eef2e8e4609abf3c3ccf4a6 | ./ctr-cavstest --algo aes128-ctr --key 987212980144b6a632e864031f52dacc --mode encrypt
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include "includes.h"
|
||||||
|
+
|
||||||
|
+#include <sys/types.h>
|
||||||
|
+#include <sys/param.h>
|
||||||
|
+#include <stdarg.h>
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+#include <ctype.h>
|
||||||
|
+
|
||||||
|
+#include "xmalloc.h"
|
||||||
|
+#include "log.h"
|
||||||
|
+#include "ssherr.h"
|
||||||
|
+#include "cipher.h"
|
||||||
|
+
|
||||||
|
+/* compatibility with old or broken OpenSSL versions */
|
||||||
|
+#include "openbsd-compat/openssl-compat.h"
|
||||||
|
+
|
||||||
|
+void usage(void) {
|
||||||
|
+ fprintf(stderr, "Usage: ctr-cavstest --algo <ssh-crypto-algorithm>\n"
|
||||||
|
+ " --key <hexadecimal-key> --mode <encrypt|decrypt>\n"
|
||||||
|
+ " [--iv <hexadecimal-iv>] --data <hexadecimal-data>\n\n"
|
||||||
|
+ "Hexadecimal output is printed to stdout.\n"
|
||||||
|
+ "Hexadecimal input data can be alternatively read from stdin.\n");
|
||||||
|
+ exit(1);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void *fromhex(char *hex, size_t *len)
|
||||||
|
+{
|
||||||
|
+ unsigned char *bin;
|
||||||
|
+ char *p;
|
||||||
|
+ size_t n = 0;
|
||||||
|
+ int shift = 4;
|
||||||
|
+ unsigned char out = 0;
|
||||||
|
+ unsigned char *optr;
|
||||||
|
+
|
||||||
|
+ bin = xmalloc(strlen(hex)/2);
|
||||||
|
+ optr = bin;
|
||||||
|
+
|
||||||
|
+ for (p = hex; *p != '\0'; ++p) {
|
||||||
|
+ unsigned char c;
|
||||||
|
+
|
||||||
|
+ c = *p;
|
||||||
|
+ if (isspace(c))
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ if (c >= '0' && c <= '9') {
|
||||||
|
+ c = c - '0';
|
||||||
|
+ } else if (c >= 'A' && c <= 'F') {
|
||||||
|
+ c = c - 'A' + 10;
|
||||||
|
+ } else if (c >= 'a' && c <= 'f') {
|
||||||
|
+ c = c - 'a' + 10;
|
||||||
|
+ } else {
|
||||||
|
+ /* truncate on nonhex cipher */
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ out |= c << shift;
|
||||||
|
+ shift = (shift + 4) % 8;
|
||||||
|
+
|
||||||
|
+ if (shift) {
|
||||||
|
+ *(optr++) = out;
|
||||||
|
+ out = 0;
|
||||||
|
+ ++n;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ *len = n;
|
||||||
|
+ return bin;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#define READ_CHUNK 4096
|
||||||
|
+#define MAX_READ_SIZE 1024*1024*100
|
||||||
|
+char *read_stdin(void)
|
||||||
|
+{
|
||||||
|
+ char *buf;
|
||||||
|
+ size_t n, total = 0;
|
||||||
|
+
|
||||||
|
+ buf = xmalloc(READ_CHUNK);
|
||||||
|
+
|
||||||
|
+ do {
|
||||||
|
+ n = fread(buf + total, 1, READ_CHUNK, stdin);
|
||||||
|
+ if (n < READ_CHUNK) /* terminate on short read */
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ total += n;
|
||||||
|
+ buf = xreallocarray(buf, total + READ_CHUNK, 1);
|
||||||
|
+ } while(total < MAX_READ_SIZE);
|
||||||
|
+ return buf;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int main (int argc, char *argv[])
|
||||||
|
+{
|
||||||
|
+
|
||||||
|
+ const struct sshcipher *c;
|
||||||
|
+ struct sshcipher_ctx *cc;
|
||||||
|
+ char *algo = "aes128-ctr";
|
||||||
|
+ char *hexkey = NULL;
|
||||||
|
+ char *hexiv = "00000000000000000000000000000000";
|
||||||
|
+ char *hexdata = NULL;
|
||||||
|
+ char *p;
|
||||||
|
+ int i, r;
|
||||||
|
+ int encrypt = 1;
|
||||||
|
+ void *key;
|
||||||
|
+ size_t keylen;
|
||||||
|
+ void *iv;
|
||||||
|
+ size_t ivlen;
|
||||||
|
+ void *data;
|
||||||
|
+ size_t datalen;
|
||||||
|
+ void *outdata;
|
||||||
|
+
|
||||||
|
+ for (i = 1; i < argc; ++i) {
|
||||||
|
+ if (strcmp(argv[i], "--algo") == 0) {
|
||||||
|
+ algo = argv[++i];
|
||||||
|
+ } else if (strcmp(argv[i], "--key") == 0) {
|
||||||
|
+ hexkey = argv[++i];
|
||||||
|
+ } else if (strcmp(argv[i], "--mode") == 0) {
|
||||||
|
+ ++i;
|
||||||
|
+ if (argv[i] == NULL) {
|
||||||
|
+ usage();
|
||||||
|
+ }
|
||||||
|
+ if (strncmp(argv[i], "enc", 3) == 0) {
|
||||||
|
+ encrypt = 1;
|
||||||
|
+ } else if (strncmp(argv[i], "dec", 3) == 0) {
|
||||||
|
+ encrypt = 0;
|
||||||
|
+ } else {
|
||||||
|
+ usage();
|
||||||
|
+ }
|
||||||
|
+ } else if (strcmp(argv[i], "--iv") == 0) {
|
||||||
|
+ hexiv = argv[++i];
|
||||||
|
+ } else if (strcmp(argv[i], "--data") == 0) {
|
||||||
|
+ hexdata = argv[++i];
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (hexkey == NULL || algo == NULL) {
|
||||||
|
+ usage();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ SSLeay_add_all_algorithms();
|
||||||
|
+
|
||||||
|
+ c = cipher_by_name(algo);
|
||||||
|
+ if (c == NULL) {
|
||||||
|
+ fprintf(stderr, "Error: unknown algorithm\n");
|
||||||
|
+ return 2;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (hexdata == NULL) {
|
||||||
|
+ hexdata = read_stdin();
|
||||||
|
+ } else {
|
||||||
|
+ hexdata = xstrdup(hexdata);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ key = fromhex(hexkey, &keylen);
|
||||||
|
+
|
||||||
|
+ if (keylen != 16 && keylen != 24 && keylen == 32) {
|
||||||
|
+ fprintf(stderr, "Error: unsupported key length\n");
|
||||||
|
+ return 2;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ iv = fromhex(hexiv, &ivlen);
|
||||||
|
+
|
||||||
|
+ if (ivlen != 16) {
|
||||||
|
+ fprintf(stderr, "Error: unsupported iv length\n");
|
||||||
|
+ return 2;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ data = fromhex(hexdata, &datalen);
|
||||||
|
+
|
||||||
|
+ if (data == NULL || datalen == 0) {
|
||||||
|
+ fprintf(stderr, "Error: no data to encrypt/decrypt\n");
|
||||||
|
+ return 2;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if ((r = cipher_init(&cc, c, key, keylen, iv, ivlen, encrypt)) != 0) {
|
||||||
|
+ fprintf(stderr, "Error: cipher_init failed: %s\n", ssh_err(r));
|
||||||
|
+ return 2;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ free(key);
|
||||||
|
+ free(iv);
|
||||||
|
+
|
||||||
|
+ outdata = malloc(datalen);
|
||||||
|
+ if(outdata == NULL) {
|
||||||
|
+ fprintf(stderr, "Error: memory allocation failure\n");
|
||||||
|
+ return 2;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if ((r = cipher_crypt(cc, 0, outdata, data, datalen, 0, 0)) != 0) {
|
||||||
|
+ fprintf(stderr, "Error: cipher_crypt failed: %s\n", ssh_err(r));
|
||||||
|
+ return 2;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ free(data);
|
||||||
|
+
|
||||||
|
+ cipher_free(cc);
|
||||||
|
+
|
||||||
|
+ for (p = outdata; datalen > 0; ++p, --datalen) {
|
||||||
|
+ printf("%02X", (unsigned char)*p);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ free(outdata);
|
||||||
|
+
|
||||||
|
+ printf("\n");
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
280
SOURCES/openssh-6.6p1-force_krb.patch
Normal file
280
SOURCES/openssh-6.6p1-force_krb.patch
Normal file
@ -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
|
||||||
|
+
|
||||||
|
if (forced != NULL) {
|
||||||
|
if (IS_INTERNAL_SFTP(command)) {
|
||||||
|
s->is_subsystem = s->is_subsystem ?
|
||||||
|
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.
|
485
SOURCES/openssh-6.6p1-keycat.patch
Normal file
485
SOURCES/openssh-6.6p1-keycat.patch
Normal file
@ -0,0 +1,485 @@
|
|||||||
|
diff -up openssh/auth.c.keycat openssh/misc.c
|
||||||
|
--- openssh/auth.c.keycat 2015-06-24 10:57:50.158849606 +0200
|
||||||
|
+++ openssh/auth.c 2015-06-24 11:04:23.989868638 +0200
|
||||||
|
@@ -966,6 +966,14 @@ subprocess(const char *tag, struct passw
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
+#ifdef WITH_SELINUX
|
||||||
|
+ if (sshd_selinux_setup_env_variables() < 0) {
|
||||||
|
+ error ("failed to copy environment: %s",
|
||||||
|
+ strerror(errno));
|
||||||
|
+ _exit(127);
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
execve(av[0], av, child_env);
|
||||||
|
error("%s exec \"%s\": %s", tag, command, strerror(errno));
|
||||||
|
_exit(127);
|
||||||
|
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
|
||||||
|
SSH_KEYSIGN=$(libexecdir)/ssh-keysign
|
||||||
|
SSH_LDAP_HELPER=$(libexecdir)/ssh-ldap-helper
|
||||||
|
SSH_LDAP_WRAPPER=$(libexecdir)/ssh-ldap-wrapper
|
||||||
|
+SSH_KEYCAT=$(libexecdir)/ssh-keycat
|
||||||
|
SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
|
||||||
|
PRIVSEP_PATH=@PRIVSEP_PATH@
|
||||||
|
SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@
|
||||||
|
@@ -52,6 +52,7 @@ K5LIBS=@K5LIBS@
|
||||||
|
GSSLIBS=@GSSLIBS@
|
||||||
|
SSHLIBS=@SSHLIBS@
|
||||||
|
SSHDLIBS=@SSHDLIBS@
|
||||||
|
+KEYCATLIBS=@KEYCATLIBS@
|
||||||
|
LIBEDIT=@LIBEDIT@
|
||||||
|
AR=@AR@
|
||||||
|
AWK=@AWK@
|
||||||
|
@@ -65,7 +66,7 @@ EXEEXT=@EXEEXT@
|
||||||
|
MKDIR_P=@MKDIR_P@
|
||||||
|
INSTALL_SSH_LDAP_HELPER=@INSTALL_SSH_LDAP_HELPER@
|
||||||
|
|
||||||
|
-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT)
|
||||||
|
+TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT) ssh-keycat$(EXEEXT)
|
||||||
|
|
||||||
|
XMSS_OBJS=\
|
||||||
|
ssh-xmss.o \
|
||||||
|
@@ -190,6 +191,9 @@ ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT)
|
||||||
|
ssh-ldap-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o
|
||||||
|
$(LD) -o $@ ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat -lfipscheck $(LIBS) $(LDAPLIBS)
|
||||||
|
|
||||||
|
+ssh-keycat$(EXEEXT): $(LIBCOMPAT) $(SSHDOBJS) libssh.a ssh-keycat.o uidswap.o
|
||||||
|
+ $(LD) -o $@ ssh-keycat.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(KEYCATLIBS) $(LIBS)
|
||||||
|
+
|
||||||
|
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o
|
||||||
|
$(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
|
||||||
|
|
||||||
|
@@ -321,6 +325,7 @@ install-files:
|
||||||
|
$(INSTALL) -m 0700 $(STRIP_OPT) ssh-ldap-helper $(DESTDIR)$(SSH_LDAP_HELPER) ; \
|
||||||
|
$(INSTALL) -m 0700 ssh-ldap-wrapper $(DESTDIR)$(SSH_LDAP_WRAPPER) ; \
|
||||||
|
fi
|
||||||
|
+ $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keycat$(EXEEXT) $(DESTDIR)$(libexecdir)/ssh-keycat$(EXEEXT)
|
||||||
|
$(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT)
|
||||||
|
$(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
|
||||||
|
$(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
|
||||||
|
diff -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 int inetd_flag;
|
||||||
|
extern int rexeced_flag;
|
||||||
|
|
||||||
|
+/* Wrapper around is_selinux_enabled() to log its return value once only */
|
||||||
|
+int
|
||||||
|
+sshd_selinux_enabled(void)
|
||||||
|
+{
|
||||||
|
+ static int enabled = -1;
|
||||||
|
+
|
||||||
|
+ if (enabled == -1) {
|
||||||
|
+ enabled = (is_selinux_enabled() == 1);
|
||||||
|
+ debug("SELinux support %s", enabled ? "enabled" : "disabled");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return (enabled);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Send audit message */
|
||||||
|
static int
|
||||||
|
sshd_selinux_send_audit_message(int success, security_context_t default_context,
|
||||||
|
@@ -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 && !rexeced_flag) {
|
||||||
|
use_current = "1";
|
||||||
|
} else {
|
||||||
|
use_current = "";
|
||||||
|
- rv = rv || do_pam_putenv("SELINUX_LEVEL_REQUESTED", reqlvl ? reqlvl: "");
|
||||||
|
+ rv = rv || set_it("SELINUX_LEVEL_REQUESTED", reqlvl ? reqlvl: "");
|
||||||
|
}
|
||||||
|
|
||||||
|
- rv = rv || do_pam_putenv("SELINUX_USE_CURRENT_RANGE", use_current);
|
||||||
|
+ rv = rv || set_it("SELINUX_USE_CURRENT_RANGE", use_current);
|
||||||
|
|
||||||
|
if (role != NULL)
|
||||||
|
free(role);
|
||||||
|
@@ -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],
|
||||||
|
)
|
||||||
|
AC_SUBST([SSHLIBS])
|
||||||
|
AC_SUBST([SSHDLIBS])
|
||||||
|
+AC_SUBST([KEYCATLIBS])
|
||||||
|
|
||||||
|
# Check whether user wants Kerberos 5 support
|
||||||
|
KRB5_MSG="no"
|
||||||
|
@@ -5031,6 +5034,9 @@ fi
|
||||||
|
if test ! -z "${SSHLIBS}"; then
|
||||||
|
echo " +for ssh: ${SSHLIBS}"
|
||||||
|
fi
|
||||||
|
+if test ! -z "${KEYCATLIBS}"; then
|
||||||
|
+echo " +for ssh-keycat: ${KEYCATLIBS}"
|
||||||
|
+fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
26
SOURCES/openssh-6.6p1-keyperm.patch
Normal file
26
SOURCES/openssh-6.6p1-keyperm.patch
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
diff --git a/authfile.c b/authfile.c
|
||||||
|
index e93d867..4fc5b3d 100644
|
||||||
|
--- a/authfile.c
|
||||||
|
+++ b/authfile.c
|
||||||
|
@@ -32,6 +32,7 @@
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
+#include <grp.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
@@ -207,6 +208,13 @@ sshkey_perm_ok(int fd, const char *filename)
|
||||||
|
#ifdef HAVE_CYGWIN
|
||||||
|
if (check_ntsec(filename))
|
||||||
|
#endif
|
||||||
|
+ if (st.st_mode & 040) {
|
||||||
|
+ struct group *gr;
|
||||||
|
+
|
||||||
|
+ if ((gr = getgrnam("ssh_keys")) && (st.st_gid == gr->gr_gid))
|
||||||
|
+ st.st_mode &= ~040;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0) {
|
||||||
|
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
||||||
|
error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @");
|
289
SOURCES/openssh-6.6p1-kuserok.patch
Normal file
289
SOURCES/openssh-6.6p1-kuserok.patch
Normal file
@ -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 (ssh_krb5_kuserok(krb_context, princ, name, k5login_exists)
|
||||||
|
+ && 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_cleanup_creds = -1;
|
||||||
|
options->gss_strict_acceptor = -1;
|
||||||
|
options->gss_store_rekey = -1;
|
||||||
|
+ options->use_kuserok = -1;
|
||||||
|
options->password_authentication = -1;
|
||||||
|
options->kbd_interactive_authentication = -1;
|
||||||
|
options->challenge_response_authentication = -1;
|
||||||
|
@@ -278,6 +279,8 @@ fill_default_server_options(ServerOption
|
||||||
|
options->gss_strict_acceptor = 1;
|
||||||
|
if (options->gss_store_rekey == -1)
|
||||||
|
options->gss_store_rekey = 0;
|
||||||
|
+ 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 {
|
||||||
|
sPermitRootLogin, sLogFacility, sLogLevel,
|
||||||
|
sRhostsRSAAuthentication, sRSAAuthentication,
|
||||||
|
sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
|
||||||
|
- sKerberosGetAFSToken, sKerberosUniqueCCache,
|
||||||
|
+ sKerberosGetAFSToken, sKerberosUniqueCCache, sKerberosUseKuserok,
|
||||||
|
sChallengeResponseAuthentication,
|
||||||
|
sPasswordAuthentication, sKbdInteractiveAuthentication,
|
||||||
|
sListenAddress, sAddressFamily,
|
||||||
|
@@ -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
|
||||||
|
*activep = value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
+ case sKerberosUseKuserok:
|
||||||
|
+ intptr = &options->use_kuserok;
|
||||||
|
+ goto parse_flag;
|
||||||
|
+
|
||||||
|
case sPermitListen:
|
||||||
|
case sPermitOpen:
|
||||||
|
if (opcode == sPermitListen) {
|
||||||
|
@@ -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 available KEX (Key Exchange) algorithms.
|
||||||
|
Multiple algorithms must be comma-separated.
|
||||||
|
@@ -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 yes
|
121
SOURCES/openssh-6.6p1-privsep-selinux.patch
Normal file
121
SOURCES/openssh-6.6p1-privsep-selinux.patch
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
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("%s: done", __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
+void
|
||||||
|
+sshd_selinux_copy_context(void)
|
||||||
|
+{
|
||||||
|
+ security_context_t *ctx;
|
||||||
|
+
|
||||||
|
+ if (!ssh_selinux_enabled())
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ if (getexeccon((security_context_t *)&ctx) != 0) {
|
||||||
|
+ logit("%s: getcon failed with %s", __func__, strerror (errno));
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ if (ctx != NULL) {
|
||||||
|
+ /* unset exec context before we will lose this capabililty */
|
||||||
|
+ if (setexeccon(NULL) != 0)
|
||||||
|
+ fatal("%s: setexeccon failed with %s", __func__, strerror (errno));
|
||||||
|
+ if (setcon(ctx) != 0)
|
||||||
|
+ fatal("%s: setcon failed with %s", __func__, 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 || !use_privsep)) {
|
||||||
|
#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.c.privsep-selinux 2016-12-23 18:58:52.973122201 +0100
|
||||||
|
+++ openssh-7.4p1/sshd.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 */
|
||||||
|
@@ -633,6 +637,9 @@ privsep_postauth(Authctxt *authctxt)
|
||||||
|
{
|
||||||
|
#ifdef DISABLE_FD_PASSING
|
||||||
|
if (1) {
|
||||||
|
+#elif defined(WITH_SELINUX)
|
||||||
|
+ if (0) {
|
||||||
|
+ /* even root user can be confined by SELinux */
|
||||||
|
#else
|
||||||
|
if (authctxt->pw->pw_uid == 0) {
|
||||||
|
#endif
|
185
SOURCES/openssh-6.7p1-coverity.patch
Normal file
185
SOURCES/openssh-6.7p1-coverity.patch
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
diff -up openssh-7.4p1/channels.c.coverity openssh-7.4p1/channels.c
|
||||||
|
--- openssh-7.4p1/channels.c.coverity 2016-12-23 16:40:26.881788686 +0100
|
||||||
|
+++ openssh-7.4p1/channels.c 2016-12-23 16:42:36.244818763 +0100
|
||||||
|
@@ -288,11 +288,11 @@ channel_register_fds(Channel *c, int rfd
|
||||||
|
|
||||||
|
/* enable nonblocking mode */
|
||||||
|
if (nonblock) {
|
||||||
|
- if (rfd != -1)
|
||||||
|
+ if (rfd >= 0)
|
||||||
|
set_nonblock(rfd);
|
||||||
|
- if (wfd != -1)
|
||||||
|
+ if (wfd >= 0)
|
||||||
|
set_nonblock(wfd);
|
||||||
|
- if (efd != -1)
|
||||||
|
+ if (efd >= 0)
|
||||||
|
set_nonblock(efd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
diff -up openssh-7.4p1/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(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)
|
||||||
|
diff -up openssh-7.4p1/monitor_wrap.c.coverity openssh-7.4p1/monitor_wrap.c
|
||||||
|
--- openssh-7.4p1/monitor_wrap.c.coverity 2016-12-23 16:40:26.892788689 +0100
|
||||||
|
+++ openssh-7.4p1/monitor_wrap.c 2016-12-23 16:40:26.900788691 +0100
|
||||||
|
@@ -525,10 +525,10 @@ mm_pty_allocate(int *ptyfd, int *ttyfd,
|
||||||
|
if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 ||
|
||||||
|
(tmp2 = dup(pmonitor->m_recvfd)) == -1) {
|
||||||
|
error("%s: cannot allocate fds for pty", __func__);
|
||||||
|
- if (tmp1 > 0)
|
||||||
|
+ if (tmp1 >= 0)
|
||||||
|
close(tmp1);
|
||||||
|
- if (tmp2 > 0)
|
||||||
|
- close(tmp2);
|
||||||
|
+ /*DEAD CODE if (tmp2 >= 0)
|
||||||
|
+ close(tmp2);*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
close(tmp1);
|
||||||
|
diff -up openssh-7.4p1/openbsd-compat/bindresvport.c.coverity openssh-7.4p1/openbsd-compat/bindresvport.c
|
||||||
|
--- openssh-7.4p1/openbsd-compat/bindresvport.c.coverity 2016-12-19 05:59:41.000000000 +0100
|
||||||
|
+++ openssh-7.4p1/openbsd-compat/bindresvport.c 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-7.4p1/scp.c.coverity openssh-7.4p1/scp.c
|
||||||
|
--- openssh-7.4p1/scp.c.coverity 2016-12-23 16:40:26.856788681 +0100
|
||||||
|
+++ openssh-7.4p1/scp.c 2016-12-23 16:40:26.901788691 +0100
|
||||||
|
@@ -157,7 +157,7 @@ killchild(int signo)
|
||||||
|
{
|
||||||
|
if (do_cmd_pid > 1) {
|
||||||
|
kill(do_cmd_pid, signo ? signo : SIGTERM);
|
||||||
|
- waitpid(do_cmd_pid, NULL, 0);
|
||||||
|
+ (void) waitpid(do_cmd_pid, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signo)
|
||||||
|
diff -up openssh-7.4p1/servconf.c.coverity openssh-7.4p1/servconf.c
|
||||||
|
--- openssh-7.4p1/servconf.c.coverity 2016-12-23 16:40:26.896788690 +0100
|
||||||
|
+++ openssh-7.4p1/servconf.c 2016-12-23 16:40:26.901788691 +0100
|
||||||
|
@@ -1547,7 +1547,7 @@ process_server_config_line(ServerOptions
|
||||||
|
fatal("%s line %d: Missing subsystem name.",
|
||||||
|
filename, linenum);
|
||||||
|
if (!*activep) {
|
||||||
|
- arg = strdelim(&cp);
|
||||||
|
+ /*arg =*/ (void) strdelim(&cp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (i = 0; i < options->num_subsystems; i++)
|
||||||
|
@@ -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-7.4p1/serverloop.c.coverity openssh-7.4p1/serverloop.c
|
||||||
|
--- openssh-7.4p1/serverloop.c.coverity 2016-12-19 05:59:41.000000000 +0100
|
||||||
|
+++ openssh-7.4p1/serverloop.c 2016-12-23 16:40:26.902788691 +0100
|
||||||
|
@@ -125,13 +125,13 @@ notify_setup(void)
|
||||||
|
static void
|
||||||
|
notify_parent(void)
|
||||||
|
{
|
||||||
|
- if (notify_pipe[1] != -1)
|
||||||
|
+ if (notify_pipe[1] >= 0)
|
||||||
|
(void)write(notify_pipe[1], "", 1);
|
||||||
|
}
|
||||||
|
static void
|
||||||
|
notify_prepare(fd_set *readset)
|
||||||
|
{
|
||||||
|
- if (notify_pipe[0] != -1)
|
||||||
|
+ if (notify_pipe[0] >= 0)
|
||||||
|
FD_SET(notify_pipe[0], readset);
|
||||||
|
}
|
||||||
|
static void
|
||||||
|
@@ -139,8 +139,8 @@ notify_done(fd_set *readset)
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
|
||||||
|
- if (notify_pipe[0] != -1 && FD_ISSET(notify_pipe[0], readset))
|
||||||
|
- while (read(notify_pipe[0], &c, 1) != -1)
|
||||||
|
+ if (notify_pipe[0] >= 0 && FD_ISSET(notify_pipe[0], readset))
|
||||||
|
+ while (read(notify_pipe[0], &c, 1) >= 0)
|
||||||
|
debug2("%s: reading", __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -518,7 +518,7 @@ server_request_tun(void)
|
||||||
|
}
|
||||||
|
|
||||||
|
tun = packet_get_int();
|
||||||
|
- if (auth_opts->force_tun_device != -1) {
|
||||||
|
+ if (auth_opts->force_tun_device >= 0) {
|
||||||
|
if (tun != SSH_TUNID_ANY && auth_opts->force_tun_device != tun)
|
||||||
|
goto done;
|
||||||
|
tun = auth_opts->force_tun_device;
|
||||||
|
diff -up openssh-7.4p1/sftp.c.coverity openssh-7.4p1/sftp.c
|
||||||
|
--- openssh-7.4p1/sftp.c.coverity 2016-12-19 05:59:41.000000000 +0100
|
||||||
|
+++ openssh-7.4p1/sftp.c 2016-12-23 16:40:26.903788691 +0100
|
||||||
|
@@ -224,7 +224,7 @@ killchild(int signo)
|
||||||
|
{
|
||||||
|
if (sshpid > 1) {
|
||||||
|
kill(sshpid, SIGTERM);
|
||||||
|
- waitpid(sshpid, NULL, 0);
|
||||||
|
+ (void) waitpid(sshpid, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
_exit(1);
|
||||||
|
diff -up openssh-7.4p1/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
|
||||||
|
@@ -1220,8 +1220,8 @@ main(int ac, char **av)
|
||||||
|
sanitise_stdfd();
|
||||||
|
|
||||||
|
/* drop */
|
||||||
|
- setegid(getgid());
|
||||||
|
- setgid(getgid());
|
||||||
|
+ (void) setegid(getgid());
|
||||||
|
+ (void) setgid(getgid());
|
||||||
|
|
||||||
|
platform_disable_tracing(0); /* strict=no */
|
||||||
|
|
||||||
|
diff -up openssh-7.4p1/sshd.c.coverity openssh-7.4p1/sshd.c
|
||||||
|
--- openssh-7.4p1/sshd.c.coverity 2016-12-23 16:40:26.897788690 +0100
|
||||||
|
+++ openssh-7.4p1/sshd.c 2016-12-23 16:40:26.904788692 +0100
|
||||||
|
@@ -691,8 +691,10 @@ privsep_preauth(Authctxt *authctxt)
|
||||||
|
|
||||||
|
privsep_preauth_child();
|
||||||
|
setproctitle("%s", "[net]");
|
||||||
|
- if (box != NULL)
|
||||||
|
+ if (box != NULL) {
|
||||||
|
ssh_sandbox_child(box);
|
||||||
|
+ free(box);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@@ -1386,6 +1388,9 @@ server_accept_loop(int *sock_in, int *so
|
||||||
|
if (num_listen_socks < 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ if (fdset != NULL)
|
||||||
|
+ free(fdset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
608
SOURCES/openssh-6.7p1-kdf-cavs.patch
Normal file
608
SOURCES/openssh-6.7p1-kdf-cavs.patch
Normal file
@ -0,0 +1,608 @@
|
|||||||
|
diff -up openssh-6.8p1/Makefile.in.kdf-cavs openssh-6.8p1/Makefile.in
|
||||||
|
--- openssh-6.8p1/Makefile.in.kdf-cavs 2015-03-18 11:23:46.346049359 +0100
|
||||||
|
+++ openssh-6.8p1/Makefile.in 2015-03-18 11:24:20.395968445 +0100
|
||||||
|
@@ -29,6 +29,7 @@ SSH_LDAP_HELPER=$(libexecdir)/ssh-ldap-h
|
||||||
|
SSH_LDAP_WRAPPER=$(libexecdir)/ssh-ldap-wrapper
|
||||||
|
SSH_KEYCAT=$(libexecdir)/ssh-keycat
|
||||||
|
CTR_CAVSTEST=$(libexecdir)/ctr-cavstest
|
||||||
|
+SSH_CAVS=$(libexecdir)/ssh-cavs
|
||||||
|
SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
|
||||||
|
PRIVSEP_PATH=@PRIVSEP_PATH@
|
||||||
|
SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@
|
||||||
|
@@ -67,7 +68,7 @@ EXEEXT=@EXEEXT@
|
||||||
|
MKDIR_P=@MKDIR_P@
|
||||||
|
INSTALL_SSH_LDAP_HELPER=@INSTALL_SSH_LDAP_HELPER@
|
||||||
|
|
||||||
|
-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT) ssh-keycat$(EXEEXT) ctr-cavstest$(EXEEXT)
|
||||||
|
+TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT) ssh-keycat$(EXEEXT) ctr-cavstest$(EXEEXT) ssh-cavs$(EXEEXT)
|
||||||
|
|
||||||
|
XMSS_OBJS=\
|
||||||
|
ssh-xmss.o \
|
||||||
|
@@ -198,6 +199,9 @@ ssh-keycat$(EXEEXT): $(LIBCOMPAT) $(SSHD
|
||||||
|
ctr-cavstest$(EXEEXT): $(LIBCOMPAT) libssh.a ctr-cavstest.o
|
||||||
|
$(LD) -o $@ ctr-cavstest.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS)
|
||||||
|
|
||||||
|
+ssh-cavs$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-cavs.o
|
||||||
|
+ $(LD) -o $@ ssh-cavs.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
|
||||||
|
+
|
||||||
|
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o
|
||||||
|
$(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
|
||||||
|
|
||||||
|
@@ -331,6 +335,8 @@ install-files:
|
||||||
|
fi
|
||||||
|
$(INSTALL) -m 0755 $(STRIP_OPT) ssh-keycat$(EXEEXT) $(DESTDIR)$(libexecdir)/ssh-keycat$(EXEEXT)
|
||||||
|
$(INSTALL) -m 0755 $(STRIP_OPT) ctr-cavstest$(EXEEXT) $(DESTDIR)$(libexecdir)/ctr-cavstest$(EXEEXT)
|
||||||
|
+ $(INSTALL) -m 0755 $(STRIP_OPT) ssh-cavs$(EXEEXT) $(DESTDIR)$(libexecdir)/ssh-cavs$(EXEEXT)
|
||||||
|
+ $(INSTALL) -m 0755 $(STRIP_OPT) ssh-cavs_driver.pl $(DESTDIR)$(libexecdir)/ssh-cavs_driver.pl
|
||||||
|
$(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT)
|
||||||
|
$(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
|
||||||
|
$(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
|
||||||
|
diff -up openssh-6.8p1/ssh-cavs.c.kdf-cavs openssh-6.8p1/ssh-cavs.c
|
||||||
|
--- openssh-6.8p1/ssh-cavs.c.kdf-cavs 2015-03-18 11:23:46.348049354 +0100
|
||||||
|
+++ openssh-6.8p1/ssh-cavs.c 2015-03-18 11:23:46.348049354 +0100
|
||||||
|
@@ -0,0 +1,377 @@
|
||||||
|
+/*
|
||||||
|
+ * Copyright (C) 2015, Stephan Mueller <smueller@chronox.de>
|
||||||
|
+ *
|
||||||
|
+ * Redistribution and use in source and binary forms, with or without
|
||||||
|
+ * modification, are permitted provided that the following conditions
|
||||||
|
+ * are met:
|
||||||
|
+ * 1. Redistributions of source code must retain the above copyright
|
||||||
|
+ * notice, and the entire permission notice in its entirety,
|
||||||
|
+ * including the disclaimer of warranties.
|
||||||
|
+ * 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
+ * notice, this list of conditions and the following disclaimer in the
|
||||||
|
+ * documentation and/or other materials provided with the distribution.
|
||||||
|
+ * 3. The name of the author may not be used to endorse or promote
|
||||||
|
+ * products derived from this software without specific prior
|
||||||
|
+ * written permission.
|
||||||
|
+ *
|
||||||
|
+ * ALTERNATIVELY, this product may be distributed under the terms of
|
||||||
|
+ * the GNU General Public License, in which case the provisions of the GPL2
|
||||||
|
+ * are required INSTEAD OF the above restrictions. (This clause is
|
||||||
|
+ * necessary due to a potential bad interaction between the GPL and
|
||||||
|
+ * the restrictions contained in a BSD-style copyright.)
|
||||||
|
+ *
|
||||||
|
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
|
||||||
|
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
|
||||||
|
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
|
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||||
|
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
+ * DAMAGE.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include "includes.h"
|
||||||
|
+
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <errno.h>
|
||||||
|
+#include <sys/types.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+
|
||||||
|
+#include <openssl/bn.h>
|
||||||
|
+
|
||||||
|
+#include "xmalloc.h"
|
||||||
|
+#include "sshbuf.h"
|
||||||
|
+#include "sshkey.h"
|
||||||
|
+#include "cipher.h"
|
||||||
|
+#include "kex.h"
|
||||||
|
+#include "packet.h"
|
||||||
|
+#include "digest.h"
|
||||||
|
+
|
||||||
|
+static int bin_char(unsigned char hex)
|
||||||
|
+{
|
||||||
|
+ if (48 <= hex && 57 >= hex)
|
||||||
|
+ return (hex - 48);
|
||||||
|
+ if (65 <= hex && 70 >= hex)
|
||||||
|
+ return (hex - 55);
|
||||||
|
+ if (97 <= hex && 102 >= hex)
|
||||||
|
+ return (hex - 87);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Convert hex representation into binary string
|
||||||
|
+ * @hex input buffer with hex representation
|
||||||
|
+ * @hexlen length of hex
|
||||||
|
+ * @bin output buffer with binary data
|
||||||
|
+ * @binlen length of already allocated bin buffer (should be at least
|
||||||
|
+ * half of hexlen -- if not, only a fraction of hexlen is converted)
|
||||||
|
+ */
|
||||||
|
+static void hex2bin(const char *hex, size_t hexlen,
|
||||||
|
+ unsigned char *bin, size_t binlen)
|
||||||
|
+{
|
||||||
|
+ size_t i = 0;
|
||||||
|
+ size_t chars = (binlen > (hexlen / 2)) ? (hexlen / 2) : binlen;
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < chars; i++) {
|
||||||
|
+ bin[i] = bin_char(hex[(i*2)]) << 4;
|
||||||
|
+ bin[i] |= bin_char(hex[((i*2)+1)]);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Allocate sufficient space for binary representation of hex
|
||||||
|
+ * and convert hex into bin
|
||||||
|
+ *
|
||||||
|
+ * Caller must free bin
|
||||||
|
+ * @hex input buffer with hex representation
|
||||||
|
+ * @hexlen length of hex
|
||||||
|
+ * @bin return value holding the pointer to the newly allocated buffer
|
||||||
|
+ * @binlen return value holding the allocated size of bin
|
||||||
|
+ *
|
||||||
|
+ * return: 0 on success, !0 otherwise
|
||||||
|
+ */
|
||||||
|
+static int hex2bin_alloc(const char *hex, size_t hexlen,
|
||||||
|
+ unsigned char **bin, size_t *binlen)
|
||||||
|
+{
|
||||||
|
+ unsigned char *out = NULL;
|
||||||
|
+ size_t outlen = 0;
|
||||||
|
+
|
||||||
|
+ if (!hexlen)
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ outlen = (hexlen + 1) / 2;
|
||||||
|
+
|
||||||
|
+ out = calloc(1, outlen);
|
||||||
|
+ if (!out)
|
||||||
|
+ return -errno;
|
||||||
|
+
|
||||||
|
+ hex2bin(hex, hexlen, out, outlen);
|
||||||
|
+ *bin = out;
|
||||||
|
+ *binlen = outlen;
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static char hex_char_map_l[] = { '0', '1', '2', '3', '4', '5', '6', '7',
|
||||||
|
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
|
||||||
|
+static char hex_char_map_u[] = { '0', '1', '2', '3', '4', '5', '6', '7',
|
||||||
|
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||||
|
+static char hex_char(unsigned int bin, int u)
|
||||||
|
+{
|
||||||
|
+ if (bin < sizeof(hex_char_map_l))
|
||||||
|
+ return (u) ? hex_char_map_u[bin] : hex_char_map_l[bin];
|
||||||
|
+ return 'X';
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Convert binary string into hex representation
|
||||||
|
+ * @bin input buffer with binary data
|
||||||
|
+ * @binlen length of bin
|
||||||
|
+ * @hex output buffer to store hex data
|
||||||
|
+ * @hexlen length of already allocated hex buffer (should be at least
|
||||||
|
+ * twice binlen -- if not, only a fraction of binlen is converted)
|
||||||
|
+ * @u case of hex characters (0=>lower case, 1=>upper case)
|
||||||
|
+ */
|
||||||
|
+static void bin2hex(const unsigned char *bin, size_t binlen,
|
||||||
|
+ char *hex, size_t hexlen, int u)
|
||||||
|
+{
|
||||||
|
+ size_t i = 0;
|
||||||
|
+ size_t chars = (binlen > (hexlen / 2)) ? (hexlen / 2) : binlen;
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < chars; i++) {
|
||||||
|
+ hex[(i*2)] = hex_char((bin[i] >> 4), u);
|
||||||
|
+ hex[((i*2)+1)] = hex_char((bin[i] & 0x0f), u);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+struct kdf_cavs {
|
||||||
|
+ unsigned char *K;
|
||||||
|
+ size_t Klen;
|
||||||
|
+ unsigned char *H;
|
||||||
|
+ size_t Hlen;
|
||||||
|
+ unsigned char *session_id;
|
||||||
|
+ size_t session_id_len;
|
||||||
|
+
|
||||||
|
+ unsigned int iv_len;
|
||||||
|
+ unsigned int ek_len;
|
||||||
|
+ unsigned int ik_len;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int sshkdf_cavs(struct kdf_cavs *test)
|
||||||
|
+{
|
||||||
|
+ int ret = 0;
|
||||||
|
+ struct kex kex;
|
||||||
|
+ BIGNUM *Kbn = NULL;
|
||||||
|
+ int mode = 0;
|
||||||
|
+ struct newkeys *ctoskeys;
|
||||||
|
+ struct newkeys *stockeys;
|
||||||
|
+ struct ssh *ssh = NULL;
|
||||||
|
+
|
||||||
|
+#define HEXOUTLEN 500
|
||||||
|
+ char hex[HEXOUTLEN];
|
||||||
|
+
|
||||||
|
+ memset(&kex, 0, sizeof(struct kex));
|
||||||
|
+
|
||||||
|
+ Kbn = BN_new();
|
||||||
|
+ BN_bin2bn(test->K, test->Klen, Kbn);
|
||||||
|
+ if (!Kbn) {
|
||||||
|
+ printf("cannot convert K into BIGNUM\n");
|
||||||
|
+ ret = 1;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ kex.session_id = test->session_id;
|
||||||
|
+ kex.session_id_len = test->session_id_len;
|
||||||
|
+
|
||||||
|
+ /* setup kex */
|
||||||
|
+
|
||||||
|
+ /* select the right hash based on struct ssh_digest digests */
|
||||||
|
+ switch (test->ik_len) {
|
||||||
|
+ case 20:
|
||||||
|
+ kex.hash_alg = SSH_DIGEST_SHA1;
|
||||||
|
+ break;
|
||||||
|
+ case 32:
|
||||||
|
+ kex.hash_alg = SSH_DIGEST_SHA256;
|
||||||
|
+ break;
|
||||||
|
+ case 48:
|
||||||
|
+ kex.hash_alg = SSH_DIGEST_SHA384;
|
||||||
|
+ break;
|
||||||
|
+ case 64:
|
||||||
|
+ kex.hash_alg = SSH_DIGEST_SHA512;
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ printf("Wrong hash type %u\n", test->ik_len);
|
||||||
|
+ ret = 1;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* implement choose_enc */
|
||||||
|
+ for (mode = 0; mode < 2; mode++) {
|
||||||
|
+ kex.newkeys[mode] = calloc(1, sizeof(struct newkeys));
|
||||||
|
+ if (!kex.newkeys[mode]) {
|
||||||
|
+ printf("allocation of newkeys failed\n");
|
||||||
|
+ ret = 1;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ kex.newkeys[mode]->enc.iv_len = test->iv_len;
|
||||||
|
+ kex.newkeys[mode]->enc.key_len = test->ek_len;
|
||||||
|
+ kex.newkeys[mode]->enc.block_size = (test->iv_len == 64) ? 8 : 16;
|
||||||
|
+ kex.newkeys[mode]->mac.key_len = test->ik_len;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* implement kex_choose_conf */
|
||||||
|
+ kex.we_need = kex.newkeys[0]->enc.key_len;
|
||||||
|
+ if (kex.we_need < kex.newkeys[0]->enc.block_size)
|
||||||
|
+ kex.we_need = kex.newkeys[0]->enc.block_size;
|
||||||
|
+ if (kex.we_need < kex.newkeys[0]->enc.iv_len)
|
||||||
|
+ kex.we_need = kex.newkeys[0]->enc.iv_len;
|
||||||
|
+ if (kex.we_need < kex.newkeys[0]->mac.key_len)
|
||||||
|
+ kex.we_need = kex.newkeys[0]->mac.key_len;
|
||||||
|
+
|
||||||
|
+ /* MODE_OUT (1) -> server to client
|
||||||
|
+ * MODE_IN (0) -> client to server */
|
||||||
|
+ kex.server = 1;
|
||||||
|
+
|
||||||
|
+ /* do it */
|
||||||
|
+ if ((ssh = ssh_packet_set_connection(NULL, -1, -1)) == NULL){
|
||||||
|
+ printf("Allocation error\n");
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ ssh->kex = &kex;
|
||||||
|
+ kex_derive_keys_bn(ssh, test->H, test->Hlen, Kbn);
|
||||||
|
+
|
||||||
|
+ ctoskeys = kex.newkeys[0];
|
||||||
|
+ stockeys = kex.newkeys[1];
|
||||||
|
+
|
||||||
|
+ /* get data */
|
||||||
|
+ memset(hex, 0, HEXOUTLEN);
|
||||||
|
+ bin2hex(ctoskeys->enc.iv, (size_t)ctoskeys->enc.iv_len,
|
||||||
|
+ hex, HEXOUTLEN, 0);
|
||||||
|
+ printf("Initial IV (client to server) = %s\n", hex);
|
||||||
|
+ memset(hex, 0, HEXOUTLEN);
|
||||||
|
+ bin2hex(stockeys->enc.iv, (size_t)stockeys->enc.iv_len,
|
||||||
|
+ hex, HEXOUTLEN, 0);
|
||||||
|
+ printf("Initial IV (server to client) = %s\n", hex);
|
||||||
|
+
|
||||||
|
+ memset(hex, 0, HEXOUTLEN);
|
||||||
|
+ bin2hex(ctoskeys->enc.key, (size_t)ctoskeys->enc.key_len,
|
||||||
|
+ hex, HEXOUTLEN, 0);
|
||||||
|
+ printf("Encryption key (client to server) = %s\n", hex);
|
||||||
|
+ memset(hex, 0, HEXOUTLEN);
|
||||||
|
+ bin2hex(stockeys->enc.key, (size_t)stockeys->enc.key_len,
|
||||||
|
+ hex, HEXOUTLEN, 0);
|
||||||
|
+ printf("Encryption key (server to client) = %s\n", hex);
|
||||||
|
+
|
||||||
|
+ memset(hex, 0, HEXOUTLEN);
|
||||||
|
+ bin2hex(ctoskeys->mac.key, (size_t)ctoskeys->mac.key_len,
|
||||||
|
+ hex, HEXOUTLEN, 0);
|
||||||
|
+ printf("Integrity key (client to server) = %s\n", hex);
|
||||||
|
+ memset(hex, 0, HEXOUTLEN);
|
||||||
|
+ bin2hex(stockeys->mac.key, (size_t)stockeys->mac.key_len,
|
||||||
|
+ hex, HEXOUTLEN, 0);
|
||||||
|
+ printf("Integrity key (server to client) = %s\n", hex);
|
||||||
|
+
|
||||||
|
+out:
|
||||||
|
+ if (Kbn)
|
||||||
|
+ BN_free(Kbn);
|
||||||
|
+ if (ssh)
|
||||||
|
+ ssh_packet_close(ssh);
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void usage(void)
|
||||||
|
+{
|
||||||
|
+ fprintf(stderr, "\nOpenSSH KDF CAVS Test\n\n");
|
||||||
|
+ fprintf(stderr, "Usage:\n");
|
||||||
|
+ fprintf(stderr, "\t-K\tShared secret string\n");
|
||||||
|
+ fprintf(stderr, "\t-H\tHash string\n");
|
||||||
|
+ fprintf(stderr, "\t-s\tSession ID string\n");
|
||||||
|
+ fprintf(stderr, "\t-i\tIV length to be generated\n");
|
||||||
|
+ fprintf(stderr, "\t-e\tEncryption key length to be generated\n");
|
||||||
|
+ fprintf(stderr, "\t-m\tMAC key length to be generated\n");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Test command example:
|
||||||
|
+ * ./ssh-cavs -K 0055d50f2d163cc07cd8a93cc7c3430c30ce786b572c01ad29fec7597000cf8618d664e2ec3dcbc8bb7a1a7eb7ef67f61cdaf291625da879186ac0a5cb27af571b59612d6a6e0627344d846271959fda61c78354aa498773d59762f8ca2d0215ec590d8633de921f920d41e47b3de6ab9a3d0869e1c826d0e4adebf8e3fb646a15dea20a410b44e969f4b791ed6a67f13f1b74234004d5fa5e87eff7abc32d49bbdf44d7b0107e8f10609233b7e2b7eff74a4daf25641de7553975dac6ac1e5117df6f6dbaa1c263d23a6c3e5a3d7d49ae8a828c1e333ac3f85fbbf57b5c1a45be45e43a7be1a4707eac779b8285522d1f531fe23f890fd38a004339932b93eda4 -H d3ab91a850febb417a25d892ec48ed5952c7a5de -s d3ab91a850febb417a25d892ec48ed5952c7a5de -i 8 -e 24 -m 20
|
||||||
|
+ *
|
||||||
|
+ * Initial IV (client to server) = 4bb320d1679dfd3a
|
||||||
|
+ * Initial IV (server to client) = 43dea6fdf263a308
|
||||||
|
+ * Encryption key (client to server) = 13048cc600b9d3cf9095aa6cf8e2ff9cf1c54ca0520c89ed
|
||||||
|
+ * Encryption key (server to client) = 1e483c5134e901aa11fc4e0a524e7ec7b75556148a222bb0
|
||||||
|
+ * Integrity key (client to server) = ecef63a092b0dcc585bdc757e01b2740af57d640
|
||||||
|
+ * Integrity key (server to client) = 7424b05f3c44a72b4ebd281fb71f9cbe7b64d479
|
||||||
|
+ */
|
||||||
|
+int main(int argc, char *argv[])
|
||||||
|
+{
|
||||||
|
+ struct kdf_cavs test;
|
||||||
|
+ int ret = 1;
|
||||||
|
+ int opt = 0;
|
||||||
|
+
|
||||||
|
+ memset(&test, 0, sizeof(struct kdf_cavs));
|
||||||
|
+ while((opt = getopt(argc, argv, "K:H:s:i:e:m:")) != -1)
|
||||||
|
+ {
|
||||||
|
+ size_t len = 0;
|
||||||
|
+ switch(opt)
|
||||||
|
+ {
|
||||||
|
+ /*
|
||||||
|
+ * CAVS K is MPINT
|
||||||
|
+ * we want a hex (i.e. the caller must ensure the
|
||||||
|
+ * following transformations already happened):
|
||||||
|
+ * 1. cut off first four bytes
|
||||||
|
+ * 2. if most significant bit of value is
|
||||||
|
+ * 1, prepend 0 byte
|
||||||
|
+ */
|
||||||
|
+ case 'K':
|
||||||
|
+ len = strlen(optarg);
|
||||||
|
+ ret = hex2bin_alloc(optarg, len,
|
||||||
|
+ &test.K, &test.Klen);
|
||||||
|
+ if (ret)
|
||||||
|
+ goto out;
|
||||||
|
+ break;
|
||||||
|
+ case 'H':
|
||||||
|
+ len = strlen(optarg);
|
||||||
|
+ ret = hex2bin_alloc(optarg, len,
|
||||||
|
+ &test.H, &test.Hlen);
|
||||||
|
+ if (ret)
|
||||||
|
+ goto out;
|
||||||
|
+ break;
|
||||||
|
+ case 's':
|
||||||
|
+ len = strlen(optarg);
|
||||||
|
+ ret = hex2bin_alloc(optarg, len,
|
||||||
|
+ &test.session_id,
|
||||||
|
+ &test.session_id_len);
|
||||||
|
+ if (ret)
|
||||||
|
+ goto out;
|
||||||
|
+ break;
|
||||||
|
+ case 'i':
|
||||||
|
+ test.iv_len = strtoul(optarg, NULL, 10);
|
||||||
|
+ break;
|
||||||
|
+ case 'e':
|
||||||
|
+ test.ek_len = strtoul(optarg, NULL, 10);
|
||||||
|
+ break;
|
||||||
|
+ case 'm':
|
||||||
|
+ test.ik_len = strtoul(optarg, NULL, 10);
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ usage();
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = sshkdf_cavs(&test);
|
||||||
|
+
|
||||||
|
+out:
|
||||||
|
+ if (test.session_id)
|
||||||
|
+ free(test.session_id);
|
||||||
|
+ if (test.K)
|
||||||
|
+ free(test.K);
|
||||||
|
+ if (test.H)
|
||||||
|
+ free(test.H);
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+}
|
||||||
|
diff -up openssh-6.8p1/ssh-cavs_driver.pl.kdf-cavs openssh-6.8p1/ssh-cavs_driver.pl
|
||||||
|
--- openssh-6.8p1/ssh-cavs_driver.pl.kdf-cavs 2015-03-18 11:23:46.348049354 +0100
|
||||||
|
+++ openssh-6.8p1/ssh-cavs_driver.pl 2015-03-18 11:23:46.348049354 +0100
|
||||||
|
@@ -0,0 +1,184 @@
|
||||||
|
+#!/usr/bin/env perl
|
||||||
|
+#
|
||||||
|
+# CAVS test driver for OpenSSH
|
||||||
|
+#
|
||||||
|
+# Copyright (C) 2015, Stephan Mueller <smueller@chronox.de>
|
||||||
|
+#
|
||||||
|
+# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
+# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
+# in the Software without restriction, including without limitation the rights
|
||||||
|
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
+# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
+# furnished to do so, subject to the following conditions:
|
||||||
|
+#
|
||||||
|
+# The above copyright notice and this permission notice shall be included in
|
||||||
|
+# all copies or substantial portions of the Software.
|
||||||
|
+#
|
||||||
|
+# NO WARRANTY
|
||||||
|
+#
|
||||||
|
+# BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
+# FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
+# OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
+# PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
+# OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
+# TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
+# PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
+# REPAIR OR CORRECTION.
|
||||||
|
+#
|
||||||
|
+# IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
+# WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
+# REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
+# INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
+# OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
+# TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
+# YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
+# PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
+# POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
+#
|
||||||
|
+use strict;
|
||||||
|
+use warnings;
|
||||||
|
+use IPC::Open2;
|
||||||
|
+
|
||||||
|
+# Executing a program by feeding STDIN and retrieving
|
||||||
|
+# STDOUT
|
||||||
|
+# $1: data string to be piped to the app on STDIN
|
||||||
|
+# rest: program and args
|
||||||
|
+# returns: STDOUT of program as string
|
||||||
|
+sub pipe_through_program($@) {
|
||||||
|
+ my $in = shift;
|
||||||
|
+ my @args = @_;
|
||||||
|
+
|
||||||
|
+ my ($CO, $CI);
|
||||||
|
+ my $pid = open2($CO, $CI, @args);
|
||||||
|
+
|
||||||
|
+ my $out = "";
|
||||||
|
+ my $len = length($in);
|
||||||
|
+ my $first = 1;
|
||||||
|
+ while (1) {
|
||||||
|
+ my $rin = "";
|
||||||
|
+ my $win = "";
|
||||||
|
+ # Output of prog is FD that we read
|
||||||
|
+ vec($rin,fileno($CO),1) = 1;
|
||||||
|
+ # Input of prog is FD that we write
|
||||||
|
+ # check for $first is needed because we can have NULL input
|
||||||
|
+ # that is to be written to the app
|
||||||
|
+ if ( $len > 0 || $first) {
|
||||||
|
+ (vec($win,fileno($CI),1) = 1);
|
||||||
|
+ $first=0;
|
||||||
|
+ }
|
||||||
|
+ # Let us wait for 100ms
|
||||||
|
+ my $nfound = select(my $rout=$rin, my $wout=$win, undef, 0.1);
|
||||||
|
+ if ( $wout ) {
|
||||||
|
+ my $written = syswrite($CI, $in, $len);
|
||||||
|
+ die "broken pipe" if !defined $written;
|
||||||
|
+ $len -= $written;
|
||||||
|
+ substr($in, 0, $written) = "";
|
||||||
|
+ if ($len <= 0) {
|
||||||
|
+ close $CI or die "broken pipe: $!";
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ if ( $rout ) {
|
||||||
|
+ my $tmp_out = "";
|
||||||
|
+ my $bytes_read = sysread($CO, $tmp_out, 4096);
|
||||||
|
+ $out .= $tmp_out;
|
||||||
|
+ last if ($bytes_read == 0);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ close $CO or die "broken pipe: $!";
|
||||||
|
+ waitpid $pid, 0;
|
||||||
|
+
|
||||||
|
+ return $out;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+# Parser of CAVS test vector file
|
||||||
|
+# $1: Test vector file
|
||||||
|
+# $2: Output file for test results
|
||||||
|
+# return: nothing
|
||||||
|
+sub parse($$) {
|
||||||
|
+ my $infile = shift;
|
||||||
|
+ my $outfile = shift;
|
||||||
|
+
|
||||||
|
+ my $out = "";
|
||||||
|
+
|
||||||
|
+ my $K = "";
|
||||||
|
+ my $H = "";
|
||||||
|
+ my $session_id = "";
|
||||||
|
+ my $ivlen = 0;
|
||||||
|
+ my $eklen = "";
|
||||||
|
+ my $iklen = "";
|
||||||
|
+
|
||||||
|
+ open(IN, "<$infile");
|
||||||
|
+ while(<IN>) {
|
||||||
|
+
|
||||||
|
+ my $line = $_;
|
||||||
|
+ chomp($line);
|
||||||
|
+ $line =~ s/\r//;
|
||||||
|
+
|
||||||
|
+ if ($line =~ /\[SHA-1\]/) {
|
||||||
|
+ $iklen = 20;
|
||||||
|
+ } elsif ($line =~ /\[SHA-256\]/) {
|
||||||
|
+ $iklen = 32;
|
||||||
|
+ } elsif ($line =~ /\[SHA-384\]/) {
|
||||||
|
+ $iklen = 48;
|
||||||
|
+ } elsif ($line =~ /\[SHA-512\]/) {
|
||||||
|
+ $iklen = 64;
|
||||||
|
+ } elsif ($line =~ /^\[IV length\s*=\s*(.*)\]/) {
|
||||||
|
+ $ivlen = $1;
|
||||||
|
+ $ivlen = $ivlen / 8;
|
||||||
|
+ } elsif ($line =~ /^\[encryption key length\s*=\s*(.*)\]/) {
|
||||||
|
+ $eklen = $1;
|
||||||
|
+ $eklen = $eklen / 8;
|
||||||
|
+ } elsif ($line =~ /^K\s*=\s*(.*)/) {
|
||||||
|
+ $K = $1;
|
||||||
|
+ $K = substr($K, 8);
|
||||||
|
+ $K = "00" . $K;
|
||||||
|
+ } elsif ($line =~ /^H\s*=\s*(.*)/) {
|
||||||
|
+ $H = $1;
|
||||||
|
+ } elsif ($line =~ /^session_id\s*=\s*(.*)/) {
|
||||||
|
+ $session_id = $1;
|
||||||
|
+ }
|
||||||
|
+ $out .= $line . "\n";
|
||||||
|
+
|
||||||
|
+ if ($K ne "" && $H ne "" && $session_id ne "" &&
|
||||||
|
+ $ivlen ne "" && $eklen ne "" && $iklen > 0) {
|
||||||
|
+ $out .= pipe_through_program("", "./ssh-cavs -H $H -K $K -s $session_id -i $ivlen -e $eklen -m $iklen");
|
||||||
|
+
|
||||||
|
+ $K = "";
|
||||||
|
+ $H = "";
|
||||||
|
+ $session_id = "";
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ close IN;
|
||||||
|
+ $out =~ s/\n/\r\n/g; # make it a dos file
|
||||||
|
+ open(OUT, ">$outfile") or die "Cannot create output file $outfile: $?";
|
||||||
|
+ print OUT $out;
|
||||||
|
+ close OUT;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+############################################################
|
||||||
|
+#
|
||||||
|
+# let us pretend to be C :-)
|
||||||
|
+sub main() {
|
||||||
|
+
|
||||||
|
+ my $infile=$ARGV[0];
|
||||||
|
+ die "Error: Test vector file $infile not found" if (! -f $infile);
|
||||||
|
+
|
||||||
|
+ my $outfile = $infile;
|
||||||
|
+ # let us add .rsp regardless whether we could strip .req
|
||||||
|
+ $outfile =~ s/\.req$//;
|
||||||
|
+ $outfile .= ".rsp";
|
||||||
|
+ if (-f $outfile) {
|
||||||
|
+ die "Output file $outfile could not be removed: $?"
|
||||||
|
+ unless unlink($outfile);
|
||||||
|
+ }
|
||||||
|
+ print STDERR "Performing tests from source file $infile with results stored in destination file $outfile\n";
|
||||||
|
+
|
||||||
|
+ # Do the job
|
||||||
|
+ parse($infile, $outfile);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+###########################################
|
||||||
|
+# Call it
|
||||||
|
+main();
|
||||||
|
+1;
|
2742
SOURCES/openssh-6.7p1-ldap.patch
Normal file
2742
SOURCES/openssh-6.7p1-ldap.patch
Normal file
File diff suppressed because it is too large
Load Diff
98
SOURCES/openssh-6.7p1-sftp-force-permission.patch
Normal file
98
SOURCES/openssh-6.7p1-sftp-force-permission.patch
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
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 blacklisted_requests
|
||||||
|
.Op Fl p Ar whitelisted_requests
|
||||||
|
.Op Fl u Ar umask
|
||||||
|
+.Op Fl m Ar force_file_perms
|
||||||
|
.Ek
|
||||||
|
.Nm
|
||||||
|
.Fl Q Ar protocol_feature
|
||||||
|
@@ -138,6 +139,10 @@ Sets an explicit
|
||||||
|
.Xr umask 2
|
||||||
|
to be applied to newly-created files and directories, instead of the
|
||||||
|
user's default mask.
|
||||||
|
+.It Fl m Ar force_file_perms
|
||||||
|
+Sets explicit file permissions to be applied to newly-created files instead
|
||||||
|
+of the default or client requested mode. Numeric values include:
|
||||||
|
+777, 755, 750, 666, 644, 640, etc. Option -u is ineffective if -m is set.
|
||||||
|
.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 blacklisted_requests] "
|
||||||
|
- "[-p whitelisted_requests] [-u umask]\n"
|
||||||
|
+ "[-p whitelisted_requests] [-u umask] [-m force_file_perms]\n"
|
||||||
|
" %s -Q protocol_feature\n",
|
||||||
|
__progname, __progname);
|
||||||
|
exit(1);
|
||||||
|
@@ -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();
|
27
SOURCES/openssh-6.8p1-sshdT-output.patch
Normal file
27
SOURCES/openssh-6.8p1-sshdT-output.patch
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
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 ? o->ciphers : KEX_SERVER_ENCRYPT);
|
||||||
|
dump_cfg_string(sMacs, o->macs ? o->macs : KEX_SERVER_MAC);
|
||||||
|
- dump_cfg_string(sBanner, o->banner);
|
||||||
|
+ dump_cfg_string(sBanner, o->banner != NULL ? 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);
|
||||||
|
diff -up openssh/ssh.1.sshdt openssh/ssh.1
|
||||||
|
--- openssh/ssh.1.sshdt 2015-06-24 11:42:19.565102807 +0200
|
||||||
|
+++ openssh/ssh.1 2015-06-24 11:42:29.042078701 +0200
|
||||||
|
@@ -441,7 +441,11 @@ For full details of the options listed b
|
||||||
|
.It GatewayPorts
|
||||||
|
.It GlobalKnownHostsFile
|
||||||
|
.It GSSAPIAuthentication
|
||||||
|
+.It GSSAPIKeyExchange
|
||||||
|
+.It GSSAPIClientIdentity
|
||||||
|
.It GSSAPIDelegateCredentials
|
||||||
|
+.It GSSAPIRenewalForcesRekey
|
||||||
|
+.It GSSAPITrustDNS
|
||||||
|
.It HashKnownHosts
|
||||||
|
.It Host
|
||||||
|
.It HostbasedAuthentication
|
12
SOURCES/openssh-6.9p1-permit-root-login.patch
Normal file
12
SOURCES/openssh-6.9p1-permit-root-login.patch
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
diff -up openssh-7.0p1/sshd_config.root-login openssh-7.0p1/sshd_config
|
||||||
|
--- openssh-7.0p1/sshd_config.root-login 2015-08-12 11:29:12.919269245 +0200
|
||||||
|
+++ openssh-7.0p1/sshd_config 2015-08-12 11:31:03.653096466 +0200
|
||||||
|
@@ -46,7 +46,7 @@ SyslogFacility AUTHPRIV
|
||||||
|
# Authentication:
|
||||||
|
|
||||||
|
#LoginGraceTime 2m
|
||||||
|
-#PermitRootLogin prohibit-password
|
||||||
|
+PermitRootLogin yes
|
||||||
|
#StrictModes yes
|
||||||
|
#MaxAuthTries 6
|
||||||
|
#MaxSessions 10
|
431
SOURCES/openssh-7.0p1-gssKexAlgorithms.patch
Normal file
431
SOURCES/openssh-7.0p1-gssKexAlgorithms.patch
Normal file
@ -0,0 +1,431 @@
|
|||||||
|
diff -up openssh-7.0p1/gss-genr.c.gsskexalg openssh-7.0p1/gss-genr.c
|
||||||
|
--- openssh-7.0p1/gss-genr.c.gsskexalg 2015-08-19 12:28:38.024518959 +0200
|
||||||
|
+++ openssh-7.0p1/gss-genr.c 2015-08-19 12:28:38.078518839 +0200
|
||||||
|
@@ -78,7 +78,8 @@ ssh_gssapi_oid_table_ok() {
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *
|
||||||
|
-ssh_gssapi_client_mechanisms(const char *host, const char *client) {
|
||||||
|
+ssh_gssapi_client_mechanisms(const char *host, const char *client,
|
||||||
|
+ const char *kex) {
|
||||||
|
gss_OID_set gss_supported;
|
||||||
|
OM_uint32 min_status;
|
||||||
|
|
||||||
|
@@ -86,12 +87,12 @@ ssh_gssapi_client_mechanisms(const char
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism,
|
||||||
|
- host, client));
|
||||||
|
+ host, client, kex));
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check,
|
||||||
|
- const char *host, const char *client) {
|
||||||
|
+ const char *host, const char *client, const char *kex) {
|
||||||
|
struct sshbuf *buf;
|
||||||
|
size_t i;
|
||||||
|
int oidpos, enclen, r;
|
||||||
|
@@ -100,6 +101,7 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_sup
|
||||||
|
char deroid[2];
|
||||||
|
const EVP_MD *evp_md = EVP_md5();
|
||||||
|
EVP_MD_CTX md;
|
||||||
|
+ char *s, *cp, *p;
|
||||||
|
|
||||||
|
if (gss_enc2oid != NULL) {
|
||||||
|
for (i = 0; gss_enc2oid[i].encoded != NULL; i++)
|
||||||
|
@@ -113,6 +115,7 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_sup
|
||||||
|
fatal("%s: sshbuf_new failed", __func__);
|
||||||
|
|
||||||
|
oidpos = 0;
|
||||||
|
+ s = cp = xstrdup(kex);
|
||||||
|
for (i = 0; i < gss_supported->count; i++) {
|
||||||
|
if (gss_supported->elements[i].length < 128 &&
|
||||||
|
(*check)(NULL, &(gss_supported->elements[i]), host, client)) {
|
||||||
|
@@ -131,28 +134,25 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_sup
|
||||||
|
enclen = __b64_ntop(digest, EVP_MD_size(evp_md),
|
||||||
|
encoded, EVP_MD_size(evp_md) * 2);
|
||||||
|
|
||||||
|
- if (oidpos != 0)
|
||||||
|
- if ((r = sshbuf_put_u8(buf, ',')) != 0)
|
||||||
|
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
-
|
||||||
|
- if ((r = sshbuf_put(buf, KEX_GSS_GEX_SHA1_ID,
|
||||||
|
- sizeof(KEX_GSS_GEX_SHA1_ID) - 1)) != 0 ||
|
||||||
|
- (r = sshbuf_put(buf, encoded, enclen)) != 0 ||
|
||||||
|
- (r = sshbuf_put_u8(buf, ',')) != 0 ||
|
||||||
|
- (r = sshbuf_put(buf, KEX_GSS_GRP1_SHA1_ID,
|
||||||
|
- sizeof(KEX_GSS_GRP1_SHA1_ID) - 1)) != 0 ||
|
||||||
|
- (r = sshbuf_put(buf, encoded, enclen)) != 0 ||
|
||||||
|
- (r = sshbuf_put_u8(buf, ',')) != 0 ||
|
||||||
|
- (r = sshbuf_put(buf, KEX_GSS_GRP14_SHA1_ID,
|
||||||
|
- sizeof(KEX_GSS_GRP14_SHA1_ID) - 1)) != 0 ||
|
||||||
|
- (r = sshbuf_put(buf, encoded, enclen)) != 0)
|
||||||
|
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
+ cp = strncpy(s, kex, strlen(kex));
|
||||||
|
+ for ((p = strsep(&cp, ",")); p && *p != '\0';
|
||||||
|
+ (p = strsep(&cp, ","))) {
|
||||||
|
+ if (sshbuf_len(buf) != 0)
|
||||||
|
+ if ((r = sshbuf_put_u8(buf, ',')) != 0)
|
||||||
|
+ fatal("%s: buffer error: %s",
|
||||||
|
+ __func__, ssh_err(r));
|
||||||
|
+ if ((r = sshbuf_put(buf, p, strlen(p))) != 0 ||
|
||||||
|
+ (r = sshbuf_put(buf, encoded, enclen)) != 0)
|
||||||
|
+ fatal("%s: buffer error: %s",
|
||||||
|
+ __func__, ssh_err(r));
|
||||||
|
+ }
|
||||||
|
|
||||||
|
gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]);
|
||||||
|
gss_enc2oid[oidpos].encoded = encoded;
|
||||||
|
oidpos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ free(s);
|
||||||
|
gss_enc2oid[oidpos].oid = NULL;
|
||||||
|
gss_enc2oid[oidpos].encoded = NULL;
|
||||||
|
|
||||||
|
diff -up openssh-7.0p1/gss-serv.c.gsskexalg openssh-7.0p1/gss-serv.c
|
||||||
|
--- openssh-7.0p1/gss-serv.c.gsskexalg 2015-08-19 12:28:38.024518959 +0200
|
||||||
|
+++ openssh-7.0p1/gss-serv.c 2015-08-19 12:28:38.078518839 +0200
|
||||||
|
@@ -149,7 +149,8 @@ ssh_gssapi_server_mechanisms() {
|
||||||
|
if (supported_oids == NULL)
|
||||||
|
ssh_gssapi_prepare_supported_oids();
|
||||||
|
return (ssh_gssapi_kex_mechs(supported_oids,
|
||||||
|
- &ssh_gssapi_server_check_mech, NULL, NULL));
|
||||||
|
+ &ssh_gssapi_server_check_mech, NULL, NULL,
|
||||||
|
+ options.gss_kex_algorithms));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unprivileged */
|
||||||
|
diff -up openssh-7.0p1/kex.c.gsskexalg openssh-7.0p1/kex.c
|
||||||
|
--- openssh-7.0p1/kex.c.gsskexalg 2015-08-19 12:28:38.078518839 +0200
|
||||||
|
+++ openssh-7.0p1/kex.c 2015-08-19 12:30:13.249306371 +0200
|
||||||
|
@@ -50,6 +50,7 @@
|
||||||
|
#include "misc.h"
|
||||||
|
#include "dispatch.h"
|
||||||
|
#include "monitor.h"
|
||||||
|
+#include "xmalloc.h"
|
||||||
|
|
||||||
|
#include "ssherr.h"
|
||||||
|
#include "sshbuf.h"
|
||||||
|
@@ -232,6 +232,29 @@ kex_assemble_names(const char *def, char
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Validate GSS KEX method name list */
|
||||||
|
+int
|
||||||
|
+gss_kex_names_valid(const char *names)
|
||||||
|
+{
|
||||||
|
+ char *s, *cp, *p;
|
||||||
|
+
|
||||||
|
+ if (names == NULL || *names == '\0')
|
||||||
|
+ return 0;
|
||||||
|
+ s = cp = xstrdup(names);
|
||||||
|
+ for ((p = strsep(&cp, ",")); p && *p != '\0';
|
||||||
|
+ (p = strsep(&cp, ","))) {
|
||||||
|
+ if (strncmp(p, "gss-", 4) != 0
|
||||||
|
+ || kex_alg_by_name(p) == NULL) {
|
||||||
|
+ error("Unsupported KEX algorithm \"%.100s\"", p);
|
||||||
|
+ free(s);
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ debug3("gss kex names ok: [%s]", names);
|
||||||
|
+ free(s);
|
||||||
|
+ return 1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* put algorithm proposal into buffer */
|
||||||
|
int
|
||||||
|
kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX])
|
||||||
|
diff -up openssh-7.0p1/kex.h.gsskexalg openssh-7.0p1/kex.h
|
||||||
|
--- openssh-7.0p1/kex.h.gsskexalg 2015-08-19 12:28:38.078518839 +0200
|
||||||
|
+++ openssh-7.0p1/kex.h 2015-08-19 12:30:52.404218958 +0200
|
||||||
|
@@ -173,6 +173,7 @@ int kex_names_valid(const char *);
|
||||||
|
char *kex_alg_list(char);
|
||||||
|
char *kex_names_cat(const char *, const char *);
|
||||||
|
int kex_assemble_names(char **, const char *, const char *);
|
||||||
|
+int gss_kex_names_valid(const char *);
|
||||||
|
|
||||||
|
int kex_new(struct ssh *, char *[PROPOSAL_MAX], struct kex **);
|
||||||
|
int kex_setup(struct ssh *, char *[PROPOSAL_MAX]);
|
||||||
|
diff -up openssh-7.0p1/readconf.c.gsskexalg openssh-7.0p1/readconf.c
|
||||||
|
--- openssh-7.0p1/readconf.c.gsskexalg 2015-08-19 12:28:38.026518955 +0200
|
||||||
|
+++ openssh-7.0p1/readconf.c 2015-08-19 12:31:28.333138747 +0200
|
||||||
|
@@ -61,6 +61,7 @@
|
||||||
|
#include "uidswap.h"
|
||||||
|
#include "myproposal.h"
|
||||||
|
#include "digest.h"
|
||||||
|
+#include "ssh-gss.h"
|
||||||
|
|
||||||
|
/* Format of the configuration file:
|
||||||
|
|
||||||
|
@@ -148,7 +149,7 @@ typedef enum {
|
||||||
|
oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
|
||||||
|
oAddressFamily, oGssAuthentication, oGssDelegateCreds,
|
||||||
|
oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey,
|
||||||
|
- oGssServerIdentity,
|
||||||
|
+ oGssServerIdentity, oGssKexAlgorithms,
|
||||||
|
oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
|
||||||
|
oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist,
|
||||||
|
oHashKnownHosts,
|
||||||
|
@@ -200,6 +201,7 @@ static struct {
|
||||||
|
{ "gssapiclientidentity", oGssClientIdentity },
|
||||||
|
{ "gssapiserveridentity", oGssServerIdentity },
|
||||||
|
{ "gssapirenewalforcesrekey", oGssRenewalRekey },
|
||||||
|
+ { "gssapikexalgorithms", oGssKexAlgorithms },
|
||||||
|
# else
|
||||||
|
{ "gssapiauthentication", oUnsupported },
|
||||||
|
{ "gssapikeyexchange", oUnsupported },
|
||||||
|
@@ -207,6 +209,7 @@ static struct {
|
||||||
|
{ "gssapitrustdns", oUnsupported },
|
||||||
|
{ "gssapiclientidentity", oUnsupported },
|
||||||
|
{ "gssapirenewalforcesrekey", oUnsupported },
|
||||||
|
+ { "gssapikexalgorithms", oUnsupported },
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_PKCS11
|
||||||
|
{ "smartcarddevice", oPKCS11Provider },
|
||||||
|
@@ -929,6 +932,18 @@ parse_time:
|
||||||
|
intptr = &options->gss_renewal_rekey;
|
||||||
|
goto parse_flag;
|
||||||
|
|
||||||
|
+ case oGssKexAlgorithms:
|
||||||
|
+ arg = strdelim(&s);
|
||||||
|
+ if (!arg || *arg == '\0')
|
||||||
|
+ fatal("%.200s line %d: Missing argument.",
|
||||||
|
+ filename, linenum);
|
||||||
|
+ if (!gss_kex_names_valid(arg))
|
||||||
|
+ fatal("%.200s line %d: Bad GSSAPI KexAlgorithms '%s'.",
|
||||||
|
+ filename, linenum, arg ? arg : "<NONE>");
|
||||||
|
+ if (*activep && options->gss_kex_algorithms == NULL)
|
||||||
|
+ options->gss_kex_algorithms = xstrdup(arg);
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
case oBatchMode:
|
||||||
|
intptr = &options->batch_mode;
|
||||||
|
goto parse_flag;
|
||||||
|
@@ -1638,6 +1653,7 @@ initialize_options(Options * options)
|
||||||
|
options->gss_renewal_rekey = -1;
|
||||||
|
options->gss_client_identity = NULL;
|
||||||
|
options->gss_server_identity = NULL;
|
||||||
|
+ options->gss_kex_algorithms = NULL;
|
||||||
|
options->password_authentication = -1;
|
||||||
|
options->kbd_interactive_authentication = -1;
|
||||||
|
options->kbd_interactive_devices = NULL;
|
||||||
|
@@ -1773,6 +1789,10 @@ fill_default_options(Options * options)
|
||||||
|
options->gss_trust_dns = 0;
|
||||||
|
if (options->gss_renewal_rekey == -1)
|
||||||
|
options->gss_renewal_rekey = 0;
|
||||||
|
+#ifdef GSSAPI
|
||||||
|
+ if (options->gss_kex_algorithms == NULL)
|
||||||
|
+ options->gss_kex_algorithms = strdup(GSS_KEX_DEFAULT_KEX);
|
||||||
|
+#endif
|
||||||
|
if (options->password_authentication == -1)
|
||||||
|
options->password_authentication = 1;
|
||||||
|
if (options->kbd_interactive_authentication == -1)
|
||||||
|
@@ -2651,6 +2671,8 @@ dump_client_config(Options *o, const cha
|
||||||
|
dump_cfg_string(oGssClientIdentity, o->gss_client_identity);
|
||||||
|
dump_cfg_string(oGssServerIdentity, o->gss_client_identity);
|
||||||
|
dump_cfg_fmtint(oGssRenewalRekey, o->gss_renewal_rekey);
|
||||||
|
+ dump_cfg_string(oGssKexAlgorithms, o->gss_kex_algorithms ?
|
||||||
|
+ o->gss_kex_algorithms : GSS_KEX_DEFAULT_KEX);
|
||||||
|
#endif /* GSSAPI */
|
||||||
|
dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);
|
||||||
|
dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);
|
||||||
|
diff -up openssh-7.9p1/readconf.h.gsskexalg openssh-7.9p1/readconf.h
|
||||||
|
--- openssh-7.9p1/readconf.h.gsskexalg 2018-11-14 09:20:06.616350574 +0100
|
||||||
|
+++ openssh-7.9p1/readconf.h 2018-11-14 09:20:06.647350828 +0100
|
||||||
|
@@ -46,6 +46,7 @@ typedef struct {
|
||||||
|
int gss_renewal_rekey; /* Credential renewal forces rekey */
|
||||||
|
char *gss_client_identity; /* Principal to initiate GSSAPI with */
|
||||||
|
char *gss_server_identity; /* GSSAPI target principal */
|
||||||
|
+ char *gss_kex_algorithms; /* GSSAPI kex methods to be offered by client. */
|
||||||
|
int password_authentication; /* Try password
|
||||||
|
* authentication. */
|
||||||
|
int kbd_interactive_authentication; /* Try keyboard-interactive auth. */
|
||||||
|
diff -up openssh-7.0p1/servconf.c.gsskexalg openssh-7.0p1/servconf.c
|
||||||
|
--- openssh-7.0p1/servconf.c.gsskexalg 2015-08-19 12:28:38.074518847 +0200
|
||||||
|
+++ openssh-7.0p1/servconf.c 2015-08-19 12:33:13.599902732 +0200
|
||||||
|
@@ -57,6 +57,7 @@
|
||||||
|
#include "auth.h"
|
||||||
|
#include "myproposal.h"
|
||||||
|
#include "digest.h"
|
||||||
|
+#include "ssh-gss.h"
|
||||||
|
|
||||||
|
static void add_listen_addr(ServerOptions *, const char *,
|
||||||
|
const char *, int);
|
||||||
|
@@ -121,6 +122,7 @@ initialize_server_options(ServerOptions
|
||||||
|
options->gss_cleanup_creds = -1;
|
||||||
|
options->gss_strict_acceptor = -1;
|
||||||
|
options->gss_store_rekey = -1;
|
||||||
|
+ options->gss_kex_algorithms = NULL;
|
||||||
|
options->use_kuserok = -1;
|
||||||
|
options->enable_k5users = -1;
|
||||||
|
options->password_authentication = -1;
|
||||||
|
@@ -288,6 +290,10 @@ fill_default_server_options(ServerOption
|
||||||
|
options->gss_strict_acceptor = 1;
|
||||||
|
if (options->gss_store_rekey == -1)
|
||||||
|
options->gss_store_rekey = 0;
|
||||||
|
+#ifdef GSSAPI
|
||||||
|
+ if (options->gss_kex_algorithms == NULL)
|
||||||
|
+ options->gss_kex_algorithms = strdup(GSS_KEX_DEFAULT_KEX);
|
||||||
|
+#endif
|
||||||
|
if (options->use_kuserok == -1)
|
||||||
|
options->use_kuserok = 1;
|
||||||
|
if (options->enable_k5users == -1)
|
||||||
|
@@ -427,7 +431,7 @@ typedef enum {
|
||||||
|
sHostKeyAlgorithms,
|
||||||
|
sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
|
||||||
|
sGssAuthentication, sGssCleanupCreds, sGssEnablek5users, sGssStrictAcceptor,
|
||||||
|
- sGssKeyEx, sGssStoreRekey, sAcceptEnv, sSetEnv, sPermitTunnel,
|
||||||
|
+ sGssKeyEx, sGssStoreRekey, sGssKexAlgorithms, sAcceptEnv, sSetEnv, sPermitTunnel,
|
||||||
|
sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory,
|
||||||
|
sUsePrivilegeSeparation, sAllowAgentForwarding,
|
||||||
|
sHostCertificate,
|
||||||
|
@@ -506,6 +510,7 @@ static struct {
|
||||||
|
{ "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL },
|
||||||
|
{ "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL },
|
||||||
|
{ "gssapienablek5users", sGssEnablek5users, SSHCFG_ALL },
|
||||||
|
+ { "gssapikexalgorithms", sGssKexAlgorithms, SSHCFG_GLOBAL },
|
||||||
|
#else
|
||||||
|
{ "gssapiauthentication", sUnsupported, SSHCFG_ALL },
|
||||||
|
{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
|
||||||
|
@@ -513,6 +518,7 @@ static struct {
|
||||||
|
{ "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL },
|
||||||
|
{ "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL },
|
||||||
|
{ "gssapienablek5users", sUnsupported, SSHCFG_ALL },
|
||||||
|
+ { "gssapikexalgorithms", sUnsupported, SSHCFG_GLOBAL },
|
||||||
|
#endif
|
||||||
|
{ "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL },
|
||||||
|
{ "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL },
|
||||||
|
@@ -1273,6 +1279,18 @@ process_server_config_line(ServerOptions
|
||||||
|
intptr = &options->gss_store_rekey;
|
||||||
|
goto parse_flag;
|
||||||
|
|
||||||
|
+ case sGssKexAlgorithms:
|
||||||
|
+ arg = strdelim(&cp);
|
||||||
|
+ if (!arg || *arg == '\0')
|
||||||
|
+ fatal("%.200s line %d: Missing argument.",
|
||||||
|
+ filename, linenum);
|
||||||
|
+ if (!gss_kex_names_valid(arg))
|
||||||
|
+ fatal("%.200s line %d: Bad GSSAPI KexAlgorithms '%s'.",
|
||||||
|
+ filename, linenum, arg ? arg : "<NONE>");
|
||||||
|
+ if (*activep && options->gss_kex_algorithms == NULL)
|
||||||
|
+ options->gss_kex_algorithms = xstrdup(arg);
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
case sPasswordAuthentication:
|
||||||
|
intptr = &options->password_authentication;
|
||||||
|
goto parse_flag;
|
||||||
|
@@ -2304,6 +2322,7 @@ dump_config(ServerOptions *o)
|
||||||
|
dump_cfg_fmtint(sGssKeyEx, o->gss_keyex);
|
||||||
|
dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor);
|
||||||
|
dump_cfg_fmtint(sGssStoreRekey, o->gss_store_rekey);
|
||||||
|
+ dump_cfg_string(sGssKexAlgorithms, o->gss_kex_algorithms);
|
||||||
|
#endif
|
||||||
|
dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
|
||||||
|
dump_cfg_fmtint(sKbdInteractiveAuthentication,
|
||||||
|
diff -up openssh-7.0p1/servconf.h.gsskexalg openssh-7.0p1/servconf.h
|
||||||
|
--- openssh-7.0p1/servconf.h.gsskexalg 2015-08-19 12:28:38.080518834 +0200
|
||||||
|
+++ openssh-7.0p1/servconf.h 2015-08-19 12:34:46.328693944 +0200
|
||||||
|
@@ -122,6 +122,7 @@ typedef struct {
|
||||||
|
int gss_cleanup_creds; /* If true, destroy cred cache on logout */
|
||||||
|
int gss_strict_acceptor; /* If true, restrict the GSSAPI acceptor name */
|
||||||
|
int gss_store_rekey;
|
||||||
|
+ char *gss_kex_algorithms; /* GSSAPI kex methods to be offered by client. */
|
||||||
|
int password_authentication; /* If true, permit password
|
||||||
|
* authentication. */
|
||||||
|
int kbd_interactive_authentication; /* If true, permit */
|
||||||
|
diff -up openssh-7.0p1/ssh.1.gsskexalg openssh-7.0p1/ssh.1
|
||||||
|
--- openssh-7.0p1/ssh.1.gsskexalg 2015-08-19 12:28:38.081518832 +0200
|
||||||
|
+++ openssh-7.0p1/ssh.1 2015-08-19 12:35:31.741591692 +0200
|
||||||
|
@@ -496,6 +496,7 @@ For full details of the options listed b
|
||||||
|
.It GSSAPIDelegateCredentials
|
||||||
|
.It GSSAPIRenewalForcesRekey
|
||||||
|
.It GSSAPITrustDNS
|
||||||
|
+.It GSSAPIKexAlgorithms
|
||||||
|
.It HashKnownHosts
|
||||||
|
.It Host
|
||||||
|
.It HostbasedAuthentication
|
||||||
|
diff -up openssh-7.0p1/ssh_config.5.gsskexalg openssh-7.0p1/ssh_config.5
|
||||||
|
--- openssh-7.0p1/ssh_config.5.gsskexalg 2015-08-19 12:28:38.028518950 +0200
|
||||||
|
+++ openssh-7.0p1/ssh_config.5 2015-08-19 12:28:38.082518830 +0200
|
||||||
|
@@ -786,6 +786,18 @@ command line will be passed untouched to
|
||||||
|
command line will be passed untouched to the GSSAPI library.
|
||||||
|
The default is
|
||||||
|
.Dq no .
|
||||||
|
+.It Cm GSSAPIKexAlgorithms
|
||||||
|
+The list of key exchange algorithms that are offered for GSSAPI
|
||||||
|
+key exchange. Possible values are
|
||||||
|
+.Bd -literal -offset 3n
|
||||||
|
+gss-gex-sha1-,
|
||||||
|
+gss-group1-sha1-,
|
||||||
|
+gss-group14-sha1-
|
||||||
|
+.Ed
|
||||||
|
+.Pp
|
||||||
|
+The default is
|
||||||
|
+.Dq gss-gex-sha1-,gss-group14-sha1- .
|
||||||
|
+This option only applies to protocol version 2 connections using GSSAPI.
|
||||||
|
.It Cm HashKnownHosts
|
||||||
|
Indicates that
|
||||||
|
.Xr ssh 1
|
||||||
|
diff -up openssh-7.0p1/sshconnect2.c.gsskexalg openssh-7.0p1/sshconnect2.c
|
||||||
|
--- openssh-7.0p1/sshconnect2.c.gsskexalg 2015-08-19 12:28:38.045518912 +0200
|
||||||
|
+++ openssh-7.0p1/sshconnect2.c 2015-08-19 12:28:38.081518832 +0200
|
||||||
|
@@ -179,7 +179,8 @@ ssh_kex2(char *host, struct sockaddr *ho
|
||||||
|
else
|
||||||
|
gss_host = host;
|
||||||
|
|
||||||
|
- gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity);
|
||||||
|
+ gss = ssh_gssapi_client_mechanisms(gss_host,
|
||||||
|
+ options.gss_client_identity, options.gss_kex_algorithms);
|
||||||
|
if (gss) {
|
||||||
|
debug("Offering GSSAPI proposal: %s", gss);
|
||||||
|
xasprintf(&options.kex_algorithms,
|
||||||
|
--- openssh-7.1p1/sshd_config.5.gsskexalg 2015-12-10 15:32:48.105418092 +0100
|
||||||
|
+++ openssh-7.1p1/sshd_config.5 2015-12-10 15:33:47.771279548 +0100
|
||||||
|
@@ -663,6 +663,18 @@ or updated credentials from a compatible
|
||||||
|
For this to work
|
||||||
|
.Cm GSSAPIKeyExchange
|
||||||
|
needs to be enabled in the server and also used by the client.
|
||||||
|
+.It Cm GSSAPIKexAlgorithms
|
||||||
|
+The list of key exchange algorithms that are accepted by GSSAPI
|
||||||
|
+key exchange. Possible values are
|
||||||
|
+.Bd -literal -offset 3n
|
||||||
|
+gss-gex-sha1-,
|
||||||
|
+gss-group1-sha1-,
|
||||||
|
+gss-group14-sha1-
|
||||||
|
+.Ed
|
||||||
|
+.Pp
|
||||||
|
+The default is
|
||||||
|
+.Dq gss-gex-sha1-,gss-group14-sha1- .
|
||||||
|
+This option only applies to protocol version 2 connections using GSSAPI.
|
||||||
|
.It Cm HostbasedAcceptedKeyTypes
|
||||||
|
Specifies the key types that will be accepted for hostbased authentication
|
||||||
|
as a list of comma-separated patterns.
|
||||||
|
diff -up openssh-7.0p1/ssh-gss.h.gsskexalg openssh-7.0p1/ssh-gss.h
|
||||||
|
--- openssh-7.0p1/ssh-gss.h.gsskexalg 2015-08-19 12:28:38.031518944 +0200
|
||||||
|
+++ openssh-7.0p1/ssh-gss.h 2015-08-19 12:28:38.081518832 +0200
|
||||||
|
@@ -76,6 +76,10 @@ extern char **k5users_allowed_cmds;
|
||||||
|
#define KEX_GSS_GRP14_SHA1_ID "gss-group14-sha1-"
|
||||||
|
#define KEX_GSS_GEX_SHA1_ID "gss-gex-sha1-"
|
||||||
|
|
||||||
|
+#define GSS_KEX_DEFAULT_KEX \
|
||||||
|
+ KEX_GSS_GEX_SHA1_ID "," \
|
||||||
|
+ KEX_GSS_GRP14_SHA1_ID
|
||||||
|
+
|
||||||
|
typedef struct {
|
||||||
|
char *envvar;
|
||||||
|
char *envval;
|
||||||
|
@@ -147,9 +151,9 @@ int ssh_gssapi_credentials_updated(Gssct
|
||||||
|
/* In the server */
|
||||||
|
typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *,
|
||||||
|
const char *);
|
||||||
|
-char *ssh_gssapi_client_mechanisms(const char *, const char *);
|
||||||
|
+char *ssh_gssapi_client_mechanisms(const char *, const char *, const char *);
|
||||||
|
char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *,
|
||||||
|
- const char *);
|
||||||
|
+ const char *, const char *);
|
||||||
|
gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int);
|
||||||
|
int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *,
|
||||||
|
const char *);
|
52
SOURCES/openssh-7.1p1-gssapi-documentation.patch
Normal file
52
SOURCES/openssh-7.1p1-gssapi-documentation.patch
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
diff -up openssh-7.4p1/ssh_config.5.gss-docs openssh-7.4p1/ssh_config.5
|
||||||
|
--- openssh-7.4p1/ssh_config.5.gss-docs 2016-12-23 14:28:34.051714486 +0100
|
||||||
|
+++ openssh-7.4p1/ssh_config.5 2016-12-23 14:34:24.568522417 +0100
|
||||||
|
@@ -765,10 +765,19 @@ The default is
|
||||||
|
If set to
|
||||||
|
.Dq yes
|
||||||
|
then renewal of the client's GSSAPI credentials will force the rekeying of the
|
||||||
|
-ssh connection. With a compatible server, this can delegate the renewed
|
||||||
|
+ssh connection. With a compatible server, this will delegate the renewed
|
||||||
|
credentials to a session on the server.
|
||||||
|
+.Pp
|
||||||
|
+Checks are made to ensure that credentials are only propagated when the new
|
||||||
|
+credentials match the old ones on the originating client and where the
|
||||||
|
+receiving server still has the old set in its cache.
|
||||||
|
+.Pp
|
||||||
|
The default is
|
||||||
|
.Dq no .
|
||||||
|
+.Pp
|
||||||
|
+For this to work
|
||||||
|
+.Cm GSSAPIKeyExchange
|
||||||
|
+needs to be enabled in the server and also used by the client.
|
||||||
|
.It Cm GSSAPIServerIdentity
|
||||||
|
If set, specifies the GSSAPI server identity that ssh should expect when
|
||||||
|
connecting to the server. The default is unset, which means that the
|
||||||
|
@@ -776,9 +785,11 @@ expected GSSAPI server identity will be
|
||||||
|
hostname.
|
||||||
|
.It Cm GSSAPITrustDns
|
||||||
|
Set to
|
||||||
|
-.Dq yes to indicate that the DNS is trusted to securely canonicalize
|
||||||
|
+.Dq yes
|
||||||
|
+to indicate that the DNS is trusted to securely canonicalize
|
||||||
|
the name of the host being connected to. If
|
||||||
|
-.Dq no, the hostname entered on the
|
||||||
|
+.Dq no ,
|
||||||
|
+the hostname entered on the
|
||||||
|
command line will be passed untouched to the GSSAPI library.
|
||||||
|
The default is
|
||||||
|
.Dq no .
|
||||||
|
diff -up openssh-7.4p1/sshd_config.5.gss-docs openssh-7.4p1/sshd_config.5
|
||||||
|
--- openssh-7.4p1/sshd_config.5.gss-docs 2016-12-23 14:28:34.043714490 +0100
|
||||||
|
+++ openssh-7.4p1/sshd_config.5 2016-12-23 14:28:34.051714486 +0100
|
||||||
|
@@ -652,6 +652,10 @@ Controls whether the user's GSSAPI crede
|
||||||
|
successful connection rekeying. This option can be used to accepted renewed
|
||||||
|
or updated credentials from a compatible client. The default is
|
||||||
|
.Dq no .
|
||||||
|
+.Pp
|
||||||
|
+For this to work
|
||||||
|
+.Cm GSSAPIKeyExchange
|
||||||
|
+needs to be enabled in the server and also used by the client.
|
||||||
|
.It Cm HostbasedAcceptedKeyTypes
|
||||||
|
Specifies the key types that will be accepted for hostbased authentication
|
||||||
|
as a list of comma-separated patterns.
|
187
SOURCES/openssh-7.1p2-audit-race-condition.patch
Normal file
187
SOURCES/openssh-7.1p2-audit-race-condition.patch
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
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("%s: entering", __func__);
|
||||||
|
+ if ((m = sshbuf_new()) == NULL)
|
||||||
|
+ fatal("%s: sshbuf_new failed", __func__);
|
||||||
|
+ do {
|
||||||
|
+ blen = atomicio(read, fdin, buf, sizeof(buf));
|
||||||
|
+ if (blen == 0) /* closed pipe */
|
||||||
|
+ break;
|
||||||
|
+ if (blen != sizeof(buf)) {
|
||||||
|
+ error("%s: Failed to read the buffer from child", __func__);
|
||||||
|
+ ret = -1;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ msg_len = get_u32(buf);
|
||||||
|
+ if (msg_len > 256 * 1024)
|
||||||
|
+ fatal("%s: read: bad msg_len %d", __func__, msg_len);
|
||||||
|
+ sshbuf_reset(m);
|
||||||
|
+ if ((r = sshbuf_reserve(m, msg_len, NULL)) != 0)
|
||||||
|
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
+ if (atomicio(read, fdin, sshbuf_mutable_ptr(m), msg_len) != msg_len) {
|
||||||
|
+ error("%s: Failed to read the the buffer content from the child", __func__);
|
||||||
|
+ ret = -1;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ if (atomicio(vwrite, pmonitor->m_recvfd, buf, blen) != blen ||
|
||||||
|
+ atomicio(vwrite, pmonitor->m_recvfd, sshbuf_mutable_ptr(m), msg_len) != msg_len) {
|
||||||
|
+ error("%s: Failed to write the message to the monitor", __func__);
|
||||||
|
+ ret = -1;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ } while (1);
|
||||||
|
+ sshbuf_free(m);
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+void mm_set_monitor_pipe(int fd)
|
||||||
|
+{
|
||||||
|
+ pmonitor->m_recvfd = fd;
|
||||||
|
+}
|
||||||
|
#endif /* SSH_AUDIT_EVENTS */
|
||||||
|
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(int, char *, char *, char *, char *, pid_t, uid_t);
|
||||||
|
void mm_audit_session_key_free_body(int, pid_t, uid_t);
|
||||||
|
void mm_audit_destroy_sensitive_data(const char *, pid_t, uid_t);
|
||||||
|
+int mm_forward_audit_messages(int);
|
||||||
|
+void mm_set_monitor_pipe(int);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct Session;
|
||||||
|
diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c
|
||||||
|
--- openssh-7.4p1/session.c.audit-race 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();
|
||||||
|
+
|
||||||
|
#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();
|
||||||
|
+
|
||||||
|
/* 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();
|
||||||
|
+
|
||||||
|
/* 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 = PRIVSEP(audit_run_command(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 (use_privsep && ret == 0) {
|
||||||
|
+ /*
|
||||||
|
+ * Read the audit messages from forked child and send them
|
||||||
|
+ * back to monitor. We don't want to communicate directly,
|
||||||
|
+ * because the messages might get mixed up.
|
||||||
|
+ * Continue after the pipe gets closed (all messages sent).
|
||||||
|
+ */
|
||||||
|
+ ret = mm_forward_audit_messages(paudit[0]);
|
||||||
|
+ }
|
||||||
|
+ close(paudit[0]);
|
||||||
|
+#endif /* SSH_AUDIT_EVENTS */
|
||||||
|
+
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1538,6 +1565,34 @@ child_close_fds(void)
|
||||||
|
endpwent();
|
||||||
|
}
|
||||||
|
|
||||||
|
+void
|
||||||
|
+child_destory_sensitive_data()
|
||||||
|
+{
|
||||||
|
+#ifdef SSH_AUDIT_EVENTS
|
||||||
|
+ int pparent = paudit[1];
|
||||||
|
+ close(paudit[0]);
|
||||||
|
+ /* Hack the monitor pipe to avoid race condition with parent */
|
||||||
|
+ if (use_privsep)
|
||||||
|
+ mm_set_monitor_pipe(pparent);
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ /* remove hostkey from the child's memory */
|
||||||
|
+ destroy_sensitive_data(use_privsep);
|
||||||
|
+ /*
|
||||||
|
+ * We can audit this, because we hacked the pipe to direct the
|
||||||
|
+ * messages over postauth child. But this message requires answer
|
||||||
|
+ * which we can't do using one-way pipe.
|
||||||
|
+ */
|
||||||
|
+ packet_destroy_all(0, 1);
|
||||||
|
+ /* XXX this will clean the rest but should not audit anymore */
|
||||||
|
+ /* packet_clear_keys(); */
|
||||||
|
+
|
||||||
|
+#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
|
||||||
|
struct passwd *pw = s->pw;
|
||||||
|
int r = 0;
|
||||||
|
|
||||||
|
- /* remove hostkey from the child's memory */
|
||||||
|
- destroy_sensitive_data(1);
|
||||||
|
- packet_clear_keys();
|
||||||
|
- /* Don't audit this - both us and the parent would be talking to the
|
||||||
|
- monitor over a single socket, with no synchronization. */
|
||||||
|
- packet_destroy_all(0, 1);
|
||||||
|
-
|
||||||
|
/* Force a password change */
|
||||||
|
if (s->authctxt->force_pwchange) {
|
||||||
|
do_setusercontext(pw);
|
87
SOURCES/openssh-7.2p2-k5login_directory.patch
Normal file
87
SOURCES/openssh-7.2p2-k5login_directory.patch
Normal file
@ -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,6 +375,22 @@ cleanup:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * 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);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
krb5_error_code
|
||||||
|
ssh_krb5_get_cctemplate(krb5_context ctx, char **ccname) {
|
||||||
|
profile_t p;
|
||||||
|
diff --git a/auth.h b/auth.h
|
||||||
|
index f9d191c..c432d2f 100644
|
||||||
|
--- a/auth.h
|
||||||
|
+++ b/auth.h
|
||||||
|
@@ -222,5 +222,7 @@ int sys_auth_passwd(Authctxt *, const char *);
|
||||||
|
#if defined(KRB5) && !defined(HEIMDAL)
|
||||||
|
#include <krb5.h>
|
||||||
|
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
|
||||||
|
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("%s: k5login_directory = %s (rv=%d)", __func__, k5login_directory, ret);
|
||||||
|
+ if (k5login_directory == NULL || ret != 0) {
|
||||||
|
+ /* If not set, the library will look for k5login
|
||||||
|
+ * files in the user's home directory, with the filename .k5login.
|
||||||
|
+ */
|
||||||
|
+ 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("%s: Checking existence of file %s", __func__, file);
|
||||||
|
|
||||||
|
- snprintf(file, sizeof(file), "%s/.k5login", pw->pw_dir);
|
||||||
|
return access(file, F_OK) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/sshd.8 b/sshd.8
|
||||||
|
index 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
|
52
SOURCES/openssh-7.2p2-s390-closefrom.patch
Normal file
52
SOURCES/openssh-7.2p2-s390-closefrom.patch
Normal file
@ -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);
|
||||||
|
} else
|
||||||
|
|
53
SOURCES/openssh-7.2p2-x11.patch
Normal file
53
SOURCES/openssh-7.2p2-x11.patch
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
diff -up openssh-7.2p2/channels.c.x11 openssh-7.2p2/channels.c
|
||||||
|
--- openssh-7.2p2/channels.c.x11 2016-03-09 19:04:48.000000000 +0100
|
||||||
|
+++ openssh-7.2p2/channels.c 2016-06-03 10:42:04.775164520 +0200
|
||||||
|
@@ -3990,21 +3990,24 @@ x11_create_display_inet(int x11_display_
|
||||||
|
}
|
||||||
|
|
||||||
|
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 < 0)
|
||||||
|
error("socket: %.100s", strerror(errno));
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -4012,8 +4015,18 @@ static int
|
||||||
|
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__
|
2688
SOURCES/openssh-7.3p1-openssl-1.1.0.patch
Normal file
2688
SOURCES/openssh-7.3p1-openssl-1.1.0.patch
Normal file
File diff suppressed because it is too large
Load Diff
213
SOURCES/openssh-7.3p1-x11-max-displays.patch
Normal file
213
SOURCES/openssh-7.3p1-x11-max-displays.patch
Normal file
@ -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 FWD_PERMIT_ANY_HOST "*"
|
||||||
|
|
||||||
|
/* -- 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 select() 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) < 0) {
|
||||||
|
debug2("connect %.100s port %u: %.100s", buf,
|
||||||
|
- 6000 + display_number, strerror(errno));
|
||||||
|
+ X11_PORT_MIN + display_number, strerror(errno));
|
||||||
|
close(sock);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
@@ -4466,8 +4472,8 @@ x11_connect_display(void)
|
||||||
|
}
|
||||||
|
freeaddrinfo(aitop);
|
||||||
|
if (!ai) {
|
||||||
|
- error("connect %.100s port %u: %.100s", buf,
|
||||||
|
- 6000 + display_number, strerror(errno));
|
||||||
|
+ error("connect %.100s port %u: %.100s", buf,
|
||||||
|
+ X11_PORT_MIN + display_number, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
set_nodelay(sock);
|
||||||
|
diff -up openssh-7.4p1/channels.h.x11max openssh-7.4p1/channels.h
|
||||||
|
--- openssh-7.4p1/channels.h.x11max 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 *, u_int);
|
||||||
|
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 {
|
||||||
|
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 StreamLocalBindUnlink ,
|
||||||
|
.Cm TrustedUserCAKeys ,
|
||||||
|
.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
|
98
SOURCES/openssh-7.4p1-systemd.patch
Normal file
98
SOURCES/openssh-7.4p1-systemd.patch
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
commit 0e22b79bfde45a7cf7a2e51a68ec11c4285f3b31
|
||||||
|
Author: Jakub Jelen <jjelen@redhat.com>
|
||||||
|
Date: Mon Nov 21 15:04:06 2016 +0100
|
||||||
|
|
||||||
|
systemd stuff
|
||||||
|
|
||||||
|
diff --git a/configure.ac b/configure.ac
|
||||||
|
index 2ffc369..162ce92 100644
|
||||||
|
--- a/configure.ac
|
||||||
|
+++ b/configure.ac
|
||||||
|
@@ -4265,6 +4265,30 @@ AC_ARG_WITH([kerberos5],
|
||||||
|
AC_SUBST([GSSLIBS])
|
||||||
|
AC_SUBST([K5LIBS])
|
||||||
|
|
||||||
|
+# Check whether user wants systemd support
|
||||||
|
+SYSTEMD_MSG="no"
|
||||||
|
+AC_ARG_WITH(systemd,
|
||||||
|
+ [ --with-systemd Enable systemd support],
|
||||||
|
+ [ if test "x$withval" != "xno" ; then
|
||||||
|
+ AC_PATH_TOOL([PKGCONFIG], [pkg-config], [no])
|
||||||
|
+ if test "$PKGCONFIG" != "no"; then
|
||||||
|
+ AC_MSG_CHECKING([for libsystemd])
|
||||||
|
+ if $PKGCONFIG --exists libsystemd; then
|
||||||
|
+ SYSTEMD_CFLAGS=`$PKGCONFIG --cflags libsystemd`
|
||||||
|
+ SYSTEMD_LIBS=`$PKGCONFIG --libs libsystemd`
|
||||||
|
+ CPPFLAGS="$CPPFLAGS $SYSTEMD_CFLAGS"
|
||||||
|
+ SSHDLIBS="$SSHDLIBS $SYSTEMD_LIBS"
|
||||||
|
+ AC_MSG_RESULT([yes])
|
||||||
|
+ AC_DEFINE(HAVE_SYSTEMD, 1, [Define if you want systemd support.])
|
||||||
|
+ SYSTEMD_MSG="yes"
|
||||||
|
+ else
|
||||||
|
+ AC_MSG_RESULT([no])
|
||||||
|
+ fi
|
||||||
|
+ fi
|
||||||
|
+ fi ]
|
||||||
|
+)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
# Looking for programs, paths and files
|
||||||
|
|
||||||
|
PRIVSEP_PATH=/var/empty
|
||||||
|
@@ -5097,6 +5121,7 @@ echo " libedit support: $LIBEDIT_MSG"
|
||||||
|
echo " Solaris process contract support: $SPC_MSG"
|
||||||
|
echo " Solaris project support: $SP_MSG"
|
||||||
|
echo " Solaris privilege support: $SPP_MSG"
|
||||||
|
+echo " systemd support: $SYSTEMD_MSG"
|
||||||
|
echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG"
|
||||||
|
echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG"
|
||||||
|
echo " BSD Auth support: $BSD_AUTH_MSG"
|
||||||
|
diff --git a/contrib/sshd.service b/contrib/sshd.service
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..e0d4923
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/contrib/sshd.service
|
||||||
|
@@ -0,0 +1,16 @@
|
||||||
|
+[Unit]
|
||||||
|
+Description=OpenSSH server daemon
|
||||||
|
+Documentation=man:sshd(8) man:sshd_config(5)
|
||||||
|
+After=network.target
|
||||||
|
+
|
||||||
|
+[Service]
|
||||||
|
+Type=notify
|
||||||
|
+ExecStart=/usr/sbin/sshd -D $OPTIONS
|
||||||
|
+ExecReload=/bin/kill -HUP $MAINPID
|
||||||
|
+KillMode=process
|
||||||
|
+Restart=on-failure
|
||||||
|
+RestartPreventExitStatus=255
|
||||||
|
+
|
||||||
|
+[Install]
|
||||||
|
+WantedBy=multi-user.target
|
||||||
|
+
|
||||||
|
diff --git a/sshd.c b/sshd.c
|
||||||
|
index 816611c..b8b9d13 100644
|
||||||
|
--- a/sshd.c
|
||||||
|
+++ b/sshd.c
|
||||||
|
@@ -85,6 +85,10 @@
|
||||||
|
#include <prot.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+#ifdef HAVE_SYSTEMD
|
||||||
|
+#include <systemd/sd-daemon.h>
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
#include "xmalloc.h"
|
||||||
|
#include "ssh.h"
|
||||||
|
#include "ssh2.h"
|
||||||
|
@@ -1888,6 +1892,11 @@ main(int ac, char **av)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+#ifdef HAVE_SYSTEMD
|
||||||
|
+ /* Signal systemd that we are ready to accept connections */
|
||||||
|
+ sd_notify(0, "READY=1");
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
/* Accept a connection and return in a forked child */
|
||||||
|
server_accept_loop(&sock_in, &sock_out,
|
||||||
|
&newsock, config_s);
|
1377
SOURCES/openssh-7.5p1-gssapi-kex-with-ec.patch
Normal file
1377
SOURCES/openssh-7.5p1-gssapi-kex-with-ec.patch
Normal file
File diff suppressed because it is too large
Load Diff
108
SOURCES/openssh-7.5p1-sandbox.patch
Normal file
108
SOURCES/openssh-7.5p1-sandbox.patch
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
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_geteuid
|
||||||
|
SC_ALLOW(__NR_geteuid),
|
||||||
|
#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
|
||||||
|
|
||||||
|
The EP11 crypto card needs to make an ioctl call, which receives an
|
||||||
|
specific argument. This crypto card is for s390 only.
|
||||||
|
|
||||||
|
Signed-off-by: Eduardo Barretto <ebarretto@xxxxxxxxxxxxxxxxxx>
|
||||||
|
---
|
||||||
|
sandbox-seccomp-filter.c | 2 ++
|
||||||
|
1 file changed, 2 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/sandbox-seccomp-filter.c b/sandbox-seccomp-filter.c
|
||||||
|
index e86aa2c..98062f1 100644
|
||||||
|
--- a/sandbox-seccomp-filter.c
|
||||||
|
+++ b/sandbox-seccomp-filter.c
|
||||||
|
@@ -250,6 +250,8 @@ static const struct sock_filter preauth_insns[] = {
|
||||||
|
SC_ALLOW_ARG(__NR_ioctl, 1, Z90STAT_STATUS_MASK),
|
||||||
|
SC_ALLOW_ARG(__NR_ioctl, 1, ICARSAMODEXPO),
|
||||||
|
SC_ALLOW_ARG(__NR_ioctl, 1, ICARSACRT),
|
||||||
|
+ /* Allow ioctls for EP11 crypto card on s390 */
|
||||||
|
+ SC_ALLOW_ARG(__NR_ioctl, 1, ZSENDEP11CPRB),
|
||||||
|
#endif
|
||||||
|
#if defined(__x86_64__) && defined(__ILP32__) && defined(__X32_SYSCALL_BIT)
|
||||||
|
/*
|
||||||
|
--
|
||||||
|
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
|
2172
SOURCES/openssh-7.6p1-audit.patch
Normal file
2172
SOURCES/openssh-7.6p1-audit.patch
Normal file
File diff suppressed because it is too large
Load Diff
253
SOURCES/openssh-7.6p1-cleanup-selinux.patch
Normal file
253
SOURCES/openssh-7.6p1-cleanup-selinux.patch
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
diff -up openssh/auth2-pubkey.c.refactor openssh/auth2-pubkey.c
|
||||||
|
--- openssh/auth2-pubkey.c.refactor 2017-09-27 13:10:19.556830609 +0200
|
||||||
|
+++ openssh/auth2-pubkey.c 2017-09-27 13:10:19.677831274 +0200
|
||||||
|
@@ -72,6 +72,9 @@
|
||||||
|
extern ServerOptions options;
|
||||||
|
extern u_char *session_id2;
|
||||||
|
extern u_int session_id2_len;
|
||||||
|
+extern int inetd_flag;
|
||||||
|
+extern int rexeced_flag;
|
||||||
|
+extern Authctxt *the_authctxt;
|
||||||
|
|
||||||
|
static char *
|
||||||
|
format_key(const struct sshkey *key)
|
||||||
|
@@ -432,7 +435,8 @@ match_principals_command(struct passwd *
|
||||||
|
|
||||||
|
if ((pid = subprocess("AuthorizedPrincipalsCommand", runas_pw, command,
|
||||||
|
ac, av, &f,
|
||||||
|
- SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD)) == 0)
|
||||||
|
+ SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD,
|
||||||
|
+ (inetd_flag && !rexeced_flag), the_authctxt)) == 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
uid_swapped = 1;
|
||||||
|
@@ -762,7 +766,8 @@ user_key_command_allowed2(struct passwd
|
||||||
|
|
||||||
|
if ((pid = subprocess("AuthorizedKeysCommand", runas_pw, command,
|
||||||
|
ac, av, &f,
|
||||||
|
- SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD)) == 0)
|
||||||
|
+ SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD,
|
||||||
|
+ (inetd_flag && !rexeced_flag), the_authctxt)) == 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
uid_swapped = 1;
|
||||||
|
diff -up openssh/auth.c.refactor openssh/auth.c
|
||||||
|
--- openssh/auth.c.refactor 2017-09-27 13:10:19.640831071 +0200
|
||||||
|
+++ openssh/auth.c 2017-09-27 13:10:19.678831279 +0200
|
||||||
|
@@ -1435,7 +1435,8 @@ argv_assemble(int argc, char **argv)
|
||||||
|
*/
|
||||||
|
pid_t
|
||||||
|
subprocess(const char *tag, struct passwd *pw, const char *command,
|
||||||
|
- int ac, char **av, FILE **child, u_int flags)
|
||||||
|
+ int ac, char **av, FILE **child, u_int flags, int inetd,
|
||||||
|
+ void *the_authctxt)
|
||||||
|
{
|
||||||
|
FILE *f = NULL;
|
||||||
|
struct stat st;
|
||||||
|
@@ -1551,7 +1552,7 @@ subprocess(const char *tag, struct passw
|
||||||
|
}
|
||||||
|
|
||||||
|
#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/auth.h.refactor openssh/auth.h
|
||||||
|
--- openssh/auth.h.refactor 2017-09-25 01:48:10.000000000 +0200
|
||||||
|
+++ openssh/auth.h 2017-09-27 13:10:19.678831279 +0200
|
||||||
|
@@ -144,7 +144,7 @@ int exited_cleanly(pid_t, const char *,
|
||||||
|
#define SSH_SUBPROCESS_STDOUT_CAPTURE (1<<1) /* Redirect stdout */
|
||||||
|
#define SSH_SUBPROCESS_STDERR_DISCARD (1<<2) /* Discard stderr */
|
||||||
|
pid_t subprocess(const char *, struct passwd *,
|
||||||
|
- const char *, int, char **, FILE **, u_int flags);
|
||||||
|
+ const char *, int, char **, FILE **, u_int flags, int, void *);
|
||||||
|
|
||||||
|
int sys_auth_passwd(struct ssh *, const char *);
|
||||||
|
|
||||||
|
diff -up openssh/openbsd-compat/port-linux.h.refactor openssh/openbsd-compat/port-linux.h
|
||||||
|
--- openssh/openbsd-compat/port-linux.h.refactor 2017-09-27 13:10:19.634831038 +0200
|
||||||
|
+++ openssh/openbsd-compat/port-linux.h 2017-09-27 13:10:54.954025248 +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 2017-09-27 13:10:19.634831038 +0200
|
||||||
|
+++ openssh/openbsd-compat/port-linux-sshd.c 2017-09-27 13:12:06.811420371 +0200
|
||||||
|
@@ -48,11 +48,6 @@
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
-extern ServerOptions options;
|
||||||
|
-extern Authctxt *the_authctxt;
|
||||||
|
-extern int inetd_flag;
|
||||||
|
-extern int rexeced_flag;
|
||||||
|
-
|
||||||
|
/* Wrapper around is_selinux_enabled() to log its return value once only */
|
||||||
|
int
|
||||||
|
sshd_selinux_enabled(void)
|
||||||
|
@@ -222,7 +217,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;
|
||||||
|
@@ -240,8 +236,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;
|
||||||
|
@@ -249,7 +245,7 @@ sshd_selinux_getctxbyname(char *pwname,
|
||||||
|
int r = 0;
|
||||||
|
context_t con = NULL;
|
||||||
|
|
||||||
|
- ssh_selinux_get_role_level(&role, &reqlvl);
|
||||||
|
+ ssh_selinux_get_role_level(&role, &reqlvl, the_authctxt);
|
||||||
|
|
||||||
|
#ifdef HAVE_GETSEUSERBYNAME
|
||||||
|
if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) {
|
||||||
|
@@ -271,7 +267,7 @@ sshd_selinux_getctxbyname(char *pwname,
|
||||||
|
|
||||||
|
if (r == 0) {
|
||||||
|
/* If launched from xinetd, we must use current level */
|
||||||
|
- if (inetd_flag && !rexeced_flag) {
|
||||||
|
+ if (inetd) {
|
||||||
|
security_context_t sshdsc=NULL;
|
||||||
|
|
||||||
|
if (getcon_raw(&sshdsc) < 0)
|
||||||
|
@@ -332,7 +328,8 @@ sshd_selinux_getctxbyname(char *pwname,
|
||||||
|
|
||||||
|
/* Setup environment variables for pam_selinux */
|
||||||
|
static int
|
||||||
|
-sshd_selinux_setup_variables(int(*set_it)(char *, const char *))
|
||||||
|
+sshd_selinux_setup_variables(int(*set_it)(char *, const char *), int inetd,
|
||||||
|
+ Authctxt *the_authctxt)
|
||||||
|
{
|
||||||
|
const char *reqlvl;
|
||||||
|
char *role;
|
||||||
|
@@ -341,11 +338,11 @@ sshd_selinux_setup_variables(int(*set_it
|
||||||
|
|
||||||
|
debug3("%s: setting execution context", __func__);
|
||||||
|
|
||||||
|
- ssh_selinux_get_role_level(&role, &reqlvl);
|
||||||
|
+ ssh_selinux_get_role_level(&role, &reqlvl, the_authctxt);
|
||||||
|
|
||||||
|
rv = set_it("SELINUX_ROLE_REQUESTED", role ? role : "");
|
||||||
|
|
||||||
|
- if (inetd_flag && !rexeced_flag) {
|
||||||
|
+ if (inetd) {
|
||||||
|
use_current = "1";
|
||||||
|
} else {
|
||||||
|
use_current = "";
|
||||||
|
@@ -361,9 +358,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
|
||||||
|
@@ -373,25 +371,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("%s: security_getenforce() failed", __func__);
|
||||||
|
@@ -409,7 +410,7 @@ sshd_selinux_setup_exec_context(char *pw
|
||||||
|
|
||||||
|
debug3("%s: setting execution context", __func__);
|
||||||
|
|
||||||
|
- 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 2017-09-27 13:10:19.574830708 +0200
|
||||||
|
+++ openssh/platform.c 2017-09-27 13:11:45.475303050 +0200
|
||||||
|
@@ -33,6 +33,9 @@
|
||||||
|
|
||||||
|
extern int use_privsep;
|
||||||
|
extern ServerOptions options;
|
||||||
|
+extern int inetd_flag;
|
||||||
|
+extern int rexeced_flag;
|
||||||
|
+extern Authctxt *the_authctxt;
|
||||||
|
|
||||||
|
void
|
||||||
|
platform_pre_listen(void)
|
||||||
|
@@ -184,7 +187,9 @@ platform_setusercontext_post_groups(stru
|
||||||
|
}
|
||||||
|
#endif /* HAVE_SETPCRED */
|
||||||
|
#ifdef WITH_SELINUX
|
||||||
|
- sshd_selinux_setup_exec_context(pw->pw_name);
|
||||||
|
+ sshd_selinux_setup_exec_context(pw->pw_name,
|
||||||
|
+ (inetd_flag && !rexeced_flag), do_pam_putenv, the_authctxt,
|
||||||
|
+ options.use_pam);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
diff -up openssh/sshd.c.refactor openssh/sshd.c
|
||||||
|
--- openssh/sshd.c.refactor 2017-09-27 13:10:19.674831257 +0200
|
||||||
|
+++ openssh/sshd.c 2017-09-27 13:12:01.635391909 +0200
|
||||||
|
@@ -2135,7 +2135,9 @@ main(int ac, char **av)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef WITH_SELINUX
|
||||||
|
- sshd_selinux_setup_exec_context(authctxt->pw->pw_name);
|
||||||
|
+ sshd_selinux_setup_exec_context(authctxt->pw->pw_name,
|
||||||
|
+ (inetd_flag && !rexeced_flag), do_pam_putenv, the_authctxt,
|
||||||
|
+ options.use_pam);
|
||||||
|
#endif
|
||||||
|
#ifdef USE_PAM
|
||||||
|
if (options.use_pam) {
|
801
SOURCES/openssh-7.6p1-pkcs11-ecdsa.patch
Normal file
801
SOURCES/openssh-7.6p1-pkcs11-ecdsa.patch
Normal file
@ -0,0 +1,801 @@
|
|||||||
|
diff -up openssh-7.6p1/ssh-pkcs11-client.c.pkcs11-ecdsa openssh-7.6p1/ssh-pkcs11-client.c
|
||||||
|
--- openssh-7.6p1/ssh-pkcs11-client.c.pkcs11-ecdsa 2018-02-16 13:25:59.426469253 +0100
|
||||||
|
+++ openssh-7.6p1/ssh-pkcs11-client.c 2018-02-16 13:25:59.428469265 +0100
|
||||||
|
@@ -31,6 +31,15 @@
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <openssl/rsa.h>
|
||||||
|
+#ifdef OPENSSL_HAS_ECC
|
||||||
|
+#include <openssl/ecdsa.h>
|
||||||
|
+#if ((defined(LIBRESSL_VERSION_NUMBER) && \
|
||||||
|
+ (LIBRESSL_VERSION_NUMBER >= 0x20010002L))) || \
|
||||||
|
+ (defined(ECDSA_F_ECDSA_METHOD_NEW)) || \
|
||||||
|
+ (OPENSSL_VERSION_NUMBER >= 0x00010100L)
|
||||||
|
+#define ENABLE_PKCS11_ECDSA 1
|
||||||
|
+#endif
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
#include "pathnames.h"
|
||||||
|
#include "xmalloc.h"
|
||||||
|
@@ -139,9 +147,9 @@ pkcs11_rsa_private_encrypt(int flen, con
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
-/* redirect the private key encrypt operation to the ssh-pkcs11-helper */
|
||||||
|
+/* redirect the RSA private key encrypt operation to the ssh-pkcs11-helper */
|
||||||
|
static int
|
||||||
|
-wrap_key(RSA *rsa)
|
||||||
|
+wrap_rsa_key(RSA *rsa)
|
||||||
|
{
|
||||||
|
static RSA_METHOD helper_rsa;
|
||||||
|
|
||||||
|
@@ -152,6 +160,88 @@ wrap_key(RSA *rsa)
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
+#ifdef ENABLE_PKCS11_ECDSA
|
||||||
|
+static ECDSA_SIG *
|
||||||
|
+pkcs11_ecdsa_private_sign(const unsigned char *from, int flen,
|
||||||
|
+ const BIGNUM *inv, const BIGNUM *rp, EC_KEY * ecdsa)
|
||||||
|
+{
|
||||||
|
+ struct sshkey *key = NULL;
|
||||||
|
+ u_char *blob, *signature = NULL;
|
||||||
|
+ size_t blen, slen = 0;
|
||||||
|
+ struct sshbuf *msg = NULL;
|
||||||
|
+ ECDSA_SIG *ret = NULL;
|
||||||
|
+ BIGNUM *r = NULL, *s = NULL;
|
||||||
|
+ int rv;
|
||||||
|
+
|
||||||
|
+ if ((key = sshkey_new(KEY_ECDSA)) == NULL)
|
||||||
|
+ fatal("%s: sshkey_new failed", __func__);
|
||||||
|
+ key->ecdsa = ecdsa;
|
||||||
|
+ key->ecdsa_nid = sshkey_ecdsa_key_to_nid(ecdsa);
|
||||||
|
+ if (sshkey_to_blob(key, &blob, &blen) == 0)
|
||||||
|
+ goto out;
|
||||||
|
+ if ((msg = sshbuf_new()) == NULL)
|
||||||
|
+ fatal("%s: sshbuf_new failed", __func__);
|
||||||
|
+ if ((rv = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 ||
|
||||||
|
+ (rv = sshbuf_put_string(msg, blob, blen)) != 0 ||
|
||||||
|
+ (rv = sshbuf_put_string(msg, from, flen)) != 0 ||
|
||||||
|
+ (rv = sshbuf_put_u32(msg, 0)) != 0)
|
||||||
|
+ fatal("%s: buffer error: %s", __func__, ssh_err(rv));
|
||||||
|
+ free(blob);
|
||||||
|
+ send_msg(msg);
|
||||||
|
+ sshbuf_reset(msg);
|
||||||
|
+
|
||||||
|
+ if (recv_msg(msg) == SSH2_AGENT_SIGN_RESPONSE) {
|
||||||
|
+ if ((rv = sshbuf_get_string(msg, &signature, &slen)) != 0)
|
||||||
|
+ fatal("%s: buffer error: %s", __func__, ssh_err(rv));
|
||||||
|
+ if (slen <= (size_t)ECDSA_size(ecdsa)) {
|
||||||
|
+ int nlen = slen / 2;
|
||||||
|
+ ret = ECDSA_SIG_new();
|
||||||
|
+ r = BN_new();
|
||||||
|
+ s = BN_new();
|
||||||
|
+ BN_bin2bn(&signature[0], nlen, r);
|
||||||
|
+ BN_bin2bn(&signature[nlen], nlen, s);
|
||||||
|
+ ECDSA_SIG_set0(ret, r, s);
|
||||||
|
+ }
|
||||||
|
+ free(signature);
|
||||||
|
+ }
|
||||||
|
+out:
|
||||||
|
+ sshkey_free(key);
|
||||||
|
+ sshbuf_free(msg);
|
||||||
|
+ return (ret);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* redirect the ECDSA private key encrypt operation to the ssh-pkcs11-helper */
|
||||||
|
+static int
|
||||||
|
+wrap_ecdsa_key(EC_KEY *ecdsa) {
|
||||||
|
+#if (OPENSSL_VERSION_NUMBER >= 0x00010100L)
|
||||||
|
+ static EC_KEY_METHOD *helper_ecdsa = NULL;
|
||||||
|
+ if (helper_ecdsa == NULL) {
|
||||||
|
+ const EC_KEY_METHOD *def = EC_KEY_get_default_method();
|
||||||
|
+ helper_ecdsa = EC_KEY_METHOD_new(def);
|
||||||
|
+ EC_KEY_METHOD_set_sign(helper_ecdsa, NULL, NULL, pkcs11_ecdsa_private_sign);
|
||||||
|
+ }
|
||||||
|
+ EC_KEY_set_method(ecdsa, helper_ecdsa);
|
||||||
|
+#else
|
||||||
|
+ static ECDSA_METHOD *helper_ecdsa = NULL;
|
||||||
|
+ if(helper_ecdsa == NULL) {
|
||||||
|
+ const ECDSA_METHOD *def = ECDSA_get_default_method();
|
||||||
|
+# ifdef ECDSA_F_ECDSA_METHOD_NEW
|
||||||
|
+ helper_ecdsa = ECDSA_METHOD_new((ECDSA_METHOD *)def);
|
||||||
|
+ ECDSA_METHOD_set_name(helper_ecdsa, "ssh-pkcs11-helper-ecdsa");
|
||||||
|
+ ECDSA_METHOD_set_sign(helper_ecdsa, pkcs11_ecdsa_private_sign);
|
||||||
|
+# else
|
||||||
|
+ helper_ecdsa = xcalloc(1, sizeof(*helper_ecdsa));
|
||||||
|
+ memcpy(helper_ecdsa, def, sizeof(*helper_ecdsa));
|
||||||
|
+ helper_ecdsa->name = "ssh-pkcs11-helper-ecdsa";
|
||||||
|
+ helper_ecdsa->ecdsa_do_sign = pkcs11_ecdsa_private_sign;
|
||||||
|
+# endif
|
||||||
|
+ }
|
||||||
|
+ ECDSA_set_method(ecdsa, helper_ecdsa);
|
||||||
|
+#endif
|
||||||
|
+ return (0);
|
||||||
|
+}
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
pkcs11_start_helper(void)
|
||||||
|
{
|
||||||
|
@@ -212,7 +281,15 @@ pkcs11_add_provider(char *name, char *pi
|
||||||
|
__func__, ssh_err(r));
|
||||||
|
if ((r = sshkey_from_blob(blob, blen, &k)) != 0)
|
||||||
|
fatal("%s: bad key: %s", __func__, ssh_err(r));
|
||||||
|
- wrap_key(k->rsa);
|
||||||
|
+ if(k->type == KEY_RSA) {
|
||||||
|
+ wrap_rsa_key(k->rsa);
|
||||||
|
+#ifdef ENABLE_PKCS11_ECDSA
|
||||||
|
+ } else if(k->type == KEY_ECDSA) {
|
||||||
|
+ wrap_ecdsa_key(k->ecdsa);
|
||||||
|
+#endif /* ENABLE_PKCS11_ECDSA */
|
||||||
|
+ } else {
|
||||||
|
+ /* Unsupported type */
|
||||||
|
+ }
|
||||||
|
(*keysp)[i] = k;
|
||||||
|
free(blob);
|
||||||
|
}
|
||||||
|
diff -up openssh-7.6p1/ssh-pkcs11.c.pkcs11-ecdsa openssh-7.6p1/ssh-pkcs11.c
|
||||||
|
--- openssh-7.6p1/ssh-pkcs11.c.pkcs11-ecdsa 2018-02-16 13:25:59.427469259 +0100
|
||||||
|
+++ openssh-7.6p1/ssh-pkcs11.c 2018-02-16 13:44:51.270554797 +0100
|
||||||
|
@@ -32,6 +32,16 @@
|
||||||
|
#include "openbsd-compat/sys-queue.h"
|
||||||
|
|
||||||
|
#include <openssl/x509.h>
|
||||||
|
+#include <openssl/rsa.h>
|
||||||
|
+#ifdef OPENSSL_HAS_ECC
|
||||||
|
+#include <openssl/ecdsa.h>
|
||||||
|
+#if ((defined(LIBRESSL_VERSION_NUMBER) && \
|
||||||
|
+ (LIBRESSL_VERSION_NUMBER >= 0x20010002L))) || \
|
||||||
|
+ (defined(ECDSA_F_ECDSA_METHOD_NEW)) || \
|
||||||
|
+ (OPENSSL_VERSION_NUMBER >= 0x00010100L)
|
||||||
|
+#define ENABLE_PKCS11_ECDSA 1
|
||||||
|
+#endif
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
#define CRYPTOKI_COMPAT
|
||||||
|
#include "pkcs11.h"
|
||||||
|
@@ -67,6 +76,7 @@ TAILQ_HEAD(, pkcs11_provider) pkcs11_pro
|
||||||
|
struct pkcs11_key {
|
||||||
|
struct pkcs11_provider *provider;
|
||||||
|
CK_ULONG slotidx;
|
||||||
|
+ CK_ULONG key_type;
|
||||||
|
int (*orig_finish)(RSA *rsa);
|
||||||
|
RSA_METHOD rsa_method;
|
||||||
|
char *keyid;
|
||||||
|
@@ -75,6 +85,9 @@ struct pkcs11_key {
|
||||||
|
};
|
||||||
|
|
||||||
|
int pkcs11_interactive = 0;
|
||||||
|
+#ifdef ENABLE_PKCS11_ECDSA
|
||||||
|
+static int pkcs11_key_idx = -1;
|
||||||
|
+#endif /* ENABLE_PKCS11_ECDSA */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This can't be in the ssh-pkcs11-uri, becase we can not depend on
|
||||||
|
@@ -289,6 +302,40 @@ pkcs11_find(struct pkcs11_provider *p, C
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
+int pkcs11_login(struct pkcs11_key *k11, CK_FUNCTION_LIST *f, struct pkcs11_slotinfo *si) {
|
||||||
|
+ char *pin = NULL, prompt[1024];
|
||||||
|
+ CK_RV rv;
|
||||||
|
+ if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) {
|
||||||
|
+ if (!pkcs11_interactive) {
|
||||||
|
+ error("need pin entry%s", (si->token.flags &
|
||||||
|
+ CKF_PROTECTED_AUTHENTICATION_PATH) ?
|
||||||
|
+ " on reader keypad" : "");
|
||||||
|
+ return (-1);
|
||||||
|
+ }
|
||||||
|
+ if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
|
||||||
|
+ verbose("Deferring PIN entry to reader keypad.");
|
||||||
|
+ else {
|
||||||
|
+ snprintf(prompt, sizeof(prompt),
|
||||||
|
+ "Enter PIN for '%s': ", si->token.label);
|
||||||
|
+ pin = read_passphrase(prompt, RP_ALLOW_EOF);
|
||||||
|
+ if (pin == NULL)
|
||||||
|
+ return (-1); /* bail out */
|
||||||
|
+ }
|
||||||
|
+ rv = f->C_Login(si->session, CKU_USER, (u_char *)pin,
|
||||||
|
+ (pin != NULL) ? strlen(pin) : 0);
|
||||||
|
+ if (pin != NULL) {
|
||||||
|
+ explicit_bzero(pin, strlen(pin));
|
||||||
|
+ free(pin);
|
||||||
|
+ }
|
||||||
|
+ if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) {
|
||||||
|
+ error("C_Login failed: %lu", rv);
|
||||||
|
+ return (-1);
|
||||||
|
+ }
|
||||||
|
+ si->logged_in = 1;
|
||||||
|
+ }
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* openssl callback doing the actual signing operation */
|
||||||
|
static int
|
||||||
|
pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
|
||||||
|
@@ -310,7 +357,6 @@ pkcs11_rsa_private_encrypt(int flen, con
|
||||||
|
{CKA_ID, NULL, 0},
|
||||||
|
{CKA_SIGN, NULL, sizeof(true_val) }
|
||||||
|
};
|
||||||
|
- char *pin = NULL, prompt[1024];
|
||||||
|
int rval = -1;
|
||||||
|
|
||||||
|
key_filter[0].pValue = &private_key_class;
|
||||||
|
@@ -326,33 +372,8 @@ pkcs11_rsa_private_encrypt(int flen, con
|
||||||
|
}
|
||||||
|
f = k11->provider->module->function_list;
|
||||||
|
si = &k11->provider->module->slotinfo[k11->slotidx];
|
||||||
|
- if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) {
|
||||||
|
- if (!pkcs11_interactive) {
|
||||||
|
- error("need pin entry%s", (si->token.flags &
|
||||||
|
- CKF_PROTECTED_AUTHENTICATION_PATH) ?
|
||||||
|
- " on reader keypad" : "");
|
||||||
|
- return (-1);
|
||||||
|
- }
|
||||||
|
- if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
|
||||||
|
- verbose("Deferring PIN entry to reader keypad.");
|
||||||
|
- else {
|
||||||
|
- snprintf(prompt, sizeof(prompt),
|
||||||
|
- "Enter PIN for '%s': ", si->token.label);
|
||||||
|
- pin = read_passphrase(prompt, RP_ALLOW_EOF);
|
||||||
|
- if (pin == NULL)
|
||||||
|
- return (-1); /* bail out */
|
||||||
|
- }
|
||||||
|
- rv = f->C_Login(si->session, CKU_USER, (u_char *)pin,
|
||||||
|
- (pin != NULL) ? strlen(pin) : 0);
|
||||||
|
- if (pin != NULL) {
|
||||||
|
- explicit_bzero(pin, strlen(pin));
|
||||||
|
- free(pin);
|
||||||
|
- }
|
||||||
|
- if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) {
|
||||||
|
- error("C_Login failed: %lu", rv);
|
||||||
|
- return (-1);
|
||||||
|
- }
|
||||||
|
- si->logged_in = 1;
|
||||||
|
+ if(pkcs11_login(k11, f, si)) {
|
||||||
|
+ return (-1);
|
||||||
|
}
|
||||||
|
key_filter[1].pValue = k11->keyid;
|
||||||
|
key_filter[1].ulValueLen = k11->keyid_len;
|
||||||
|
@@ -390,6 +411,7 @@ pkcs11_rsa_wrap(struct pkcs11_provider *
|
||||||
|
const RSA_METHOD *def = RSA_get_default_method();
|
||||||
|
|
||||||
|
k11 = xcalloc(1, sizeof(*k11));
|
||||||
|
+ k11->key_type = CKK_RSA;
|
||||||
|
k11->provider = provider;
|
||||||
|
provider->refcount++; /* provider referenced by RSA key */
|
||||||
|
k11->slotidx = slotidx;
|
||||||
|
@@ -415,6 +437,184 @@ pkcs11_rsa_wrap(struct pkcs11_provider *
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
+#ifdef ENABLE_PKCS11_ECDSA
|
||||||
|
+static ECDSA_SIG *pkcs11_ecdsa_sign(const unsigned char *dgst, int dgst_len,
|
||||||
|
+ const BIGNUM *inv, const BIGNUM *rp,
|
||||||
|
+ EC_KEY *ecdsa) {
|
||||||
|
+ struct pkcs11_key *k11;
|
||||||
|
+ struct pkcs11_slotinfo *si;
|
||||||
|
+ CK_FUNCTION_LIST *f;
|
||||||
|
+ CK_OBJECT_HANDLE obj;
|
||||||
|
+ CK_ULONG tlen = 0;
|
||||||
|
+ CK_RV rv;
|
||||||
|
+ CK_OBJECT_CLASS private_key_class = CKO_PRIVATE_KEY;
|
||||||
|
+ CK_BBOOL true_val = CK_TRUE;
|
||||||
|
+ CK_MECHANISM mech = {
|
||||||
|
+ CKM_ECDSA, NULL_PTR, 0
|
||||||
|
+ };
|
||||||
|
+ CK_ATTRIBUTE key_filter[] = {
|
||||||
|
+ {CKA_CLASS, NULL, sizeof(private_key_class) },
|
||||||
|
+ {CKA_ID, NULL, 0},
|
||||||
|
+ {CKA_SIGN, NULL, sizeof(true_val) }
|
||||||
|
+ };
|
||||||
|
+ ECDSA_SIG *rval = NULL;
|
||||||
|
+ key_filter[0].pValue = &private_key_class;
|
||||||
|
+ key_filter[2].pValue = &true_val;
|
||||||
|
+
|
||||||
|
+ #if (OPENSSL_VERSION_NUMBER >= 0x00010100L)
|
||||||
|
+ if ((k11 = (struct pkcs11_key *)EC_KEY_get_ex_data(ecdsa, pkcs11_key_idx)) == NULL) {
|
||||||
|
+ error("EC_KEY_get_ex_data failed for ecdsa %p", ecdsa);
|
||||||
|
+ #else
|
||||||
|
+ if ((k11 = (struct pkcs11_key *)ECDSA_get_ex_data(ecdsa, pkcs11_key_idx)) == NULL) {
|
||||||
|
+ error("ECDSA_get_ex_data failed for ecdsa %p", ecdsa);
|
||||||
|
+ #endif
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
+ if (!k11->provider || !k11->provider->valid) {
|
||||||
|
+ error("no pkcs11 (valid) provider for ecdsa %p", ecdsa);
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
+ f = k11->provider->module->function_list;
|
||||||
|
+ si = &k11->provider->module->slotinfo[k11->slotidx];
|
||||||
|
+ if(pkcs11_login(k11, f, si)) {
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
+ key_filter[1].pValue = k11->keyid;
|
||||||
|
+ key_filter[1].ulValueLen = k11->keyid_len;
|
||||||
|
+ /* try to find object w/CKA_SIGN first, retry w/o */
|
||||||
|
+ if (pkcs11_find(k11->provider, k11->slotidx, key_filter, 3, &obj) < 0 &&
|
||||||
|
+ pkcs11_find(k11->provider, k11->slotidx, key_filter, 2, &obj) < 0) {
|
||||||
|
+ error("cannot find private key");
|
||||||
|
+ } else if ((rv = f->C_SignInit(si->session, &mech, obj)) != CKR_OK) {
|
||||||
|
+ error("C_SignInit failed: %lu", rv);
|
||||||
|
+ } else {
|
||||||
|
+ CK_BYTE_PTR buf = NULL;
|
||||||
|
+ BIGNUM *r = NULL, *s = NULL;
|
||||||
|
+ int nlen;
|
||||||
|
+ /* Make a call to C_Sign to find out the size of the signature */
|
||||||
|
+ rv = f->C_Sign(si->session, (CK_BYTE *)dgst, dgst_len, NULL, &tlen);
|
||||||
|
+ if (rv != CKR_OK) {
|
||||||
|
+ error("C_Sign failed: %lu", rv);
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
+ if ((buf = xmalloc(tlen)) == NULL) {
|
||||||
|
+ error("failure to allocate signature buffer");
|
||||||
|
+ return NULL;
|
||||||
|
+ }
|
||||||
|
+ rv = f->C_Sign(si->session, (CK_BYTE *)dgst, dgst_len, buf, &tlen);
|
||||||
|
+ if (rv != CKR_OK) {
|
||||||
|
+ error("C_Sign failed: %lu", rv);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if ((rval = ECDSA_SIG_new()) == NULL ||
|
||||||
|
+ (r = BN_new()) == NULL ||
|
||||||
|
+ (s = BN_new()) == NULL) {
|
||||||
|
+ error("failure to allocate ECDSA signature");
|
||||||
|
+ } else {
|
||||||
|
+ /*
|
||||||
|
+ * ECDSA signature is 2 large integers of same size returned
|
||||||
|
+ * concatenated by PKCS#11, we separate them to create an
|
||||||
|
+ * ECDSA_SIG for OpenSSL.
|
||||||
|
+ */
|
||||||
|
+ nlen = tlen / 2;
|
||||||
|
+ BN_bin2bn(&buf[0], nlen, r);
|
||||||
|
+ BN_bin2bn(&buf[nlen], nlen, s);
|
||||||
|
+ ECDSA_SIG_set0(rval, r, s);
|
||||||
|
+ }
|
||||||
|
+ free(buf);
|
||||||
|
+ }
|
||||||
|
+ return (rval);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#if (OPENSSL_VERSION_NUMBER >= 0x00010100L)
|
||||||
|
+static EC_KEY_METHOD *get_pkcs11_ecdsa_method(void) {
|
||||||
|
+ static EC_KEY_METHOD *pkcs11_ecdsa_method = NULL;
|
||||||
|
+ if(pkcs11_key_idx == -1) {
|
||||||
|
+ pkcs11_key_idx = EC_KEY_get_ex_new_index(0, NULL, NULL, NULL, 0);
|
||||||
|
+ }
|
||||||
|
+ if (pkcs11_ecdsa_method == NULL) {
|
||||||
|
+ const EC_KEY_METHOD *def = EC_KEY_get_default_method();
|
||||||
|
+ pkcs11_ecdsa_method = EC_KEY_METHOD_new(def);
|
||||||
|
+ EC_KEY_METHOD_set_sign(pkcs11_ecdsa_method, NULL, NULL, pkcs11_ecdsa_sign);
|
||||||
|
+ }
|
||||||
|
+#else
|
||||||
|
+static ECDSA_METHOD *get_pkcs11_ecdsa_method(void) {
|
||||||
|
+ static ECDSA_METHOD *pkcs11_ecdsa_method = NULL;
|
||||||
|
+ if(pkcs11_key_idx == -1) {
|
||||||
|
+ pkcs11_key_idx = ECDSA_get_ex_new_index(0, NULL, NULL, NULL, 0);
|
||||||
|
+ }
|
||||||
|
+ if(pkcs11_ecdsa_method == NULL) {
|
||||||
|
+ const ECDSA_METHOD *def = ECDSA_get_default_method();
|
||||||
|
+ #ifdef ECDSA_F_ECDSA_METHOD_NEW
|
||||||
|
+ pkcs11_ecdsa_method = ECDSA_METHOD_new((ECDSA_METHOD *)def);
|
||||||
|
+ ECDSA_METHOD_set_name(pkcs11_ecdsa_method, "pkcs11");
|
||||||
|
+ ECDSA_METHOD_set_sign(pkcs11_ecdsa_method, pkcs11_ecdsa_sign);
|
||||||
|
+ #else
|
||||||
|
+ pkcs11_ecdsa_method = xcalloc(1, sizeof(*pkcs11_ecdsa_method));
|
||||||
|
+ memcpy(pkcs11_ecdsa_method, def, sizeof(*pkcs11_ecdsa_method));
|
||||||
|
+ pkcs11_ecdsa_method->name = "pkcs11";
|
||||||
|
+ pkcs11_ecdsa_method->ecdsa_do_sign = pkcs11_ecdsa_sign;
|
||||||
|
+ #endif
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+ return pkcs11_ecdsa_method;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx,
|
||||||
|
+ CK_ATTRIBUTE *keyid_attrib, CK_ATTRIBUTE *label_attrib, EC_KEY *ecdsa)
|
||||||
|
+{
|
||||||
|
+ struct pkcs11_key *k11;
|
||||||
|
+ k11 = xcalloc(1, sizeof(*k11));
|
||||||
|
+ k11->key_type = CKK_EC;
|
||||||
|
+ k11->provider = provider;
|
||||||
|
+ provider->refcount++; /* provider referenced by ECDSA key */
|
||||||
|
+ k11->slotidx = slotidx;
|
||||||
|
+ /* identify key object on smartcard */
|
||||||
|
+ k11->keyid_len = keyid_attrib->ulValueLen;
|
||||||
|
+ if (k11->keyid_len > 0) {
|
||||||
|
+ k11->keyid = xmalloc(k11->keyid_len);
|
||||||
|
+ memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len);
|
||||||
|
+ }
|
||||||
|
+ if (label_attrib->ulValueLen > 0 ) {
|
||||||
|
+ k11->label = xmalloc(label_attrib->ulValueLen+1);
|
||||||
|
+ memcpy(k11->label, label_attrib->pValue, label_attrib->ulValueLen);
|
||||||
|
+ k11->label[label_attrib->ulValueLen] = 0;
|
||||||
|
+ }
|
||||||
|
+ #if (OPENSSL_VERSION_NUMBER >= 0x00010100L)
|
||||||
|
+ EC_KEY_set_method(ecdsa, get_pkcs11_ecdsa_method());
|
||||||
|
+ EC_KEY_set_ex_data(ecdsa, pkcs11_key_idx, k11);
|
||||||
|
+ #else
|
||||||
|
+ ECDSA_set_method(ecdsa, get_pkcs11_ecdsa_method());
|
||||||
|
+ ECDSA_set_ex_data(ecdsa, pkcs11_key_idx, k11);
|
||||||
|
+ #endif
|
||||||
|
+ return (0);
|
||||||
|
+}
|
||||||
|
+#endif /* ENABLE_PKCS11_ECDSA */
|
||||||
|
+
|
||||||
|
+int pkcs11_del_key(struct sshkey *key) {
|
||||||
|
+#ifdef ENABLE_PKCS11_ECDSA
|
||||||
|
+ if(key->type == KEY_ECDSA) {
|
||||||
|
+ struct pkcs11_key *k11 = (struct pkcs11_key *)
|
||||||
|
+ #if (OPENSSL_VERSION_NUMBER >= 0x00010100L)
|
||||||
|
+ EC_KEY_get_ex_data(key->ecdsa, pkcs11_key_idx);
|
||||||
|
+ #else
|
||||||
|
+ ECDSA_get_ex_data(key->ecdsa, pkcs11_key_idx);
|
||||||
|
+ #endif
|
||||||
|
+ if (k11 == NULL) {
|
||||||
|
+ error("EC_KEY_get_ex_data failed for ecdsa %p", key->ecdsa);
|
||||||
|
+ } else {
|
||||||
|
+ if (k11->provider)
|
||||||
|
+ pkcs11_provider_unref(k11->provider);
|
||||||
|
+ free(k11->keyid);
|
||||||
|
+ free(k11);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+#endif /* ENABLE_PKCS11_ECDSA */
|
||||||
|
+ sshkey_free(key);
|
||||||
|
+ return (0);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* remove trailing spaces */
|
||||||
|
static void
|
||||||
|
rmspace(u_char *buf, size_t len)
|
||||||
|
@@ -482,11 +646,13 @@ static int
|
||||||
|
pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,
|
||||||
|
struct sshkey ***keysp, int *nkeys, struct pkcs11_uri *uri)
|
||||||
|
{
|
||||||
|
- size_t filter_size = 1;
|
||||||
|
+ size_t filter_size = 2;
|
||||||
|
+ CK_KEY_TYPE pubkey_type = CKK_RSA;
|
||||||
|
CK_OBJECT_CLASS pubkey_class = CKO_PUBLIC_KEY;
|
||||||
|
CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE;
|
||||||
|
CK_ATTRIBUTE pubkey_filter[] = {
|
||||||
|
{ CKA_CLASS, NULL, sizeof(pubkey_class) },
|
||||||
|
+ { CKA_KEY_TYPE, NULL, sizeof(pubkey_type) },
|
||||||
|
{ CKA_ID, NULL, 0 },
|
||||||
|
{ CKA_LABEL, NULL, 0 }
|
||||||
|
};
|
||||||
|
@@ -507,29 +673,60 @@ pkcs11_fetch_keys(struct pkcs11_provider
|
||||||
|
{ CKA_SUBJECT, NULL, 0 },
|
||||||
|
{ CKA_VALUE, NULL, 0 }
|
||||||
|
};
|
||||||
|
+#ifdef ENABLE_PKCS11_ECDSA
|
||||||
|
+ CK_KEY_TYPE ecdsa_type = CKK_EC;
|
||||||
|
+ CK_ATTRIBUTE ecdsa_filter[] = {
|
||||||
|
+ { CKA_CLASS, NULL, sizeof(pubkey_class) },
|
||||||
|
+ { CKA_KEY_TYPE, NULL, sizeof(ecdsa_type) },
|
||||||
|
+ { CKA_ID, NULL, 0 },
|
||||||
|
+ { CKA_LABEL, NULL, 0 }
|
||||||
|
+ };
|
||||||
|
+ CK_ATTRIBUTE ecdsa_attribs[] = {
|
||||||
|
+ { CKA_ID, NULL, 0 },
|
||||||
|
+ { CKA_LABEL, NULL, 0 },
|
||||||
|
+ { CKA_EC_PARAMS, NULL, 0 },
|
||||||
|
+ { CKA_EC_POINT, NULL, 0 }
|
||||||
|
+ };
|
||||||
|
+ ecdsa_filter[0].pValue = &pubkey_class;
|
||||||
|
+ ecdsa_filter[1].pValue = &ecdsa_type;
|
||||||
|
+#endif /* ENABLE_PKCS11_ECDSA */
|
||||||
|
pubkey_filter[0].pValue = &pubkey_class;
|
||||||
|
+ pubkey_filter[1].pValue = &pubkey_type;
|
||||||
|
cert_filter[0].pValue = &cert_class;
|
||||||
|
|
||||||
|
if (uri->id != NULL) {
|
||||||
|
pubkey_filter[filter_size].pValue = uri->id;
|
||||||
|
pubkey_filter[filter_size].ulValueLen = uri->id_len;
|
||||||
|
- cert_filter[filter_size].pValue = uri->id;
|
||||||
|
- cert_filter[filter_size].ulValueLen = uri->id_len;
|
||||||
|
+#ifdef ENABLE_PKCS11_ECDSA
|
||||||
|
+ ecdsa_filter[filter_size].pValue = uri->id;
|
||||||
|
+ ecdsa_filter[filter_size].ulValueLen = uri->id_len;
|
||||||
|
+#endif /* ENABLE_PKCS11_ECDSA */
|
||||||
|
+ cert_filter[filter_size-1].pValue = uri->id;
|
||||||
|
+ cert_filter[filter_size-1].ulValueLen = uri->id_len;
|
||||||
|
filter_size++;
|
||||||
|
}
|
||||||
|
if (uri->object != NULL) {
|
||||||
|
pubkey_filter[filter_size].pValue = uri->object;
|
||||||
|
pubkey_filter[filter_size].ulValueLen = strlen(uri->object);
|
||||||
|
pubkey_filter[filter_size].type = CKA_LABEL;
|
||||||
|
- cert_filter[filter_size].pValue = uri->object;
|
||||||
|
- cert_filter[filter_size].ulValueLen = strlen(uri->object);
|
||||||
|
- cert_filter[filter_size].type = CKA_LABEL;
|
||||||
|
+#ifdef ENABLE_PKCS11_ECDSA
|
||||||
|
+ ecdsa_filter[filter_size].pValue = uri->object;
|
||||||
|
+ ecdsa_filter[filter_size].ulValueLen = strlen(uri->object);
|
||||||
|
+ ecdsa_filter[filter_size].type = CKA_LABEL;
|
||||||
|
+#endif /* ENABLE_PKCS11_ECDSA */
|
||||||
|
+ cert_filter[filter_size-1].pValue = uri->object;
|
||||||
|
+ cert_filter[filter_size-1].ulValueLen = strlen(uri->object);
|
||||||
|
+ cert_filter[filter_size-1].type = CKA_LABEL;
|
||||||
|
filter_size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pkcs11_fetch_keys_filter(p, slotidx, pubkey_filter, filter_size,
|
||||||
|
pubkey_attribs, keysp, nkeys) < 0 ||
|
||||||
|
- pkcs11_fetch_keys_filter(p, slotidx, cert_filter, filter_size,
|
||||||
|
+#ifdef ENABLE_PKCS11_ECDSA
|
||||||
|
+ pkcs11_fetch_keys_filter(p, slotidx, ecdsa_filter, filter_size,
|
||||||
|
+ ecdsa_attribs, keysp, nkeys) < 0||
|
||||||
|
+#endif /* ENABLE_PKCS11_ECDSA */
|
||||||
|
+ pkcs11_fetch_keys_filter(p, slotidx, cert_filter, filter_size - 1,
|
||||||
|
cert_attribs, keysp, nkeys) < 0)
|
||||||
|
return (-1);
|
||||||
|
return (0);
|
||||||
|
@@ -553,6 +746,11 @@ pkcs11_fetch_keys_filter(struct pkcs11_p
|
||||||
|
{
|
||||||
|
struct sshkey *key;
|
||||||
|
RSA *rsa;
|
||||||
|
+#ifdef ENABLE_PKCS11_ECDSA
|
||||||
|
+ EC_KEY *ecdsa;
|
||||||
|
+#else
|
||||||
|
+ void *ecdsa;
|
||||||
|
+#endif /* ENABLE_PKCS11_ECDSA */
|
||||||
|
X509 *x509;
|
||||||
|
EVP_PKEY *evp = NULL;
|
||||||
|
int i;
|
||||||
|
@@ -608,6 +806,9 @@ pkcs11_fetch_keys_filter(struct pkcs11_p
|
||||||
|
* or ID, label, subject and value for certificates.
|
||||||
|
*/
|
||||||
|
rsa = NULL;
|
||||||
|
+#ifdef ENABLE_PKCS11_ECDSA
|
||||||
|
+ ecdsa = NULL;
|
||||||
|
+#endif /* ENABLE_PKCS11_ECDSA */
|
||||||
|
if ((rv = f->C_GetAttributeValue(session, obj, attribs, nattribs))
|
||||||
|
!= CKR_OK) {
|
||||||
|
error("C_GetAttributeValue failed: %lu", rv);
|
||||||
|
@@ -620,6 +821,45 @@ pkcs11_fetch_keys_filter(struct pkcs11_p
|
||||||
|
rsa->e = BN_bin2bn(attribs[3].pValue,
|
||||||
|
attribs[3].ulValueLen, NULL);
|
||||||
|
}
|
||||||
|
+#ifdef ENABLE_PKCS11_ECDSA
|
||||||
|
+ } else if (attribs[2].type == CKA_EC_PARAMS ) {
|
||||||
|
+ if ((ecdsa = EC_KEY_new()) == NULL) {
|
||||||
|
+ error("EC_KEY_new failed");
|
||||||
|
+ } else {
|
||||||
|
+ const unsigned char *ptr1 = attribs[2].pValue;
|
||||||
|
+ const unsigned char *ptr2 = attribs[3].pValue;
|
||||||
|
+ CK_ULONG len1 = attribs[2].ulValueLen;
|
||||||
|
+ CK_ULONG len2 = attribs[3].ulValueLen;
|
||||||
|
+ ASN1_OCTET_STRING *point = NULL;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * CKA_EC_PARAMS contains the curve parameters of the key
|
||||||
|
+ * either referenced as an OID or directly with all values.
|
||||||
|
+ * CKA_EC_POINT contains the point (public key) on the curve.
|
||||||
|
+ * The point is should be returned inside a DER-encoded
|
||||||
|
+ * ASN.1 OCTET STRING value (but some implementation).
|
||||||
|
+ */
|
||||||
|
+ if ((point = d2i_ASN1_OCTET_STRING(NULL, &ptr2, len2))) {
|
||||||
|
+ /* Pointing to OCTET STRING content */
|
||||||
|
+ ptr2 = point->data;
|
||||||
|
+ len2 = point->length;
|
||||||
|
+ } else {
|
||||||
|
+ /* No OCTET STRING */
|
||||||
|
+ ptr2 = attribs[3].pValue;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if((d2i_ECParameters(&ecdsa, &ptr1, len1) == NULL) ||
|
||||||
|
+ (o2i_ECPublicKey(&ecdsa, &ptr2, len2) == NULL)) {
|
||||||
|
+ EC_KEY_free(ecdsa);
|
||||||
|
+ ecdsa = NULL;
|
||||||
|
+ error("EC public key parsing failed");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if(point) {
|
||||||
|
+ ASN1_OCTET_STRING_free(point);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+#endif /* ENABLE_PKCS11_ECDSA */
|
||||||
|
} else {
|
||||||
|
cp = attribs[3].pValue;
|
||||||
|
if ((x509 = X509_new()) == NULL) {
|
||||||
|
@@ -639,13 +879,28 @@ pkcs11_fetch_keys_filter(struct pkcs11_p
|
||||||
|
X509_free(x509);
|
||||||
|
EVP_PKEY_free(evp);
|
||||||
|
}
|
||||||
|
- if (rsa && rsa->n && rsa->e &&
|
||||||
|
- pkcs11_rsa_wrap(p, slotidx, &attribs[0], &attribs[1], rsa) == 0) {
|
||||||
|
- if ((key = sshkey_new(KEY_UNSPEC)) == NULL)
|
||||||
|
- fatal("sshkey_new failed");
|
||||||
|
- key->rsa = rsa;
|
||||||
|
- key->type = KEY_RSA;
|
||||||
|
- key->flags |= SSHKEY_FLAG_EXT;
|
||||||
|
+ key = NULL;
|
||||||
|
+ if (rsa || ecdsa) {
|
||||||
|
+ if (rsa && rsa->n && rsa->e &&
|
||||||
|
+ pkcs11_rsa_wrap(p, slotidx, &attribs[0], &attribs[1], rsa) == 0) {
|
||||||
|
+ if ((key = sshkey_new(KEY_UNSPEC)) == NULL)
|
||||||
|
+ fatal("sshkey_new failed");
|
||||||
|
+ key->rsa = rsa;
|
||||||
|
+ key->type = KEY_RSA;
|
||||||
|
+ key->flags |= SSHKEY_FLAG_EXT;
|
||||||
|
+#ifdef ENABLE_PKCS11_ECDSA
|
||||||
|
+ } else if(ecdsa && pkcs11_ecdsa_wrap(p, slotidx, &attribs[0], &attribs[1], ecdsa) == 0) {
|
||||||
|
+ if ((key = sshkey_new(KEY_UNSPEC)) == NULL)
|
||||||
|
+ fatal("sshkey_new failed");
|
||||||
|
+ key->ecdsa = ecdsa;
|
||||||
|
+ key->ecdsa_nid = sshkey_ecdsa_key_to_nid(ecdsa);
|
||||||
|
+ key->type = KEY_ECDSA;
|
||||||
|
+ key->flags |= SSHKEY_FLAG_EXT;
|
||||||
|
+#endif /* ENABLE_PKCS11_ECDSA */
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if(key) {
|
||||||
|
if (pkcs11_key_included(keysp, nkeys, key)) {
|
||||||
|
sshkey_free(key);
|
||||||
|
} else {
|
||||||
|
@@ -658,6 +913,10 @@ pkcs11_fetch_keys_filter(struct pkcs11_p
|
||||||
|
}
|
||||||
|
} else if (rsa) {
|
||||||
|
RSA_free(rsa);
|
||||||
|
+#ifdef ENABLE_PKCS11_ECDSA
|
||||||
|
+ } else if (ecdsa) {
|
||||||
|
+ EC_KEY_free(ecdsa);
|
||||||
|
+#endif /* ENABLE_PKCS11_ECDSA */
|
||||||
|
}
|
||||||
|
for (i = 0; i < nattribs; i++)
|
||||||
|
free(attribs[i].pValue);
|
||||||
|
diff -up openssh-7.6p1/ssh-pkcs11-helper.c.pkcs11-ecdsa openssh-7.6p1/ssh-pkcs11-helper.c
|
||||||
|
--- openssh-7.6p1/ssh-pkcs11-helper.c.pkcs11-ecdsa 2017-10-02 21:34:26.000000000 +0200
|
||||||
|
+++ openssh-7.6p1/ssh-pkcs11-helper.c 2018-02-16 13:25:59.428469265 +0100
|
||||||
|
@@ -24,6 +24,17 @@
|
||||||
|
|
||||||
|
#include "openbsd-compat/sys-queue.h"
|
||||||
|
|
||||||
|
+#include <openssl/rsa.h>
|
||||||
|
+#ifdef OPENSSL_HAS_ECC
|
||||||
|
+#include <openssl/ecdsa.h>
|
||||||
|
+#if ((defined(LIBRESSL_VERSION_NUMBER) && \
|
||||||
|
+ (LIBRESSL_VERSION_NUMBER >= 0x20010002L))) || \
|
||||||
|
+ (defined(ECDSA_F_ECDSA_METHOD_NEW)) || \
|
||||||
|
+ (OPENSSL_VERSION_NUMBER >= 0x00010100L)
|
||||||
|
+#define ENABLE_PKCS11_ECDSA 1
|
||||||
|
+#endif
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
@@ -80,7 +90,7 @@ del_keys_by_name(char *name)
|
||||||
|
if (!strcmp(ki->providername, name)) {
|
||||||
|
TAILQ_REMOVE(&pkcs11_keylist, ki, next);
|
||||||
|
free(ki->providername);
|
||||||
|
- sshkey_free(ki->key);
|
||||||
|
+ pkcs11_del_key(ki->key);
|
||||||
|
free(ki);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -164,6 +174,20 @@ process_del(void)
|
||||||
|
sshbuf_free(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
+#ifdef ENABLE_PKCS11_ECDSA
|
||||||
|
+static u_int EC_KEY_order_size(EC_KEY *key)
|
||||||
|
+{
|
||||||
|
+ const EC_GROUP *group = EC_KEY_get0_group(key);
|
||||||
|
+ BIGNUM *order = BN_new();
|
||||||
|
+ u_int nbytes = 0;
|
||||||
|
+ if ((group != NULL) && (order != NULL) && EC_GROUP_get_order(group, order, NULL)) {
|
||||||
|
+ nbytes = BN_num_bytes(order);
|
||||||
|
+ }
|
||||||
|
+ BN_clear_free(order);
|
||||||
|
+ return nbytes;
|
||||||
|
+}
|
||||||
|
+#endif /* ENABLE_PKCS11_ECDSA */
|
||||||
|
+
|
||||||
|
static void
|
||||||
|
process_sign(void)
|
||||||
|
{
|
||||||
|
@@ -180,14 +204,38 @@ process_sign(void)
|
||||||
|
else {
|
||||||
|
if ((found = lookup_key(key)) != NULL) {
|
||||||
|
#ifdef WITH_OPENSSL
|
||||||
|
- int ret;
|
||||||
|
-
|
||||||
|
- slen = RSA_size(key->rsa);
|
||||||
|
- signature = xmalloc(slen);
|
||||||
|
- if ((ret = RSA_private_encrypt(dlen, data, signature,
|
||||||
|
- found->rsa, RSA_PKCS1_PADDING)) != -1) {
|
||||||
|
- slen = ret;
|
||||||
|
- ok = 0;
|
||||||
|
+ if(found->type == KEY_RSA) {
|
||||||
|
+ int ret;
|
||||||
|
+ slen = RSA_size(key->rsa);
|
||||||
|
+ signature = xmalloc(slen);
|
||||||
|
+ if ((ret = RSA_private_encrypt(dlen, data, signature,
|
||||||
|
+ found->rsa, RSA_PKCS1_PADDING)) != -1) {
|
||||||
|
+ slen = ret;
|
||||||
|
+ ok = 0;
|
||||||
|
+ }
|
||||||
|
+#ifdef ENABLE_PKCS11_ECDSA
|
||||||
|
+ } else if(found->type == KEY_ECDSA) {
|
||||||
|
+ ECDSA_SIG *sig;
|
||||||
|
+ const BIGNUM *r = NULL, *s = NULL;
|
||||||
|
+ if ((sig = ECDSA_do_sign(data, dlen, found->ecdsa)) != NULL) {
|
||||||
|
+ /* PKCS11 2.3.1 recommends both r and s to have the order size for
|
||||||
|
+ backward compatiblity */
|
||||||
|
+ ECDSA_SIG_get0(sig, &r, &s);
|
||||||
|
+ u_int o_len = EC_KEY_order_size(found->ecdsa);
|
||||||
|
+ u_int r_len = BN_num_bytes(r);
|
||||||
|
+ u_int s_len = BN_num_bytes(s);
|
||||||
|
+ if (o_len > 0 && r_len <= o_len && s_len <= o_len) {
|
||||||
|
+ signature = xcalloc(2, o_len);
|
||||||
|
+ BN_bn2bin(r, signature + o_len - r_len);
|
||||||
|
+ BN_bn2bin(s, signature + (2 * o_len) - s_len);
|
||||||
|
+ slen = 2 * o_len;
|
||||||
|
+ ok = 0;
|
||||||
|
+ }
|
||||||
|
+ ECDSA_SIG_free(sig);
|
||||||
|
+ }
|
||||||
|
+#endif /* ENABLE_PKCS11_ECDSA */
|
||||||
|
+ } else {
|
||||||
|
+ /* Unsupported type */
|
||||||
|
}
|
||||||
|
#endif /* WITH_OPENSSL */
|
||||||
|
}
|
||||||
|
diff -up openssh-7.6p1/ssh-pkcs11.h.pkcs11-ecdsa openssh-7.6p1/ssh-pkcs11.h
|
||||||
|
--- openssh-7.6p1/ssh-pkcs11.h.pkcs11-ecdsa 2018-02-16 13:25:59.429469272 +0100
|
||||||
|
+++ openssh-7.6p1/ssh-pkcs11.h 2018-02-16 13:45:29.623800048 +0100
|
||||||
|
@@ -20,6 +20,7 @@
|
||||||
|
int pkcs11_init(int);
|
||||||
|
void pkcs11_terminate(void);
|
||||||
|
int pkcs11_add_provider(char *, char *, struct sshkey ***);
|
||||||
|
+int pkcs11_del_key(struct sshkey *);
|
||||||
|
int pkcs11_add_provider_by_uri(struct pkcs11_uri *, char *, struct sshkey ***);
|
||||||
|
int pkcs11_del_provider(char *);
|
||||||
|
int pkcs11_uri_write(const struct sshkey *, FILE *);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
diff -up openssh-7.6p1/ssh-pkcs11.c.old openssh-7.6p1/ssh-pkcs11.c
|
||||||
|
--- openssh-7.6p1/ssh-pkcs11.c.old 2018-02-16 16:43:08.861520255 +0100
|
||||||
|
+++ openssh-7.6p1/ssh-pkcs11.c 2018-02-16 16:56:35.312601451 +0100
|
||||||
|
@@ -917,13 +917,28 @@ pkcs11_fetch_keys_filter(struct pkcs11_p
|
||||||
|
} else if (d2i_X509(&x509, &cp, attribs[3].ulValueLen)
|
||||||
|
== NULL) {
|
||||||
|
error("d2i_X509 failed");
|
||||||
|
- } else if ((evp = X509_get_pubkey(x509)) == NULL ||
|
||||||
|
- evp->type != EVP_PKEY_RSA ||
|
||||||
|
- evp->pkey.rsa == NULL) {
|
||||||
|
- debug("X509_get_pubkey failed or no rsa");
|
||||||
|
- } else if ((rsa = RSAPublicKey_dup(evp->pkey.rsa))
|
||||||
|
- == NULL) {
|
||||||
|
- error("RSAPublicKey_dup");
|
||||||
|
+ } else if ((evp = X509_get_pubkey(x509)) == NULL) {
|
||||||
|
+ debug("X509_get_pubkey failed");
|
||||||
|
+ } else {
|
||||||
|
+ switch (evp->type) {
|
||||||
|
+ case EVP_PKEY_RSA:
|
||||||
|
+ if (evp->pkey.rsa == NULL)
|
||||||
|
+ debug("Missing RSA key");
|
||||||
|
+ else if ((rsa = RSAPublicKey_dup(
|
||||||
|
+ evp->pkey.rsa)) == NULL)
|
||||||
|
+ error("RSAPublicKey_dup failed");
|
||||||
|
+ break;
|
||||||
|
+ case EVP_PKEY_EC:
|
||||||
|
+ if (evp->pkey.ecdsa == NULL)
|
||||||
|
+ debug("Missing ECDSA key");
|
||||||
|
+ else if ((ecdsa = EC_KEY_dup(
|
||||||
|
+ evp->pkey.ecdsa)) == NULL)
|
||||||
|
+ error("EC_KEY_dup failed");
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ debug("not a RSA or ECDSA key");
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
X509_free(x509);
|
||||||
|
EVP_PKEY_free(evp);
|
4771
SOURCES/openssh-7.6p1-pkcs11-uri.patch
Normal file
4771
SOURCES/openssh-7.6p1-pkcs11-uri.patch
Normal file
File diff suppressed because it is too large
Load Diff
709
SOURCES/openssh-7.7p1-fips.patch
Normal file
709
SOURCES/openssh-7.7p1-fips.patch
Normal file
@ -0,0 +1,709 @@
|
|||||||
|
diff -up openssh-7.7p1/cipher.c.fips openssh-7.7p1/cipher.c
|
||||||
|
--- openssh-7.7p1/cipher.c.fips 2018-08-08 10:08:40.814719906 +0200
|
||||||
|
+++ openssh-7.7p1/cipher.c 2018-08-08 10:08:40.821719965 +0200
|
||||||
|
@@ -39,6 +39,8 @@
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
+#include <openssl/fips.h>
|
||||||
|
+
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
@@ -90,6 +92,33 @@ static const struct sshcipher ciphers[]
|
||||||
|
{ NULL, 0, 0, 0, 0, 0, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
+static const struct sshcipher fips_ciphers[] = {
|
||||||
|
+#ifdef WITH_OPENSSL
|
||||||
|
+ { "3des-cbc", 8, 24, 0, 0, CFLAG_CBC, EVP_des_ede3_cbc },
|
||||||
|
+ { "aes128-cbc", 16, 16, 0, 0, CFLAG_CBC, EVP_aes_128_cbc },
|
||||||
|
+ { "aes192-cbc", 16, 24, 0, 0, CFLAG_CBC, EVP_aes_192_cbc },
|
||||||
|
+ { "aes256-cbc", 16, 32, 0, 0, CFLAG_CBC, EVP_aes_256_cbc },
|
||||||
|
+ { "rijndael-cbc@lysator.liu.se",
|
||||||
|
+ 16, 32, 0, 0, CFLAG_CBC, EVP_aes_256_cbc },
|
||||||
|
+ { "aes128-ctr", 16, 16, 0, 0, 0, EVP_aes_128_ctr },
|
||||||
|
+ { "aes192-ctr", 16, 24, 0, 0, 0, EVP_aes_192_ctr },
|
||||||
|
+ { "aes256-ctr", 16, 32, 0, 0, 0, EVP_aes_256_ctr },
|
||||||
|
+# ifdef OPENSSL_HAVE_EVPGCM
|
||||||
|
+ { "aes128-gcm@openssh.com",
|
||||||
|
+ 16, 16, 12, 16, 0, EVP_aes_128_gcm },
|
||||||
|
+ { "aes256-gcm@openssh.com",
|
||||||
|
+ 16, 32, 12, 16, 0, EVP_aes_256_gcm },
|
||||||
|
+# endif /* OPENSSL_HAVE_EVPGCM */
|
||||||
|
+#else
|
||||||
|
+ { "aes128-ctr", 16, 16, 0, 0, CFLAG_AESCTR, NULL },
|
||||||
|
+ { "aes192-ctr", 16, 24, 0, 0, CFLAG_AESCTR, NULL },
|
||||||
|
+ { "aes256-ctr", 16, 32, 0, 0, CFLAG_AESCTR, NULL },
|
||||||
|
+#endif
|
||||||
|
+ { "none", 8, 0, 0, 0, CFLAG_NONE, NULL },
|
||||||
|
+
|
||||||
|
+ { NULL, 0, 0, 0, 0, 0, NULL }
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
/*--*/
|
||||||
|
|
||||||
|
/* Returns a comma-separated list of supported ciphers. */
|
||||||
|
@@ -100,7 +129,7 @@ cipher_alg_list(char sep, int auth_only)
|
||||||
|
size_t nlen, rlen = 0;
|
||||||
|
const struct sshcipher *c;
|
||||||
|
|
||||||
|
- for (c = ciphers; c->name != NULL; c++) {
|
||||||
|
+ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) {
|
||||||
|
if ((c->flags & CFLAG_INTERNAL) != 0)
|
||||||
|
continue;
|
||||||
|
if (auth_only && c->auth_len == 0)
|
||||||
|
@@ -172,7 +201,7 @@ const struct sshcipher *
|
||||||
|
cipher_by_name(const char *name)
|
||||||
|
{
|
||||||
|
const struct sshcipher *c;
|
||||||
|
- for (c = ciphers; c->name != NULL; c++)
|
||||||
|
+ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++)
|
||||||
|
if (strcmp(c->name, name) == 0)
|
||||||
|
return c;
|
||||||
|
return NULL;
|
||||||
|
diff -up openssh-7.7p1/cipher-ctr.c.fips openssh-7.7p1/cipher-ctr.c
|
||||||
|
--- openssh-7.7p1/cipher-ctr.c.fips 2018-08-08 10:08:40.709719021 +0200
|
||||||
|
+++ openssh-7.7p1/cipher-ctr.c 2018-08-08 10:08:40.821719965 +0200
|
||||||
|
@@ -179,7 +179,8 @@ evp_aes_128_ctr(void)
|
||||||
|
aes_ctr.do_cipher = ssh_aes_ctr;
|
||||||
|
#ifndef SSH_OLD_EVP
|
||||||
|
aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH |
|
||||||
|
- EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV;
|
||||||
|
+ EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV |
|
||||||
|
+ EVP_CIPH_FLAG_FIPS;
|
||||||
|
#endif
|
||||||
|
return (&aes_ctr);
|
||||||
|
}
|
||||||
|
diff -up openssh-7.7p1/clientloop.c.fips openssh-7.7p1/clientloop.c
|
||||||
|
--- openssh-7.7p1/clientloop.c.fips 2018-08-08 10:08:40.769719527 +0200
|
||||||
|
+++ openssh-7.7p1/clientloop.c 2018-08-08 10:08:40.822719973 +0200
|
||||||
|
@@ -1978,7 +1978,8 @@ key_accepted_by_hostkeyalgs(const struct
|
||||||
|
{
|
||||||
|
const char *ktype = sshkey_ssh_name(key);
|
||||||
|
const char *hostkeyalgs = options.hostkeyalgorithms != NULL ?
|
||||||
|
- options.hostkeyalgorithms : KEX_DEFAULT_PK_ALG;
|
||||||
|
+ options.hostkeyalgorithms : (FIPS_mode() ?
|
||||||
|
+ KEX_FIPS_PK_ALG : KEX_DEFAULT_PK_ALG);
|
||||||
|
|
||||||
|
if (key == NULL || key->type == KEY_UNSPEC)
|
||||||
|
return 0;
|
||||||
|
diff -up openssh-7.7p1/dh.h.fips openssh-7.7p1/dh.h
|
||||||
|
--- openssh-7.7p1/dh.h.fips 2018-04-02 07:38:28.000000000 +0200
|
||||||
|
+++ openssh-7.7p1/dh.h 2018-08-08 10:08:40.822719973 +0200
|
||||||
|
@@ -51,6 +51,7 @@ u_int dh_estimate(int);
|
||||||
|
* Miniumum increased in light of DH precomputation attacks.
|
||||||
|
*/
|
||||||
|
#define DH_GRP_MIN 2048
|
||||||
|
+#define DH_GRP_MIN_FIPS 2048
|
||||||
|
#define DH_GRP_MAX 8192
|
||||||
|
|
||||||
|
/*
|
||||||
|
diff -up openssh-7.7p1/entropy.c.fips openssh-7.7p1/entropy.c
|
||||||
|
--- openssh-7.7p1/entropy.c.fips 2018-08-08 10:08:40.698718928 +0200
|
||||||
|
+++ openssh-7.7p1/entropy.c 2018-08-08 10:08:40.822719973 +0200
|
||||||
|
@@ -217,6 +217,9 @@ seed_rng(void)
|
||||||
|
fatal("OpenSSL version mismatch. Built against %lx, you "
|
||||||
|
"have %lx", (u_long)OPENSSL_VERSION_NUMBER, SSLeay());
|
||||||
|
|
||||||
|
+ /* clean the PRNG status when exiting the program */
|
||||||
|
+ atexit(RAND_cleanup);
|
||||||
|
+
|
||||||
|
#ifndef OPENSSL_PRNG_ONLY
|
||||||
|
if (RAND_status() == 1) {
|
||||||
|
debug3("RNG is ready, skipping seeding");
|
||||||
|
diff -up openssh-7.7p1/kex.c.fips openssh-7.7p1/kex.c
|
||||||
|
--- openssh-7.7p1/kex.c.fips 2018-08-08 10:08:40.815719915 +0200
|
||||||
|
+++ openssh-7.7p1/kex.c 2018-08-08 10:11:24.109081924 +0200
|
||||||
|
@@ -35,6 +35,7 @@
|
||||||
|
#ifdef WITH_OPENSSL
|
||||||
|
#include <openssl/crypto.h>
|
||||||
|
#include <openssl/dh.h>
|
||||||
|
+#include <openssl/fips.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "ssh2.h"
|
||||||
|
@@ -122,6 +123,26 @@ static const struct kexalg kexalgs[] = {
|
||||||
|
{ NULL, -1, -1, -1},
|
||||||
|
};
|
||||||
|
|
||||||
|
+static const struct kexalg kexalgs_fips[] = {
|
||||||
|
+ { KEX_DH14_SHA256, KEX_DH_GRP14_SHA256, 0, SSH_DIGEST_SHA256 },
|
||||||
|
+ { KEX_DH16_SHA512, KEX_DH_GRP16_SHA512, 0, SSH_DIGEST_SHA512 },
|
||||||
|
+ { KEX_DH18_SHA512, KEX_DH_GRP18_SHA512, 0, SSH_DIGEST_SHA512 },
|
||||||
|
+#ifdef HAVE_EVP_SHA256
|
||||||
|
+ { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, SSH_DIGEST_SHA256 },
|
||||||
|
+#endif
|
||||||
|
+#ifdef OPENSSL_HAS_ECC
|
||||||
|
+ { KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2,
|
||||||
|
+ NID_X9_62_prime256v1, SSH_DIGEST_SHA256 },
|
||||||
|
+ { KEX_ECDH_SHA2_NISTP384, KEX_ECDH_SHA2, NID_secp384r1,
|
||||||
|
+ SSH_DIGEST_SHA384 },
|
||||||
|
+# ifdef OPENSSL_HAS_NISTP521
|
||||||
|
+ { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1,
|
||||||
|
+ SSH_DIGEST_SHA512 },
|
||||||
|
+# endif
|
||||||
|
+#endif
|
||||||
|
+ { NULL, -1, -1, -1},
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
char *
|
||||||
|
kex_alg_list(char sep)
|
||||||
|
{
|
||||||
|
@@ -129,7 +150,7 @@ kex_alg_list(char sep)
|
||||||
|
size_t nlen, rlen = 0;
|
||||||
|
const struct kexalg *k;
|
||||||
|
|
||||||
|
- for (k = kexalgs; k->name != NULL; k++) {
|
||||||
|
+ for (k = (FIPS_mode() ? kexalgs_fips : kexalgs); k->name != NULL; k++) {
|
||||||
|
if (ret != NULL)
|
||||||
|
ret[rlen++] = sep;
|
||||||
|
nlen = strlen(k->name);
|
||||||
|
@@ -149,7 +170,7 @@ kex_alg_by_name(const char *name)
|
||||||
|
{
|
||||||
|
const struct kexalg *k;
|
||||||
|
|
||||||
|
- for (k = kexalgs; k->name != NULL; k++) {
|
||||||
|
+ for (k = (FIPS_mode() ? kexalgs_fips : kexalgs); k->name != NULL; k++) {
|
||||||
|
if (strcmp(k->name, name) == 0)
|
||||||
|
return k;
|
||||||
|
#ifdef GSSAPI
|
||||||
|
@@ -175,7 +196,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-7.7p1/kexgexc.c.fips openssh-7.7p1/kexgexc.c
|
||||||
|
--- openssh-7.7p1/kexgexc.c.fips 2018-04-02 07:38:28.000000000 +0200
|
||||||
|
+++ openssh-7.7p1/kexgexc.c 2018-08-08 10:08:40.822719973 +0200
|
||||||
|
@@ -28,6 +28,7 @@
|
||||||
|
|
||||||
|
#ifdef WITH_OPENSSL
|
||||||
|
|
||||||
|
+#include <openssl/fips.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <openssl/dh.h>
|
||||||
|
@@ -63,7 +64,7 @@ kexgex_client(struct ssh *ssh)
|
||||||
|
|
||||||
|
nbits = dh_estimate(kex->dh_need * 8);
|
||||||
|
|
||||||
|
- kex->min = DH_GRP_MIN;
|
||||||
|
+ kex->min = FIPS_mode() ? DH_GRP_MIN_FIPS : DH_GRP_MIN;
|
||||||
|
kex->max = DH_GRP_MAX;
|
||||||
|
kex->nbits = nbits;
|
||||||
|
if (datafellows & SSH_BUG_DHGEX_LARGE)
|
||||||
|
diff -up openssh-7.7p1/kexgexs.c.fips openssh-7.7p1/kexgexs.c
|
||||||
|
--- openssh-7.7p1/kexgexs.c.fips 2018-04-02 07:38:28.000000000 +0200
|
||||||
|
+++ openssh-7.7p1/kexgexs.c 2018-08-08 10:08:40.823719982 +0200
|
||||||
|
@@ -82,9 +82,9 @@ input_kex_dh_gex_request(int type, u_int
|
||||||
|
kex->nbits = nbits;
|
||||||
|
kex->min = min;
|
||||||
|
kex->max = max;
|
||||||
|
- min = MAXIMUM(DH_GRP_MIN, min);
|
||||||
|
+ min = MAXIMUM(FIPS_mode() ? DH_GRP_MIN_FIPS : DH_GRP_MIN, min);
|
||||||
|
max = MINIMUM(DH_GRP_MAX, max);
|
||||||
|
- nbits = MAXIMUM(DH_GRP_MIN, nbits);
|
||||||
|
+ nbits = MAXIMUM(FIPS_mode() ? DH_GRP_MIN_FIPS : DH_GRP_MIN, nbits);
|
||||||
|
nbits = MINIMUM(DH_GRP_MAX, nbits);
|
||||||
|
|
||||||
|
if (kex->max < kex->min || kex->nbits < kex->min ||
|
||||||
|
diff -up openssh-7.7p1/mac.c.fips openssh-7.7p1/mac.c
|
||||||
|
--- openssh-7.7p1/mac.c.fips 2018-08-08 10:08:40.815719915 +0200
|
||||||
|
+++ openssh-7.7p1/mac.c 2018-08-08 10:11:56.915352642 +0200
|
||||||
|
@@ -27,6 +27,8 @@
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
+#include <openssl/fips.h>
|
||||||
|
+
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
@@ -54,7 +56,7 @@ struct macalg {
|
||||||
|
int etm; /* Encrypt-then-MAC */
|
||||||
|
};
|
||||||
|
|
||||||
|
-static const struct macalg macs[] = {
|
||||||
|
+static const struct macalg all_macs[] = {
|
||||||
|
/* Encrypt-and-MAC (encrypt-and-authenticate) variants */
|
||||||
|
{ "hmac-sha1", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 0 },
|
||||||
|
{ "hmac-sha1-96", SSH_DIGEST, SSH_DIGEST_SHA1, 96, 0, 0, 0 },
|
||||||
|
@@ -82,6 +84,24 @@ static const struct macalg macs[] = {
|
||||||
|
{ NULL, 0, 0, 0, 0, 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
+static const struct macalg fips_macs[] = {
|
||||||
|
+ /* Encrypt-and-MAC (encrypt-and-authenticate) variants */
|
||||||
|
+ { "hmac-sha1", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 0 },
|
||||||
|
+#ifdef HAVE_EVP_SHA256
|
||||||
|
+ { "hmac-sha2-256", SSH_DIGEST, SSH_DIGEST_SHA256, 0, 0, 0, 0 },
|
||||||
|
+ { "hmac-sha2-512", SSH_DIGEST, SSH_DIGEST_SHA512, 0, 0, 0, 0 },
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ /* Encrypt-then-MAC variants */
|
||||||
|
+ { "hmac-sha1-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 1 },
|
||||||
|
+#ifdef HAVE_EVP_SHA256
|
||||||
|
+ { "hmac-sha2-256-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA256, 0, 0, 0, 1 },
|
||||||
|
+ { "hmac-sha2-512-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA512, 0, 0, 0, 1 },
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ { NULL, 0, 0, 0, 0, 0, 0 }
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
/* Returns a list of supported MACs separated by the specified char. */
|
||||||
|
char *
|
||||||
|
mac_alg_list(char sep)
|
||||||
|
@@ -90,7 +110,7 @@ mac_alg_list(char sep)
|
||||||
|
size_t nlen, rlen = 0;
|
||||||
|
const struct macalg *m;
|
||||||
|
|
||||||
|
- for (m = macs; m->name != NULL; m++) {
|
||||||
|
+ for (m = FIPS_mode() ? fips_macs : all_macs; m->name != NULL; m++) {
|
||||||
|
if (ret != NULL)
|
||||||
|
ret[rlen++] = sep;
|
||||||
|
nlen = strlen(m->name);
|
||||||
|
@@ -129,7 +149,7 @@ mac_setup(struct sshmac *mac, char *name
|
||||||
|
{
|
||||||
|
const struct macalg *m;
|
||||||
|
|
||||||
|
- for (m = macs; m->name != NULL; m++) {
|
||||||
|
+ for (m = FIPS_mode() ? fips_macs : all_macs; m->name != NULL; m++) {
|
||||||
|
if (strcmp(name, m->name) != 0)
|
||||||
|
continue;
|
||||||
|
if (mac != NULL)
|
||||||
|
diff -up openssh-7.7p1/Makefile.in.fips openssh-7.7p1/Makefile.in
|
||||||
|
--- openssh-7.7p1/Makefile.in.fips 2018-08-08 10:08:40.815719915 +0200
|
||||||
|
+++ openssh-7.7p1/Makefile.in 2018-08-08 10:08:40.823719982 +0200
|
||||||
|
@@ -179,25 +179,25 @@ libssh.a: $(LIBSSH_OBJS)
|
||||||
|
$(RANLIB) $@
|
||||||
|
|
||||||
|
ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS)
|
||||||
|
- $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHLIBS) $(LIBS) $(GSSLIBS)
|
||||||
|
+ $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(SSHLIBS) $(LIBS) $(GSSLIBS)
|
||||||
|
|
||||||
|
sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS)
|
||||||
|
- $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS)
|
||||||
|
+ $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS)
|
||||||
|
|
||||||
|
scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o
|
||||||
|
$(LD) -o $@ scp.o progressmeter.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
|
||||||
|
|
||||||
|
ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o
|
||||||
|
- $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
|
||||||
|
+ $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS)
|
||||||
|
|
||||||
|
ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o ssh-pkcs11-client.o
|
||||||
|
- $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
|
||||||
|
+ $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS)
|
||||||
|
|
||||||
|
ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o
|
||||||
|
- $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
|
||||||
|
+ $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS)
|
||||||
|
|
||||||
|
ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o readconf.o uidswap.o
|
||||||
|
- $(LD) -o $@ ssh-keysign.o readconf.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
|
||||||
|
+ $(LD) -o $@ ssh-keysign.o readconf.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS)
|
||||||
|
|
||||||
|
ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-pkcs11-helper.o ssh-pkcs11.o
|
||||||
|
$(LD) -o $@ ssh-pkcs11-helper.o ssh-pkcs11.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
|
||||||
|
@@ -215,7 +215,7 @@ ssh-cavs$(EXEEXT): $(LIBCOMPAT) libssh.a
|
||||||
|
$(LD) -o $@ ssh-cavs.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
|
||||||
|
|
||||||
|
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o
|
||||||
|
- $(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
|
||||||
|
+ $(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS)
|
||||||
|
|
||||||
|
sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o
|
||||||
|
$(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
|
||||||
|
diff -up openssh-7.7p1/myproposal.h.fips openssh-7.7p1/myproposal.h
|
||||||
|
--- openssh-7.7p1/myproposal.h.fips 2018-04-02 07:38:28.000000000 +0200
|
||||||
|
+++ openssh-7.7p1/myproposal.h 2018-08-08 10:08:40.823719982 +0200
|
||||||
|
@@ -114,6 +114,14 @@
|
||||||
|
"rsa-sha2-256," \
|
||||||
|
"ssh-rsa"
|
||||||
|
|
||||||
|
+#define KEX_FIPS_PK_ALG \
|
||||||
|
+ HOSTKEY_ECDSA_CERT_METHODS \
|
||||||
|
+ "ssh-rsa-cert-v01@openssh.com," \
|
||||||
|
+ HOSTKEY_ECDSA_METHODS \
|
||||||
|
+ "rsa-sha2-512," \
|
||||||
|
+ "rsa-sha2-256," \
|
||||||
|
+ "ssh-rsa"
|
||||||
|
+
|
||||||
|
/* the actual algorithms */
|
||||||
|
|
||||||
|
#define KEX_SERVER_ENCRYPT \
|
||||||
|
@@ -137,6 +145,38 @@
|
||||||
|
|
||||||
|
#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" \
|
||||||
|
+ AESGCM_CIPHER_MODES
|
||||||
|
+#ifdef HAVE_EVP_SHA256
|
||||||
|
+# define KEX_DEFAULT_KEX_FIPS \
|
||||||
|
+ KEX_ECDH_METHODS \
|
||||||
|
+ KEX_SHA2_METHODS \
|
||||||
|
+ "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"
|
||||||
|
+#else
|
||||||
|
+# ifdef OPENSSL_HAS_NISTP521
|
||||||
|
+# define KEX_DEFAULT_KEX_FIPS \
|
||||||
|
+ "ecdh-sha2-nistp256," \
|
||||||
|
+ "ecdh-sha2-nistp384," \
|
||||||
|
+ "ecdh-sha2-nistp521"
|
||||||
|
+# else
|
||||||
|
+# define KEX_DEFAULT_KEX_FIPS \
|
||||||
|
+ "ecdh-sha2-nistp256," \
|
||||||
|
+ "ecdh-sha2-nistp384"
|
||||||
|
+# endif
|
||||||
|
+#define KEX_FIPS_MAC \
|
||||||
|
+ "hmac-sha1"
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
#else /* WITH_OPENSSL */
|
||||||
|
|
||||||
|
#define KEX_SERVER_KEX \
|
||||||
|
diff -up openssh-7.7p1/readconf.c.fips openssh-7.7p1/readconf.c
|
||||||
|
--- openssh-7.7p1/readconf.c.fips 2018-08-08 10:08:40.769719527 +0200
|
||||||
|
+++ openssh-7.7p1/readconf.c 2018-08-08 10:08:40.824719990 +0200
|
||||||
|
@@ -2081,17 +2081,18 @@ fill_default_options(Options * options)
|
||||||
|
all_mac = mac_alg_list(',');
|
||||||
|
all_kex = kex_alg_list(',');
|
||||||
|
all_key = sshkey_alg_list(0, 0, 1, ',');
|
||||||
|
-#define ASSEMBLE(what, defaults, all) \
|
||||||
|
+#define ASSEMBLE(what, defaults, fips_defaults, all) \
|
||||||
|
do { \
|
||||||
|
if ((r = kex_assemble_names(&options->what, \
|
||||||
|
- defaults, all)) != 0) \
|
||||||
|
+ (FIPS_mode() ? fips_defaults : defaults), \
|
||||||
|
+ all)) != 0) \
|
||||||
|
fatal("%s: %s: %s", __func__, #what, ssh_err(r)); \
|
||||||
|
} while (0)
|
||||||
|
- ASSEMBLE(ciphers, KEX_SERVER_ENCRYPT, all_cipher);
|
||||||
|
- ASSEMBLE(macs, KEX_SERVER_MAC, all_mac);
|
||||||
|
- ASSEMBLE(kex_algorithms, KEX_SERVER_KEX, all_kex);
|
||||||
|
- ASSEMBLE(hostbased_key_types, KEX_DEFAULT_PK_ALG, all_key);
|
||||||
|
- ASSEMBLE(pubkey_key_types, KEX_DEFAULT_PK_ALG, all_key);
|
||||||
|
+ ASSEMBLE(ciphers, KEX_SERVER_ENCRYPT, KEX_FIPS_ENCRYPT, all_cipher);
|
||||||
|
+ ASSEMBLE(macs, KEX_SERVER_MAC, KEX_FIPS_MAC, all_mac);
|
||||||
|
+ ASSEMBLE(kex_algorithms, KEX_SERVER_KEX, KEX_DEFAULT_KEX_FIPS, all_kex);
|
||||||
|
+ ASSEMBLE(hostbased_key_types, KEX_DEFAULT_PK_ALG, KEX_FIPS_PK_ALG, all_key);
|
||||||
|
+ ASSEMBLE(pubkey_key_types, KEX_DEFAULT_PK_ALG, KEX_FIPS_PK_ALG, all_key);
|
||||||
|
#undef ASSEMBLE
|
||||||
|
free(all_cipher);
|
||||||
|
free(all_mac);
|
||||||
|
diff -up openssh-7.7p1/sandbox-seccomp-filter.c.fips openssh-7.7p1/sandbox-seccomp-filter.c
|
||||||
|
--- openssh-7.7p1/sandbox-seccomp-filter.c.fips 2018-08-08 10:08:40.794719737 +0200
|
||||||
|
+++ openssh-7.7p1/sandbox-seccomp-filter.c 2018-08-08 10:08:40.824719990 +0200
|
||||||
|
@@ -137,6 +137,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-7.7p1/servconf.c.fips openssh-7.7p1/servconf.c
|
||||||
|
--- openssh-7.7p1/servconf.c.fips 2018-08-08 10:08:40.778719603 +0200
|
||||||
|
+++ openssh-7.7p1/servconf.c 2018-08-08 10:08:40.824719990 +0200
|
||||||
|
@@ -196,17 +196,18 @@ option_clear_or_none(const char *o)
|
||||||
|
all_mac = mac_alg_list(',');
|
||||||
|
all_kex = kex_alg_list(',');
|
||||||
|
all_key = sshkey_alg_list(0, 0, 1, ',');
|
||||||
|
-#define ASSEMBLE(what, defaults, all) \
|
||||||
|
+#define ASSEMBLE(what, defaults, fips_defaults, all) \
|
||||||
|
do { \
|
||||||
|
- if ((r = kex_assemble_names(&o->what, defaults, all)) != 0) \
|
||||||
|
+ if ((r = kex_assemble_names(&o->what, (FIPS_mode() \
|
||||||
|
+ ? fips_defaults : defaults), all)) != 0) \
|
||||||
|
fatal("%s: %s: %s", __func__, #what, ssh_err(r)); \
|
||||||
|
} while (0)
|
||||||
|
- ASSEMBLE(ciphers, KEX_SERVER_ENCRYPT, all_cipher);
|
||||||
|
- ASSEMBLE(macs, KEX_SERVER_MAC, all_mac);
|
||||||
|
- ASSEMBLE(kex_algorithms, KEX_SERVER_KEX, all_kex);
|
||||||
|
- ASSEMBLE(hostkeyalgorithms, KEX_DEFAULT_PK_ALG, all_key);
|
||||||
|
- ASSEMBLE(hostbased_key_types, KEX_DEFAULT_PK_ALG, all_key);
|
||||||
|
- ASSEMBLE(pubkey_key_types, KEX_DEFAULT_PK_ALG, all_key);
|
||||||
|
+ ASSEMBLE(ciphers, KEX_SERVER_ENCRYPT, KEX_FIPS_ENCRYPT, all_cipher);
|
||||||
|
+ ASSEMBLE(macs, KEX_SERVER_MAC, KEX_FIPS_MAC, all_mac);
|
||||||
|
+ ASSEMBLE(kex_algorithms, KEX_SERVER_KEX, KEX_DEFAULT_KEX_FIPS, all_kex);
|
||||||
|
+ ASSEMBLE(hostkeyalgorithms, KEX_DEFAULT_PK_ALG, KEX_FIPS_PK_ALG, all_key);
|
||||||
|
+ ASSEMBLE(hostbased_key_types, KEX_DEFAULT_PK_ALG, KEX_FIPS_PK_ALG, all_key);
|
||||||
|
+ ASSEMBLE(pubkey_key_types, KEX_DEFAULT_PK_ALG, KEX_FIPS_PK_ALG, all_key);
|
||||||
|
#undef ASSEMBLE
|
||||||
|
free(all_cipher);
|
||||||
|
free(all_mac);
|
||||||
|
diff -up openssh-7.7p1/ssh.c.fips openssh-7.7p1/ssh.c
|
||||||
|
--- openssh-7.7p1/ssh.c.fips 2018-08-08 10:08:40.811719881 +0200
|
||||||
|
+++ openssh-7.7p1/ssh.c 2018-08-08 10:08:40.825719999 +0200
|
||||||
|
@@ -76,6 +76,8 @@
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#endif
|
||||||
|
+#include <openssl/fips.h>
|
||||||
|
+#include <fipscheck.h>
|
||||||
|
#include "openbsd-compat/openssl-compat.h"
|
||||||
|
#include "openbsd-compat/sys-queue.h"
|
||||||
|
|
||||||
|
@@ -579,6 +581,14 @@ main(int ac, char **av)
|
||||||
|
sanitise_stdfd();
|
||||||
|
|
||||||
|
__progname = ssh_get_progname(av[0]);
|
||||||
|
+ SSLeay_add_all_algorithms();
|
||||||
|
+ if (access("/etc/system-fips", F_OK) == 0)
|
||||||
|
+ if (! FIPSCHECK_verify(NULL, NULL)){
|
||||||
|
+ if (FIPS_mode())
|
||||||
|
+ fatal("FIPS integrity verification test failed.");
|
||||||
|
+ else
|
||||||
|
+ logit("FIPS integrity verification test failed.");
|
||||||
|
+ }
|
||||||
|
|
||||||
|
#ifndef HAVE_SETPROCTITLE
|
||||||
|
/* Prepare for later setproctitle emulation */
|
||||||
|
@@ -1045,7 +1055,6 @@ main(int ac, char **av)
|
||||||
|
host_arg = xstrdup(host);
|
||||||
|
|
||||||
|
#ifdef WITH_OPENSSL
|
||||||
|
- OpenSSL_add_all_algorithms();
|
||||||
|
ERR_load_crypto_strings();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@@ -1268,6 +1277,10 @@ main(int ac, char **av)
|
||||||
|
|
||||||
|
seed_rng();
|
||||||
|
|
||||||
|
+ if (FIPS_mode()) {
|
||||||
|
+ logit("FIPS mode initialized");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (options.user == NULL)
|
||||||
|
options.user = xstrdup(pw->pw_name);
|
||||||
|
|
||||||
|
diff -up openssh-7.7p1/sshconnect2.c.fips openssh-7.7p1/sshconnect2.c
|
||||||
|
--- openssh-7.7p1/sshconnect2.c.fips 2018-08-08 10:08:40.786719670 +0200
|
||||||
|
+++ openssh-7.7p1/sshconnect2.c 2018-08-08 10:08:40.825719999 +0200
|
||||||
|
@@ -44,6 +44,8 @@
|
||||||
|
#include <vis.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+#include <openssl/fips.h>
|
||||||
|
+
|
||||||
|
#include "openbsd-compat/sys-queue.h"
|
||||||
|
|
||||||
|
#include "xmalloc.h"
|
||||||
|
@@ -235,7 +237,8 @@ order_hostkeyalgs(char *host, struct soc
|
||||||
|
for (i = 0; i < options.num_system_hostfiles; i++)
|
||||||
|
load_hostkeys(hostkeys, hostname, options.system_hostfiles[i]);
|
||||||
|
|
||||||
|
- oavail = avail = xstrdup(KEX_DEFAULT_PK_ALG);
|
||||||
|
+ oavail = avail = xstrdup((FIPS_mode()
|
||||||
|
+ ? KEX_FIPS_PK_ALG : KEX_DEFAULT_PK_ALG));
|
||||||
|
maxlen = strlen(avail) + 1;
|
||||||
|
first = xmalloc(maxlen);
|
||||||
|
last = xmalloc(maxlen);
|
||||||
|
@@ -290,23 +293,28 @@ ssh_kex2(char *host, struct sockaddr *ho
|
||||||
|
|
||||||
|
#ifdef GSSAPI
|
||||||
|
if (options.gss_keyex) {
|
||||||
|
- /* Add the GSSAPI mechanisms currently supported on this
|
||||||
|
- * client to the key exchange algorithm proposal */
|
||||||
|
- orig = options.kex_algorithms;
|
||||||
|
-
|
||||||
|
- if (options.gss_server_identity)
|
||||||
|
- gss_host = options.gss_server_identity;
|
||||||
|
- else if (options.gss_trust_dns)
|
||||||
|
- gss_host = (char *)get_canonical_hostname(active_state, 1);
|
||||||
|
- else
|
||||||
|
- gss_host = 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(&options.kex_algorithms,
|
||||||
|
- "%s,%s", gss, orig);
|
||||||
|
+ 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 = options.kex_algorithms;
|
||||||
|
+
|
||||||
|
+ if (options.gss_server_identity)
|
||||||
|
+ gss_host = options.gss_server_identity;
|
||||||
|
+ else if (options.gss_trust_dns)
|
||||||
|
+ gss_host = (char *)get_canonical_hostname(active_state, 1);
|
||||||
|
+ else
|
||||||
|
+ gss_host = 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(&options.kex_algorithms,
|
||||||
|
+ "%s,%s", gss, orig);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@@ -322,14 +330,16 @@ ssh_kex2(char *host, struct sockaddr *ho
|
||||||
|
if (options.hostkeyalgorithms != NULL) {
|
||||||
|
all_key = sshkey_alg_list(0, 0, 1, ',');
|
||||||
|
if (kex_assemble_names(&options.hostkeyalgorithms,
|
||||||
|
- KEX_DEFAULT_PK_ALG, all_key) != 0)
|
||||||
|
+ (FIPS_mode() ? KEX_FIPS_PK_ALG : KEX_DEFAULT_PK_ALG),
|
||||||
|
+ all_key) != 0)
|
||||||
|
fatal("%s: kex_assemble_namelist", __func__);
|
||||||
|
free(all_key);
|
||||||
|
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
|
||||||
|
compat_pkalg_proposal(options.hostkeyalgorithms);
|
||||||
|
} else {
|
||||||
|
/* Enforce default */
|
||||||
|
- options.hostkeyalgorithms = xstrdup(KEX_DEFAULT_PK_ALG);
|
||||||
|
+ options.hostkeyalgorithms = xstrdup((FIPS_mode()
|
||||||
|
+ ? KEX_FIPS_PK_ALG : KEX_DEFAULT_PK_ALG));
|
||||||
|
/* Prefer algorithms that we already have keys for */
|
||||||
|
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
|
||||||
|
compat_pkalg_proposal(
|
||||||
|
diff -up openssh-7.7p1/sshd.c.fips openssh-7.7p1/sshd.c
|
||||||
|
--- openssh-7.7p1/sshd.c.fips 2018-08-08 10:08:40.818719940 +0200
|
||||||
|
+++ openssh-7.7p1/sshd.c 2018-08-08 10:08:40.826720007 +0200
|
||||||
|
@@ -66,6 +66,7 @@
|
||||||
|
#include <grp.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <signal.h>
|
||||||
|
+#include <syslog.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
@@ -77,6 +78,8 @@
|
||||||
|
#include <openssl/dh.h>
|
||||||
|
#include <openssl/bn.h>
|
||||||
|
#include <openssl/rand.h>
|
||||||
|
+#include <openssl/fips.h>
|
||||||
|
+#include <fipscheck.h>
|
||||||
|
#include "openbsd-compat/openssl-compat.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@@ -1534,6 +1537,18 @@ main(int ac, char **av)
|
||||||
|
#endif
|
||||||
|
__progname = ssh_get_progname(av[0]);
|
||||||
|
|
||||||
|
+ SSLeay_add_all_algorithms();
|
||||||
|
+ if (access("/etc/system-fips", F_OK) == 0)
|
||||||
|
+ if (! FIPSCHECK_verify(NULL, NULL)) {
|
||||||
|
+ openlog(__progname, LOG_PID, LOG_AUTHPRIV);
|
||||||
|
+ if (FIPS_mode()) {
|
||||||
|
+ syslog(LOG_CRIT, "FIPS integrity verification test failed.");
|
||||||
|
+ cleanup_exit(255);
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ syslog(LOG_INFO, "FIPS integrity verification test failed.");
|
||||||
|
+ closelog();
|
||||||
|
+ }
|
||||||
|
/* Save argv. Duplicate so setproctitle emulation doesn't clobber it */
|
||||||
|
saved_argc = ac;
|
||||||
|
rexec_argc = ac;
|
||||||
|
@@ -1675,7 +1690,7 @@ main(int ac, char **av)
|
||||||
|
else
|
||||||
|
closefrom(REEXEC_DEVCRYPTO_RESERVED_FD);
|
||||||
|
|
||||||
|
-#ifdef WITH_OPENSSL
|
||||||
|
+#if 0 /* FIPS */
|
||||||
|
OpenSSL_add_all_algorithms();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@@ -1979,6 +1994,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()) {
|
||||||
|
+ logit("FIPS mode initialized");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* Chdir to the root directory so that the current disk can be
|
||||||
|
unmounted if desired. */
|
||||||
|
if (chdir("/") == -1)
|
||||||
|
@@ -2359,10 +2378,14 @@ do_ssh2_kex(void)
|
||||||
|
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-7.7p1/sshkey.c.fips openssh-7.7p1/sshkey.c
|
||||||
|
--- openssh-7.7p1/sshkey.c.fips 2018-08-08 10:08:40.818719940 +0200
|
||||||
|
+++ openssh-7.7p1/sshkey.c 2018-08-08 10:08:40.826720007 +0200
|
||||||
|
@@ -34,6 +34,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 @@
|
||||||
|
#include "sshkey.h"
|
||||||
|
#include "sshkey-xmss.h"
|
||||||
|
#include "match.h"
|
||||||
|
+#include "log.h"
|
||||||
|
|
||||||
|
#include "xmss_fast.h"
|
||||||
|
|
||||||
|
@@ -1526,6 +1528,8 @@ rsa_generate_private_key(u_int bits, RSA
|
||||||
|
}
|
||||||
|
if (!BN_set_word(f4, RSA_F4) ||
|
||||||
|
!RSA_generate_key_ex(private, bits, f4, NULL)) {
|
||||||
|
+ if (FIPS_mode())
|
||||||
|
+ logit("%s: the key length might be unsupported by FIPS mode approved key generation method", __func__);
|
||||||
|
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
diff -up openssh-7.7p1/ssh-keygen.c.fips openssh-7.7p1/ssh-keygen.c
|
||||||
|
--- openssh-7.7p1/ssh-keygen.c.fips 2018-08-08 10:08:40.801719797 +0200
|
||||||
|
+++ openssh-7.7p1/ssh-keygen.c 2018-08-08 10:08:40.827720016 +0200
|
||||||
|
@@ -229,6 +229,12 @@ type_bits_valid(int type, const char *na
|
||||||
|
OPENSSL_DSA_MAX_MODULUS_BITS : OPENSSL_RSA_MAX_MODULUS_BITS;
|
||||||
|
if (*bitsp > maxbits)
|
||||||
|
fatal("key bits exceeds maximum %d", maxbits);
|
||||||
|
+ if (FIPS_mode()) {
|
||||||
|
+ if (type == KEY_DSA)
|
||||||
|
+ fatal("DSA keys are not allowed in FIPS mode");
|
||||||
|
+ if (type == KEY_ED25519)
|
||||||
|
+ fatal("ED25519 keys are not allowed in FIPS mode");
|
||||||
|
+ }
|
||||||
|
switch (type) {
|
||||||
|
case KEY_DSA:
|
||||||
|
if (*bitsp != 1024)
|
648
SOURCES/openssh-7.7p1-gssapi-new-unique.patch
Normal file
648
SOURCES/openssh-7.7p1-gssapi-new-unique.patch
Normal file
@ -0,0 +1,648 @@
|
|||||||
|
diff --git a/auth-krb5.c b/auth-krb5.c
|
||||||
|
index a5a81ed2..63f877f2 100644
|
||||||
|
--- a/auth-krb5.c
|
||||||
|
+++ b/auth-krb5.c
|
||||||
|
@@ -51,6 +51,7 @@
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <krb5.h>
|
||||||
|
+#include <profile.h>
|
||||||
|
|
||||||
|
extern ServerOptions options;
|
||||||
|
|
||||||
|
@@ -77,7 +78,7 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
|
||||||
|
#endif
|
||||||
|
krb5_error_code problem;
|
||||||
|
krb5_ccache ccache = NULL;
|
||||||
|
- int len;
|
||||||
|
+ char *ticket_name = NULL;
|
||||||
|
char *client, *platform_client;
|
||||||
|
const char *errmsg;
|
||||||
|
|
||||||
|
@@ -163,7 +164,8 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
- problem = ssh_krb5_cc_gen(authctxt->krb5_ctx, &authctxt->krb5_fwd_ccache);
|
||||||
|
+ problem = ssh_krb5_cc_new_unique(authctxt->krb5_ctx,
|
||||||
|
+ &authctxt->krb5_fwd_ccache, &authctxt->krb5_set_env);
|
||||||
|
if (problem)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
@@ -172,21 +174,20 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
|
||||||
|
if (problem)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
- problem= krb5_cc_store_cred(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache,
|
||||||
|
+ problem = krb5_cc_store_cred(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache,
|
||||||
|
&creds);
|
||||||
|
if (problem)
|
||||||
|
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
|
||||||
|
|
||||||
|
@@ -222,11 +223,54 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
|
||||||
|
void
|
||||||
|
krb5_cleanup_proc(Authctxt *authctxt)
|
||||||
|
{
|
||||||
|
+ struct stat krb5_ccname_stat;
|
||||||
|
+ char krb5_ccname[128], *krb5_ccname_dir_start, *krb5_ccname_dir_end;
|
||||||
|
+
|
||||||
|
debug("krb5_cleanup_proc called");
|
||||||
|
if (authctxt->krb5_fwd_ccache) {
|
||||||
|
- krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);
|
||||||
|
+ krb5_context ctx = authctxt->krb5_ctx;
|
||||||
|
+ krb5_cccol_cursor cursor;
|
||||||
|
+ krb5_ccache ccache;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ krb5_cc_destroy(ctx, authctxt->krb5_fwd_ccache);
|
||||||
|
authctxt->krb5_fwd_ccache = NULL;
|
||||||
|
+
|
||||||
|
+ ret = krb5_cccol_cursor_new(ctx, &cursor);
|
||||||
|
+ if (ret)
|
||||||
|
+ goto out;
|
||||||
|
+
|
||||||
|
+ ret = krb5_cccol_cursor_next(ctx, cursor, &ccache);
|
||||||
|
+ if (ret == 0 && ccache != NULL) {
|
||||||
|
+ /* There is at least one other ccache in collection
|
||||||
|
+ * we can switch to */
|
||||||
|
+ krb5_cc_switch(ctx, ccache);
|
||||||
|
+ } else if (authctxt->krb5_ccname != NULL) {
|
||||||
|
+ /* Clean up the collection too */
|
||||||
|
+ strncpy(krb5_ccname, authctxt->krb5_ccname, sizeof(krb5_ccname) - 10);
|
||||||
|
+ krb5_ccname_dir_start = strchr(krb5_ccname, ':') + 1;
|
||||||
|
+ *krb5_ccname_dir_start++ = '\0';
|
||||||
|
+ if (strcmp(krb5_ccname, "DIR") == 0) {
|
||||||
|
+
|
||||||
|
+ strcat(krb5_ccname_dir_start, "/primary");
|
||||||
|
+
|
||||||
|
+ if (stat(krb5_ccname_dir_start, &krb5_ccname_stat) == 0) {
|
||||||
|
+ if (unlink(krb5_ccname_dir_start) == 0) {
|
||||||
|
+ krb5_ccname_dir_end = strrchr(krb5_ccname_dir_start, '/');
|
||||||
|
+ *krb5_ccname_dir_end = '\0';
|
||||||
|
+ if (rmdir(krb5_ccname_dir_start) == -1)
|
||||||
|
+ debug("cache dir '%s' remove failed: %s",
|
||||||
|
+ krb5_ccname_dir_start, strerror(errno));
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ debug("cache primary file '%s', remove failed: %s",
|
||||||
|
+ krb5_ccname_dir_start, strerror(errno));
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ krb5_cccol_cursor_free(ctx, &cursor);
|
||||||
|
}
|
||||||
|
+out:
|
||||||
|
if (authctxt->krb5_user) {
|
||||||
|
krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user);
|
||||||
|
authctxt->krb5_user = NULL;
|
||||||
|
@@ -237,36 +287,186 @@ krb5_cleanup_proc(Authctxt *authctxt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-#ifndef HEIMDAL
|
||||||
|
-krb5_error_code
|
||||||
|
-ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
|
||||||
|
- int tmpfd, ret, oerrno;
|
||||||
|
- char ccname[40];
|
||||||
|
- mode_t old_umask;
|
||||||
|
|
||||||
|
- ret = snprintf(ccname, sizeof(ccname),
|
||||||
|
- "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
|
||||||
|
- if (ret < 0 || (size_t)ret >= sizeof(ccname))
|
||||||
|
- return ENOMEM;
|
||||||
|
-
|
||||||
|
- old_umask = umask(0177);
|
||||||
|
- tmpfd = mkstemp(ccname + strlen("FILE:"));
|
||||||
|
- oerrno = errno;
|
||||||
|
- umask(old_umask);
|
||||||
|
- if (tmpfd == -1) {
|
||||||
|
- logit("mkstemp(): %.100s", strerror(oerrno));
|
||||||
|
- return oerrno;
|
||||||
|
+#if !defined(HEIMDAL)
|
||||||
|
+int
|
||||||
|
+ssh_asprintf_append(char **dsc, const char *fmt, ...) {
|
||||||
|
+ char *src, *old;
|
||||||
|
+ va_list ap;
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
+ va_start(ap, fmt);
|
||||||
|
+ i = vasprintf(&src, fmt, ap);
|
||||||
|
+ va_end(ap);
|
||||||
|
+
|
||||||
|
+ if (i == -1 || src == NULL)
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ old = *dsc;
|
||||||
|
+
|
||||||
|
+ i = asprintf(dsc, "%s%s", *dsc, src);
|
||||||
|
+ if (i == -1 || 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("%s: called, template = %s", __func__, template);
|
||||||
|
+ if (template == NULL)
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ tmp_template = p_n = p_o = xstrdup(template);
|
||||||
|
+ r = xstrdup("");
|
||||||
|
+
|
||||||
|
+ while ((p_n = strstr(p_o, "%{")) != NULL) {
|
||||||
|
+
|
||||||
|
+ *p_n++ = '\0';
|
||||||
|
+ if (ssh_asprintf_append(&r, "%s", p_o) == -1)
|
||||||
|
+ goto cleanup;
|
||||||
|
+
|
||||||
|
+ if (strncmp(p_n, "{uid}", 5) == 0 || strncmp(p_n, "{euid}", 6) == 0 ||
|
||||||
|
+ strncmp(p_n, "{USERID}", 8) == 0) {
|
||||||
|
+ p_o = strchr(p_n, '}') + 1;
|
||||||
|
+ if (ssh_asprintf_append(&r, "%d", geteuid()) == -1)
|
||||||
|
+ goto cleanup;
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+ else if (strncmp(p_n, "{TEMP}", 6) == 0) {
|
||||||
|
+ p_o = strchr(p_n, '}') + 1;
|
||||||
|
+ if (ssh_asprintf_append(&r, "/tmp") == -1)
|
||||||
|
+ goto cleanup;
|
||||||
|
+ continue;
|
||||||
|
+ } else {
|
||||||
|
+ p_o = strchr(p_n, '}') + 1;
|
||||||
|
+ p_o = '\0';
|
||||||
|
+ debug("%s: unsupported token %s in %s", __func__, p_n, template);
|
||||||
|
+ /* unknown token, fallback to the default */
|
||||||
|
+ goto cleanup;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) {
|
||||||
|
+ if (ssh_asprintf_append(&r, "%s", p_o) == -1)
|
||||||
|
+ goto cleanup;
|
||||||
|
+
|
||||||
|
+ *result = r;
|
||||||
|
+ free(tmp_template);
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+cleanup:
|
||||||
|
+ free(r);
|
||||||
|
+ free(tmp_template);
|
||||||
|
+ return -1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+krb5_error_code
|
||||||
|
+ssh_krb5_get_cctemplate(krb5_context ctx, char **ccname) {
|
||||||
|
+ profile_t p;
|
||||||
|
+ int ret = 0;
|
||||||
|
+ char *value = NULL;
|
||||||
|
+
|
||||||
|
+ debug3("%s: called", __func__);
|
||||||
|
+ 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("%s: returning with ccname = %s", __func__, *ccname);
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+krb5_error_code
|
||||||
|
+ssh_krb5_cc_new_unique(krb5_context ctx, krb5_ccache *ccache, int *need_environment) {
|
||||||
|
+ int tmpfd, ret, oerrno, type_len;
|
||||||
|
+ char *ccname = NULL;
|
||||||
|
+ mode_t old_umask;
|
||||||
|
+ char *type = NULL, *colon = NULL;
|
||||||
|
+
|
||||||
|
+ debug3("%s: called", __func__);
|
||||||
|
+ if (need_environment)
|
||||||
|
+ *need_environment = 0;
|
||||||
|
+ ret = ssh_krb5_get_cctemplate(ctx, &ccname);
|
||||||
|
+ if (ret || !ccname || options.kerberos_unique_ccache) {
|
||||||
|
+ /* Otherwise, go with the old method */
|
||||||
|
+ if (ccname)
|
||||||
|
+ free(ccname);
|
||||||
|
+ ccname = NULL;
|
||||||
|
+
|
||||||
|
+ ret = asprintf(&ccname,
|
||||||
|
+ "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ return ENOMEM;
|
||||||
|
+
|
||||||
|
+ old_umask = umask(0177);
|
||||||
|
+ tmpfd = mkstemp(ccname + strlen("FILE:"));
|
||||||
|
oerrno = errno;
|
||||||
|
- logit("fchmod(): %.100s", strerror(oerrno));
|
||||||
|
+ umask(old_umask);
|
||||||
|
+ if (tmpfd == -1) {
|
||||||
|
+ logit("mkstemp(): %.100s", strerror(oerrno));
|
||||||
|
+ return oerrno;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) {
|
||||||
|
+ oerrno = errno;
|
||||||
|
+ logit("fchmod(): %.100s", strerror(oerrno));
|
||||||
|
+ close(tmpfd);
|
||||||
|
+ return oerrno;
|
||||||
|
+ }
|
||||||
|
+ /* make sure the KRB5CCNAME is set for non-standard location */
|
||||||
|
+ if (need_environment)
|
||||||
|
+ *need_environment = 1;
|
||||||
|
close(tmpfd);
|
||||||
|
- return oerrno;
|
||||||
|
}
|
||||||
|
- close(tmpfd);
|
||||||
|
|
||||||
|
- return (krb5_cc_resolve(ctx, ccname, ccache));
|
||||||
|
+ debug3("%s: setting default ccname to %s", __func__, 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("%s: calling cc_new_unique(%s)", __func__, ccname);
|
||||||
|
+ ret = krb5_cc_new_unique(ctx, type, NULL, ccache);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ debug3("%s: calling cc_switch()", __func__);
|
||||||
|
+ 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
|
||||||
|
+ */
|
||||||
|
+ debug3("%s: calling cc_resolve(%s)", __func__, ccname);
|
||||||
|
+ return (krb5_cc_resolve(ctx, ccname, ccache));
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
#endif /* !HEIMDAL */
|
||||||
|
#endif /* KRB5 */
|
||||||
|
diff --git a/auth.h b/auth.h
|
||||||
|
index 29491df9..fdab5040 100644
|
||||||
|
--- a/auth.h
|
||||||
|
+++ b/auth.h
|
||||||
|
@@ -82,6 +82,7 @@ struct Authctxt {
|
||||||
|
krb5_principal krb5_user;
|
||||||
|
char *krb5_ticket_file;
|
||||||
|
char *krb5_ccname;
|
||||||
|
+ int krb5_set_env;
|
||||||
|
#endif
|
||||||
|
struct sshbuf *loginmsg;
|
||||||
|
|
||||||
|
@@ -243,6 +244,6 @@ int sys_auth_passwd(struct ssh *, const char *);
|
||||||
|
|
||||||
|
#if defined(KRB5) && !defined(HEIMDAL)
|
||||||
|
#include <krb5.h>
|
||||||
|
-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
|
||||||
|
diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c
|
||||||
|
index 795992d9..0623a107 100644
|
||||||
|
--- a/gss-serv-krb5.c
|
||||||
|
+++ b/gss-serv-krb5.c
|
||||||
|
@@ -114,7 +114,7 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name)
|
||||||
|
/* This writes out any forwarded credentials from the structure populated
|
||||||
|
* during userauth. Called after we have setuid to the user */
|
||||||
|
|
||||||
|
-static void
|
||||||
|
+static int
|
||||||
|
ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
|
||||||
|
{
|
||||||
|
krb5_ccache ccache;
|
||||||
|
@@ -121,16 +121,17 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
|
||||||
|
krb5_error_code problem;
|
||||||
|
krb5_principal princ;
|
||||||
|
OM_uint32 maj_status, min_status;
|
||||||
|
- const char *new_ccname, *new_cctype;
|
||||||
|
+ int len;
|
||||||
|
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
|
||||||
|
@@ -144,14 +145,14 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
|
||||||
|
krb5_get_err_text(krb_context, problem));
|
||||||
|
# endif
|
||||||
|
krb5_free_error_message(krb_context, errmsg);
|
||||||
|
- return;
|
||||||
|
+ return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
- if ((problem = ssh_krb5_cc_gen(krb_context, &ccache))) {
|
||||||
|
+ if ((problem = ssh_krb5_cc_new_unique(krb_context, &ccache, &set_env)) != 0) {
|
||||||
|
errmsg = krb5_get_error_message(krb_context, problem);
|
||||||
|
- logit("ssh_krb5_cc_gen(): %.100s", errmsg);
|
||||||
|
+ logit("ssh_krb5_cc_new_unique(): %.100s", errmsg);
|
||||||
|
krb5_free_error_message(krb_context, errmsg);
|
||||||
|
- return;
|
||||||
|
+ return 0;
|
||||||
|
}
|
||||||
|
#endif /* #ifdef HEIMDAL */
|
||||||
|
|
||||||
|
@@ -160,7 +161,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
|
||||||
|
errmsg = krb5_get_error_message(krb_context, problem);
|
||||||
|
logit("krb5_parse_name(): %.100s", errmsg);
|
||||||
|
krb5_free_error_message(krb_context, errmsg);
|
||||||
|
- return;
|
||||||
|
+ return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((problem = krb5_cc_initialize(krb_context, ccache, princ))) {
|
||||||
|
@@ -169,7 +170,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
|
||||||
|
krb5_free_error_message(krb_context, errmsg);
|
||||||
|
krb5_free_principal(krb_context, princ);
|
||||||
|
krb5_cc_destroy(krb_context, ccache);
|
||||||
|
- return;
|
||||||
|
+ return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
krb5_free_principal(krb_context, princ);
|
||||||
|
@@ -178,37 +179,27 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
|
||||||
|
client->creds, ccache))) {
|
||||||
|
logit("gss_krb5_copy_ccache() failed");
|
||||||
|
krb5_cc_destroy(krb_context, ccache);
|
||||||
|
- return;
|
||||||
|
+ return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
- new_cctype = krb5_cc_get_type(krb_context, ccache);
|
||||||
|
- new_ccname = krb5_cc_get_name(krb_context, ccache);
|
||||||
|
-
|
||||||
|
- client->store.envvar = "KRB5CCNAME";
|
||||||
|
-#ifdef USE_CCAPI
|
||||||
|
- xasprintf(&client->store.envval, "API:%s", new_ccname);
|
||||||
|
-#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';
|
||||||
|
- }
|
||||||
|
-#endif
|
||||||
|
+ if (set_env) {
|
||||||
|
+ const char *filename = krb5_cc_get_name(krb_context, ccache);
|
||||||
|
+ client->store.envvar = "KRB5CCNAME";
|
||||||
|
+ len = strlen(filename) + 6;
|
||||||
|
+ client->store.envval = xmalloc(len);
|
||||||
|
+ snprintf(client->store.envval, len, "FILE:%s", filename);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
#ifdef USE_PAM
|
||||||
|
- if (options.use_pam)
|
||||||
|
+ if (options.use_pam && set_env)
|
||||||
|
do_pam_putenv(client->store.envvar, client->store.envval);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
krb5_cc_close(krb_context, ccache);
|
||||||
|
|
||||||
|
client->store.data = krb_context;
|
||||||
|
|
||||||
|
- return;
|
||||||
|
+ return set_env;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
diff --git a/gss-serv.c b/gss-serv.c
|
||||||
|
index 6cae720e..16e55cbc 100644
|
||||||
|
--- a/gss-serv.c
|
||||||
|
+++ b/gss-serv.c
|
||||||
|
@@ -320,13 +320,15 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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 childs environment based
|
||||||
|
diff --git a/servconf.c b/servconf.c
|
||||||
|
index cb578658..a6e01df2 100644
|
||||||
|
--- a/servconf.c
|
||||||
|
+++ b/servconf.c
|
||||||
|
@@ -122,6 +122,7 @@ initialize_server_options(ServerOptions *options)
|
||||||
|
options->kerberos_or_local_passwd = -1;
|
||||||
|
options->kerberos_ticket_cleanup = -1;
|
||||||
|
options->kerberos_get_afs_token = -1;
|
||||||
|
+ options->kerberos_unique_ccache = -1;
|
||||||
|
options->gss_authentication=-1;
|
||||||
|
options->gss_keyex = -1;
|
||||||
|
options->gss_cleanup_creds = -1;
|
||||||
|
@@ -315,6 +316,8 @@ fill_default_server_options(ServerOptions *options)
|
||||||
|
options->kerberos_ticket_cleanup = 1;
|
||||||
|
if (options->kerberos_get_afs_token == -1)
|
||||||
|
options->kerberos_get_afs_token = 0;
|
||||||
|
+ if (options->kerberos_unique_ccache == -1)
|
||||||
|
+ options->kerberos_unique_ccache = 0;
|
||||||
|
if (options->gss_authentication == -1)
|
||||||
|
options->gss_authentication = 0;
|
||||||
|
if (options->gss_keyex == -1)
|
||||||
|
@@ -447,7 +450,8 @@ typedef enum {
|
||||||
|
sPermitRootLogin, sLogFacility, sLogLevel,
|
||||||
|
sRhostsRSAAuthentication, sRSAAuthentication,
|
||||||
|
sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
|
||||||
|
- sKerberosGetAFSToken, sChallengeResponseAuthentication,
|
||||||
|
+ sKerberosGetAFSToken, sKerberosUniqueCCache,
|
||||||
|
+ sChallengeResponseAuthentication,
|
||||||
|
sPasswordAuthentication, sKbdInteractiveAuthentication,
|
||||||
|
sListenAddress, sAddressFamily,
|
||||||
|
sPrintMotd, sPrintLastLog, sIgnoreRhosts,
|
||||||
|
@@ -526,11 +530,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 },
|
||||||
|
@@ -1437,6 +1443,10 @@ process_server_config_line(ServerOptions *options, char *line,
|
||||||
|
intptr = &options->kerberos_get_afs_token;
|
||||||
|
goto parse_flag;
|
||||||
|
|
||||||
|
+ case sKerberosUniqueCCache:
|
||||||
|
+ intptr = &options->kerberos_unique_ccache;
|
||||||
|
+ goto parse_flag;
|
||||||
|
+
|
||||||
|
case sGssAuthentication:
|
||||||
|
intptr = &options->gss_authentication;
|
||||||
|
goto parse_flag;
|
||||||
|
@@ -2507,6 +2517,7 @@ dump_config(ServerOptions *o)
|
||||||
|
# ifdef USE_AFS
|
||||||
|
dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token);
|
||||||
|
# endif
|
||||||
|
+ dump_cfg_fmtint(sKerberosUniqueCCache, o->kerberos_unique_ccache);
|
||||||
|
#endif
|
||||||
|
#ifdef GSSAPI
|
||||||
|
dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
|
||||||
|
diff --git a/servconf.h b/servconf.h
|
||||||
|
index db8362c6..4fa42d64 100644
|
||||||
|
--- a/servconf.h
|
||||||
|
+++ b/servconf.h
|
||||||
|
@@ -123,6 +123,8 @@ typedef struct {
|
||||||
|
* file on logout. */
|
||||||
|
int kerberos_get_afs_token; /* If true, try to get AFS token if
|
||||||
|
* authenticated with Kerberos. */
|
||||||
|
+ int kerberos_unique_ccache; /* If true, the acquired ticket will
|
||||||
|
+ * be stored in per-session ccache */
|
||||||
|
int gss_authentication; /* If true, permit GSSAPI authentication */
|
||||||
|
int gss_keyex; /* If true, permit GSSAPI key exchange */
|
||||||
|
int gss_cleanup_creds; /* If true, destroy cred cache on logout */
|
||||||
|
diff --git a/session.c b/session.c
|
||||||
|
index 85df6a27..480a5ead 100644
|
||||||
|
--- a/session.c
|
||||||
|
+++ b/session.c
|
||||||
|
@@ -1033,7 +1033,8 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell)
|
||||||
|
/* Allow any GSSAPI methods that we've used to alter
|
||||||
|
* the childs 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. */
|
||||||
|
@@ -1105,7 +1106,7 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef KRB5
|
||||||
|
- if (s->authctxt->krb5_ccname)
|
||||||
|
+ if (s->authctxt->krb5_ccname && s->authctxt->krb5_set_env)
|
||||||
|
child_set_env(&env, &envsize, "KRB5CCNAME",
|
||||||
|
s->authctxt->krb5_ccname);
|
||||||
|
#endif
|
||||||
|
diff --git a/ssh-gss.h b/ssh-gss.h
|
||||||
|
index 6593e422..245178af 100644
|
||||||
|
--- a/ssh-gss.h
|
||||||
|
+++ b/ssh-gss.h
|
||||||
|
@@ -62,7 +62,6 @@
|
||||||
|
#define KEX_GSS_GEX_SHA1_ID "gss-gex-sha1-"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
- char *filename;
|
||||||
|
char *envvar;
|
||||||
|
char *envval;
|
||||||
|
struct passwd *owner;
|
||||||
|
@@ -83,7 +82,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;
|
||||||
|
|
||||||
|
@@ -127,7 +126,7 @@ int ssh_gssapi_userok(char *name);
|
||||||
|
OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
|
||||||
|
void ssh_gssapi_do_child(char ***, u_int *);
|
||||||
|
void ssh_gssapi_cleanup_creds(void);
|
||||||
|
-void ssh_gssapi_storecreds(void);
|
||||||
|
+int ssh_gssapi_storecreds(void);
|
||||||
|
const char *ssh_gssapi_displayname(void);
|
||||||
|
|
||||||
|
char *ssh_gssapi_server_mechanisms(void);
|
||||||
|
diff --git a/sshd.c b/sshd.c
|
||||||
|
index edbe815c..89514e8a 100644
|
||||||
|
--- a/sshd.c
|
||||||
|
+++ b/sshd.c
|
||||||
|
@@ -2162,7 +2162,7 @@ main(int ac, char **av)
|
||||||
|
#ifdef GSSAPI
|
||||||
|
if (options.gss_authentication) {
|
||||||
|
temporarily_use_uid(authctxt->pw);
|
||||||
|
- ssh_gssapi_storecreds();
|
||||||
|
+ authctxt->krb5_set_env = ssh_gssapi_storecreds();
|
||||||
|
restore_uid();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
diff --git a/sshd_config.5 b/sshd_config.5
|
||||||
|
index c0683d4a..2349f477 100644
|
||||||
|
--- a/sshd_config.5
|
||||||
|
+++ b/sshd_config.5
|
||||||
|
@@ -860,6 +860,14 @@ Specifies whether to automatically destroy the user's ticket cache
|
||||||
|
file on logout.
|
||||||
|
The default is
|
||||||
|
.Cm yes .
|
||||||
|
+.It Cm KerberosUniqueCCache
|
||||||
|
+Specifies whether to store the acquired tickets in the per-session credential
|
||||||
|
+cache under /tmp/ or whether to use per-user credential cache as configured in
|
||||||
|
+.Pa /etc/krb5.conf .
|
||||||
|
+The default value
|
||||||
|
+.Cm no
|
||||||
|
+can lead to overwriting previous tickets by subseqent connections to the same
|
||||||
|
+user account.
|
||||||
|
.It Cm KexAlgorithms
|
||||||
|
Specifies the available KEX (Key Exchange) algorithms.
|
||||||
|
Multiple algorithms must be comma-separated.
|
164
SOURCES/openssh-7.7p1-redhat.patch
Normal file
164
SOURCES/openssh-7.7p1-redhat.patch
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
diff -up openssh-7.7p1/ssh_config.redhat openssh-7.7p1/ssh_config
|
||||||
|
--- openssh-7.7p1/ssh_config.redhat 2018-04-02 07:38:28.000000000 +0200
|
||||||
|
+++ openssh-7.7p1/ssh_config 2018-07-03 10:44:06.522245125 +0200
|
||||||
|
@@ -44,3 +44,7 @@
|
||||||
|
# VisualHostKey no
|
||||||
|
# ProxyCommand ssh -q -W %h:%p gateway.example.com
|
||||||
|
# RekeyLimit 1G 1h
|
||||||
|
+#
|
||||||
|
+# To modify the system-wide ssh configuration, create a *.conf file under
|
||||||
|
+# /etc/ssh/ssh_config.d/ which will be automatically included below
|
||||||
|
+Include /etc/ssh/ssh_config.d/*.conf
|
||||||
|
diff -up openssh-7.7p1/ssh_config_redhat.redhat openssh-7.7p1/ssh_config_redhat
|
||||||
|
--- openssh-7.7p1/ssh_config_redhat.redhat 2018-07-03 10:44:06.522245125 +0200
|
||||||
|
+++ openssh-7.7p1/ssh_config_redhat 2018-07-03 10:44:06.522245125 +0200
|
||||||
|
@@ -0,0 +1,20 @@
|
||||||
|
+# Follow system-wide Crypto Policy, if defined:
|
||||||
|
+Include /etc/crypto-policies/back-ends/openssh.config
|
||||||
|
+
|
||||||
|
+# Uncomment this if you want to use .local domain
|
||||||
|
+# Host *.local
|
||||||
|
+# CheckHostIP no
|
||||||
|
+
|
||||||
|
+Host *
|
||||||
|
+ GSSAPIAuthentication yes
|
||||||
|
+
|
||||||
|
+# If this option is set to yes then remote X11 clients will have full access
|
||||||
|
+# to the original X11 display. As virtually no X11 client supports the untrusted
|
||||||
|
+# mode correctly we set this to yes.
|
||||||
|
+ ForwardX11Trusted yes
|
||||||
|
+
|
||||||
|
+# Send locale-related environment variables
|
||||||
|
+ SendEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
|
||||||
|
+ SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
|
||||||
|
+ SendEnv LC_IDENTIFICATION LC_ALL LANGUAGE
|
||||||
|
+ SendEnv XMODIFIERS
|
||||||
|
diff -up openssh-7.7p1/sshd_config.0.redhat openssh-7.7p1/sshd_config.0
|
||||||
|
--- openssh-7.7p1/sshd_config.0.redhat 2018-04-02 07:39:27.000000000 +0200
|
||||||
|
+++ openssh-7.7p1/sshd_config.0 2018-07-03 10:44:06.523245133 +0200
|
||||||
|
@@ -872,9 +872,9 @@ DESCRIPTION
|
||||||
|
|
||||||
|
SyslogFacility
|
||||||
|
Gives the facility code that is used when logging messages from
|
||||||
|
- sshd(8). The possible values are: DAEMON, USER, AUTH, LOCAL0,
|
||||||
|
- LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The
|
||||||
|
- default is AUTH.
|
||||||
|
+ sshd(8). The possible values are: DAEMON, USER, AUTH, AUTHPRIV,
|
||||||
|
+ LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
|
||||||
|
+ The default is AUTH.
|
||||||
|
|
||||||
|
TCPKeepAlive
|
||||||
|
Specifies whether the system should send TCP keepalive messages
|
||||||
|
diff -up openssh-7.7p1/sshd_config.5.redhat openssh-7.7p1/sshd_config.5
|
||||||
|
--- openssh-7.7p1/sshd_config.5.redhat 2018-04-02 07:38:28.000000000 +0200
|
||||||
|
+++ openssh-7.7p1/sshd_config.5 2018-07-03 10:44:06.523245133 +0200
|
||||||
|
@@ -1461,7 +1461,7 @@ By default no subsystems are defined.
|
||||||
|
.It Cm SyslogFacility
|
||||||
|
Gives the facility code that is used when logging messages from
|
||||||
|
.Xr sshd 8 .
|
||||||
|
-The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2,
|
||||||
|
+The possible values are: DAEMON, USER, AUTH, AUTHPRIV, LOCAL0, LOCAL1, LOCAL2,
|
||||||
|
LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
|
||||||
|
The default is AUTH.
|
||||||
|
.It Cm TCPKeepAlive
|
||||||
|
diff -up openssh-7.7p1/sshd_config.redhat openssh-7.7p1/sshd_config
|
||||||
|
--- openssh-7.7p1/sshd_config.redhat 2018-04-02 07:38:28.000000000 +0200
|
||||||
|
+++ openssh-7.7p1/sshd_config 2018-07-03 10:45:16.950782466 +0200
|
||||||
|
@@ -10,20 +10,34 @@
|
||||||
|
# possible, but leave them commented. Uncommented options override the
|
||||||
|
# default value.
|
||||||
|
|
||||||
|
+# If you want to change the port on a SELinux system, you have to tell
|
||||||
|
+# SELinux about this change.
|
||||||
|
+# semanage port -a -t ssh_port_t -p tcp #PORTNUMBER
|
||||||
|
+#
|
||||||
|
#Port 22
|
||||||
|
#AddressFamily any
|
||||||
|
#ListenAddress 0.0.0.0
|
||||||
|
#ListenAddress ::
|
||||||
|
|
||||||
|
-#HostKey /etc/ssh/ssh_host_rsa_key
|
||||||
|
-#HostKey /etc/ssh/ssh_host_ecdsa_key
|
||||||
|
-#HostKey /etc/ssh/ssh_host_ed25519_key
|
||||||
|
+HostKey /etc/ssh/ssh_host_rsa_key
|
||||||
|
+HostKey /etc/ssh/ssh_host_ecdsa_key
|
||||||
|
+HostKey /etc/ssh/ssh_host_ed25519_key
|
||||||
|
|
||||||
|
# Ciphers and keying
|
||||||
|
#RekeyLimit default none
|
||||||
|
|
||||||
|
+# System-wide Crypto policy:
|
||||||
|
+# This system is following system-wide crypto policy. The changes to
|
||||||
|
+# Ciphers, MACs, KexAlgoritms and GSSAPIKexAlgorithsm will not have any
|
||||||
|
+# effect here. They will be overridden by command-line options passed on
|
||||||
|
+# the server start up.
|
||||||
|
+# To opt out, uncomment a line with redefinition of CRYPTO_POLICY=
|
||||||
|
+# variable in /etc/sysconfig/sshd to overwrite the policy.
|
||||||
|
+# For more information, see manual page for update-crypto-policies(8).
|
||||||
|
+
|
||||||
|
# Logging
|
||||||
|
#SyslogFacility AUTH
|
||||||
|
+SyslogFacility AUTHPRIV
|
||||||
|
#LogLevel INFO
|
||||||
|
|
||||||
|
# Authentication:
|
||||||
|
@@ -56,9 +70,11 @@ AuthorizedKeysFile .ssh/authorized_keys
|
||||||
|
# To disable tunneled clear text passwords, change to no here!
|
||||||
|
#PasswordAuthentication yes
|
||||||
|
#PermitEmptyPasswords no
|
||||||
|
+PasswordAuthentication yes
|
||||||
|
|
||||||
|
# Change to no to disable s/key passwords
|
||||||
|
#ChallengeResponseAuthentication yes
|
||||||
|
+ChallengeResponseAuthentication no
|
||||||
|
|
||||||
|
# Kerberos options
|
||||||
|
#KerberosAuthentication no
|
||||||
|
@@ -67,8 +83,8 @@ AuthorizedKeysFile .ssh/authorized_keys
|
||||||
|
#KerberosGetAFSToken no
|
||||||
|
|
||||||
|
# GSSAPI options
|
||||||
|
-#GSSAPIAuthentication no
|
||||||
|
-#GSSAPICleanupCredentials yes
|
||||||
|
+GSSAPIAuthentication yes
|
||||||
|
+GSSAPICleanupCredentials no
|
||||||
|
|
||||||
|
# Set this to 'yes' to enable PAM authentication, account processing,
|
||||||
|
# and session processing. If this is enabled, PAM authentication will
|
||||||
|
@@ -79,16 +95,20 @@ AuthorizedKeysFile .ssh/authorized_keys
|
||||||
|
# If you just want the PAM account and session checks to run without
|
||||||
|
# PAM authentication, then enable this but set PasswordAuthentication
|
||||||
|
# and ChallengeResponseAuthentication to 'no'.
|
||||||
|
-#UsePAM no
|
||||||
|
+UsePAM yes
|
||||||
|
|
||||||
|
#AllowAgentForwarding yes
|
||||||
|
#AllowTcpForwarding yes
|
||||||
|
#GatewayPorts no
|
||||||
|
-#X11Forwarding no
|
||||||
|
+X11Forwarding yes
|
||||||
|
#X11DisplayOffset 10
|
||||||
|
#X11UseLocalhost yes
|
||||||
|
#PermitTTY yes
|
||||||
|
-#PrintMotd 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
|
||||||
|
+
|
||||||
|
#PrintLastLog yes
|
||||||
|
#TCPKeepAlive yes
|
||||||
|
#PermitUserEnvironment no
|
||||||
|
@@ -106,6 +126,12 @@ AuthorizedKeysFile .ssh/authorized_keys
|
||||||
|
# no default banner path
|
||||||
|
#Banner none
|
||||||
|
|
||||||
|
+# Accept locale-related environment variables
|
||||||
|
+AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
|
||||||
|
+AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
|
||||||
|
+AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
|
||||||
|
+AcceptEnv XMODIFIERS
|
||||||
|
+
|
||||||
|
# override default of no subsystems
|
||||||
|
Subsystem sftp /usr/libexec/sftp-server
|
||||||
|
|
26
SOURCES/openssh-7.8p1-UsePAM-warning.patch
Normal file
26
SOURCES/openssh-7.8p1-UsePAM-warning.patch
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
diff --git a/sshd.c b/sshd.c
|
||||||
|
--- a/sshd.c
|
||||||
|
+++ b/sshd.c
|
||||||
|
@@ -1701,6 +1701,10 @@ main(int ac, char **av)
|
||||||
|
parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name,
|
||||||
|
cfg, NULL);
|
||||||
|
|
||||||
|
+ /* 'UsePAM no' is not supported in Fedora */
|
||||||
|
+ if (! options.use_pam)
|
||||||
|
+ logit("WARNING: 'UsePAM no' is not supported in Fedora and may cause several problems.");
|
||||||
|
+
|
||||||
|
seed_rng();
|
||||||
|
|
||||||
|
/* Fill in default values for those options not explicitly set. */
|
||||||
|
diff --git a/sshd_config b/sshd_config
|
||||||
|
--- a/sshd_config
|
||||||
|
+++ b/sshd_config
|
||||||
|
@@ -101,6 +101,8 @@ GSSAPICleanupCredentials no
|
||||||
|
# If you just want the PAM account and session checks to run without
|
||||||
|
# PAM authentication, then enable this but set PasswordAuthentication
|
||||||
|
# and ChallengeResponseAuthentication to 'no'.
|
||||||
|
+# WARNING: 'UsePAM no' is not supported in Fedora and may cause several
|
||||||
|
+# problems.
|
||||||
|
UsePAM yes
|
||||||
|
|
||||||
|
#AllowAgentForwarding yes
|
2907
SOURCES/openssh-7.8p1-gsskex.patch
Normal file
2907
SOURCES/openssh-7.8p1-gsskex.patch
Normal file
File diff suppressed because it is too large
Load Diff
72
SOURCES/openssh-7.8p1-ip-port-config-parser.patch
Normal file
72
SOURCES/openssh-7.8p1-ip-port-config-parser.patch
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
diff -up openssh/misc.c.config openssh/misc.c
|
||||||
|
--- openssh/misc.c.config 2018-08-22 13:58:54.922807799 +0200
|
||||||
|
+++ openssh/misc.c 2018-08-22 13:58:55.000808428 +0200
|
||||||
|
@@ -485,7 +485,7 @@ put_host_port(const char *host, u_short
|
||||||
|
* The delimiter char, if present, is stored in delim.
|
||||||
|
* If this is the last field, *cp is set to NULL.
|
||||||
|
*/
|
||||||
|
-static char *
|
||||||
|
+char *
|
||||||
|
hpdelim2(char **cp, char *delim)
|
||||||
|
{
|
||||||
|
char *s, *old;
|
||||||
|
diff -up openssh/misc.h.config openssh/misc.h
|
||||||
|
--- openssh/misc.h.config 2018-08-20 07:57:29.000000000 +0200
|
||||||
|
+++ openssh/misc.h 2018-08-22 13:58:55.001808436 +0200
|
||||||
|
@@ -54,6 +54,7 @@ int set_rdomain(int, const char *);
|
||||||
|
int a2port(const char *);
|
||||||
|
int a2tun(const char *, int *);
|
||||||
|
char *put_host_port(const char *, u_short);
|
||||||
|
+char *hpdelim2(char **, char *);
|
||||||
|
char *hpdelim(char **);
|
||||||
|
char *cleanhostname(char *);
|
||||||
|
char *colon(char *);
|
||||||
|
diff -up openssh/servconf.c.config openssh/servconf.c
|
||||||
|
--- openssh/servconf.c.config 2018-08-22 13:58:54.989808340 +0200
|
||||||
|
+++ openssh/servconf.c 2018-08-22 14:18:49.235443937 +0200
|
||||||
|
@@ -886,7 +886,7 @@ process_permitopen_list(struct ssh *ssh,
|
||||||
|
{
|
||||||
|
u_int i;
|
||||||
|
int port;
|
||||||
|
- char *host, *arg, *oarg;
|
||||||
|
+ char *host, *arg, *oarg, ch;
|
||||||
|
int where = opcode == sPermitOpen ? FORWARD_LOCAL : FORWARD_REMOTE;
|
||||||
|
const char *what = lookup_opcode_name(opcode);
|
||||||
|
|
||||||
|
@@ -904,8 +904,8 @@ process_permitopen_list(struct ssh *ssh,
|
||||||
|
/* Otherwise treat it as a list of permitted host:port */
|
||||||
|
for (i = 0; i < num_opens; i++) {
|
||||||
|
oarg = arg = xstrdup(opens[i]);
|
||||||
|
- host = hpdelim(&arg);
|
||||||
|
- if (host == NULL)
|
||||||
|
+ host = hpdelim2(&arg, &ch);
|
||||||
|
+ if (host == NULL || ch == '/')
|
||||||
|
fatal("%s: missing host in %s", __func__, what);
|
||||||
|
host = cleanhostname(host);
|
||||||
|
if (arg == NULL || ((port = permitopen_port(arg)) < 0))
|
||||||
|
@@ -1323,8 +1323,10 @@ process_server_config_line(ServerOptions
|
||||||
|
port = 0;
|
||||||
|
p = arg;
|
||||||
|
} else {
|
||||||
|
- p = hpdelim(&arg);
|
||||||
|
- if (p == NULL)
|
||||||
|
+ char ch;
|
||||||
|
+ arg2 = NULL;
|
||||||
|
+ p = hpdelim2(&arg, &ch);
|
||||||
|
+ if (p == NULL || ch == '/')
|
||||||
|
fatal("%s line %d: bad address:port usage",
|
||||||
|
filename, linenum);
|
||||||
|
p = cleanhostname(p);
|
||||||
|
@@ -1965,9 +1967,10 @@ process_server_config_line(ServerOptions
|
||||||
|
*/
|
||||||
|
xasprintf(&arg2, "*:%s", arg);
|
||||||
|
} else {
|
||||||
|
+ char ch;
|
||||||
|
arg2 = xstrdup(arg);
|
||||||
|
- p = hpdelim(&arg);
|
||||||
|
- if (p == NULL) {
|
||||||
|
+ p = hpdelim2(&arg, &ch);
|
||||||
|
+ if (p == NULL || ch == '/') {
|
||||||
|
fatal("%s line %d: missing host in %s",
|
||||||
|
filename, linenum,
|
||||||
|
lookup_opcode_name(opcode));
|
885
SOURCES/openssh-7.8p1-role-mls.patch
Normal file
885
SOURCES/openssh-7.8p1-role-mls.patch
Normal file
@ -0,0 +1,885 @@
|
|||||||
|
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, *service, *method, *style = NULL;
|
||||||
|
+#ifdef WITH_SELINUX
|
||||||
|
+ char *role = NULL;
|
||||||
|
+#endif
|
||||||
|
int 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;
|
||||||
|
|
||||||
|
@@ -296,8 +304,15 @@ input_userauth_request(int type, u_int32
|
||||||
|
use_privsep ? " [net]" : "");
|
||||||
|
authctxt->service = xstrdup(service);
|
||||||
|
authctxt->style = style ? xstrdup(style) : NULL;
|
||||||
|
- if (use_privsep)
|
||||||
|
+#ifdef WITH_SELINUX
|
||||||
|
+ authctxt->role = role ? xstrdup(role) : NULL;
|
||||||
|
+#endif
|
||||||
|
+ if (use_privsep) {
|
||||||
|
mm_inform_authserv(service, style);
|
||||||
|
+#ifdef WITH_SELINUX
|
||||||
|
+ mm_inform_authrole(role);
|
||||||
|
+#endif
|
||||||
|
+ }
|
||||||
|
userauth_banner();
|
||||||
|
if (auth2_setup_methods_lists(authctxt) != 0)
|
||||||
|
packet_disconnect("no authentication methods enabled");
|
||||||
|
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;
|
||||||
|
const char *displayname;
|
||||||
|
@@ -298,7 +299,13 @@ input_gssapi_mic(int type, u_int32_t ple
|
||||||
|
fatal("%s: sshbuf_new failed", __func__);
|
||||||
|
mic.value = p;
|
||||||
|
mic.length = len;
|
||||||
|
- ssh_gssapi_buildmic(b, authctxt->user, authctxt->service,
|
||||||
|
+#ifdef WITH_SELINUX
|
||||||
|
+ if (authctxt->role && (strlen(authctxt->role) > 0))
|
||||||
|
+ xasprintf(&micuser, "%s/%s", authctxt->user, authctxt->role);
|
||||||
|
+ else
|
||||||
|
+#endif
|
||||||
|
+ micuser = authctxt->user;
|
||||||
|
+ ssh_gssapi_buildmic(b, micuser, authctxt->service,
|
||||||
|
"gssapi-with-mic");
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if ((!use_privsep || mm_is_monitor()) &&
|
||||||
|
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_string(b, session_id2, session_id2_len)) != 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, "hostbased")) != 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;
|
||||||
|
#ifdef HAVE_PAM_PUTENV
|
||||||
|
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(int );
|
||||||
|
void do_pam_chauthtok(void);
|
||||||
|
-int do_pam_putenv(char *, char *);
|
||||||
|
+int do_pam_putenv(char *, const char *);
|
||||||
|
char ** fetch_pam_environment(void);
|
||||||
|
char ** fetch_pam_child_environment(void);
|
||||||
|
void free_pam_environment(char **);
|
||||||
|
diff -up openssh/configure.ac.role-mls openssh/configure.ac
|
||||||
|
--- openssh/configure.ac.role-mls 2018-08-20 07:57:29.000000000 +0200
|
||||||
|
+++ openssh/configure.ac 2018-08-22 11:14:56.820430957 +0200
|
||||||
|
@@ -4241,10 +4241,7 @@ AC_ARG_WITH([selinux],
|
||||||
|
LIBS="$LIBS -lselinux"
|
||||||
|
],
|
||||||
|
AC_MSG_ERROR([SELinux support requires libselinux library]))
|
||||||
|
- SSHLIBS="$SSHLIBS $LIBSELINUX"
|
||||||
|
- SSHDLIBS="$SSHDLIBS $LIBSELINUX"
|
||||||
|
AC_CHECK_FUNCS([getseuserbyname get_default_context_with_level])
|
||||||
|
- LIBS="$save_LIBS"
|
||||||
|
fi ]
|
||||||
|
)
|
||||||
|
AC_SUBST([SSHLIBS])
|
||||||
|
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/monitor.c.role-mls openssh/monitor.c
|
||||||
|
--- openssh/monitor.c.role-mls 2018-08-20 07:57:29.000000000 +0200
|
||||||
|
+++ openssh/monitor.c 2018-08-22 11:19:56.006844867 +0200
|
||||||
|
@@ -115,6 +115,9 @@ int mm_answer_sign(int, struct sshbuf *)
|
||||||
|
int mm_answer_pwnamallow(int, struct sshbuf *);
|
||||||
|
int mm_answer_auth2_read_banner(int, struct sshbuf *);
|
||||||
|
int mm_answer_authserv(int, struct sshbuf *);
|
||||||
|
+#ifdef WITH_SELINUX
|
||||||
|
+int mm_answer_authrole(int, struct sshbuf *);
|
||||||
|
+#endif
|
||||||
|
int mm_answer_authpassword(int, struct sshbuf *);
|
||||||
|
int mm_answer_bsdauthquery(int, struct sshbuf *);
|
||||||
|
int mm_answer_bsdauthrespond(int, struct sshbuf *);
|
||||||
|
@@ -189,6 +192,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
|
||||||
|
@@ -796,6 +802,9 @@ mm_answer_pwnamallow(int sock, struct ss
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
@@ -842,6 +851,26 @@ mm_answer_authserv(int sock, struct sshb
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
+#ifdef WITH_SELINUX
|
||||||
|
+int
|
||||||
|
+mm_answer_authrole(int sock, struct sshbuf *m)
|
||||||
|
+{
|
||||||
|
+ int r;
|
||||||
|
+ monitor_permit_authentications(1);
|
||||||
|
+
|
||||||
|
+ if ((r = sshbuf_get_cstring(m, &authctxt->role, NULL)) != 0)
|
||||||
|
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
+ debug3("%s: role=%s", __func__, authctxt->role);
|
||||||
|
+
|
||||||
|
+ if (strlen(authctxt->role) == 0) {
|
||||||
|
+ free(authctxt->role);
|
||||||
|
+ authctxt->role = NULL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return (0);
|
||||||
|
+}
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
int
|
||||||
|
mm_answer_authpassword(int sock, struct sshbuf *m)
|
||||||
|
{
|
||||||
|
@@ -1218,7 +1247,7 @@ monitor_valid_userblob(u_char *data, u_i
|
||||||
|
{
|
||||||
|
struct sshbuf *b;
|
||||||
|
const u_char *p;
|
||||||
|
- char *userstyle, *cp;
|
||||||
|
+ char *userstyle, *s, *cp;
|
||||||
|
size_t len;
|
||||||
|
u_char type;
|
||||||
|
int r, fail = 0;
|
||||||
|
@@ -1251,6 +1280,8 @@ monitor_valid_userblob(u_char *data, u_i
|
||||||
|
fail++;
|
||||||
|
if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0)
|
||||||
|
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
+ if ((s = strchr(cp, '/')) != NULL)
|
||||||
|
+ *s = '\0';
|
||||||
|
xasprintf(&userstyle, "%s%s%s", authctxt->user,
|
||||||
|
authctxt->style ? ":" : "",
|
||||||
|
authctxt->style ? authctxt->style : "");
|
||||||
|
@@ -1286,7 +1317,7 @@ monitor_valid_hostbasedblob(u_char *data
|
||||||
|
{
|
||||||
|
struct sshbuf *b;
|
||||||
|
const u_char *p;
|
||||||
|
- char *cp, *userstyle;
|
||||||
|
+ char *cp, *s, *userstyle;
|
||||||
|
size_t len;
|
||||||
|
int r, fail = 0;
|
||||||
|
u_char type;
|
||||||
|
@@ -1308,6 +1339,8 @@ monitor_valid_hostbasedblob(u_char *data
|
||||||
|
fail++;
|
||||||
|
if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0)
|
||||||
|
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
+ if ((s = strchr(p, '/')) != 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("%s entering", __func__);
|
||||||
|
+
|
||||||
|
+ if ((m = sshbuf_new()) == NULL)
|
||||||
|
+ fatal("%s: sshbuf_new failed", __func__);
|
||||||
|
+ if ((r = sshbuf_put_cstring(m, role ? role : "")) != 0)
|
||||||
|
+ fatal("%s: buffer error: %s", __func__, 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);
|
||||||
|
int mm_sshkey_sign(struct sshkey *, u_char **, size_t *, const u_char *, size_t,
|
||||||
|
const char *, u_int compat);
|
||||||
|
void mm_inform_authserv(char *, char *);
|
||||||
|
+#ifdef WITH_SELINUX
|
||||||
|
+void mm_inform_authrole(char *);
|
||||||
|
+#endif
|
||||||
|
struct passwd *mm_getpwnamallow(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-linux.o \
|
||||||
|
port-solaris.o \
|
||||||
|
port-net.o \
|
||||||
|
- port-uw.o
|
||||||
|
+ port-uw.o \
|
||||||
|
+ port-linux-sshd.o
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
$(CC) $(CFLAGS) $(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)
|
||||||
|
-{
|
||||||
|
- security_context_t 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("%s: getexeccon: %s", __func__, 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,425 @@
|
||||||
|
+/*
|
||||||
|
+ * Copyright (c) 2005 Daniel Walsh <dwalsh@redhat.com>
|
||||||
|
+ * Copyright (c) 2014 Petr Lautrbach <plautrba@redhat.com>
|
||||||
|
+ *
|
||||||
|
+ * Permission to use, copy, modify, and distribute this software for any
|
||||||
|
+ * purpose with or without fee is hereby granted, provided that the above
|
||||||
|
+ * copyright notice and this permission notice appear in all copies.
|
||||||
|
+ *
|
||||||
|
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Linux-specific portability code - just SELinux support for sshd at present
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include "includes.h"
|
||||||
|
+
|
||||||
|
+#if defined(WITH_SELINUX) || defined(LINUX_OOM_ADJUST)
|
||||||
|
+#include <errno.h>
|
||||||
|
+#include <stdarg.h>
|
||||||
|
+#include <string.h>
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+
|
||||||
|
+#include "log.h"
|
||||||
|
+#include "xmalloc.h"
|
||||||
|
+#include "misc.h" /* servconf.h needs misc.h for struct ForwardOptions */
|
||||||
|
+#include "servconf.h"
|
||||||
|
+#include "port-linux.h"
|
||||||
|
+#include "sshkey.h"
|
||||||
|
+#include "hostfile.h"
|
||||||
|
+#include "auth.h"
|
||||||
|
+
|
||||||
|
+#ifdef WITH_SELINUX
|
||||||
|
+#include <selinux/selinux.h>
|
||||||
|
+#include <selinux/context.h>
|
||||||
|
+#include <selinux/get_context_list.h>
|
||||||
|
+#include <selinux/get_default_type.h>
|
||||||
|
+
|
||||||
|
+#ifdef HAVE_LINUX_AUDIT
|
||||||
|
+#include <libaudit.h>
|
||||||
|
+#include <unistd.h>
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+extern ServerOptions options;
|
||||||
|
+extern Authctxt *the_authctxt;
|
||||||
|
+extern int inetd_flag;
|
||||||
|
+extern int rexeced_flag;
|
||||||
|
+
|
||||||
|
+/* Send audit message */
|
||||||
|
+static int
|
||||||
|
+sshd_selinux_send_audit_message(int success, security_context_t default_context,
|
||||||
|
+ security_context_t selected_context)
|
||||||
|
+{
|
||||||
|
+ int rc=0;
|
||||||
|
+#ifdef HAVE_LINUX_AUDIT
|
||||||
|
+ char *msg = NULL;
|
||||||
|
+ int audit_fd = audit_open();
|
||||||
|
+ security_context_t default_raw=NULL;
|
||||||
|
+ security_context_t selected_raw=NULL;
|
||||||
|
+ rc = -1;
|
||||||
|
+ if (audit_fd < 0) {
|
||||||
|
+ if (errno == EINVAL || errno == EPROTONOSUPPORT ||
|
||||||
|
+ errno == EAFNOSUPPORT)
|
||||||
|
+ return 0; /* No audit support in kernel */
|
||||||
|
+ error("Error connecting to audit system.");
|
||||||
|
+ return rc;
|
||||||
|
+ }
|
||||||
|
+ if (selinux_trans_to_raw_context(default_context, &default_raw) < 0) {
|
||||||
|
+ error("Error translating default context.");
|
||||||
|
+ default_raw = NULL;
|
||||||
|
+ }
|
||||||
|
+ if (selinux_trans_to_raw_context(selected_context, &selected_raw) < 0) {
|
||||||
|
+ error("Error translating selected context.");
|
||||||
|
+ selected_raw = NULL;
|
||||||
|
+ }
|
||||||
|
+ if (asprintf(&msg, "sshd: default-context=%s selected-context=%s",
|
||||||
|
+ default_raw ? default_raw : (default_context ? default_context: "?"),
|
||||||
|
+ selected_context ? selected_raw : (selected_context ? selected_context :"?")) < 0) {
|
||||||
|
+ error("Error allocating memory.");
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ if (audit_log_user_message(audit_fd, AUDIT_USER_ROLE_CHANGE,
|
||||||
|
+ msg, NULL, NULL, NULL, success) <= 0) {
|
||||||
|
+ error("Error sending audit message.");
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ rc = 0;
|
||||||
|
+ out:
|
||||||
|
+ free(msg);
|
||||||
|
+ freecon(default_raw);
|
||||||
|
+ freecon(selected_raw);
|
||||||
|
+ close(audit_fd);
|
||||||
|
+#endif
|
||||||
|
+ return rc;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+mls_range_allowed(security_context_t src, security_context_t dst)
|
||||||
|
+{
|
||||||
|
+ struct av_decision avd;
|
||||||
|
+ int retval;
|
||||||
|
+ access_vector_t bit;
|
||||||
|
+ security_class_t class;
|
||||||
|
+
|
||||||
|
+ debug("%s: src:%s dst:%s", __func__, src, dst);
|
||||||
|
+ class = string_to_security_class("context");
|
||||||
|
+ if (!class) {
|
||||||
|
+ error("string_to_security_class failed to translate security class context");
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ bit = string_to_av_perm(class, "contains");
|
||||||
|
+ if (!bit) {
|
||||||
|
+ error("string_to_av_perm failed to translate av perm contains");
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ retval = security_compute_av(src, dst, class, bit, &avd);
|
||||||
|
+ if (retval || ((bit & avd.allowed) != bit))
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ return 1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+get_user_context(const char *sename, const char *role, const char *lvl,
|
||||||
|
+ security_context_t *sc) {
|
||||||
|
+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
|
||||||
|
+ if (lvl == NULL || lvl[0] == '\0' || get_default_context_with_level(sename, lvl, NULL, sc) != 0) {
|
||||||
|
+ /* User may have requested a level completely outside of his
|
||||||
|
+ allowed range. We get a context just for auditing as the
|
||||||
|
+ range check below will certainly fail for default context. */
|
||||||
|
+#endif
|
||||||
|
+ if (get_default_context(sename, NULL, sc) != 0) {
|
||||||
|
+ *sc = NULL;
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+ if (role != NULL && role[0]) {
|
||||||
|
+ context_t con;
|
||||||
|
+ char *type=NULL;
|
||||||
|
+ if (get_default_type(role, &type) != 0) {
|
||||||
|
+ error("get_default_type: failed to get default type for '%s'",
|
||||||
|
+ role);
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ con = context_new(*sc);
|
||||||
|
+ if (!con) {
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ context_role_set(con, role);
|
||||||
|
+ context_type_set(con, type);
|
||||||
|
+ freecon(*sc);
|
||||||
|
+ *sc = strdup(context_str(con));
|
||||||
|
+ context_free(con);
|
||||||
|
+ if (!*sc)
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
|
||||||
|
+ if (lvl != NULL && lvl[0]) {
|
||||||
|
+ /* verify that the requested range is obtained */
|
||||||
|
+ context_t con;
|
||||||
|
+ security_context_t obtained_raw;
|
||||||
|
+ security_context_t requested_raw;
|
||||||
|
+ con = context_new(*sc);
|
||||||
|
+ if (!con) {
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ context_range_set(con, lvl);
|
||||||
|
+ if (selinux_trans_to_raw_context(*sc, &obtained_raw) < 0) {
|
||||||
|
+ context_free(con);
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ if (selinux_trans_to_raw_context(context_str(con), &requested_raw) < 0) {
|
||||||
|
+ freecon(obtained_raw);
|
||||||
|
+ context_free(con);
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ debug("get_user_context: obtained context '%s' requested context '%s'",
|
||||||
|
+ obtained_raw, requested_raw);
|
||||||
|
+ if (strcmp(obtained_raw, requested_raw)) {
|
||||||
|
+ /* set the context to the real requested one but fail */
|
||||||
|
+ freecon(requested_raw);
|
||||||
|
+ freecon(obtained_raw);
|
||||||
|
+ freecon(*sc);
|
||||||
|
+ *sc = strdup(context_str(con));
|
||||||
|
+ context_free(con);
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+ freecon(requested_raw);
|
||||||
|
+ freecon(obtained_raw);
|
||||||
|
+ context_free(con);
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+ return 0;
|
||||||
|
+ out:
|
||||||
|
+ freecon(*sc);
|
||||||
|
+ *sc = NULL;
|
||||||
|
+ return -1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+ssh_selinux_get_role_level(char **role, const char **level)
|
||||||
|
+{
|
||||||
|
+ *role = NULL;
|
||||||
|
+ *level = NULL;
|
||||||
|
+ if (the_authctxt) {
|
||||||
|
+ if (the_authctxt->role != NULL) {
|
||||||
|
+ char *slash;
|
||||||
|
+ *role = xstrdup(the_authctxt->role);
|
||||||
|
+ if ((slash = strchr(*role, '/')) != NULL) {
|
||||||
|
+ *slash = '\0';
|
||||||
|
+ *level = slash + 1;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Return the default security context for the given username */
|
||||||
|
+static int
|
||||||
|
+sshd_selinux_getctxbyname(char *pwname,
|
||||||
|
+ security_context_t *default_sc, security_context_t *user_sc)
|
||||||
|
+{
|
||||||
|
+ char *sename, *lvl;
|
||||||
|
+ char *role;
|
||||||
|
+ const char *reqlvl;
|
||||||
|
+ int r = 0;
|
||||||
|
+ context_t con = NULL;
|
||||||
|
+
|
||||||
|
+ ssh_selinux_get_role_level(&role, &reqlvl);
|
||||||
|
+
|
||||||
|
+#ifdef HAVE_GETSEUSERBYNAME
|
||||||
|
+ if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) {
|
||||||
|
+ sename = NULL;
|
||||||
|
+ lvl = NULL;
|
||||||
|
+ }
|
||||||
|
+#else
|
||||||
|
+ sename = pwname;
|
||||||
|
+ lvl = "";
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ if (r == 0) {
|
||||||
|
+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
|
||||||
|
+ r = get_default_context_with_level(sename, lvl, NULL, default_sc);
|
||||||
|
+#else
|
||||||
|
+ r = get_default_context(sename, NULL, default_sc);
|
||||||
|
+#endif
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (r == 0) {
|
||||||
|
+ /* If launched from xinetd, we must use current level */
|
||||||
|
+ if (inetd_flag && !rexeced_flag) {
|
||||||
|
+ security_context_t sshdsc=NULL;
|
||||||
|
+
|
||||||
|
+ if (getcon_raw(&sshdsc) < 0)
|
||||||
|
+ fatal("failed to allocate security context");
|
||||||
|
+
|
||||||
|
+ if ((con=context_new(sshdsc)) == NULL)
|
||||||
|
+ fatal("failed to allocate selinux context");
|
||||||
|
+ reqlvl = context_range_get(con);
|
||||||
|
+ freecon(sshdsc);
|
||||||
|
+ if (reqlvl !=NULL && lvl != NULL && strcmp(reqlvl, lvl) == 0)
|
||||||
|
+ /* we actually don't change level */
|
||||||
|
+ reqlvl = "";
|
||||||
|
+
|
||||||
|
+ debug("%s: current connection level '%s'", __func__, 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("%s: Failed to get default SELinux security "
|
||||||
|
+ "context for %s", __func__, 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("%s: setting execution context", __func__);
|
||||||
|
+
|
||||||
|
+ ssh_selinux_get_role_level(&role, &reqlvl);
|
||||||
|
+
|
||||||
|
+ rv = do_pam_putenv("SELINUX_ROLE_REQUESTED", role ? role : "");
|
||||||
|
+
|
||||||
|
+ if (inetd_flag && !rexeced_flag) {
|
||||||
|
+ use_current = "1";
|
||||||
|
+ } else {
|
||||||
|
+ use_current = "";
|
||||||
|
+ rv = rv || do_pam_putenv("SELINUX_LEVEL_REQUESTED", reqlvl ? reqlvl: "");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ rv = rv || do_pam_putenv("SELINUX_USE_CURRENT_RANGE", use_current);
|
||||||
|
+
|
||||||
|
+ if (role != NULL)
|
||||||
|
+ free(role);
|
||||||
|
+
|
||||||
|
+ return rv;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Set the execution context to the default for the specified user */
|
||||||
|
+void
|
||||||
|
+sshd_selinux_setup_exec_context(char *pwname)
|
||||||
|
+{
|
||||||
|
+ security_context_t user_ctx = NULL;
|
||||||
|
+ int r = 0;
|
||||||
|
+ security_context_t default_ctx = NULL;
|
||||||
|
+
|
||||||
|
+ if (!ssh_selinux_enabled())
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ if (options.use_pam) {
|
||||||
|
+ /* do not compute context, just setup environment for pam_selinux */
|
||||||
|
+ if (sshd_selinux_setup_pam_variables()) {
|
||||||
|
+ switch (security_getenforce()) {
|
||||||
|
+ case -1:
|
||||||
|
+ fatal("%s: security_getenforce() failed", __func__);
|
||||||
|
+ case 0:
|
||||||
|
+ error("%s: SELinux PAM variable setup failure. Continuing in permissive mode.",
|
||||||
|
+ __func__);
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ fatal("%s: SELinux PAM variable setup failure. Aborting connection.",
|
||||||
|
+ __func__);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ debug3("%s: setting execution context", __func__);
|
||||||
|
+
|
||||||
|
+ r = sshd_selinux_getctxbyname(pwname, &default_ctx, &user_ctx);
|
||||||
|
+ if (r >= 0) {
|
||||||
|
+ r = setexeccon(user_ctx);
|
||||||
|
+ if (r < 0) {
|
||||||
|
+ error("%s: Failed to set SELinux execution context %s for %s",
|
||||||
|
+ __func__, user_ctx, pwname);
|
||||||
|
+ }
|
||||||
|
+#ifdef HAVE_SETKEYCREATECON
|
||||||
|
+ else if (setkeycreatecon(user_ctx) < 0) {
|
||||||
|
+ error("%s: Failed to set SELinux keyring creation context %s for %s",
|
||||||
|
+ __func__, 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("%s: security_getenforce() failed", __func__);
|
||||||
|
+ case 0:
|
||||||
|
+ error("%s: SELinux failure. Continuing in permissive mode.",
|
||||||
|
+ __func__);
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ fatal("%s: SELinux failure. Aborting connection.",
|
||||||
|
+ __func__);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ if (user_ctx != NULL && user_ctx != default_ctx)
|
||||||
|
+ freecon(user_ctx);
|
||||||
|
+ if (default_ctx != NULL)
|
||||||
|
+ freecon(default_ctx);
|
||||||
|
+
|
||||||
|
+ debug3("%s: done", __func__);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#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.c.role-mls 2018-08-20 07:57:29.000000000 +0200
|
||||||
|
+++ openssh/sshd.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(1);
|
16
SOURCES/openssh-7.8p1-scp-ipv6.patch
Normal file
16
SOURCES/openssh-7.8p1-scp-ipv6.patch
Normal file
@ -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)
|
||||||
|
|
14
SOURCES/openssh-7.8p1.tar.gz.asc
Normal file
14
SOURCES/openssh-7.8p1.tar.gz.asc
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
-----BEGIN PGP SIGNATURE-----
|
||||||
|
|
||||||
|
iQHDBAABCgAdFiEEWcIRjtIG2SfmZ+vj0+X1a22SDTAFAlt+Xa8ACgkQ0+X1a22S
|
||||||
|
DTAJPwx9HIW/obxNJYTU7M8trpalBekdl1SqUjxdDwInIsKTLSOpJCsnynBai/3c
|
||||||
|
SuvZkBwcKwZZFe+xCvRQDHkf/YYLT+d7slUQolb0OJmzFKbvu6xwuv7q12ag9hQj
|
||||||
|
/8BUfdYRKb63uemfKuVAHfcnUm9WlwSbif+Au/j1yg/MlETY47ezYA9/q75wignx
|
||||||
|
3g38JVHVgKDenDd8o9/hgjeQpEHKNdCQo71nN2h3MYRlh4xrR9ENZj7y8x65Kp1j
|
||||||
|
WoZEhlvjYkka4deSGwj2MIAJnzsc39uppEoEjkB7F9SUo4O7CxbWFein70Ct7Xbs
|
||||||
|
VDWXQibnJGHKatHIecaPLUYexGWO1XYNZErDhY7fPw0ChfMGbz3+0eDfDJqGY49r
|
||||||
|
Lo6wzsrgv2kDJMqwciT/D/Zb3ocHnCrq1Isnz/Ug2lW58LMk7Y1HisPteZFQ/pkC
|
||||||
|
xKeO+K1RkaRUSCrB5iToqF+7i8eRNVROYmkKLgKcMrC0WYEjnbEoFdr4bktAS9QM
|
||||||
|
BS6aIsh2cyg2H0FjDKmYvcKOUf0IgA==
|
||||||
|
=ZiYm
|
||||||
|
-----END PGP SIGNATURE-----
|
62
SOURCES/openssh-7.9p1-disable-sha1.patch
Normal file
62
SOURCES/openssh-7.9p1-disable-sha1.patch
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
diff --git a/monitor.c b/monitor.c
|
||||||
|
index 12b33e7..a1c3c97 100644
|
||||||
|
--- a/monitor.c
|
||||||
|
+++ b/monitor.c
|
||||||
|
@@ -875,6 +875,34 @@ mm_answer_bsdauthrespond(int sock, struct sshbuf *m)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * Check that the key type appears in the supplied pattern list, ignoring
|
||||||
|
+ * mismastches in the signature algorithm. (Signature algorithm checks are
|
||||||
|
+ * performed in the unprivileged authentication code).
|
||||||
|
+ * Returns 1 on success, 0 otherwise.
|
||||||
|
+ */
|
||||||
|
+static int
|
||||||
|
+key_base_type_match(const struct sshkey *key, const char *list)
|
||||||
|
+{
|
||||||
|
+ char *s, *l, *ol = xstrdup(list);
|
||||||
|
+ int found = 0;
|
||||||
|
+
|
||||||
|
+ l = ol;
|
||||||
|
+ for ((s = strsep(&l, ",")); s && *s != '\0'; (s = strsep(&l, ","))) {
|
||||||
|
+ if (sshkey_type_from_name(s) == key->type) {
|
||||||
|
+ found = 1;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ if (!found) {
|
||||||
|
+ debug("key type %s does not appear in list %s",
|
||||||
|
+ sshkey_ssh_name(key), list);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ free(ol);
|
||||||
|
+ return found;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int
|
||||||
|
mm_answer_keyallowed(int sock, struct sshbuf *m)
|
||||||
|
{
|
||||||
|
@@ -909,8 +937,8 @@ mm_answer_keyallowed(int sock, struct sshbuf *m)
|
||||||
|
break;
|
||||||
|
if (auth2_key_already_used(authctxt, key))
|
||||||
|
break;
|
||||||
|
- if (match_pattern_list(sshkey_ssh_name(key),
|
||||||
|
- options.pubkey_key_types, 0) != 1)
|
||||||
|
+ if (!key_base_type_match(key,
|
||||||
|
+ options.pubkey_key_types))
|
||||||
|
break;
|
||||||
|
allowed = user_key_allowed(ssh, authctxt->pw, key,
|
||||||
|
pubkey_auth_attempt, &opts);
|
||||||
|
@@ -921,8 +949,8 @@ mm_answer_keyallowed(int sock, struct sshbuf *m)
|
||||||
|
break;
|
||||||
|
if (auth2_key_already_used(authctxt, key))
|
||||||
|
break;
|
||||||
|
- if (match_pattern_list(sshkey_ssh_name(key),
|
||||||
|
- options.hostbased_key_types, 0) != 1)
|
||||||
|
+ if (!key_base_type_match(key,
|
||||||
|
+ options.hostbased_key_types))
|
||||||
|
break;
|
||||||
|
allowed = hostbased_key_allowed(authctxt->pw,
|
||||||
|
cuser, chost, key);
|
||||||
|
|
150
SOURCES/openssh-7.9p1-gsskex-method.patch
Normal file
150
SOURCES/openssh-7.9p1-gsskex-method.patch
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
From bc74944ce7a2eabd228d47051f277ce108914c96 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jakub Jelen <jjelen@redhat.com>
|
||||||
|
Date: Tue, 16 Oct 2018 16:44:40 +0200
|
||||||
|
Subject: [PATCH] Unbreak authentication using gssapi-keyex (#1625366)
|
||||||
|
|
||||||
|
---
|
||||||
|
auth2-gss.c | 6 +++---
|
||||||
|
gss-serv.c | 4 +++-
|
||||||
|
monitor.c | 13 ++++++++++---
|
||||||
|
monitor_wrap.c | 4 +++-
|
||||||
|
monitor_wrap.h | 2 +-
|
||||||
|
ssh-gss.h | 2 +-
|
||||||
|
6 files changed, 21 insertions(+), 10 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/auth2-gss.c b/auth2-gss.c
|
||||||
|
index 3f2ad21d..a61ac089 100644
|
||||||
|
--- a/auth2-gss.c
|
||||||
|
+++ b/auth2-gss.c
|
||||||
|
@@ -84,7 +84,7 @@ userauth_gsskeyex(Authctxt *authctxt)
|
||||||
|
if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context,
|
||||||
|
&gssbuf, &mic))))
|
||||||
|
authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,
|
||||||
|
- authctxt->pw));
|
||||||
|
+ authctxt->pw, 1));
|
||||||
|
|
||||||
|
sshbuf_free(b);
|
||||||
|
free(mic.value);
|
||||||
|
@@ -299,7 +299,7 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh)
|
||||||
|
fatal("%s: %s", __func__, ssh_err(r));
|
||||||
|
|
||||||
|
authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,
|
||||||
|
- authctxt->pw));
|
||||||
|
+ authctxt->pw, 1));
|
||||||
|
|
||||||
|
if ((!use_privsep || mm_is_monitor()) &&
|
||||||
|
(displayname = ssh_gssapi_displayname()) != NULL)
|
||||||
|
@@ -347,7 +347,7 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh)
|
||||||
|
|
||||||
|
if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))))
|
||||||
|
authenticated =
|
||||||
|
- PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw));
|
||||||
|
+ PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw, 0));
|
||||||
|
else
|
||||||
|
logit("GSSAPI MIC check failed");
|
||||||
|
|
||||||
|
diff --git a/gss-serv.c b/gss-serv.c
|
||||||
|
index 786ac95c..87de2baa 100644
|
||||||
|
--- a/gss-serv.c
|
||||||
|
+++ b/gss-serv.c
|
||||||
|
@@ -493,10 +493,12 @@ verify_authentication_indicators(Gssctxt *gssctxt)
|
||||||
|
|
||||||
|
/* Privileged */
|
||||||
|
int
|
||||||
|
-ssh_gssapi_userok(char *user, struct passwd *pw)
|
||||||
|
+ssh_gssapi_userok(char *user, struct passwd *pw, int kex)
|
||||||
|
{
|
||||||
|
OM_uint32 lmin;
|
||||||
|
|
||||||
|
+ (void) kex; /* used in privilege separation */
|
||||||
|
+
|
||||||
|
if (gssapi_client.exportedname.length == 0 ||
|
||||||
|
gssapi_client.exportedname.value == NULL) {
|
||||||
|
debug("No suitable client data");
|
||||||
|
diff --git a/monitor.c b/monitor.c
|
||||||
|
index 9bbe8cc4..7b1903af 100644
|
||||||
|
--- a/monitor.c
|
||||||
|
+++ b/monitor.c
|
||||||
|
@@ -1877,14 +1877,17 @@ mm_answer_gss_checkmic(int sock, struct sshbuf *m)
|
||||||
|
int
|
||||||
|
mm_answer_gss_userok(int sock, struct sshbuf *m)
|
||||||
|
{
|
||||||
|
- int r, authenticated;
|
||||||
|
+ int r, authenticated, kex;
|
||||||
|
const char *displayname;
|
||||||
|
|
||||||
|
if (!options.gss_authentication && !options.gss_keyex)
|
||||||
|
fatal("%s: GSSAPI authentication not enabled", __func__);
|
||||||
|
|
||||||
|
+ if ((r = sshbuf_get_u32(m, &kex)) != 0)
|
||||||
|
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
+
|
||||||
|
authenticated = authctxt->valid &&
|
||||||
|
- ssh_gssapi_userok(authctxt->user, authctxt->pw);
|
||||||
|
+ ssh_gssapi_userok(authctxt->user, authctxt->pw, kex);
|
||||||
|
|
||||||
|
sshbuf_reset(m);
|
||||||
|
if ((r = sshbuf_put_u32(m, authenticated)) != 0)
|
||||||
|
@@ -1893,7 +1896,11 @@ mm_answer_gss_userok(int sock, struct sshbuf *m)
|
||||||
|
debug3("%s: sending result %d", __func__, authenticated);
|
||||||
|
mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m);
|
||||||
|
|
||||||
|
- auth_method = "gssapi-with-mic";
|
||||||
|
+ if (kex) {
|
||||||
|
+ auth_method = "gssapi-keyex";
|
||||||
|
+ } else {
|
||||||
|
+ auth_method = "gssapi-with-mic";
|
||||||
|
+ }
|
||||||
|
|
||||||
|
if ((displayname = ssh_gssapi_displayname()) != NULL)
|
||||||
|
auth2_record_info(authctxt, "%s", displayname);
|
||||||
|
diff --git a/monitor_wrap.c b/monitor_wrap.c
|
||||||
|
index fb52a530..508d926d 100644
|
||||||
|
--- a/monitor_wrap.c
|
||||||
|
+++ b/monitor_wrap.c
|
||||||
|
@@ -984,13 +984,15 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
-mm_ssh_gssapi_userok(char *user, struct passwd *pw)
|
||||||
|
+mm_ssh_gssapi_userok(char *user, struct passwd *pw, int kex)
|
||||||
|
{
|
||||||
|
struct sshbuf *m;
|
||||||
|
int r, authenticated = 0;
|
||||||
|
|
||||||
|
if ((m = sshbuf_new()) == NULL)
|
||||||
|
fatal("%s: sshbuf_new failed", __func__);
|
||||||
|
+ if ((r = sshbuf_put_u32(m, kex)) != 0)
|
||||||
|
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
|
||||||
|
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, m);
|
||||||
|
mm_request_receive_expect(pmonitor->m_recvfd,
|
||||||
|
diff --git a/monitor_wrap.h b/monitor_wrap.h
|
||||||
|
index 494760dd..5eba5ecc 100644
|
||||||
|
--- a/monitor_wrap.h
|
||||||
|
+++ b/monitor_wrap.h
|
||||||
|
@@ -60,7 +60,7 @@ int mm_sshkey_verify(const struct sshkey *, const u_char *, size_t,
|
||||||
|
OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
|
||||||
|
OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *,
|
||||||
|
gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *);
|
||||||
|
-int mm_ssh_gssapi_userok(char *user, struct passwd *);
|
||||||
|
+int mm_ssh_gssapi_userok(char *user, struct passwd *, int kex);
|
||||||
|
OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
|
||||||
|
OM_uint32 mm_ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t);
|
||||||
|
int mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *);
|
||||||
|
diff --git a/ssh-gss.h b/ssh-gss.h
|
||||||
|
index 39b6ce69..98262837 100644
|
||||||
|
--- a/ssh-gss.h
|
||||||
|
+++ b/ssh-gss.h
|
||||||
|
@@ -162,7 +162,7 @@ gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int);
|
||||||
|
int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *,
|
||||||
|
const char *);
|
||||||
|
OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
|
||||||
|
-int ssh_gssapi_userok(char *name, struct passwd *);
|
||||||
|
+int ssh_gssapi_userok(char *name, struct passwd *, int kex);
|
||||||
|
OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
|
||||||
|
void ssh_gssapi_do_child(char ***, u_int *);
|
||||||
|
void ssh_gssapi_cleanup_creds(void);
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
37
SOURCES/pam_ssh_agent-rmheaders
Normal file
37
SOURCES/pam_ssh_agent-rmheaders
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
authfd.c
|
||||||
|
authfd.h
|
||||||
|
atomicio.c
|
||||||
|
atomicio.h
|
||||||
|
bufaux.c
|
||||||
|
bufbn.c
|
||||||
|
buffer.h
|
||||||
|
buffer.c
|
||||||
|
cleanup.c
|
||||||
|
cipher.h
|
||||||
|
compat.h
|
||||||
|
defines.h
|
||||||
|
entropy.c
|
||||||
|
entropy.h
|
||||||
|
fatal.c
|
||||||
|
includes.h
|
||||||
|
kex.h
|
||||||
|
key.c
|
||||||
|
key.h
|
||||||
|
log.c
|
||||||
|
log.h
|
||||||
|
match.h
|
||||||
|
misc.c
|
||||||
|
misc.h
|
||||||
|
pathnames.h
|
||||||
|
platform.h
|
||||||
|
rsa.h
|
||||||
|
ssh-dss.c
|
||||||
|
ssh-rsa.c
|
||||||
|
ssh.h
|
||||||
|
ssh2.h
|
||||||
|
uidswap.c
|
||||||
|
uidswap.h
|
||||||
|
uuencode.c
|
||||||
|
uuencode.h
|
||||||
|
xmalloc.c
|
||||||
|
xmalloc.h
|
939
SOURCES/pam_ssh_agent_auth-0.10.2-compat.patch
Normal file
939
SOURCES/pam_ssh_agent_auth-0.10.2-compat.patch
Normal file
@ -0,0 +1,939 @@
|
|||||||
|
diff -up openssh/pam_ssh_agent_auth-0.10.3/get_command_line.c.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/get_command_line.c
|
||||||
|
--- openssh/pam_ssh_agent_auth-0.10.3/get_command_line.c.psaa-compat 2016-11-13 04:24:32.000000000 +0100
|
||||||
|
+++ openssh/pam_ssh_agent_auth-0.10.3/get_command_line.c 2018-08-24 10:22:56.281930322 +0200
|
||||||
|
@@ -27,6 +27,7 @@
|
||||||
|
* or implied, of Jamie Beverly.
|
||||||
|
*/
|
||||||
|
|
||||||
|
+#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
@@ -65,8 +66,8 @@ proc_pid_cmdline(char *** inargv)
|
||||||
|
case EOF:
|
||||||
|
case '\0':
|
||||||
|
if (len > 0) {
|
||||||
|
- argv = pamsshagentauth_xrealloc(argv, count + 1, sizeof(*argv));
|
||||||
|
- argv[count] = pamsshagentauth_xcalloc(len + 1, sizeof(*argv[count]));
|
||||||
|
+ argv = xreallocarray(argv, count + 1, sizeof(*argv));
|
||||||
|
+ argv[count] = xcalloc(len + 1, sizeof(*argv[count]));
|
||||||
|
strncpy(argv[count++], argbuf, len);
|
||||||
|
memset(argbuf, '\0', MAX_LEN_PER_CMDLINE_ARG + 1);
|
||||||
|
len = 0;
|
||||||
|
@@ -105,9 +106,9 @@ pamsshagentauth_free_command_line(char *
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < n_args; i++)
|
||||||
|
- pamsshagentauth_xfree(argv[i]);
|
||||||
|
+ free(argv[i]);
|
||||||
|
|
||||||
|
- pamsshagentauth_xfree(argv);
|
||||||
|
+ free(argv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff -up openssh/pam_ssh_agent_auth-0.10.3/identity.h.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/identity.h
|
||||||
|
--- openssh/pam_ssh_agent_auth-0.10.3/identity.h.psaa-compat 2016-11-13 04:24:32.000000000 +0100
|
||||||
|
+++ openssh/pam_ssh_agent_auth-0.10.3/identity.h 2018-08-24 10:18:05.009393312 +0200
|
||||||
|
@@ -30,8 +30,8 @@
|
||||||
|
#include "openbsd-compat/sys-queue.h"
|
||||||
|
#include "xmalloc.h"
|
||||||
|
#include "log.h"
|
||||||
|
-#include "buffer.h"
|
||||||
|
-#include "key.h"
|
||||||
|
+#include "sshbuf.h"
|
||||||
|
+#include "sshkey.h"
|
||||||
|
#include "authfd.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
@@ -41,7 +41,7 @@ typedef struct idlist Idlist;
|
||||||
|
struct identity {
|
||||||
|
TAILQ_ENTRY(identity) next;
|
||||||
|
AuthenticationConnection *ac; /* set if agent supports key */
|
||||||
|
- Key *key; /* public/private key */
|
||||||
|
+ struct sshkey *key; /* public/private key */
|
||||||
|
char *filename; /* comment for agent-only keys */
|
||||||
|
int tried;
|
||||||
|
int isprivate; /* key points to the private key */
|
||||||
|
diff -up openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c
|
||||||
|
--- openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-compat 2018-08-24 10:18:05.007393297 +0200
|
||||||
|
+++ openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c 2018-08-24 10:18:32.937612513 +0200
|
||||||
|
@@ -36,8 +36,8 @@
|
||||||
|
#include "openbsd-compat/sys-queue.h"
|
||||||
|
#include "xmalloc.h"
|
||||||
|
#include "log.h"
|
||||||
|
-#include "buffer.h"
|
||||||
|
-#include "key.h"
|
||||||
|
+#include "sshbuf.h"
|
||||||
|
+#include "sshkey.h"
|
||||||
|
#include "authfd.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
@@ -58,6 +58,8 @@
|
||||||
|
#include "get_command_line.h"
|
||||||
|
extern char **environ;
|
||||||
|
|
||||||
|
+#define PAM_SSH_AGENT_AUTH_REQUESTv1 101
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Added by Jamie Beverly, ensure socket fd points to a socket owned by the user
|
||||||
|
* A cursory check is done, but to avoid race conditions, it is necessary
|
||||||
|
@@ -77,7 +79,7 @@ log_action(char ** action, size_t count)
|
||||||
|
if (count == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
- buf = pamsshagentauth_xcalloc((count * MAX_LEN_PER_CMDLINE_ARG) + (count * 3), sizeof(*buf));
|
||||||
|
+ buf = xcalloc((count * MAX_LEN_PER_CMDLINE_ARG) + (count * 3), sizeof(*buf));
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
strcat(buf, (i > 0) ? " '" : "'");
|
||||||
|
strncat(buf, action[i], MAX_LEN_PER_CMDLINE_ARG);
|
||||||
|
@@ -87,21 +89,25 @@ log_action(char ** action, size_t count)
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
-agent_action(Buffer *buf, char ** action, size_t count)
|
||||||
|
+agent_action(struct sshbuf **buf, char ** action, size_t count)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
- pamsshagentauth_buffer_init(buf);
|
||||||
|
+ int r;
|
||||||
|
|
||||||
|
- pamsshagentauth_buffer_put_int(buf, count);
|
||||||
|
+ if ((*buf = sshbuf_new()) == NULL)
|
||||||
|
+ fatal("%s: sshbuf_new failed", __func__);
|
||||||
|
+ if ((r = sshbuf_put_u32(*buf, count)) != 0)
|
||||||
|
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
- pamsshagentauth_buffer_put_cstring(buf, action[i]);
|
||||||
|
+ if ((r = sshbuf_put_cstring(*buf, action[i])) != 0)
|
||||||
|
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-void
|
||||||
|
-pamsshagentauth_session_id2_gen(Buffer * session_id2, const char * user,
|
||||||
|
+static void
|
||||||
|
+pamsshagentauth_session_id2_gen(struct sshbuf ** session_id2, const char * user,
|
||||||
|
const char * ruser, const char * servicename)
|
||||||
|
{
|
||||||
|
u_char *cookie = NULL;
|
||||||
|
@@ -114,22 +116,23 @@ pamsshagentauth_session_id2_gen(Buffer *
|
||||||
|
char ** reported_argv = NULL;
|
||||||
|
size_t count = 0;
|
||||||
|
char * action_logbuf = NULL;
|
||||||
|
- Buffer action_agentbuf;
|
||||||
|
+ struct sshbuf *action_agentbuf = NULL;
|
||||||
|
uint8_t free_logbuf = 0;
|
||||||
|
char * retc;
|
||||||
|
int32_t reti;
|
||||||
|
+ int r;
|
||||||
|
|
||||||
|
- rnd = pamsshagentauth_arc4random();
|
||||||
|
+ rnd = arc4random();
|
||||||
|
cookie_len = ((uint8_t) rnd);
|
||||||
|
while (cookie_len < 16) {
|
||||||
|
cookie_len += 16; /* Add 16 bytes to the size to ensure that while the length is random, the length is always reasonable; ticket #18 */
|
||||||
|
}
|
||||||
|
|
||||||
|
- cookie = pamsshagentauth_xcalloc(1,cookie_len);
|
||||||
|
+ cookie = xcalloc(1, cookie_len);
|
||||||
|
|
||||||
|
for (i = 0; i < cookie_len; i++) {
|
||||||
|
if (i % 4 == 0) {
|
||||||
|
- rnd = pamsshagentauth_arc4random();
|
||||||
|
+ rnd = arc4random();
|
||||||
|
}
|
||||||
|
cookie[i] = (u_char) rnd;
|
||||||
|
rnd >>= 8;
|
||||||
|
@@ -139,12 +141,13 @@ pamsshagentauth_session_id2_gen(Buffer *
|
||||||
|
if (count > 0) {
|
||||||
|
free_logbuf = 1;
|
||||||
|
action_logbuf = log_action(reported_argv, count);
|
||||||
|
- agent_action(&action_agentbuf, reported_argv, count);
|
||||||
|
+ agent_action(&action_agentbuf, reported_argv, count);
|
||||||
|
pamsshagentauth_free_command_line(reported_argv, count);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
action_logbuf = "unknown on this platform";
|
||||||
|
- pamsshagentauth_buffer_init(&action_agentbuf); /* stays empty, means unavailable */
|
||||||
|
+ if ((action_agentbuf = sshbuf_new()) == NULL) /* stays empty, means unavailable */
|
||||||
|
+ fatal("%s: sshbuf_new failed", __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -161,35 +163,39 @@ pamsshagentauth_session_id2_gen(Buffer *
|
||||||
|
retc = getcwd(pwd, sizeof(pwd) - 1);
|
||||||
|
time(&ts);
|
||||||
|
|
||||||
|
- pamsshagentauth_buffer_init(session_id2);
|
||||||
|
+ if ((*session_id2 = sshbuf_new()) == NULL)
|
||||||
|
+ fatal("%s: sshbuf_new failed", __func__);
|
||||||
|
|
||||||
|
- pamsshagentauth_buffer_put_int(session_id2, PAM_SSH_AGENT_AUTH_REQUESTv1);
|
||||||
|
- /* pamsshagentauth_debug3("cookie: %s", pamsshagentauth_tohex(cookie, cookie_len)); */
|
||||||
|
- pamsshagentauth_buffer_put_string(session_id2, cookie, cookie_len);
|
||||||
|
- /* pamsshagentauth_debug3("user: %s", user); */
|
||||||
|
- pamsshagentauth_buffer_put_cstring(session_id2, user);
|
||||||
|
- /* pamsshagentauth_debug3("ruser: %s", ruser); */
|
||||||
|
- pamsshagentauth_buffer_put_cstring(session_id2, ruser);
|
||||||
|
- /* pamsshagentauth_debug3("servicename: %s", servicename); */
|
||||||
|
- pamsshagentauth_buffer_put_cstring(session_id2, servicename);
|
||||||
|
- /* pamsshagentauth_debug3("pwd: %s", pwd); */
|
||||||
|
- if(retc)
|
||||||
|
- pamsshagentauth_buffer_put_cstring(session_id2, pwd);
|
||||||
|
- else
|
||||||
|
- pamsshagentauth_buffer_put_cstring(session_id2, "");
|
||||||
|
- /* pamsshagentauth_debug3("action: %s", action_logbuf); */
|
||||||
|
- pamsshagentauth_buffer_put_string(session_id2, action_agentbuf.buf + action_agentbuf.offset, action_agentbuf.end - action_agentbuf.offset);
|
||||||
|
+ if ((r = sshbuf_put_u32(*session_id2, PAM_SSH_AGENT_AUTH_REQUESTv1)) != 0 ||
|
||||||
|
+ (r = sshbuf_put_string(*session_id2, cookie, cookie_len)) != 0 ||
|
||||||
|
+ (r = sshbuf_put_cstring(*session_id2, user)) != 0 ||
|
||||||
|
+ (r = sshbuf_put_cstring(*session_id2, ruser)) != 0 ||
|
||||||
|
+ (r = sshbuf_put_cstring(*session_id2, servicename)) != 0)
|
||||||
|
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
+ if (retc) {
|
||||||
|
+ if ((r = sshbuf_put_cstring(*session_id2, pwd)) != 0)
|
||||||
|
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
+ } else {
|
||||||
|
+ if ((r = sshbuf_put_cstring(*session_id2, "")) != 0)
|
||||||
|
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
+ }
|
||||||
|
+ if ((r = sshbuf_put_stringb(*session_id2, action_agentbuf)) != 0)
|
||||||
|
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
if (free_logbuf) {
|
||||||
|
- pamsshagentauth_xfree(action_logbuf);
|
||||||
|
- pamsshagentauth_buffer_free(&action_agentbuf);
|
||||||
|
+ free(action_logbuf);
|
||||||
|
+ sshbuf_free(action_agentbuf);
|
||||||
|
}
|
||||||
|
- /* pamsshagentauth_debug3("hostname: %s", hostname); */
|
||||||
|
- if(reti >= 0)
|
||||||
|
- pamsshagentauth_buffer_put_cstring(session_id2, hostname);
|
||||||
|
- else
|
||||||
|
- pamsshagentauth_buffer_put_cstring(session_id2, "");
|
||||||
|
- /* pamsshagentauth_debug3("ts: %ld", ts); */
|
||||||
|
- pamsshagentauth_buffer_put_int64(session_id2, (uint64_t) ts);
|
||||||
|
+ /* debug3("hostname: %s", hostname); */
|
||||||
|
+ if (reti >= 0) {
|
||||||
|
+ if ((r = sshbuf_put_cstring(*session_id2, hostname)) != 0)
|
||||||
|
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
+ } else {
|
||||||
|
+ if ((r = sshbuf_put_cstring(*session_id2, "")) != 0)
|
||||||
|
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
+ }
|
||||||
|
+ /* debug3("ts: %ld", ts); */
|
||||||
|
+ if ((r = sshbuf_put_u64(*session_id2, (uint64_t) ts)) != 0)
|
||||||
|
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
|
||||||
|
free(cookie);
|
||||||
|
return;
|
||||||
|
@@ -278,7 +280,8 @@ ssh_get_authentication_connection_for_ui
|
||||||
|
|
||||||
|
auth = xmalloc(sizeof(*auth));
|
||||||
|
auth->fd = sock;
|
||||||
|
- buffer_init(&auth->identities);
|
||||||
|
+ if ((auth->identities = sshbuf_new()) == NULL)
|
||||||
|
+ fatal("%s: sshbuf_new failed", __func__);
|
||||||
|
auth->howmany = 0;
|
||||||
|
|
||||||
|
return auth;
|
||||||
|
@@ -287,43 +289,42 @@ ssh_get_authentication_connection_for_ui
|
||||||
|
int
|
||||||
|
pamsshagentauth_find_authorized_keys(const char * user, const char * ruser, const char * servicename)
|
||||||
|
{
|
||||||
|
- Buffer session_id2 = { 0 };
|
||||||
|
+ struct sshbuf *session_id2 = NULL;
|
||||||
|
Identity *id;
|
||||||
|
- Key *key;
|
||||||
|
+ struct sshkey *key;
|
||||||
|
AuthenticationConnection *ac;
|
||||||
|
char *comment;
|
||||||
|
uint8_t retval = 0;
|
||||||
|
uid_t uid = getpwnam(ruser)->pw_uid;
|
||||||
|
|
||||||
|
OpenSSL_add_all_digests();
|
||||||
|
- pamsshagentauth_session_id2_gen(&session_id2, user, ruser, servicename);
|
||||||
|
+ pamsshagentauth_session_id2_gen(&session_id2, user, ruser, servicename);
|
||||||
|
|
||||||
|
if ((ac = ssh_get_authentication_connection_for_uid(uid))) {
|
||||||
|
- pamsshagentauth_verbose("Contacted ssh-agent of user %s (%u)", ruser, uid);
|
||||||
|
+ verbose("Contacted ssh-agent of user %s (%u)", ruser, uid);
|
||||||
|
for (key = ssh_get_first_identity(ac, &comment, 2); key != NULL; key = ssh_get_next_identity(ac, &comment, 2))
|
||||||
|
{
|
||||||
|
if(key != NULL) {
|
||||||
|
- id = pamsshagentauth_xcalloc(1, sizeof(*id));
|
||||||
|
+ id = xcalloc(1, sizeof(*id));
|
||||||
|
id->key = key;
|
||||||
|
id->filename = comment;
|
||||||
|
id->ac = ac;
|
||||||
|
- if(userauth_pubkey_from_id(ruser, id, &session_id2)) {
|
||||||
|
+ if(userauth_pubkey_from_id(ruser, id, session_id2)) {
|
||||||
|
retval = 1;
|
||||||
|
}
|
||||||
|
- pamsshagentauth_xfree(id->filename);
|
||||||
|
- pamsshagentauth_key_free(id->key);
|
||||||
|
- pamsshagentauth_xfree(id);
|
||||||
|
+ free(id->filename);
|
||||||
|
+ key_free(id->key);
|
||||||
|
+ free(id);
|
||||||
|
if(retval == 1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- pamsshagentauth_buffer_free(&session_id2);
|
||||||
|
+ sshbuf_free(session_id2);
|
||||||
|
ssh_close_authentication_connection(ac);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
- pamsshagentauth_verbose("No ssh-agent could be contacted");
|
||||||
|
+ verbose("No ssh-agent could be contacted");
|
||||||
|
}
|
||||||
|
- /* pamsshagentauth_xfree(session_id2); */
|
||||||
|
EVP_cleanup();
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
diff -up openssh/pam_ssh_agent_auth-0.10.3/pam_ssh_agent_auth.c.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/pam_ssh_agent_auth.c
|
||||||
|
--- openssh/pam_ssh_agent_auth-0.10.3/pam_ssh_agent_auth.c.psaa-compat 2018-08-24 10:18:05.008393305 +0200
|
||||||
|
+++ openssh/pam_ssh_agent_auth-0.10.3/pam_ssh_agent_auth.c 2018-08-24 10:18:05.009393312 +0200
|
||||||
|
@@ -104,7 +104,7 @@ pam_sm_authenticate(pam_handle_t * pamh,
|
||||||
|
* a patch 8-)
|
||||||
|
*/
|
||||||
|
#if ! HAVE___PROGNAME || HAVE_BUNDLE
|
||||||
|
- __progname = pamsshagentauth_xstrdup(servicename);
|
||||||
|
+ __progname = xstrdup(servicename);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for(i = argc, argv_ptr = (char **) argv; i > 0; ++argv_ptr, i--) {
|
||||||
|
@@ -130,11 +130,11 @@ pam_sm_authenticate(pam_handle_t * pamh,
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
- pamsshagentauth_log_init(__progname, log_lvl, facility, getenv("PAM_SSH_AGENT_AUTH_DEBUG") ? 1 : 0);
|
||||||
|
+ log_init(__progname, log_lvl, facility, getenv("PAM_SSH_AGENT_AUTH_DEBUG") ? 1 : 0);
|
||||||
|
pam_get_item(pamh, PAM_USER, (void *) &user);
|
||||||
|
pam_get_item(pamh, PAM_RUSER, (void *) &ruser_ptr);
|
||||||
|
|
||||||
|
- pamsshagentauth_verbose("Beginning pam_ssh_agent_auth for user %s", user);
|
||||||
|
+ verbose("Beginning pam_ssh_agent_auth for user %s", user);
|
||||||
|
|
||||||
|
if(ruser_ptr) {
|
||||||
|
strncpy(ruser, ruser_ptr, sizeof(ruser) - 1);
|
||||||
|
@@ -149,12 +149,12 @@ pam_sm_authenticate(pam_handle_t * pamh,
|
||||||
|
#ifdef ENABLE_SUDO_HACK
|
||||||
|
if( (strlen(sudo_service_name) > 0) && strncasecmp(servicename, sudo_service_name, sizeof(sudo_service_name) - 1) == 0 && getenv("SUDO_USER") ) {
|
||||||
|
strncpy(ruser, getenv("SUDO_USER"), sizeof(ruser) - 1 );
|
||||||
|
- pamsshagentauth_verbose( "Using environment variable SUDO_USER (%s)", ruser );
|
||||||
|
+ verbose( "Using environment variable SUDO_USER (%s)", ruser );
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if( ! getpwuid(getuid()) ) {
|
||||||
|
- pamsshagentauth_verbose("Unable to getpwuid(getuid())");
|
||||||
|
+ verbose("Unable to getpwuid(getuid())");
|
||||||
|
goto cleanexit;
|
||||||
|
}
|
||||||
|
strncpy(ruser, getpwuid(getuid())->pw_name, sizeof(ruser) - 1);
|
||||||
|
@@ -163,11 +163,11 @@ pam_sm_authenticate(pam_handle_t * pamh,
|
||||||
|
|
||||||
|
/* Might as well explicitely confirm the user exists here */
|
||||||
|
if(! getpwnam(ruser) ) {
|
||||||
|
- pamsshagentauth_verbose("getpwnam(%s) failed, bailing out", ruser);
|
||||||
|
+ verbose("getpwnam(%s) failed, bailing out", ruser);
|
||||||
|
goto cleanexit;
|
||||||
|
}
|
||||||
|
if( ! getpwnam(user) ) {
|
||||||
|
- pamsshagentauth_verbose("getpwnam(%s) failed, bailing out", user);
|
||||||
|
+ verbose("getpwnam(%s) failed, bailing out", user);
|
||||||
|
goto cleanexit;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -177,8 +177,8 @@ pam_sm_authenticate(pam_handle_t * pamh,
|
||||||
|
*/
|
||||||
|
parse_authorized_key_file(user, authorized_keys_file_input);
|
||||||
|
} else {
|
||||||
|
- pamsshagentauth_verbose("Using default file=/etc/security/authorized_keys");
|
||||||
|
- authorized_keys_file = pamsshagentauth_xstrdup("/etc/security/authorized_keys");
|
||||||
|
+ verbose("Using default file=/etc/security/authorized_keys");
|
||||||
|
+ authorized_keys_file = xstrdup("/etc/security/authorized_keys");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -187,19 +187,19 @@ pam_sm_authenticate(pam_handle_t * pamh,
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(user && strlen(ruser) > 0) {
|
||||||
|
- pamsshagentauth_verbose("Attempting authentication: `%s' as `%s' using %s", ruser, user, authorized_keys_file);
|
||||||
|
+ verbose("Attempting authentication: `%s' as `%s' using %s", ruser, user, authorized_keys_file);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* this pw_uid is used to validate the SSH_AUTH_SOCK, and so must be the uid of the ruser invoking the program, not the target-user
|
||||||
|
*/
|
||||||
|
if(pamsshagentauth_find_authorized_keys(user, ruser, servicename)) { /* getpwnam(ruser)->pw_uid)) { */
|
||||||
|
- pamsshagentauth_logit("Authenticated: `%s' as `%s' using %s", ruser, user, authorized_keys_file);
|
||||||
|
+ logit("Authenticated: `%s' as `%s' using %s", ruser, user, authorized_keys_file);
|
||||||
|
retval = PAM_SUCCESS;
|
||||||
|
} else {
|
||||||
|
- pamsshagentauth_logit("Failed Authentication: `%s' as `%s' using %s", ruser, user, authorized_keys_file);
|
||||||
|
+ logit("Failed Authentication: `%s' as `%s' using %s", ruser, user, authorized_keys_file);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
- pamsshagentauth_logit("No %s specified, cannot continue with this form of authentication", (user) ? "ruser" : "user" );
|
||||||
|
+ logit("No %s specified, cannot continue with this form of authentication", (user) ? "ruser" : "user" );
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanexit:
|
||||||
|
diff -up openssh/pam_ssh_agent_auth-0.10.3/pam_user_authorized_keys.c.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/pam_user_authorized_keys.c
|
||||||
|
--- openssh/pam_ssh_agent_auth-0.10.3/pam_user_authorized_keys.c.psaa-compat 2016-11-13 04:24:32.000000000 +0100
|
||||||
|
+++ openssh/pam_ssh_agent_auth-0.10.3/pam_user_authorized_keys.c 2018-08-24 10:18:05.009393312 +0200
|
||||||
|
@@ -66,8 +66,8 @@
|
||||||
|
#include "xmalloc.h"
|
||||||
|
#include "match.h"
|
||||||
|
#include "log.h"
|
||||||
|
-#include "buffer.h"
|
||||||
|
-#include "key.h"
|
||||||
|
+#include "sshbuf.h"
|
||||||
|
+#include "sshkey.h"
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
|
#include "xmalloc.h"
|
||||||
|
@@ -77,7 +77,6 @@
|
||||||
|
#include "pathnames.h"
|
||||||
|
#include "secure_filename.h"
|
||||||
|
|
||||||
|
-#include "identity.h"
|
||||||
|
#include "pam_user_key_allowed2.h"
|
||||||
|
|
||||||
|
extern char *authorized_keys_file;
|
||||||
|
@@ -117,12 +116,12 @@ parse_authorized_key_file(const char *us
|
||||||
|
} else {
|
||||||
|
slash_ptr = strchr(auth_keys_file_buf, '/');
|
||||||
|
if(!slash_ptr)
|
||||||
|
- pamsshagentauth_fatal
|
||||||
|
+ fatal
|
||||||
|
("cannot expand tilde in path without a `/'");
|
||||||
|
|
||||||
|
owner_uname_len = slash_ptr - auth_keys_file_buf - 1;
|
||||||
|
if(owner_uname_len > (sizeof(owner_uname) - 1))
|
||||||
|
- pamsshagentauth_fatal("Username too long");
|
||||||
|
+ fatal("Username too long");
|
||||||
|
|
||||||
|
strncat(owner_uname, auth_keys_file_buf + 1, owner_uname_len);
|
||||||
|
if(!authorized_keys_file_allowed_owner_uid)
|
||||||
|
@@ -130,11 +129,11 @@ parse_authorized_key_file(const char *us
|
||||||
|
getpwnam(owner_uname)->pw_uid;
|
||||||
|
}
|
||||||
|
authorized_keys_file =
|
||||||
|
- pamsshagentauth_tilde_expand_filename(auth_keys_file_buf,
|
||||||
|
+ tilde_expand_filename(auth_keys_file_buf,
|
||||||
|
authorized_keys_file_allowed_owner_uid);
|
||||||
|
strncpy(auth_keys_file_buf, authorized_keys_file,
|
||||||
|
sizeof(auth_keys_file_buf) - 1);
|
||||||
|
- pamsshagentauth_xfree(authorized_keys_file) /* when we
|
||||||
|
+ free(authorized_keys_file) /* when we
|
||||||
|
percent_expand
|
||||||
|
later, we'd step
|
||||||
|
on this, so free
|
||||||
|
@@ -150,13 +149,13 @@ parse_authorized_key_file(const char *us
|
||||||
|
strncat(hostname, fqdn, strcspn(fqdn, "."));
|
||||||
|
#endif
|
||||||
|
authorized_keys_file =
|
||||||
|
- pamsshagentauth_percent_expand(auth_keys_file_buf, "h",
|
||||||
|
+ percent_expand(auth_keys_file_buf, "h",
|
||||||
|
getpwnam(user)->pw_dir, "H", hostname,
|
||||||
|
"f", fqdn, "u", user, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
-pam_user_key_allowed(const char *ruser, Key * key)
|
||||||
|
+pam_user_key_allowed(const char *ruser, struct sshkey * key)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
pamsshagentauth_user_key_allowed2(getpwuid(authorized_keys_file_allowed_owner_uid),
|
||||||
|
diff -up openssh/pam_ssh_agent_auth-0.10.3/pam_user_authorized_keys.h.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/pam_user_authorized_keys.h
|
||||||
|
--- openssh/pam_ssh_agent_auth-0.10.3/pam_user_authorized_keys.h.psaa-compat 2016-11-13 04:24:32.000000000 +0100
|
||||||
|
+++ openssh/pam_ssh_agent_auth-0.10.3/pam_user_authorized_keys.h 2018-08-24 10:18:05.010393320 +0200
|
||||||
|
@@ -32,7 +32,7 @@
|
||||||
|
#define _PAM_USER_KEY_ALLOWED_H
|
||||||
|
|
||||||
|
#include "identity.h"
|
||||||
|
-int pam_user_key_allowed(const char *, Key *);
|
||||||
|
+int pam_user_key_allowed(const char *, struct sshkey *);
|
||||||
|
void parse_authorized_key_file(const char *, const char *);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
diff -up openssh/pam_ssh_agent_auth-0.10.3/pam_user_key_allowed2.c.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/pam_user_key_allowed2.c
|
||||||
|
--- openssh/pam_ssh_agent_auth-0.10.3/pam_user_key_allowed2.c.psaa-compat 2016-11-13 04:24:32.000000000 +0100
|
||||||
|
+++ openssh/pam_ssh_agent_auth-0.10.3/pam_user_key_allowed2.c 2018-08-24 10:18:05.010393320 +0200
|
||||||
|
@@ -45,44 +45,46 @@
|
||||||
|
#include "xmalloc.h"
|
||||||
|
#include "ssh.h"
|
||||||
|
#include "ssh2.h"
|
||||||
|
-#include "buffer.h"
|
||||||
|
+#include "sshbuf.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "compat.h"
|
||||||
|
-#include "key.h"
|
||||||
|
+#include "digest.h"
|
||||||
|
+#include "sshkey.h"
|
||||||
|
#include "pathnames.h"
|
||||||
|
#include "misc.h"
|
||||||
|
#include "secure_filename.h"
|
||||||
|
#include "uidswap.h"
|
||||||
|
-
|
||||||
|
-#include "identity.h"
|
||||||
|
+#include <unistd.h>
|
||||||
|
|
||||||
|
/* return 1 if user allows given key */
|
||||||
|
/* Modified slightly from original found in auth2-pubkey.c */
|
||||||
|
static int
|
||||||
|
-pamsshagentauth_check_authkeys_file(FILE * f, char *file, Key * key)
|
||||||
|
+pamsshagentauth_check_authkeys_file(FILE * f, char *file, struct sshkey * key)
|
||||||
|
{
|
||||||
|
- char line[SSH_MAX_PUBKEY_BYTES];
|
||||||
|
+ char *line = NULL;
|
||||||
|
int found_key = 0;
|
||||||
|
u_long linenum = 0;
|
||||||
|
- Key *found;
|
||||||
|
+ struct sshkey *found;
|
||||||
|
char *fp;
|
||||||
|
+ size_t linesize = 0;
|
||||||
|
|
||||||
|
found_key = 0;
|
||||||
|
- found = pamsshagentauth_key_new(key->type);
|
||||||
|
+ found = sshkey_new(key->type);
|
||||||
|
|
||||||
|
- while(read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
|
||||||
|
+ while ((getline(&line, &linesize, f)) != -1) {
|
||||||
|
char *cp = NULL; /* *key_options = NULL; */
|
||||||
|
|
||||||
|
+ linenum++;
|
||||||
|
/* Skip leading whitespace, empty and comment lines. */
|
||||||
|
for(cp = line; *cp == ' ' || *cp == '\t'; cp++);
|
||||||
|
if(!*cp || *cp == '\n' || *cp == '#')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
- if(pamsshagentauth_key_read(found, &cp) != 1) {
|
||||||
|
+ if (sshkey_read(found, &cp) != 0) {
|
||||||
|
/* no key? check if there are options for this key */
|
||||||
|
int quoted = 0;
|
||||||
|
|
||||||
|
- pamsshagentauth_verbose("user_key_allowed: check options: '%s'", cp);
|
||||||
|
+ verbose("user_key_allowed: check options: '%s'", cp);
|
||||||
|
/* key_options = cp; */
|
||||||
|
for(; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
|
||||||
|
if(*cp == '\\' && cp[1] == '"')
|
||||||
|
@@ -92,26 +94,27 @@ pamsshagentauth_check_authkeys_file(FILE
|
||||||
|
}
|
||||||
|
/* Skip remaining whitespace. */
|
||||||
|
for(; *cp == ' ' || *cp == '\t'; cp++);
|
||||||
|
- if(pamsshagentauth_key_read(found, &cp) != 1) {
|
||||||
|
- pamsshagentauth_verbose("user_key_allowed: advance: '%s'", cp);
|
||||||
|
+ if(sshkey_read(found, &cp) != 0) {
|
||||||
|
+ verbose("user_key_allowed: advance: '%s'", cp);
|
||||||
|
/* still no key? advance to next line */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- if(pamsshagentauth_key_equal(found, key)) {
|
||||||
|
+ if(sshkey_equal(found, key)) {
|
||||||
|
found_key = 1;
|
||||||
|
- pamsshagentauth_logit("matching key found: file/command %s, line %lu", file,
|
||||||
|
+ logit("matching key found: file/command %s, line %lu", file,
|
||||||
|
linenum);
|
||||||
|
- fp = pamsshagentauth_key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
|
||||||
|
- pamsshagentauth_logit("Found matching %s key: %s",
|
||||||
|
- pamsshagentauth_key_type(found), fp);
|
||||||
|
- pamsshagentauth_xfree(fp);
|
||||||
|
+ fp = sshkey_fingerprint(found, SSH_DIGEST_SHA256, SSH_FP_BASE64);
|
||||||
|
+ logit("Found matching %s key: %s",
|
||||||
|
+ sshkey_type(found), fp);
|
||||||
|
+ free(fp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- pamsshagentauth_key_free(found);
|
||||||
|
+ free(line);
|
||||||
|
+ sshkey_free(found);
|
||||||
|
if(!found_key)
|
||||||
|
- pamsshagentauth_verbose("key not found");
|
||||||
|
+ verbose("key not found");
|
||||||
|
return found_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -120,19 +123,19 @@ pamsshagentauth_check_authkeys_file(FILE
|
||||||
|
* returns 1 if the key is allowed or 0 otherwise.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
-pamsshagentauth_user_key_allowed2(struct passwd *pw, Key * key, char *file)
|
||||||
|
+pamsshagentauth_user_key_allowed2(struct passwd *pw, struct sshkey * key, char *file)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
int found_key = 0;
|
||||||
|
struct stat st;
|
||||||
|
- char buf[SSH_MAX_PUBKEY_BYTES];
|
||||||
|
+ char buf[256];
|
||||||
|
|
||||||
|
/* Temporarily use the user's uid. */
|
||||||
|
- pamsshagentauth_verbose("trying public key file %s", file);
|
||||||
|
+ verbose("trying public key file %s", file);
|
||||||
|
|
||||||
|
/* Fail not so quietly if file does not exist */
|
||||||
|
if(stat(file, &st) < 0) {
|
||||||
|
- pamsshagentauth_verbose("File not found: %s", file);
|
||||||
|
+ verbose("File not found: %s", file);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -144,7 +147,7 @@ pamsshagentauth_user_key_allowed2(struct
|
||||||
|
|
||||||
|
if(pamsshagentauth_secure_filename(f, file, pw, buf, sizeof(buf)) != 0) {
|
||||||
|
fclose(f);
|
||||||
|
- pamsshagentauth_logit("Authentication refused: %s", buf);
|
||||||
|
+ logit("Authentication refused: %s", buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -160,7 +163,7 @@ pamsshagentauth_user_key_allowed2(struct
|
||||||
|
int
|
||||||
|
pamsshagentauth_user_key_command_allowed2(char *authorized_keys_command,
|
||||||
|
char *authorized_keys_command_user,
|
||||||
|
- struct passwd *user_pw, Key * key)
|
||||||
|
+ struct passwd *user_pw, struct sshkey * key)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
int ok, found_key = 0;
|
||||||
|
@@ -187,44 +190,44 @@ pamsshagentauth_user_key_command_allowed
|
||||||
|
else {
|
||||||
|
pw = getpwnam(authorized_keys_command_user);
|
||||||
|
if(pw == NULL) {
|
||||||
|
- pamsshagentauth_logerror("authorized_keys_command_user \"%s\" not found: %s",
|
||||||
|
+ error("authorized_keys_command_user \"%s\" not found: %s",
|
||||||
|
authorized_keys_command_user, strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- pamsshagentauth_temporarily_use_uid(pw);
|
||||||
|
+ temporarily_use_uid(pw);
|
||||||
|
|
||||||
|
if(stat(authorized_keys_command, &st) < 0) {
|
||||||
|
- pamsshagentauth_logerror
|
||||||
|
+ error
|
||||||
|
("Could not stat AuthorizedKeysCommand \"%s\": %s",
|
||||||
|
authorized_keys_command, strerror(errno));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if(pamsshagentauth_auth_secure_path
|
||||||
|
(authorized_keys_command, &st, NULL, 0, errmsg, sizeof(errmsg)) != 0) {
|
||||||
|
- pamsshagentauth_logerror("Unsafe AuthorizedKeysCommand: %s", errmsg);
|
||||||
|
+ error("Unsafe AuthorizedKeysCommand: %s", errmsg);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* open the pipe and read the keys */
|
||||||
|
if(pipe(p) != 0) {
|
||||||
|
- pamsshagentauth_logerror("%s: pipe: %s", __func__, strerror(errno));
|
||||||
|
+ error("%s: pipe: %s", __func__, strerror(errno));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
- pamsshagentauth_debug("Running AuthorizedKeysCommand: \"%s\" as \"%s\" with argument: \"%s\"",
|
||||||
|
+ debug("Running AuthorizedKeysCommand: \"%s\" as \"%s\" with argument: \"%s\"",
|
||||||
|
authorized_keys_command, pw->pw_name, username);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't want to call this in the child, where it can fatal() and
|
||||||
|
* run cleanup_exit() code.
|
||||||
|
*/
|
||||||
|
- pamsshagentauth_restore_uid();
|
||||||
|
+ restore_uid();
|
||||||
|
|
||||||
|
switch ((pid = fork())) {
|
||||||
|
case -1: /* error */
|
||||||
|
- pamsshagentauth_logerror("%s: fork: %s", __func__, strerror(errno));
|
||||||
|
+ error("%s: fork: %s", __func__, strerror(errno));
|
||||||
|
close(p[0]);
|
||||||
|
close(p[1]);
|
||||||
|
return 0;
|
||||||
|
@@ -234,13 +237,13 @@ pamsshagentauth_user_key_command_allowed
|
||||||
|
|
||||||
|
/* do this before the setresuid so thta they can be logged */
|
||||||
|
if((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
|
||||||
|
- pamsshagentauth_logerror("%s: open %s: %s", __func__, _PATH_DEVNULL,
|
||||||
|
+ error("%s: open %s: %s", __func__, _PATH_DEVNULL,
|
||||||
|
strerror(errno));
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
if(dup2(devnull, STDIN_FILENO) == -1 || dup2(p[1], STDOUT_FILENO) == -1
|
||||||
|
|| dup2(devnull, STDERR_FILENO) == -1) {
|
||||||
|
- pamsshagentauth_logerror("%s: dup2: %s", __func__, strerror(errno));
|
||||||
|
+ error("%s: dup2: %s", __func__, strerror(errno));
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
#if defined(HAVE_SETRESGID) && !defined(BROKEN_SETRESGID)
|
||||||
|
@@ -248,7 +251,7 @@ pamsshagentauth_user_key_command_allowed
|
||||||
|
#else
|
||||||
|
if (setgid(pw->pw_gid) != 0 || setegid(pw->pw_gid) != 0) {
|
||||||
|
#endif
|
||||||
|
- pamsshagentauth_logerror("setresgid %u: %s", (u_int) pw->pw_gid,
|
||||||
|
+ error("setresgid %u: %s", (u_int) pw->pw_gid,
|
||||||
|
strerror(errno));
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
@@ -258,7 +261,7 @@ pamsshagentauth_user_key_command_allowed
|
||||||
|
#else
|
||||||
|
if (setuid(pw->pw_uid) != 0 || seteuid(pw->pw_uid) != 0) {
|
||||||
|
#endif
|
||||||
|
- pamsshagentauth_logerror("setresuid %u: %s", (u_int) pw->pw_uid,
|
||||||
|
+ error("setresuid %u: %s", (u_int) pw->pw_uid,
|
||||||
|
strerror(errno));
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
@@ -270,18 +273,18 @@ pamsshagentauth_user_key_command_allowed
|
||||||
|
|
||||||
|
/* pretty sure this will barf because we are now suid, but since we
|
||||||
|
should't reach this anyway, I'll leave it here */
|
||||||
|
- pamsshagentauth_logerror("AuthorizedKeysCommand %s exec failed: %s",
|
||||||
|
+ error("AuthorizedKeysCommand %s exec failed: %s",
|
||||||
|
authorized_keys_command, strerror(errno));
|
||||||
|
_exit(127);
|
||||||
|
default: /* parent */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
- pamsshagentauth_temporarily_use_uid(pw);
|
||||||
|
+ temporarily_use_uid(pw);
|
||||||
|
|
||||||
|
close(p[1]);
|
||||||
|
if((f = fdopen(p[0], "r")) == NULL) {
|
||||||
|
- pamsshagentauth_logerror("%s: fdopen: %s", __func__, strerror(errno));
|
||||||
|
+ error("%s: fdopen: %s", __func__, strerror(errno));
|
||||||
|
close(p[0]);
|
||||||
|
/* Don't leave zombie child */
|
||||||
|
while(waitpid(pid, NULL, 0) == -1 && errno == EINTR);
|
||||||
|
@@ -292,22 +295,22 @@ pamsshagentauth_user_key_command_allowed
|
||||||
|
|
||||||
|
while(waitpid(pid, &status, 0) == -1) {
|
||||||
|
if(errno != EINTR) {
|
||||||
|
- pamsshagentauth_logerror("%s: waitpid: %s", __func__,
|
||||||
|
+ error("%s: waitpid: %s", __func__,
|
||||||
|
strerror(errno));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(WIFSIGNALED(status)) {
|
||||||
|
- pamsshagentauth_logerror("AuthorizedKeysCommand %s exited on signal %d",
|
||||||
|
+ error("AuthorizedKeysCommand %s exited on signal %d",
|
||||||
|
authorized_keys_command, WTERMSIG(status));
|
||||||
|
goto out;
|
||||||
|
} else if(WEXITSTATUS(status) != 0) {
|
||||||
|
- pamsshagentauth_logerror("AuthorizedKeysCommand %s returned status %d",
|
||||||
|
+ error("AuthorizedKeysCommand %s returned status %d",
|
||||||
|
authorized_keys_command, WEXITSTATUS(status));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
found_key = ok;
|
||||||
|
out:
|
||||||
|
- pamsshagentauth_restore_uid();
|
||||||
|
+ restore_uid();
|
||||||
|
return found_key;
|
||||||
|
}
|
||||||
|
diff -up openssh/pam_ssh_agent_auth-0.10.3/pam_user_key_allowed2.h.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/pam_user_key_allowed2.h
|
||||||
|
--- openssh/pam_ssh_agent_auth-0.10.3/pam_user_key_allowed2.h.psaa-compat 2016-11-13 04:24:32.000000000 +0100
|
||||||
|
+++ openssh/pam_ssh_agent_auth-0.10.3/pam_user_key_allowed2.h 2018-08-24 10:18:05.010393320 +0200
|
||||||
|
@@ -32,7 +32,7 @@
|
||||||
|
#define _PAM_USER_KEY_ALLOWED_H
|
||||||
|
|
||||||
|
#include "identity.h"
|
||||||
|
-int pamsshagentauth_user_key_allowed2(struct passwd *, Key *, char *);
|
||||||
|
-int pamsshagentauth_user_key_command_allowed2(char *, char *, struct passwd *, Key *);
|
||||||
|
+int pamsshagentauth_user_key_allowed2(struct passwd *, struct sshkey *, char *);
|
||||||
|
+int pamsshagentauth_user_key_command_allowed2(char *, char *, struct passwd *, struct sshkey *);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
diff -up openssh/pam_ssh_agent_auth-0.10.3/secure_filename.c.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/secure_filename.c
|
||||||
|
--- openssh/pam_ssh_agent_auth-0.10.3/secure_filename.c.psaa-compat 2016-11-13 04:24:32.000000000 +0100
|
||||||
|
+++ openssh/pam_ssh_agent_auth-0.10.3/secure_filename.c 2018-08-24 10:18:05.010393320 +0200
|
||||||
|
@@ -53,8 +53,8 @@
|
||||||
|
#include "xmalloc.h"
|
||||||
|
#include "match.h"
|
||||||
|
#include "log.h"
|
||||||
|
-#include "buffer.h"
|
||||||
|
-#include "key.h"
|
||||||
|
+#include "sshbuf.h"
|
||||||
|
+#include "sshkey.h"
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
|
|
||||||
|
@@ -80,7 +80,7 @@ pamsshagentauth_auth_secure_path(const c
|
||||||
|
int comparehome = 0;
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
- pamsshagentauth_verbose("auth_secure_filename: checking for uid: %u", uid);
|
||||||
|
+ verbose("auth_secure_filename: checking for uid: %u", uid);
|
||||||
|
|
||||||
|
if (realpath(name, buf) == NULL) {
|
||||||
|
snprintf(err, errlen, "realpath %s failed: %s", name,
|
||||||
|
@@ -115,9 +115,9 @@ pamsshagentauth_auth_secure_path(const c
|
||||||
|
snprintf(err, errlen, "dirname() failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
- pamsshagentauth_strlcpy(buf, cp, sizeof(buf));
|
||||||
|
+ strlcpy(buf, cp, sizeof(buf));
|
||||||
|
|
||||||
|
- pamsshagentauth_verbose("secure_filename: checking '%s'", buf);
|
||||||
|
+ verbose("secure_filename: checking '%s'", buf);
|
||||||
|
if (stat(buf, &st) < 0 ||
|
||||||
|
(st.st_uid != 0 && st.st_uid != uid) ||
|
||||||
|
(st.st_mode & 022) != 0) {
|
||||||
|
@@ -128,7 +128,7 @@ pamsshagentauth_auth_secure_path(const c
|
||||||
|
|
||||||
|
/* If are passed the homedir then we can stop */
|
||||||
|
if (comparehome && strcmp(homedir, buf) == 0) {
|
||||||
|
- pamsshagentauth_verbose("secure_filename: terminating check at '%s'",
|
||||||
|
+ verbose("secure_filename: terminating check at '%s'",
|
||||||
|
buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
diff -up openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c
|
||||||
|
--- openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c.psaa-compat 2016-11-13 04:24:32.000000000 +0100
|
||||||
|
+++ openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c 2018-08-24 10:22:13.202657025 +0200
|
||||||
|
@@ -37,10 +37,11 @@
|
||||||
|
#include "xmalloc.h"
|
||||||
|
#include "ssh.h"
|
||||||
|
#include "ssh2.h"
|
||||||
|
-#include "buffer.h"
|
||||||
|
+#include "sshbuf.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "compat.h"
|
||||||
|
-#include "key.h"
|
||||||
|
+#include "sshkey.h"
|
||||||
|
+#include "ssherr.h"
|
||||||
|
#include "pathnames.h"
|
||||||
|
#include "misc.h"
|
||||||
|
#include "secure_filename.h"
|
||||||
|
@@ -48,54 +48,59 @@
|
||||||
|
#include "identity.h"
|
||||||
|
#include "pam_user_authorized_keys.h"
|
||||||
|
|
||||||
|
+#define SSH2_MSG_USERAUTH_TRUST_REQUEST 54
|
||||||
|
+
|
||||||
|
/* extern u_char *session_id2;
|
||||||
|
extern uint8_t session_id_len;
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
-userauth_pubkey_from_id(const char *ruser, Identity * id, Buffer * session_id2)
|
||||||
|
+userauth_pubkey_from_id(const char *ruser, Identity * id, struct sshbuf * session_id2)
|
||||||
|
{
|
||||||
|
- Buffer b = { 0 };
|
||||||
|
+ struct sshbuf *b = NULL;
|
||||||
|
char *pkalg = NULL;
|
||||||
|
u_char *pkblob = NULL, *sig = NULL;
|
||||||
|
- u_int blen = 0, slen = 0;
|
||||||
|
+ size_t blen = 0, slen = 0;
|
||||||
|
- int authenticated = 0;
|
||||||
|
+ int r, authenticated = 0;
|
||||||
|
|
||||||
|
- pkalg = (char *) key_ssh_name(id->key);
|
||||||
|
+ pkalg = (char *) sshkey_ssh_name(id->key);
|
||||||
|
|
||||||
|
/* first test if this key is even allowed */
|
||||||
|
if(! pam_user_key_allowed(ruser, id->key))
|
||||||
|
- goto user_auth_clean_exit;
|
||||||
|
+ goto user_auth_clean_exit_without_buffer;
|
||||||
|
|
||||||
|
- if(pamsshagentauth_key_to_blob(id->key, &pkblob, &blen) == 0)
|
||||||
|
- goto user_auth_clean_exit;
|
||||||
|
+ if(sshkey_to_blob(id->key, &pkblob, &blen) != 0)
|
||||||
|
+ goto user_auth_clean_exit_without_buffer;
|
||||||
|
|
||||||
|
/* construct packet to sign and test */
|
||||||
|
- pamsshagentauth_buffer_init(&b);
|
||||||
|
+ if ((b = sshbuf_new()) == NULL)
|
||||||
|
+ fatal("%s: sshbuf_new failed", __func__);
|
||||||
|
|
||||||
|
- pamsshagentauth_buffer_put_string(&b, session_id2->buf + session_id2->offset, session_id2->end - session_id2->offset);
|
||||||
|
- pamsshagentauth_buffer_put_char(&b, SSH2_MSG_USERAUTH_TRUST_REQUEST);
|
||||||
|
- pamsshagentauth_buffer_put_cstring(&b, ruser);
|
||||||
|
- pamsshagentauth_buffer_put_cstring(&b, "pam_ssh_agent_auth");
|
||||||
|
- pamsshagentauth_buffer_put_cstring(&b, "publickey");
|
||||||
|
- pamsshagentauth_buffer_put_char(&b, 1);
|
||||||
|
- pamsshagentauth_buffer_put_cstring(&b, pkalg);
|
||||||
|
- pamsshagentauth_buffer_put_string(&b, pkblob, blen);
|
||||||
|
+ if ((r = sshbuf_put_string(b, sshbuf_ptr(session_id2), sshbuf_len(session_id2))) != 0 ||
|
||||||
|
+ (r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_TRUST_REQUEST)) != 0 ||
|
||||||
|
+ (r = sshbuf_put_cstring(b, ruser)) != 0 ||
|
||||||
|
+ (r = sshbuf_put_cstring(b, "pam_ssh_agent_auth")) != 0 ||
|
||||||
|
+ (r = sshbuf_put_cstring(b, "publickey")) != 0 ||
|
||||||
|
+ (r = sshbuf_put_u8(b, 1)) != 0 ||
|
||||||
|
+ (r = sshbuf_put_cstring(b, pkalg)) != 0 ||
|
||||||
|
+ (r = sshbuf_put_string(b, pkblob, blen)) != 0)
|
||||||
|
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
|
||||||
|
- if(ssh_agent_sign(id->ac, id->key, &sig, &slen, pamsshagentauth_buffer_ptr(&b), pamsshagentauth_buffer_len(&b)) != 0)
|
||||||
|
+ if (ssh_agent_sign(id->ac, id->key, &sig, &slen, sshbuf_ptr(b), sshbuf_len(b)) != 0)
|
||||||
|
goto user_auth_clean_exit;
|
||||||
|
|
||||||
|
/* test for correct signature */
|
||||||
|
- if(pamsshagentauth_key_verify(id->key, sig, slen, pamsshagentauth_buffer_ptr(&b), pamsshagentauth_buffer_len(&b)) == 1)
|
||||||
|
+ if (sshkey_verify(id->key, sig, slen, sshbuf_ptr(b), sshbuf_len(b), NULL, 0) == 0)
|
||||||
|
authenticated = 1;
|
||||||
|
|
||||||
|
user_auth_clean_exit:
|
||||||
|
/* if(&b != NULL) */
|
||||||
|
- pamsshagentauth_buffer_free(&b);
|
||||||
|
+ sshbuf_free(b);
|
||||||
|
+ user_auth_clean_exit_without_buffer:
|
||||||
|
if(sig != NULL)
|
||||||
|
- pamsshagentauth_xfree(sig);
|
||||||
|
+ free(sig);
|
||||||
|
if(pkblob != NULL)
|
||||||
|
- pamsshagentauth_xfree(pkblob);
|
||||||
|
+ free(pkblob);
|
||||||
|
CRYPTO_cleanup_all_ex_data();
|
||||||
|
return authenticated;
|
||||||
|
}
|
||||||
|
diff -up openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.h.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.h
|
||||||
|
--- openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.h.psaa-compat 2016-11-13 04:24:32.000000000 +0100
|
||||||
|
+++ openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.h 2018-08-24 10:18:05.010393320 +0200
|
||||||
|
@@ -31,7 +31,7 @@
|
||||||
|
#ifndef _USERAUTH_PUBKEY_FROM_ID_H
|
||||||
|
#define _USERAUTH_PUBKEY_FROM_ID_H
|
||||||
|
|
||||||
|
-#include <identity.h>
|
||||||
|
-int userauth_pubkey_from_id(const char *, Identity *, Buffer *);
|
||||||
|
+#include "identity.h"
|
||||||
|
+int userauth_pubkey_from_id(const char *, Identity *, struct sshbuf *);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
diff -up openssh/pam_ssh_agent_auth-0.10.3/uuencode.c.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/uuencode.c
|
||||||
|
--- openssh/pam_ssh_agent_auth-0.10.3/uuencode.c.psaa-compat 2016-11-13 04:24:32.000000000 +0100
|
||||||
|
+++ openssh/pam_ssh_agent_auth-0.10.3/uuencode.c 2018-08-24 10:18:05.010393320 +0200
|
||||||
|
@@ -56,7 +56,7 @@ pamsshagentauth_uudecode(const char *src
|
||||||
|
/* and remove trailing whitespace because __b64_pton needs this */
|
||||||
|
*p = '\0';
|
||||||
|
len = pamsshagentauth___b64_pton(encoded, target, targsize);
|
||||||
|
- pamsshagentauth_xfree(encoded);
|
||||||
|
+ xfree(encoded);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -70,7 +70,7 @@ pamsshagentauth_dump_base64(FILE *fp, co
|
||||||
|
fprintf(fp, "dump_base64: len > 65536\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
- buf = pamsshagentauth_xmalloc(2*len);
|
||||||
|
+ buf = malloc(2*len);
|
||||||
|
n = pamsshagentauth_uuencode(data, len, buf, 2*len);
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
fprintf(fp, "%c", buf[i]);
|
||||||
|
@@ -79,5 +79,5 @@ pamsshagentauth_dump_base64(FILE *fp, co
|
||||||
|
}
|
||||||
|
if (i % 70 != 69)
|
||||||
|
fprintf(fp, "\n");
|
||||||
|
- pamsshagentauth_xfree(buf);
|
||||||
|
+ free(buf);
|
||||||
|
}
|
20
SOURCES/pam_ssh_agent_auth-0.10.2-dereference.patch
Normal file
20
SOURCES/pam_ssh_agent_auth-0.10.2-dereference.patch
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
diff --git a/pam_ssh_agent_auth-0.10.2/pam_user_authorized_keys.c b/pam_ssh_agent_auth-0.10.2/pam_user_authorized_keys.c
|
||||||
|
--- a/pam_ssh_agent_auth-0.10.2/pam_user_authorized_keys.c
|
||||||
|
+++ b/pam_ssh_agent_auth-0.10.2/pam_user_authorized_keys.c
|
||||||
|
@@ -158,11 +158,12 @@ parse_authorized_key_file(const char *user,
|
||||||
|
int
|
||||||
|
pam_user_key_allowed(const char *ruser, struct sshkey * key)
|
||||||
|
{
|
||||||
|
+ struct passwd *pw;
|
||||||
|
return
|
||||||
|
- pamsshagentauth_user_key_allowed2(getpwuid(authorized_keys_file_allowed_owner_uid),
|
||||||
|
- key, authorized_keys_file)
|
||||||
|
- || pamsshagentauth_user_key_allowed2(getpwuid(0), key,
|
||||||
|
- authorized_keys_file)
|
||||||
|
+ ( (pw = getpwuid(authorized_keys_file_allowed_owner_uid)) &&
|
||||||
|
+ pamsshagentauth_user_key_allowed2(pw, key, authorized_keys_file))
|
||||||
|
+ || ((pw = getpwuid(0)) &&
|
||||||
|
+ pamsshagentauth_user_key_allowed2(pw, key, authorized_keys_file))
|
||||||
|
|| pamsshagentauth_user_key_command_allowed2(authorized_keys_command,
|
||||||
|
authorized_keys_command_user,
|
||||||
|
getpwnam(ruser), key);
|
37
SOURCES/pam_ssh_agent_auth-0.10.3-seteuid.patch
Normal file
37
SOURCES/pam_ssh_agent_auth-0.10.3-seteuid.patch
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
diff -up openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-seteuid openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c
|
||||||
|
--- openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-seteuid 2017-02-07 15:41:53.172334151 +0100
|
||||||
|
+++ openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c 2017-02-07 15:41:53.174334149 +0100
|
||||||
|
@@ -238,17 +238,26 @@ ssh_get_authentication_socket_for_uid(ui
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
- seteuid(uid); /* To ensure a race condition is not used to circumvent the stat
|
||||||
|
- above, we will temporarily drop UID to the caller */
|
||||||
|
- if (connect(sock, (struct sockaddr *)&sunaddr, sizeof sunaddr) < 0) {
|
||||||
|
+ /* To ensure a race condition is not used to circumvent the stat
|
||||||
|
+ above, we will temporarily drop UID to the caller */
|
||||||
|
+ if (seteuid(uid) == -1) {
|
||||||
|
close(sock);
|
||||||
|
- if(errno == EACCES)
|
||||||
|
- fatal("MAJOR SECURITY WARNING: uid %lu made a deliberate and malicious attempt to open an agent socket owned by another user", (unsigned long) uid);
|
||||||
|
+ error("seteuid(%lu) failed with error: %s",
|
||||||
|
+ (unsigned long) uid, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
+ if (connect(sock, (struct sockaddr *)&sunaddr, sizeof sunaddr) < 0) {
|
||||||
|
+ close(sock);
|
||||||
|
+ sock = -1;
|
||||||
|
+ if(errno == EACCES)
|
||||||
|
+ fatal("MAJOR SECURITY WARNING: uid %lu made a deliberate and malicious attempt to open an agent socket owned by another user", (unsigned long) uid);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- seteuid(0); /* we now continue the regularly scheduled programming */
|
||||||
|
-
|
||||||
|
+ /* we now continue the regularly scheduled programming */
|
||||||
|
+ if (0 != seteuid(0)) {
|
||||||
|
+ fatal("setuid(0) failed with error: %s", strerror(errno));
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
return sock;
|
||||||
|
}
|
||||||
|
|
21
SOURCES/pam_ssh_agent_auth-0.9.2-visibility.patch
Normal file
21
SOURCES/pam_ssh_agent_auth-0.9.2-visibility.patch
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
diff -up openssh-7.1p2/pam_ssh_agent_auth-0.10.2/pam_ssh_agent_auth.c.psaa-visibility openssh-7.1p2/pam_ssh_agent_auth-0.10.2/pam_ssh_agent_auth.c
|
||||||
|
--- openssh-7.1p2/pam_ssh_agent_auth-0.10.2/pam_ssh_agent_auth.c.psaa-visibility 2014-03-31 19:35:17.000000000 +0200
|
||||||
|
+++ openssh-7.1p2/pam_ssh_agent_auth-0.10.2/pam_ssh_agent_auth.c 2016-01-22 15:22:40.984469774 +0100
|
||||||
|
@@ -72,7 +72,7 @@ char *__progname;
|
||||||
|
extern char *__progname;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
-PAM_EXTERN int
|
||||||
|
+PAM_EXTERN int __attribute__ ((visibility ("default")))
|
||||||
|
pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char **argv)
|
||||||
|
{
|
||||||
|
char **argv_ptr;
|
||||||
|
@@ -214,7 +214,7 @@ cleanexit:
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-PAM_EXTERN int
|
||||||
|
+PAM_EXTERN int __attribute__ ((visibility ("default")))
|
||||||
|
pam_sm_setcred(pam_handle_t * pamh, int flags, int argc, const char **argv)
|
||||||
|
{
|
||||||
|
UNUSED(pamh);
|
96
SOURCES/pam_ssh_agent_auth-0.9.3-agent_structure.patch
Normal file
96
SOURCES/pam_ssh_agent_auth-0.9.3-agent_structure.patch
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
diff -up openssh/pam_ssh_agent_auth-0.10.3/identity.h.psaa-agent openssh/pam_ssh_agent_auth-0.10.3/identity.h
|
||||||
|
--- openssh/pam_ssh_agent_auth-0.10.3/identity.h.psaa-agent 2016-11-13 04:24:32.000000000 +0100
|
||||||
|
+++ openssh/pam_ssh_agent_auth-0.10.3/identity.h 2017-09-27 14:25:49.421739027 +0200
|
||||||
|
@@ -38,6 +38,12 @@
|
||||||
|
typedef struct identity Identity;
|
||||||
|
typedef struct idlist Idlist;
|
||||||
|
|
||||||
|
+typedef struct {
|
||||||
|
+ int fd;
|
||||||
|
+ struct sshbuf *identities;
|
||||||
|
+ int howmany;
|
||||||
|
+} AuthenticationConnection;
|
||||||
|
+
|
||||||
|
struct identity {
|
||||||
|
TAILQ_ENTRY(identity) next;
|
||||||
|
AuthenticationConnection *ac; /* set if agent supports key */
|
||||||
|
diff -up openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-agent openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c
|
||||||
|
--- openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-agent 2017-09-27 14:25:49.420739021 +0200
|
||||||
|
+++ openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c 2017-09-27 14:25:49.421739027 +0200
|
||||||
|
@@ -39,6 +39,7 @@
|
||||||
|
#include "sshbuf.h"
|
||||||
|
#include "sshkey.h"
|
||||||
|
#include "authfd.h"
|
||||||
|
+#include "ssherr.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include "ssh2.h"
|
||||||
|
@@ -291,36 +292,43 @@ pamsshagentauth_find_authorized_keys(con
|
||||||
|
{
|
||||||
|
struct sshbuf *session_id2 = NULL;
|
||||||
|
Identity *id;
|
||||||
|
- struct sshkey *key;
|
||||||
|
AuthenticationConnection *ac;
|
||||||
|
- char *comment;
|
||||||
|
uint8_t retval = 0;
|
||||||
|
uid_t uid = getpwnam(ruser)->pw_uid;
|
||||||
|
+ struct ssh_identitylist *idlist;
|
||||||
|
+ int r;
|
||||||
|
+ unsigned int i;
|
||||||
|
|
||||||
|
OpenSSL_add_all_digests();
|
||||||
|
pamsshagentauth_session_id2_gen(&session_id2, user, ruser, servicename);
|
||||||
|
|
||||||
|
if ((ac = ssh_get_authentication_connection_for_uid(uid))) {
|
||||||
|
verbose("Contacted ssh-agent of user %s (%u)", ruser, uid);
|
||||||
|
- for (key = ssh_get_first_identity(ac, &comment, 2); key != NULL; key = ssh_get_next_identity(ac, &comment, 2))
|
||||||
|
- {
|
||||||
|
- if(key != NULL) {
|
||||||
|
+ if ((r = ssh_fetch_identitylist(ac->fd, &idlist)) != 0) {
|
||||||
|
+ if (r != SSH_ERR_AGENT_NO_IDENTITIES)
|
||||||
|
+ fprintf(stderr, "error fetching identities for "
|
||||||
|
+ "protocol %d: %s\n", 2, ssh_err(r));
|
||||||
|
+ } else {
|
||||||
|
+ for (i = 0; i < idlist->nkeys; i++)
|
||||||
|
+ {
|
||||||
|
+ if (idlist->keys[i] != NULL) {
|
||||||
|
id = xcalloc(1, sizeof(*id));
|
||||||
|
- id->key = key;
|
||||||
|
- id->filename = comment;
|
||||||
|
+ id->key = idlist->keys[i];
|
||||||
|
+ id->filename = idlist->comments[i];
|
||||||
|
id->ac = ac;
|
||||||
|
if(userauth_pubkey_from_id(ruser, id, session_id2)) {
|
||||||
|
retval = 1;
|
||||||
|
}
|
||||||
|
- free(id->filename);
|
||||||
|
- key_free(id->key);
|
||||||
|
free(id);
|
||||||
|
if(retval == 1)
|
||||||
|
break;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
- sshbuf_free(session_id2);
|
||||||
|
- ssh_close_authentication_connection(ac);
|
||||||
|
+ sshbuf_free(session_id2);
|
||||||
|
+ ssh_free_identitylist(idlist);
|
||||||
|
+ }
|
||||||
|
+ ssh_close_authentication_socket(ac->fd);
|
||||||
|
+ free(ac);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
verbose("No ssh-agent could be contacted");
|
||||||
|
diff -up openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c.psaa-agent openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c
|
||||||
|
--- openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c.psaa-agent 2017-09-27 14:25:49.420739021 +0200
|
||||||
|
+++ openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c 2017-09-27 14:25:49.422739032 +0200
|
||||||
|
@@ -84,7 +85,7 @@ userauth_pubkey_from_id(const char *ruse
|
||||||
|
(r = sshbuf_put_string(b, pkblob, blen)) != 0)
|
||||||
|
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
|
||||||
|
- if (ssh_agent_sign(id->ac, id->key, &sig, &slen, sshbuf_ptr(b), sshbuf_len(b)) != 0)
|
||||||
|
+ if (ssh_agent_sign(id->ac->fd, id->key, &sig, &slen, sshbuf_ptr(b), sshbuf_len(b), NULL, 0) != 0)
|
||||||
|
goto user_auth_clean_exit;
|
||||||
|
|
||||||
|
/* test for correct signature */
|
196
SOURCES/pam_ssh_agent_auth-0.9.3-build.patch
Normal file
196
SOURCES/pam_ssh_agent_auth-0.9.3-build.patch
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
diff -up openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-build openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c
|
||||||
|
--- openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-build 2016-11-13 04:24:32.000000000 +0100
|
||||||
|
+++ openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c 2017-02-07 14:29:41.626116675 +0100
|
||||||
|
@@ -43,12 +43,31 @@
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include "ssh2.h"
|
||||||
|
#include "misc.h"
|
||||||
|
+#include "ssh.h"
|
||||||
|
+#include <sys/types.h>
|
||||||
|
+#include <sys/stat.h>
|
||||||
|
+#include <sys/socket.h>
|
||||||
|
+#include <sys/un.h>
|
||||||
|
+#include <unistd.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <errno.h>
|
||||||
|
+#include <fcntl.h>
|
||||||
|
|
||||||
|
#include "userauth_pubkey_from_id.h"
|
||||||
|
#include "identity.h"
|
||||||
|
#include "get_command_line.h"
|
||||||
|
extern char **environ;
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * Added by Jamie Beverly, ensure socket fd points to a socket owned by the user
|
||||||
|
+ * A cursory check is done, but to avoid race conditions, it is necessary
|
||||||
|
+ * to drop effective UID when connecting to the socket.
|
||||||
|
+ *
|
||||||
|
+ * If the cause of error is EACCES, because we verified we would not have that
|
||||||
|
+ * problem initially, we can safely assume that somebody is attempting to find a
|
||||||
|
+ * race condition; so a more "direct" log message is generated.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
static char *
|
||||||
|
log_action(char ** action, size_t count)
|
||||||
|
{
|
||||||
|
@@ -85,7 +104,7 @@ void
|
||||||
|
pamsshagentauth_session_id2_gen(Buffer * session_id2, const char * user,
|
||||||
|
const char * ruser, const char * servicename)
|
||||||
|
{
|
||||||
|
- char *cookie = NULL;
|
||||||
|
+ u_char *cookie = NULL;
|
||||||
|
uint8_t i = 0;
|
||||||
|
uint32_t rnd = 0;
|
||||||
|
uint8_t cookie_len;
|
||||||
|
@@ -112,7 +131,7 @@ pamsshagentauth_session_id2_gen(Buffer *
|
||||||
|
if (i % 4 == 0) {
|
||||||
|
rnd = pamsshagentauth_arc4random();
|
||||||
|
}
|
||||||
|
- cookie[i] = (char) rnd;
|
||||||
|
+ cookie[i] = (u_char) rnd;
|
||||||
|
rnd >>= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -177,6 +196,86 @@ pamsshagentauth_session_id2_gen(Buffer *
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
+ssh_get_authentication_socket_for_uid(uid_t uid)
|
||||||
|
+{
|
||||||
|
+ const char *authsocket;
|
||||||
|
+ int sock;
|
||||||
|
+ struct sockaddr_un sunaddr;
|
||||||
|
+ struct stat sock_st;
|
||||||
|
+
|
||||||
|
+ authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
|
||||||
|
+ if (!authsocket)
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ /* Advisory only; seteuid ensures no race condition; but will only log if we see EACCES */
|
||||||
|
+ if( stat(authsocket,&sock_st) == 0) {
|
||||||
|
+ if(uid != 0 && sock_st.st_uid != uid) {
|
||||||
|
+ fatal("uid %lu attempted to open an agent socket owned by uid %lu", (unsigned long) uid, (unsigned long) sock_st.st_uid);
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Ensures that the EACCES tested for below can _only_ happen if somebody
|
||||||
|
+ * is attempting to race the stat above to bypass authentication.
|
||||||
|
+ */
|
||||||
|
+ if( (sock_st.st_mode & S_IWUSR) != S_IWUSR || (sock_st.st_mode & S_IRUSR) != S_IRUSR) {
|
||||||
|
+ error("ssh-agent socket has incorrect permissions for owner");
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ sunaddr.sun_family = AF_UNIX;
|
||||||
|
+ strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));
|
||||||
|
+
|
||||||
|
+ sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
+ if (sock < 0)
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ /* close on exec */
|
||||||
|
+ if (fcntl(sock, F_SETFD, 1) == -1) {
|
||||||
|
+ close(sock);
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ errno = 0;
|
||||||
|
+ seteuid(uid); /* To ensure a race condition is not used to circumvent the stat
|
||||||
|
+ above, we will temporarily drop UID to the caller */
|
||||||
|
+ if (connect(sock, (struct sockaddr *)&sunaddr, sizeof sunaddr) < 0) {
|
||||||
|
+ close(sock);
|
||||||
|
+ if(errno == EACCES)
|
||||||
|
+ fatal("MAJOR SECURITY WARNING: uid %lu made a deliberate and malicious attempt to open an agent socket owned by another user", (unsigned long) uid);
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ seteuid(0); /* we now continue the regularly scheduled programming */
|
||||||
|
+
|
||||||
|
+ return sock;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+AuthenticationConnection *
|
||||||
|
+ssh_get_authentication_connection_for_uid(uid_t uid)
|
||||||
|
+{
|
||||||
|
+ AuthenticationConnection *auth;
|
||||||
|
+ int sock;
|
||||||
|
+
|
||||||
|
+ sock = ssh_get_authentication_socket_for_uid(uid);
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Fail if we couldn't obtain a connection. This happens if we
|
||||||
|
+ * exited due to a timeout.
|
||||||
|
+ */
|
||||||
|
+ if (sock < 0)
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ auth = xmalloc(sizeof(*auth));
|
||||||
|
+ auth->fd = sock;
|
||||||
|
+ buffer_init(&auth->identities);
|
||||||
|
+ auth->howmany = 0;
|
||||||
|
+
|
||||||
|
+ return auth;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
pamsshagentauth_find_authorized_keys(const char * user, const char * ruser, const char * servicename)
|
||||||
|
{
|
||||||
|
Buffer session_id2 = { 0 };
|
||||||
|
@@ -190,7 +289,7 @@ pamsshagentauth_find_authorized_keys(con
|
||||||
|
OpenSSL_add_all_digests();
|
||||||
|
pamsshagentauth_session_id2_gen(&session_id2, user, ruser, servicename);
|
||||||
|
|
||||||
|
- if ((ac = ssh_get_authentication_connection(uid))) {
|
||||||
|
+ if ((ac = ssh_get_authentication_connection_for_uid(uid))) {
|
||||||
|
pamsshagentauth_verbose("Contacted ssh-agent of user %s (%u)", ruser, uid);
|
||||||
|
for (key = ssh_get_first_identity(ac, &comment, 2); key != NULL; key = ssh_get_next_identity(ac, &comment, 2))
|
||||||
|
{
|
||||||
|
diff -up openssh-7.4p1/pam_ssh_agent_auth-0.10.3/Makefile.in.psaa-build openssh-7.4p1/pam_ssh_agent_auth-0.10.3/Makefile.in
|
||||||
|
--- openssh-7.4p1/pam_ssh_agent_auth-0.10.3/Makefile.in.psaa-build 2016-11-13 04:24:32.000000000 +0100
|
||||||
|
+++ openssh-7.4p1/pam_ssh_agent_auth-0.10.3/Makefile.in 2017-02-07 14:40:14.407566921 +0100
|
||||||
|
@@ -52,7 +52,7 @@ PATHS=
|
||||||
|
CC=@CC@
|
||||||
|
LD=@LD@
|
||||||
|
CFLAGS=@CFLAGS@
|
||||||
|
-CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@
|
||||||
|
+CPPFLAGS=-I.. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@
|
||||||
|
LIBS=@LIBS@
|
||||||
|
AR=@AR@
|
||||||
|
AWK=@AWK@
|
||||||
|
@@ -61,7 +61,7 @@ INSTALL=@INSTALL@
|
||||||
|
PERL=@PERL@
|
||||||
|
SED=@SED@
|
||||||
|
ENT=@ENT@
|
||||||
|
-LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@
|
||||||
|
+LDFLAGS=-L.. -L../openbsd-compat/ @LDFLAGS@
|
||||||
|
LDFLAGS_SHARED = @LDFLAGS_SHARED@
|
||||||
|
EXEEXT=@EXEEXT@
|
||||||
|
|
||||||
|
@@ -74,7 +74,7 @@ SSHOBJS=xmalloc.o atomicio.o authfd.o bu
|
||||||
|
|
||||||
|
ED25519OBJS=ed25519-donna/ed25519.o
|
||||||
|
|
||||||
|
-PAM_SSH_AGENT_AUTH_OBJS=pam_user_key_allowed2.o iterate_ssh_agent_keys.o userauth_pubkey_from_id.o pam_user_authorized_keys.o get_command_line.o
|
||||||
|
+PAM_SSH_AGENT_AUTH_OBJS=pam_user_key_allowed2.o iterate_ssh_agent_keys.o userauth_pubkey_from_id.o pam_user_authorized_keys.o get_command_line.o secure_filename.o
|
||||||
|
|
||||||
|
|
||||||
|
MANPAGES_IN = pam_ssh_agent_auth.pod
|
||||||
|
@@ -94,13 +94,13 @@ $(PAM_MODULES): Makefile.in config.h
|
||||||
|
.c.o:
|
||||||
|
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
-LIBCOMPAT=openbsd-compat/libopenbsd-compat.a
|
||||||
|
+LIBCOMPAT=../openbsd-compat/libopenbsd-compat.a
|
||||||
|
$(LIBCOMPAT): always
|
||||||
|
(cd openbsd-compat && $(MAKE))
|
||||||
|
always:
|
||||||
|
|
||||||
|
-pam_ssh_agent_auth.so: $(LIBCOMPAT) $(SSHOBJS) $(ED25519OBJS) $(PAM_SSH_AGENT_AUTH_OBJS) pam_ssh_agent_auth.o
|
||||||
|
- $(LD) $(LDFLAGS_SHARED) -o $@ $(SSHOBJS) $(ED25519OBJS) $(PAM_SSH_AGENT_AUTH_OBJS) $(LDFLAGS) -lopenbsd-compat pam_ssh_agent_auth.o $(LIBS) -lpam
|
||||||
|
+pam_ssh_agent_auth.so: $(PAM_SSH_AGENT_AUTH_OBJS) pam_ssh_agent_auth.o ../uidswap.o
|
||||||
|
+ $(LD) $(LDFLAGS_SHARED) -o $@ $(PAM_SSH_AGENT_AUTH_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat pam_ssh_agent_auth.o ../uidswap.o $(LIBS) -lpam
|
||||||
|
|
||||||
|
$(MANPAGES): $(MANPAGES_IN)
|
||||||
|
pod2man --section=8 --release=v0.10.3 --name=pam_ssh_agent_auth --official --center "PAM" pam_ssh_agent_auth.pod > pam_ssh_agent_auth.8
|
8
SOURCES/ssh-keycat.pam
Normal file
8
SOURCES/ssh-keycat.pam
Normal file
@ -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
|
||||||
|
|
40
SOURCES/sshd-keygen
Normal file
40
SOURCES/sshd-keygen
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#!/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") ;; # always ok
|
||||||
|
"ecdsa") ;;
|
||||||
|
*) # 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 -f $KEY -C '' -N '' >&/dev/null; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# sanitize permissions
|
||||||
|
/usr/bin/chgrp ssh_keys $KEY
|
||||||
|
/usr/bin/chmod 640 $KEY
|
||||||
|
/usr/bin/chmod 644 $KEY.pub
|
||||||
|
if [[ -x /usr/sbin/restorecon ]]; then
|
||||||
|
/usr/sbin/restorecon $KEY{,.pub}
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
5
SOURCES/sshd-keygen.target
Normal file
5
SOURCES/sshd-keygen.target
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
[Unit]
|
||||||
|
Wants=sshd-keygen@rsa.service
|
||||||
|
Wants=sshd-keygen@ecdsa.service
|
||||||
|
Wants=sshd-keygen@ed25519.service
|
||||||
|
PartOf=sshd.service
|
11
SOURCES/sshd-keygen@.service
Normal file
11
SOURCES/sshd-keygen@.service
Normal file
@ -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
|
17
SOURCES/sshd.pam
Normal file
17
SOURCES/sshd.pam
Normal file
@ -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
|
18
SOURCES/sshd.service
Normal file
18
SOURCES/sshd.service
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=OpenSSH server daemon
|
||||||
|
Documentation=man:sshd(8) man:sshd_config(5)
|
||||||
|
After=network.target sshd-keygen.target
|
||||||
|
Wants=sshd-keygen.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=notify
|
||||||
|
EnvironmentFile=-/etc/crypto-policies/back-ends/opensshserver.config
|
||||||
|
EnvironmentFile=-/etc/sysconfig/sshd
|
||||||
|
ExecStart=/usr/sbin/sshd -D $OPTIONS $CRYPTO_POLICY
|
||||||
|
ExecReload=/bin/kill -HUP $MAINPID
|
||||||
|
KillMode=process
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=42s
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
11
SOURCES/sshd.socket
Normal file
11
SOURCES/sshd.socket
Normal file
@ -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
|
11
SOURCES/sshd.sysconfig
Normal file
11
SOURCES/sshd.sysconfig
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
# System-wide crypto policy:
|
||||||
|
# To opt-out, uncomment the following line
|
||||||
|
# CRYPTO_POLICY=
|
1
SOURCES/sshd.tmpfiles
Normal file
1
SOURCES/sshd.tmpfiles
Normal file
@ -0,0 +1 @@
|
|||||||
|
d /var/empty/sshd 711 root root -
|
11
SOURCES/sshd@.service
Normal file
11
SOURCES/sshd@.service
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=OpenSSH per-connection server daemon
|
||||||
|
Documentation=man:sshd(8) man:sshd_config(5)
|
||||||
|
Wants=sshd-keygen.target
|
||||||
|
After=sshd-keygen.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
EnvironmentFile=-/etc/crypto-policies/back-ends/opensshserver.config
|
||||||
|
EnvironmentFile=-/etc/sysconfig/sshd
|
||||||
|
ExecStart=-/usr/sbin/sshd -i $OPTIONS $CRYPTO_POLICY
|
||||||
|
StandardInput=socket
|
2817
SPECS/openssh.spec
Normal file
2817
SPECS/openssh.spec
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user