Compare commits

..

21 Commits
master ... f18

Author SHA1 Message Date
Petr Lautrbach 36854a5a23 6.1p1-11 + 0.9.3-3 2013-12-11 16:00:37 +01:00
Petr Lautrbach 3b37f5b889 sshd-keygen - create an ecdsa host key with 640 permissions (#1023945) 2013-12-09 11:22:51 +01:00
Petr Lautrbach 6ca2f775e1 minor change in HOWTO.ssh-keycat - s/AuthorizedKeysCommandRunAs/AuthorizedKeysCommandUser/ 2013-12-09 11:22:50 +01:00
Petr Lautrbach a23056d990 6.1p1-10 + 0.9.3-3 2013-11-18 14:31:52 +01:00
Petr Lautrbach 8115d9469c sshd-keygen to generate ECDSA keys <i.grok@comcast.net> (#1019222) 2013-11-18 14:18:04 +01:00
Petr Lautrbach 05765c1225 Increase the size of the Diffie-Hellman groups requested for a each symmetric key size. New values from NIST Special Publication 800-57 with the upper limit specified by RFC4419. Pointed out by Peter Backes, ok djm@. (#1010607) 2013-11-18 14:10:27 +01:00
Petr Lautrbach c7eccad288 don't show Success for EAI_SYSTEM (#985964) 2013-11-18 14:08:48 +01:00
Petr Lautrbach 82946ad504 6.1p1-9 + 0.9.3-3 2013-06-20 10:42:41 +02:00
Petr Lautrbach b5b762a4d1 make sftp's libedit interface marginally multibyte aware (#841771) 2013-06-20 10:28:25 +02:00
Petr Lautrbach 1784dd0d3b 6.1p1-8 + 0.9.3-3 2013-04-23 12:23:05 +02:00
Petr Lautrbach fb00871f19 AuthorizedKeysCommandUser: use the user being authenticated by default (#953534) 2013-04-19 15:30:36 +02:00
Petr Lautrbach 1e3cc96dcb 6.1p1-7 + 0.9.3-3 2013-04-17 18:07:20 +02:00
Petr Lautrbach 3c8d85c214 don't use export in sysconfig file (#953111) 2013-04-17 18:00:29 +02:00
Petr Lautrbach 134fe470bd sshd.service: use KillMode=process (#890376) 2013-04-17 18:00:13 +02:00
Petr Lautrbach 52161dcd5f allow specification of alternate host key location(s) via /etc/sysconfig/sshd
<john_florian@dart.biz> (#865803)
2013-03-26 15:47:25 +01:00
Petr Lautrbach 7524ce4c02 6.1p1-6 + 0.9.3-3 2013-02-15 13:40:34 +01:00
Petr Lautrbach 5c8cd31261 fix AuthorizedKeysCommand option and adopt latest upstream changes 2013-02-15 13:38:55 +01:00
Petr Lautrbach fa0507a75a pam_ssh_agent_auth - change paths from %{_lib} to %{_libdir} 2013-02-15 13:38:49 +01:00
Petr Lautrbach 8b4b7fffad fix bogus day names in changelog dates 2013-02-15 13:38:39 +01:00
Petr Lautrbach a9eca237d2 6.1p1-5 + 0.9.3-3 2013-02-08 14:59:33 +01:00
Petr Lautrbach 984bb05a16 change default value of MaxStartups - CVE-2010-5107 - #908707 2013-02-08 14:59:24 +01:00
120 changed files with 15397 additions and 19369 deletions

37
.gitignore vendored
View File

@ -8,40 +8,3 @@ pam_ssh_agent_auth-0.9.2.tar.bz2
/pam_ssh_agent_auth-0.9.3.tar.bz2
/openssh-6.0p1-noacss.tar.bz2
/openssh-6.1p1-noacss.tar.bz2
/openssh-6.2p1.tar.gz
/openssh-6.2p2.tar.gz
/openssh-6.3p1.tar.gz
/openssh-6.4p1.tar.gz
/openssh-6.6p1.tar.gz
/openssh-6.7p1.tar.gz
/openssh-6.8p1.tar.gz
/openssh-6.9p1.tar.gz
/openssh-7.0p1.tar.gz
/openssh-7.1p1.tar.gz
/openssh-7.1p2.tar.gz
/pam_ssh_agent_auth-0.10.2.tar.bz2
/openssh-7.2p1.tar.gz
/openssh-7.2p2.tar.gz
/openssh-7.3p1.tar.gz
/openssh-7.4p1.tar.gz
/pam_ssh_agent_auth-0.10.3.tar.bz2
/openssh-7.5p1.tar.gz
/openssh-7.6p1.tar.gz
/openssh-7.7p1.tar.gz
/openssh-7.7p1.tar.gz.asc
/DJM-GPG-KEY.gpg
/openssh-7.8p1.tar.gz
/openssh-7.8p1.tar.gz.asc
/openssh-7.9p1.tar.gz
/openssh-7.9p1.tar.gz.asc
/openssh-8.0p1.tar.gz
/openssh-8.0p1.tar.gz.asc
/openssh-8.1p1.tar.gz
/openssh-8.1p1.tar.gz.asc
/openssh-8.2p1.tar.gz
/openssh-8.2p1.tar.gz.asc
/openssh-8.3p1.tar.gz
/openssh-8.3p1.tar.gz.asc
/openssh-8.4p1.tar.gz
/openssh-8.4p1.tar.gz.asc
/pam_ssh_agent_auth-0.10.4.tar.gz

View File

@ -1,8 +1,7 @@
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,
--- openssh-4.3p2/contrib/gnome-ssh-askpass2.c.grab-info 2006-07-17 15:10:11.000000000 +0200
+++ openssh-4.3p2/contrib/gnome-ssh-askpass2.c 2006-07-17 15:25:04.000000000 +0200
@@ -65,9 +65,12 @@
err = gtk_message_dialog_new(NULL, 0,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
- "Could not grab %s. "
@ -15,5 +14,5 @@ diff -up openssh-7.4p1/contrib/gnome-ssh-askpass2.c.grab-info openssh-7.4p1/cont
+ "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));
gtk_label_set_line_wrap(GTK_LABEL((GTK_MESSAGE_DIALOG(err))->label),
TRUE);

View File

@ -1,16 +1,16 @@
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
diff -up openssh-5.1p1/contrib/gnome-ssh-askpass2.c.progress openssh-5.1p1/contrib/gnome-ssh-askpass2.c
--- openssh-5.1p1/contrib/gnome-ssh-askpass2.c.progress 2008-07-23 19:05:26.000000000 +0200
+++ openssh-5.1p1/contrib/gnome-ssh-askpass2.c 2008-07-23 19:05:26.000000000 +0200
@@ -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>
#include <gdk/gdkkeysyms.h>
@@ -81,14 +82,25 @@ ok_dialog(GtkWidget *entry, gpointer dia
return 1;
@@ -83,13 +84,24 @@ ok_dialog(GtkWidget *entry, gpointer dia
gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
}
+static void
@ -25,59 +25,55 @@ diff -up openssh-7.4p1/contrib/gnome-ssh-askpass2.c.progress openssh-7.4p1/contr
+}
+
static int
passphrase_dialog(char *message, int prompt_type)
passphrase_dialog(char *message)
{
const char *failed;
char *passphrase, *local;
int result, grab_tries, grab_server, grab_pointer;
int buttons, default_response;
- GtkWidget *parent_window, *dialog, *entry;
+ GtkWidget *parent_window, *dialog, *entry, *progress, *hbox;
- GtkWidget *dialog, *entry;
+ GtkWidget *dialog, *entry, *progress, *hbox;
GdkGrabStatus status;
GdkColor fg, bg;
int fg_set = 0, bg_set = 0;
@@ -104,14 +116,19 @@ passphrase_dialog(char *message)
gtk_widget_modify_bg(dialog, GTK_STATE_NORMAL, &bg);
if (prompt_type == PROMPT_ENTRY || prompt_type == PROMPT_NONE) {
+ hbox = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, FALSE,
+ FALSE, 0);
+ gtk_widget_show(hbox);
+
entry = gtk_entry_new();
if (fg_set)
gtk_widget_modify_fg(entry, GTK_STATE_NORMAL, &fg);
if (bg_set)
gtk_widget_modify_bg(entry, GTK_STATE_NORMAL, &bg);
gtk_box_pack_start(
- GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))),
- entry, FALSE, FALSE, 0);
+ GTK_BOX(hbox), entry, TRUE, FALSE, 0);
+ gtk_entry_set_width_chars(GTK_ENTRY(entry), 2);
gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE);
gtk_widget_grab_focus(entry);
if (prompt_type == PROMPT_ENTRY) {
@@ -130,6 +145,22 @@ passphrase_dialog(char *message)
g_signal_connect(G_OBJECT(entry), "key_press_event",
G_CALLBACK(check_none), dialog);
}
+
+ hbox = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
+ hbox, FALSE, FALSE, 8);
+ gtk_widget_show(hbox);
+
+ progress = gtk_progress_bar_new();
+
+ gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress),
+ "Passphrase length hidden intentionally");
+ gtk_box_pack_start(GTK_BOX(hbox), progress, TRUE,
+ TRUE, 5);
+ gtk_widget_show(progress);
+ g_signal_connect(G_OBJECT(entry), "changed",
+ G_CALLBACK(move_progress), progress);
+
}
grab_server = (getenv("GNOME_SSH_ASKPASS_GRAB_SERVER") != NULL);
@@ -102,13 +114,31 @@ 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(dialog)->vbox), entry, FALSE,
+ gtk_box_pack_start(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);
@@ -119,6 +149,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);
/* Grab focus */

View File

@ -0,0 +1,18 @@
diff -up openssh-5.1p1/scp.1.manpage openssh-5.1p1/scp.1
--- openssh-5.1p1/scp.1.manpage 2008-07-12 09:12:49.000000000 +0200
+++ openssh-5.1p1/scp.1 2008-07-23 19:18:15.000000000 +0200
@@ -66,6 +66,14 @@ treating file names containing
as host specifiers.
Copies between two remote hosts are also permitted.
.Pp
+When copying a source file to a target file which already exists,
+.Nm
+will replace the contents of the target file (keeping the inode).
+.Pp
+If the target file does not yet exist, an empty file with the target
+file name is created, then filled with the source file contents.
+No attempt is made at "near-atomic" transfer using temporary files.
+.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl 1

View File

@ -0,0 +1,37 @@
diff -up openssh-5.2p1/canohost.c.ip-opts openssh-5.2p1/canohost.c
--- openssh-5.2p1/canohost.c.ip-opts 2009-02-14 06:28:21.000000000 +0100
+++ openssh-5.2p1/canohost.c 2009-09-01 15:31:29.000000000 +0200
@@ -169,12 +169,27 @@ check_ip_options(int sock, char *ipaddr)
option_size = sizeof(options);
if (getsockopt(sock, ipproto, IP_OPTIONS, options,
&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", options[i]);
- fatal("Connection from %.100s with IP options:%.800s",
- ipaddr, text);
+ i = 0;
+ do {
+ switch (options[i]) {
+ case 0:
+ case 1:
+ ++i;
+ break;
+ case 131:
+ case 137:
+ /* 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", options[i]);
+ fatal("Connection from %.100s with IP options:%.800s",
+ ipaddr, text);
+ default:
+ i += options[i + 1];
+ }
+ } while (i < option_size);
}
#endif /* IP_OPTIONS */
}

View File

@ -1,7 +1,7 @@
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_
diff -up openssh-5.3p1/channels.c.bz595935 openssh-5.3p1/channels.c
--- openssh-5.3p1/channels.c.bz595935 2010-08-12 14:19:28.000000000 +0200
+++ openssh-5.3p1/channels.c 2010-08-12 14:33:51.000000000 +0200
@@ -3185,7 +3185,7 @@ x11_create_display_inet(int x11_display_
}
static int
@ -10,16 +10,14 @@ diff -up openssh-7.2p2/channels.c.x11 openssh-7.2p2/channels.c
{
int sock;
struct sockaddr_un addr;
+ if (len <= 0)
+ return -1;
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock == -1)
@@ -3195,11 +3195,14 @@ connect_local_xsocket_path(const char *p
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 <= 0)
+ return -1;
+ if (len > sizeof addr.sun_path)
+ len = sizeof addr.sun_path;
+ memcpy(addr.sun_path, pathname, len);
@ -30,13 +28,16 @@ diff -up openssh-7.2p2/channels.c.x11 openssh-7.2p2/channels.c
return -1;
}
@@ -4012,8 +4015,18 @@ static int
@@ -3207,8 +3210,21 @@ 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;
+ int len;
+#ifdef linux
+ int ret;
+#endif
+ len = snprintf(buf + 1, sizeof (buf) - 1, _PATH_UNIX_X, dnr);
+#ifdef linux
+ /* try abstract socket first */
@ -50,4 +51,4 @@ diff -up openssh-7.2p2/channels.c.x11 openssh-7.2p2/channels.c
+ return -1;
}
#ifdef __APPLE__
int

View File

@ -0,0 +1,14 @@
diff -up openssh-5.6p1/channels.c.exit-deadlock openssh-5.6p1/channels.c
--- openssh-5.6p1/channels.c.exit-deadlock 2010-08-05 15:09:48.000000000 +0200
+++ openssh-5.6p1/channels.c 2010-08-23 12:41:43.000000000 +0200
@@ -1647,6 +1647,10 @@ channel_handle_wfd(Channel *c, fd_set *r
u_int dlen, olen = 0;
int len;
+ if(c->wfd != -1 && buffer_len(&c->output) > 0 && c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
+ debug("channel %d: forcing write", c->self);
+ FD_SET(c->wfd, writeset);
+ }
/* Send buffered output data to the socket. */
if (c->wfd != -1 &&
FD_ISSET(c->wfd, writeset) &&

View File

@ -0,0 +1,17 @@
Don't audit SSH_INVALID_USER twice.
PRIVSEP(getpwnamallow()) a few lines above already did this.
diff -ur openssh/auth2.c openssh-5.8p1/auth2.c
--- openssh/auth2.c 2011-03-02 02:32:52.383773622 +0100
+++ openssh-5.8p1/auth2.c 2011-03-02 03:32:34.585110911 +0100
@@ -250,9 +250,6 @@
} else {
logit("input_userauth_request: invalid user %s", user);
authctxt->pw = fakepw();
-#ifdef SSH_AUDIT_EVENTS
- PRIVSEP(audit_event(SSH_INVALID_USER));
-#endif
}
#ifdef USE_PAM
if (options.use_pam)

View File

@ -0,0 +1,421 @@
diff -up openssh-5.8p1/auth2-hostbased.c.fingerprint openssh-5.8p1/auth2-hostbased.c
--- openssh-5.8p1/auth2-hostbased.c.fingerprint 2010-08-05 05:04:50.000000000 +0200
+++ openssh-5.8p1/auth2-hostbased.c 2011-02-25 09:17:18.000000000 +0100
@@ -196,16 +196,18 @@ hostbased_key_allowed(struct passwd *pw,
if (host_status == HOST_OK) {
if (key_is_cert(key)) {
- fp = key_fingerprint(key->cert->signature_key,
- SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_selected_fingerprint(key->cert->signature_key,
+ SSH_FP_HEX);
verbose("Accepted certificate ID \"%s\" signed by "
- "%s CA %s from %s@%s", key->cert->key_id,
- key_type(key->cert->signature_key), fp,
+ "%s CA %s%s from %s@%s", key->cert->key_id,
+ key_type(key->cert->signature_key),
+ key_fingerprint_prefix(), fp,
cuser, lookup);
} else {
- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
- verbose("Accepted %s public key %s from %s@%s",
- key_type(key), fp, cuser, lookup);
+ fp = key_selected_fingerprint(key, SSH_FP_HEX);
+ verbose("Accepted %s public key %s%s from %s@%s",
+ key_type(key), key_fingerprint_prefix(),
+ fp, cuser, lookup);
}
xfree(fp);
}
diff -up openssh-5.8p1/auth2-pubkey.c.fingerprint openssh-5.8p1/auth2-pubkey.c
--- openssh-5.8p1/auth2-pubkey.c.fingerprint 2010-12-01 01:50:14.000000000 +0100
+++ openssh-5.8p1/auth2-pubkey.c 2011-02-25 09:17:18.000000000 +0100
@@ -319,10 +319,10 @@ user_key_allowed2(struct passwd *pw, Key
continue;
if (!key_is_cert_authority)
continue;
- fp = key_fingerprint(found, SSH_FP_MD5,
- SSH_FP_HEX);
- debug("matching CA found: file %s, line %lu, %s %s",
- file, linenum, key_type(found), fp);
+ fp = key_selected_fingerprint(found, SSH_FP_HEX);
+ debug("matching CA found: file %s, line %lu, %s %s%s",
+ file, linenum, key_type(found),
+ key_fingerprint_prefix(), fp);
/*
* If the user has specified a list of principals as
* a key option, then prefer that list to matching
@@ -362,9 +362,9 @@ user_key_allowed2(struct passwd *pw, Key
found_key = 1;
debug("matching key found: file %s, line %lu",
file, linenum);
- fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
- verbose("Found matching %s key: %s",
- key_type(found), fp);
+ fp = key_selected_fingerprint(found, SSH_FP_HEX);
+ verbose("Found matching %s key: %s%s",
+ key_type(found), key_fingerprint_prefix(), fp);
xfree(fp);
break;
}
@@ -388,13 +388,13 @@ user_cert_trusted_ca(struct passwd *pw,
if (!key_is_cert(key) || options.trusted_user_ca_keys == NULL)
return 0;
- ca_fp = key_fingerprint(key->cert->signature_key,
- SSH_FP_MD5, SSH_FP_HEX);
+ ca_fp = key_selected_fingerprint(key->cert->signature_key, SSH_FP_HEX);
if (key_in_file(key->cert->signature_key,
options.trusted_user_ca_keys, 1) != 1) {
- debug2("%s: CA %s %s is not listed in %s", __func__,
- key_type(key->cert->signature_key), ca_fp,
+ debug2("%s: CA %s%s %s is not listed in %s", __func__,
+ key_type(key->cert->signature_key),
+ key_fingerprint_prefix(), ca_fp,
options.trusted_user_ca_keys);
goto out;
}
diff -up openssh-5.8p1/auth.c.fingerprint openssh-5.8p1/auth.c
--- openssh-5.8p1/auth.c.fingerprint 2010-12-01 02:21:51.000000000 +0100
+++ openssh-5.8p1/auth.c 2011-02-25 09:17:18.000000000 +0100
@@ -639,9 +639,10 @@ auth_key_is_revoked(Key *key)
return 1;
case 1:
/* Key revoked */
- key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+ key_fp = key_selected_fingerprint(key, SSH_FP_HEX);
error("WARNING: authentication attempt with a revoked "
- "%s key %s ", key_type(key), key_fp);
+ "%s key %s%s ", key_type(key),
+ key_fingerprint_prefix(), key_fp);
xfree(key_fp);
return 1;
}
diff -up openssh-5.8p1/auth-rsa.c.fingerprint openssh-5.8p1/auth-rsa.c
--- openssh-5.8p1/auth-rsa.c.fingerprint 2010-12-04 23:01:47.000000000 +0100
+++ openssh-5.8p1/auth-rsa.c 2011-02-25 09:17:18.000000000 +0100
@@ -318,9 +318,9 @@ auth_rsa(Authctxt *authctxt, BIGNUM *cli
* options; this will be reset if the options cause the
* authentication to be rejected.
*/
- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
- verbose("Found matching %s key: %s",
- key_type(key), fp);
+ fp = key_selected_fingerprint(key, SSH_FP_HEX);
+ verbose("Found matching %s key: %s%s",
+ key_type(key), key_fingerprint_prefix(), fp);
xfree(fp);
key_free(key);
diff -up openssh-5.8p1/key.c.fingerprint openssh-5.8p1/key.c
--- openssh-5.8p1/key.c.fingerprint 2011-02-04 01:48:34.000000000 +0100
+++ openssh-5.8p1/key.c 2011-02-25 09:18:16.000000000 +0100
@@ -594,6 +594,34 @@ key_fingerprint(Key *k, enum fp_type dgs
return retval;
}
+enum fp_type
+key_fingerprint_selection(void)
+{
+ static enum fp_type rv;
+ static char rv_defined = 0;
+ char *env;
+
+ if (!rv_defined) {
+ env = getenv("SSH_FINGERPRINT_TYPE");
+ rv = (env && !strcmp (env, "sha")) ?
+ SSH_FP_SHA1 : SSH_FP_MD5;
+ rv_defined = 1;
+ }
+ return rv;
+}
+
+char *
+key_selected_fingerprint(Key *k, enum fp_rep dgst_rep)
+{
+ return key_fingerprint(k, key_fingerprint_selection(), dgst_rep);
+}
+
+char *
+key_fingerprint_prefix(void)
+{
+ return key_fingerprint_selection() == SSH_FP_SHA1 ? "sha1:" : "";
+}
+
/*
* Reads a multiple-precision integer in decimal from the buffer, and advances
* the pointer. The integer must already be initialized. This function is
diff -up openssh-5.8p1/key.h.fingerprint openssh-5.8p1/key.h
--- openssh-5.8p1/key.h.fingerprint 2010-11-05 00:19:49.000000000 +0100
+++ openssh-5.8p1/key.h 2011-02-25 09:17:18.000000000 +0100
@@ -96,6 +96,9 @@ int key_equal_public(const Key *, cons
int key_equal(const Key *, const Key *);
char *key_fingerprint(Key *, enum fp_type, enum fp_rep);
u_char *key_fingerprint_raw(Key *, enum fp_type, u_int *);
+enum fp_type key_fingerprint_selection(void);
+char *key_selected_fingerprint(Key *, enum fp_rep);
+char *key_fingerprint_prefix(void);
const char *key_type(const Key *);
const char *key_cert_type(const Key *);
int key_write(const Key *, FILE *);
diff -up openssh-5.8p1/ssh-add.c.fingerprint openssh-5.8p1/ssh-add.c
--- openssh-5.8p1/ssh-add.c.fingerprint 2010-11-11 04:17:02.000000000 +0100
+++ openssh-5.8p1/ssh-add.c 2011-02-25 09:17:18.000000000 +0100
@@ -280,10 +280,10 @@ list_identities(AuthenticationConnection
key = ssh_get_next_identity(ac, &comment, version)) {
had_identities = 1;
if (do_fp) {
- fp = key_fingerprint(key, SSH_FP_MD5,
- SSH_FP_HEX);
- printf("%d %s %s (%s)\n",
- key_size(key), fp, comment, key_type(key));
+ fp = key_selected_fingerprint(key, SSH_FP_HEX);
+ printf("%d %s%s %s (%s)\n",
+ key_size(key), key_fingerprint_prefix(),
+ fp, comment, key_type(key));
xfree(fp);
} else {
if (!key_write(key, stdout))
diff -up openssh-5.8p1/ssh-agent.c.fingerprint openssh-5.8p1/ssh-agent.c
--- openssh-5.8p1/ssh-agent.c.fingerprint 2010-12-01 01:50:35.000000000 +0100
+++ openssh-5.8p1/ssh-agent.c 2011-02-25 09:17:18.000000000 +0100
@@ -199,9 +199,9 @@ confirm_key(Identity *id)
char *p;
int ret = -1;
- p = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX);
- if (ask_permission("Allow use of key %s?\nKey fingerprint %s.",
- id->comment, p))
+ p = key_selected_fingerprint(id->key, SSH_FP_HEX);
+ if (ask_permission("Allow use of key %s?\nKey fingerprint %s%s.",
+ id->comment, key_fingerprint_prefix(), p))
ret = 0;
xfree(p);
diff -up openssh-5.8p1/sshconnect2.c.fingerprint openssh-5.8p1/sshconnect2.c
--- openssh-5.8p1/sshconnect2.c.fingerprint 2010-12-01 02:21:51.000000000 +0100
+++ openssh-5.8p1/sshconnect2.c 2011-02-25 09:17:18.000000000 +0100
@@ -590,8 +590,9 @@ input_userauth_pk_ok(int type, u_int32_t
key->type, pktype);
goto done;
}
- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
- debug2("input_userauth_pk_ok: fp %s", fp);
+ fp = key_selected_fingerprint(key, SSH_FP_HEX);
+ debug2("input_userauth_pk_ok: fp %s%s",
+ key_fingerprint_prefix(), fp);
xfree(fp);
/*
@@ -1203,8 +1204,9 @@ sign_and_send_pubkey(Authctxt *authctxt,
int have_sig = 1;
char *fp;
- fp = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX);
- debug3("sign_and_send_pubkey: %s %s", key_type(id->key), fp);
+ fp = key_selected_fingerprint(id->key, SSH_FP_HEX);
+ debug3("sign_and_send_pubkey: %s %s%s", key_type(id->key),
+ key_fingerprint_prefix(), fp);
xfree(fp);
if (key_to_blob(id->key, &blob, &bloblen) == 0) {
diff -up openssh-5.8p1/sshconnect.c.fingerprint openssh-5.8p1/sshconnect.c
--- openssh-5.8p1/sshconnect.c.fingerprint 2011-01-16 13:17:59.000000000 +0100
+++ openssh-5.8p1/sshconnect.c 2011-02-25 09:17:18.000000000 +0100
@@ -798,10 +798,10 @@ check_host_key(char *hostname, struct so
"key for IP address '%.128s' to the list "
"of known hosts.", type, ip);
} else if (options.visual_host_key) {
- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
- ra = key_fingerprint(host_key, SSH_FP_MD5,
- SSH_FP_RANDOMART);
- logit("Host key fingerprint is %s\n%s\n", fp, ra);
+ fp = key_selected_fingerprint(host_key, SSH_FP_HEX);
+ ra = key_selected_fingerprint(host_key, SSH_FP_RANDOMART);
+ logit("Host key fingerprint is %s%s\n%s\n",
+ key_fingerprint_prefix(), fp, ra);
xfree(ra);
xfree(fp);
}
@@ -838,9 +838,8 @@ check_host_key(char *hostname, struct so
else
snprintf(msg1, sizeof(msg1), ".");
/* The default */
- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
- ra = key_fingerprint(host_key, SSH_FP_MD5,
- SSH_FP_RANDOMART);
+ fp = key_selected_fingerprint(host_key, SSH_FP_HEX);
+ ra = key_selected_fingerprint(host_key, SSH_FP_RANDOMART);
msg2[0] = '\0';
if (options.verify_host_key_dns) {
if (matching_host_key_dns)
@@ -855,10 +854,11 @@ check_host_key(char *hostname, struct so
snprintf(msg, sizeof(msg),
"The authenticity of host '%.200s (%s)' can't be "
"established%s\n"
- "%s key fingerprint is %s.%s%s\n%s"
+ "%s key fingerprint is %s%s.%s%s\n%s"
"Are you sure you want to continue connecting "
"(yes/no)? ",
- host, ip, msg1, type, fp,
+ host, ip, msg1, type,
+ key_fingerprint_prefix(), fp,
options.visual_host_key ? "\n" : "",
options.visual_host_key ? ra : "",
msg2);
@@ -1104,8 +1104,9 @@ verify_host_key(char *host, struct socka
int flags = 0;
char *fp;
- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
- debug("Server host key: %s %s", key_type(host_key), fp);
+ fp = key_selected_fingerprint(host_key, SSH_FP_HEX);
+ debug("Server host key: %s %s%s", key_type(host_key),
+ key_fingerprint_prefix(), fp);
xfree(fp);
/* XXX certs are not yet supported for DNS */
@@ -1214,14 +1215,15 @@ show_other_keys(struct hostkeys *hostkey
continue;
if (!lookup_key_in_hostkeys_by_type(hostkeys, type[i], &found))
continue;
- fp = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_HEX);
- ra = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_RANDOMART);
+ fp = key_selected_fingerprint(found->key, SSH_FP_HEX);
+ ra = key_selected_fingerprint(found->key, SSH_FP_RANDOMART);
logit("WARNING: %s key found for host %s\n"
"in %s:%lu\n"
- "%s key fingerprint %s.",
+ "%s key fingerprint %s%s.",
key_type(found->key),
found->host, found->file, found->line,
- key_type(found->key), fp);
+ key_type(found->key),
+ key_fingerprint_prefix(), fp);
if (options.visual_host_key)
logit("%s", ra);
xfree(ra);
@@ -1236,7 +1238,7 @@ warn_changed_key(Key *host_key)
{
char *fp;
- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_selected_fingerprint(host_key, SSH_FP_HEX);
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @");
@@ -1244,8 +1246,8 @@ warn_changed_key(Key *host_key)
error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!");
error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!");
error("It is also possible that a host key has just been changed.");
- error("The fingerprint for the %s key sent by the remote host is\n%s.",
- key_type(host_key), fp);
+ error("The fingerprint for the %s key sent by the remote host is\n%s%s.",
+ key_type(host_key),key_fingerprint_prefix(), fp);
error("Please contact your system administrator.");
xfree(fp);
diff -up openssh-5.8p1/ssh-keygen.c.fingerprint openssh-5.8p1/ssh-keygen.c
--- openssh-5.8p1/ssh-keygen.c.fingerprint 2011-01-11 07:20:31.000000000 +0100
+++ openssh-5.8p1/ssh-keygen.c 2011-02-25 09:17:18.000000000 +0100
@@ -714,13 +714,14 @@ do_fingerprint(struct passwd *pw)
{
FILE *f;
Key *public;
- char *comment = NULL, *cp, *ep, line[16*1024], *fp, *ra;
+ char *comment = NULL, *cp, *ep, line[16*1024], *fp, *ra, *pfx;
int i, skip = 0, num = 0, invalid = 1;
enum fp_rep rep;
enum fp_type fptype;
struct stat st;
- fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
+ fptype = print_bubblebabble ? SSH_FP_SHA1 : key_fingerprint_selection();
+ pfx = print_bubblebabble ? "" : key_fingerprint_prefix();
rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
if (!have_identity)
@@ -732,8 +733,8 @@ do_fingerprint(struct passwd *pw)
public = key_load_public(identity_file, &comment);
if (public != NULL) {
fp = key_fingerprint(public, fptype, rep);
- ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART);
- printf("%u %s %s (%s)\n", key_size(public), fp, comment,
+ ra = key_selected_fingerprint(public, SSH_FP_RANDOMART);
+ printf("%u %s%s %s (%s)\n", key_size(public), pfx, fp, comment,
key_type(public));
if (log_level >= SYSLOG_LEVEL_VERBOSE)
printf("%s\n", ra);
@@ -798,8 +799,8 @@ do_fingerprint(struct passwd *pw)
}
comment = *cp ? cp : comment;
fp = key_fingerprint(public, fptype, rep);
- ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART);
- printf("%u %s %s (%s)\n", key_size(public), fp,
+ ra = key_selected_fingerprint(public, SSH_FP_RANDOMART);
+ printf("%u %s%s %s (%s)\n", key_size(public), pfx, fp,
comment ? comment : "no comment", key_type(public));
if (log_level >= SYSLOG_LEVEL_VERBOSE)
printf("%s\n", ra);
@@ -823,13 +824,15 @@ printhost(FILE *f, const char *name, Key
if (print_fingerprint) {
enum fp_rep rep;
enum fp_type fptype;
- char *fp, *ra;
+ char *fp, *ra, *pfx;
- fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
+ fptype = print_bubblebabble ? SSH_FP_SHA1 : key_fingerprint_selection();
+ pfx = print_bubblebabble ? "" : key_fingerprint_prefix();
rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
+
fp = key_fingerprint(public, fptype, rep);
- ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART);
- printf("%u %s %s (%s)\n", key_size(public), fp, name,
+ ra = key_selected_fingerprint(public, SSH_FP_RANDOMART);
+ printf("%u %s%s %s (%s)\n", key_size(public), pfx, fp, name,
key_type(public));
if (log_level >= SYSLOG_LEVEL_VERBOSE)
printf("%s\n", ra);
@@ -1695,16 +1698,17 @@ do_show_cert(struct passwd *pw)
fatal("%s is not a certificate", identity_file);
v00 = key->type == KEY_RSA_CERT_V00 || key->type == KEY_DSA_CERT_V00;
- key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
- ca_fp = key_fingerprint(key->cert->signature_key,
- SSH_FP_MD5, SSH_FP_HEX);
+ key_fp = key_selected_fingerprint(key, SSH_FP_HEX);
+ ca_fp = key_selected_fingerprint(key->cert->signature_key, SSH_FP_HEX);
printf("%s:\n", identity_file);
printf(" Type: %s %s certificate\n", key_ssh_name(key),
key_cert_type(key));
- printf(" Public key: %s %s\n", key_type(key), key_fp);
- printf(" Signing CA: %s %s\n",
- key_type(key->cert->signature_key), ca_fp);
+ printf(" Public key: %s %s%s\n", key_type(key),
+ key_fingerprint_prefix(), key_fp);
+ printf(" Signing CA: %s %s%s\n",
+ key_type(key->cert->signature_key),
+ key_fingerprint_prefix(), ca_fp);
printf(" Key ID: \"%s\"\n", key->cert->key_id);
if (!v00) {
printf(" Serial: %llu\n",
@@ -2249,13 +2253,12 @@ passphrase_again:
fclose(f);
if (!quiet) {
- char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX);
- char *ra = key_fingerprint(public, SSH_FP_MD5,
- SSH_FP_RANDOMART);
+ char *fp = key_selected_fingerprint(public, SSH_FP_HEX);
+ char *ra = key_selected_fingerprint(public, SSH_FP_RANDOMART);
printf("Your public key has been saved in %s.\n",
identity_file);
printf("The key fingerprint is:\n");
- printf("%s %s\n", fp, comment);
+ printf("%s%s %s\n", key_fingerprint_prefix(), fp, comment);
printf("The key's randomart image is:\n");
printf("%s\n", ra);
xfree(ra);

View File

@ -0,0 +1,24 @@
diff -up openssh-5.6p1/channels.c.getaddrinfo openssh-5.6p1/channels.c
--- openssh-5.6p1/channels.c.getaddrinfo 2012-02-14 16:12:54.427852524 +0100
+++ openssh-5.6p1/channels.c 2012-02-14 16:13:22.818928690 +0100
@@ -3275,6 +3275,9 @@ x11_create_display_inet(int x11_display_
memset(&hints, 0, sizeof(hints));
hints.ai_family = IPv4or6;
hints.ai_flags = x11_use_localhost ? 0: AI_PASSIVE;
+#ifdef AI_ADDRCONFIG
+ hints.ai_flags |= AI_ADDRCONFIG;
+#endif
hints.ai_socktype = SOCK_STREAM;
snprintf(strport, sizeof strport, "%d", port);
if ((gaierr = getaddrinfo(NULL, strport, &hints, &aitop)) != 0) {
diff -up openssh-5.6p1/sshconnect.c.getaddrinfo openssh-5.6p1/sshconnect.c
--- openssh-5.6p1/sshconnect.c.getaddrinfo 2012-02-14 16:09:25.057964291 +0100
+++ openssh-5.6p1/sshconnect.c 2012-02-14 16:09:25.106047007 +0100
@@ -343,6 +343,7 @@ ssh_connect(const char *host, struct soc
memset(&hints, 0, sizeof(hints));
hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG;
snprintf(strport, sizeof strport, "%u", port);
if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0)
fatal("%s: Could not resolve hostname %.100s: %s", __progname,

10
openssh-5.8p1-glob.patch Normal file
View File

@ -0,0 +1,10 @@
diff -up openssh-5.8p1/sftp-glob.c.glob openssh-5.8p1/sftp-glob.c
--- openssh-5.8p1/sftp-glob.c.glob 2011-03-07 20:17:34.000000000 +0100
+++ openssh-5.8p1/sftp-glob.c 2011-03-07 20:18:47.000000000 +0100
@@ -145,5 +145,5 @@ remote_glob(struct sftp_conn *conn, cons
memset(&cur, 0, sizeof(cur));
cur.conn = conn;
- return(glob(pattern, flags | GLOB_ALTDIRFUNC, errfunc, pglob));
+ return(glob(pattern, flags | GLOB_LIMIT | GLOB_ALTDIRFUNC, errfunc, pglob));
}

View File

@ -0,0 +1,25 @@
diff -up openssh-5.8p1/authfile.c.keyperm openssh-5.8p1/authfile.c
--- openssh-5.8p1/authfile.c.keyperm 2010-12-01 02:03:39.000000000 +0100
+++ openssh-5.8p1/authfile.c 2011-04-21 16:43:36.859648916 +0200
@@ -57,6 +57,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <grp.h>
#include "xmalloc.h"
#include "cipher.h"
@@ -600,6 +612,13 @@ key_perm_ok(int fd, const char *filename
#ifdef HAVE_CYGWIN
if (check_ntsec(filename))
#endif
+ if (st.st_mode & 040) {
+ struct group *gr;
+
+ if ((gr = getgrnam("ssh_keys")) && (st.st_gid == gr->gr_gid))
+ st.st_mode &= ~040;
+ }
+
if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0) {
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @");

View File

@ -0,0 +1,14 @@
diff -up openssh-5.8p1/sshd_config.localdomain openssh-5.8p1/sshd_config
--- openssh-5.8p1/sshd_config.localdomain 2011-04-22 11:37:49.273648812 +0200
+++ openssh-5.8p1/sshd_config 2011-04-22 11:39:31.758648401 +0200
@@ -130,6 +130,10 @@ X11Forwarding yes
# override default of no subsystems
Subsystem sftp /usr/libexec/sftp-server
+# Uncomment this if you want to use .local domain
+#Host *.local
+# CheckHostIP no
+
# Example of overriding settings on a per-user basis
#Match User anoncvs
# X11Forwarding no

View File

@ -0,0 +1,12 @@
diff -up openssh-5.8p1/packet.c.packet openssh-5.8p1/packet.c
--- openssh-5.8p1/packet.c.packet 2011-04-05 13:29:06.998648899 +0200
+++ openssh-5.8p1/packet.c 2011-04-05 13:30:32.967648596 +0200
@@ -294,6 +294,8 @@ packet_connection_is_on_socket(void)
struct sockaddr_storage from, to;
socklen_t fromlen, tolen;
+ if (!active_state)
+ return 0;
/* filedescriptors in and out are the same, so it's a socket */
if (active_state->connection_in == active_state->connection_out)
return 1;

View File

@ -1,7 +1,6 @@
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
diff -up openssh-5.8p2/gss-serv-krb5.c.force_krb openssh-5.8p2/gss-serv-krb5.c
--- openssh-5.8p2/gss-serv-krb5.c.force_krb 2006-09-01 07:38:36.000000000 +0200
+++ openssh-5.8p2/gss-serv-krb5.c 2011-05-19 03:41:45.801109545 +0200
@@ -32,7 +32,9 @@
#include <sys/types.h>
@ -11,19 +10,28 @@ index 413b845..54dd383 100644
+#include <unistd.h>
#include "xmalloc.h"
#include "sshkey.h"
@@ -45,6 +47,7 @@
#include "key.h"
@@ -40,12 +42,11 @@
#include "auth.h"
#include "log.h"
#include "servconf.h"
+#include "misc.h"
#include "buffer.h"
#include "ssh-gss.h"
+extern Authctxt *the_authctxt;
extern ServerOptions options;
-extern ServerOptions options;
-
#ifdef HEIMDAL
@@ -56,6 +59,13 @@ extern ServerOptions options;
# include <gssapi/gssapi_krb5.h>
# include <krb5.h>
#else
@@ -56,6 +57,16 @@ extern ServerOptions options;
# endif
#endif
+extern Authctxt *the_authctxt;
+extern ServerOptions options;
+
+/* all commands are allowed by default */
+char **k5users_allowed_cmds = NULL;
+
@ -34,16 +42,21 @@ index 413b845..54dd383 100644
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)
@@ -83,10 +94,11 @@ ssh_gssapi_krb5_init(void)
*/
static int
-ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name)
+ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *luser)
{
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);
@@ -97,10 +109,22 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client
krb5_get_err_text(krb_context, retval));
return 0;
}
- if (krb5_kuserok(krb_context, princ, name)) {
@ -53,20 +66,21 @@ index 413b845..54dd383 100644
+ /* 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 (krb5_kuserok(krb_context, princ, luser) && k5login_exists) {
retval = 1;
logit("Authorized to %s, krb5 principal %s (krb5_kuserok)",
name, (char *)client->displayname.value);
- name, (char *)client->displayname.value);
+ luser, (char *)client->displayname.value);
+ } else if (ssh_gssapi_krb5_cmdok(princ, client->exportedname.value,
+ name, k5login_exists)) {
+ luser, k5login_exists)) {
+ retval = 1;
+ logit("Authorized to %s, krb5 principal %s "
+ "(ssh_gssapi_krb5_cmdok)",
+ name, (char *)client->displayname.value);
+ luser, (char *)client->displayname.value);
} else
retval = 0;
@@ -110,6 +133,137 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name)
@@ -108,6 +132,135 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client
return retval;
}
@ -97,14 +111,13 @@ index 413b845..54dd383 100644
+{
+ FILE *fp;
+ char file[MAXPATHLEN];
+ char *line = NULL;
+ char line[BUFSIZ];
+ char kuser[65]; /* match krb5_kuserok() */
+ struct stat st;
+ struct passwd *pw = the_authctxt->pw;
+ int found_principal = 0;
+ int ncommands = 0, allcommands = 0;
+ u_long linenum = 0;
+ size_t linesize = 0;
+ u_long linenum;
+
+ snprintf(file, sizeof(file), "%s/.k5users", pw->pw_dir);
+ /* If both .k5login and .k5users DNE, self-login is ok. */
@ -148,9 +161,9 @@ index 413b845..54dd383 100644
+ k5users_allowed_cmds = xcalloc(++ncommands,
+ sizeof(*k5users_allowed_cmds));
+
+ /* Check each line. ksu allows unlimited length lines. */
+ while (!allcommands && getline(&line, &linesize, fp) != -1) {
+ linenum++;
+ /* Check each line. ksu allows unlimited length lines. We don't. */
+ while (!allcommands && read_keyfile_line(fp, file, line, sizeof(line),
+ &linenum) != -1) {
+ char *token;
+
+ /* we parse just like ksu, even though we could do better */
@ -164,7 +177,7 @@ index 413b845..54dd383 100644
+ k5users_allowed_cmds[ncommands-1] =
+ xstrdup(pw->pw_shell);
+ k5users_allowed_cmds =
+ xreallocarray(k5users_allowed_cmds, ++ncommands,
+ xrealloc(k5users_allowed_cmds, ++ncommands,
+ sizeof(*k5users_allowed_cmds));
+ break;
+ }
@ -177,13 +190,12 @@ index 413b845..54dd383 100644
+ k5users_allowed_cmds[ncommands-1] =
+ xstrdup(token);
+ k5users_allowed_cmds =
+ xreallocarray(k5users_allowed_cmds, ++ncommands,
+ xrealloc(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;
@ -204,20 +216,19 @@ index 413b845..54dd383 100644
/* This writes out any forwarded credentials from the structure populated
* during userauth. Called after we have setuid to the user */
diff --git a/session.c b/session.c
index 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)";
diff -up openssh-5.8p2/session.c.force_krb openssh-5.8p2/session.c
--- openssh-5.8p2/session.c.force_krb 2011-05-19 03:41:41.000000000 +0200
+++ openssh-5.8p2/session.c 2011-05-19 03:43:32.437173662 +0200
@@ -820,6 +820,29 @@ do_exec(Session *s, const char *command)
debug("Forced command (key option) '%.900s'", command);
}
+#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]) {
@ -235,29 +246,13 @@ index 28659ec..9c94d8e 100644
+#endif
+#endif
+
s->forced = 0;
if (forced != NULL) {
s->forced = 1;
diff --git a/ssh-gss.h b/ssh-gss.h
index 0374c88..509109a 100644
--- a/ssh-gss.h
+++ b/ssh-gss.h
@@ -49,6 +49,10 @@
# endif /* !HAVE_DECL_GSS_C_NT_... */
# endif /* !HEIMDAL */
+
+/* .k5users support */
+extern char **k5users_allowed_cmds;
+
#endif /* KRB5 */
/* draft-ietf-secsh-gsskeyex-06 */
diff --git a/sshd.8 b/sshd.8
index adcaaf9..824163b 100644
--- a/sshd.8
+++ b/sshd.8
@@ -324,6 +324,7 @@ Finally, the server and the client enter an authentication dialog.
#ifdef SSH_AUDIT_EVENTS
if (s->command != NULL || s->command_handle != -1)
fatal("do_exec: command already set");
diff -up openssh-5.8p2/sshd.8.force_krb openssh-5.8p2/sshd.8
--- openssh-5.8p2/sshd.8.force_krb 2011-05-19 03:41:30.582114401 +0200
+++ openssh-5.8p2/sshd.8 2011-05-19 03:41:46.159106308 +0200
@@ -323,6 +323,7 @@ Finally, the server and the client enter
The client tries to authenticate itself using
host-based authentication,
public key authentication,
@ -265,7 +260,7 @@ index adcaaf9..824163b 100644
challenge-response authentication,
or password authentication.
.Pp
@@ -800,6 +801,12 @@ This file is used in exactly the same way as
@@ -796,6 +797,12 @@ This file is used in exactly the same wa
but allows host-based authentication without permitting login with
rlogin/rsh.
.Pp
@ -278,3 +273,17 @@ index adcaaf9..824163b 100644
.It Pa ~/.ssh/
This directory is the default location for all user-specific configuration
and authentication information.
diff -up openssh-5.8p2/ssh-gss.h.force_krb openssh-5.8p2/ssh-gss.h
--- openssh-5.8p2/ssh-gss.h.force_krb 2007-06-12 15:40:39.000000000 +0200
+++ openssh-5.8p2/ssh-gss.h 2011-05-19 03:41:46.302234118 +0200
@@ -48,6 +48,10 @@
#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
#endif /* GSS_C_NT_... */
#endif /* !HEIMDAL */
+
+/* .k5users support */
+extern char **k5users_allowed_cmds;
+
#endif /* KRB5 */
/* draft-ietf-secsh-gsskeyex-06 */

View File

@ -0,0 +1,13 @@
diff -up openssh-5.8p2/mux.c.remove_stale openssh-5.8p2/mux.c
--- openssh-5.8p2/mux.c.remove_stale 2011-01-14 02:01:32.000000000 +0100
+++ openssh-5.8p2/mux.c 2011-06-09 15:27:42.556360291 +0200
@@ -1867,6 +1867,9 @@ muxclient(const char *path)
unlink(path);
} else if (errno == ENOENT) {
debug("Control socket \"%.100s\" does not exist", path);
+ } else if (errno == ECONNREFUSED) {
+ debug("Removing stale control socket \"%.100s\"", path);
+ unlink(path);
} else {
error("Control socket connect(%.100s): %s", path,
strerror(errno));

353
openssh-5.9p1-audit2.patch Normal file
View File

@ -0,0 +1,353 @@
diff -up openssh-5.9p0/audit-bsm.c.audit2 openssh-5.9p0/audit-bsm.c
--- openssh-5.9p0/audit-bsm.c.audit2 2011-08-30 10:55:35.281025258 +0200
+++ openssh-5.9p0/audit-bsm.c 2011-08-30 10:55:37.500052231 +0200
@@ -329,6 +329,12 @@ audit_session_close(struct logininfo *li
/* not implemented */
}
+int
+audit_keyusage(int host_user, const char *type, unsigned bits, char *fp, int rv)
+{
+ /* not implemented */
+}
+
void
audit_event(ssh_audit_event_t event)
{
diff -up openssh-5.9p0/audit-linux.c.audit2 openssh-5.9p0/audit-linux.c
--- openssh-5.9p0/audit-linux.c.audit2 2011-08-30 10:55:35.385102905 +0200
+++ openssh-5.9p0/audit-linux.c 2011-08-30 10:55:38.009088040 +0200
@@ -41,6 +41,8 @@
#include "servconf.h"
#include "canohost.h"
+#define AUDIT_LOG_SIZE 128
+
extern ServerOptions options;
extern Authctxt *the_authctxt;
extern u_int utmp_len;
@@ -130,6 +132,37 @@ fatal_report:
}
}
+int
+audit_keyusage(int host_user, const char *type, unsigned bits, char *fp, int rv)
+{
+ char buf[AUDIT_LOG_SIZE];
+ int audit_fd, rc, saved_errno;
+
+ audit_fd = audit_open();
+ if (audit_fd < 0) {
+ if (errno == EINVAL || errno == EPROTONOSUPPORT ||
+ errno == EAFNOSUPPORT)
+ return 1; /* No audit support in kernel */
+ else
+ return 0; /* Must prevent login */
+ }
+ snprintf(buf, sizeof(buf), "%s_auth rport=%d", host_user ? "pubkey" : "hostbased", get_remote_port());
+ rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH, NULL,
+ buf, audit_username(), -1, NULL, get_remote_ipaddr(), NULL, rv);
+ if ((rc < 0) && ((rc != -1) || (getuid() == 0)))
+ goto out;
+ snprintf(buf, sizeof(buf), "key algo=%s size=%d fp=%s%s rport=%d",
+ type, bits, key_fingerprint_prefix(), fp, get_remote_port());
+ rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH, NULL,
+ buf, audit_username(), -1, NULL, get_remote_ipaddr(), NULL, rv);
+out:
+ saved_errno = errno;
+ audit_close(audit_fd);
+ errno = saved_errno;
+ /* do not report error if the error is EPERM and sshd is run as non root user */
+ return (rc >= 0) || ((rc == -EPERM) && (getuid() != 0));
+}
+
static int user_login_count = 0;
/* Below is the sshd audit API code */
diff -up openssh-5.9p0/audit.c.audit2 openssh-5.9p0/audit.c
--- openssh-5.9p0/audit.c.audit2 2011-08-30 10:55:35.523141273 +0200
+++ openssh-5.9p0/audit.c 2011-08-30 10:55:37.658024710 +0200
@@ -36,6 +36,7 @@
#include "key.h"
#include "hostfile.h"
#include "auth.h"
+#include "xmalloc.h"
/*
* Care must be taken when using this since it WILL NOT be initialized when
@@ -111,6 +112,22 @@ audit_event_lookup(ssh_audit_event_t ev)
return(event_lookup[i].name);
}
+void
+audit_key(int host_user, int *rv, const Key *key)
+{
+ char *fp;
+ const char *crypto_name;
+
+ fp = key_selected_fingerprint(key, SSH_FP_HEX);
+ if (key->type == KEY_RSA1)
+ crypto_name = "ssh-rsa1";
+ else
+ crypto_name = key_ssh_name(key);
+ if (audit_keyusage(host_user, crypto_name, key_size(key), fp, *rv) == 0)
+ *rv = 0;
+ xfree(fp);
+}
+
# ifndef CUSTOM_SSH_AUDIT_EVENTS
/*
* Null implementations of audit functions.
@@ -209,5 +226,17 @@ audit_end_command(int handle, const char
audit_username(), command);
}
+/*
+ * This will be called when user is successfully autherized by the RSA1/RSA/DSA key.
+ *
+ * Type is the key type, len is the key length(byte) and fp is the fingerprint of the key.
+ */
+int
+audit_keyusage(int host_user, const char *type, unsigned bits, char *fp, int rv)
+{
+ debug("audit %s key usage euid %d user %s key type %s key length %d fingerprint %s%s, result %d",
+ host_user ? "pubkey" : "hostbased", geteuid(), audit_username(), type, bits,
+ key_fingerprint_prefix(), fp, rv);
+}
# endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */
#endif /* SSH_AUDIT_EVENTS */
diff -up openssh-5.9p0/audit.h.audit2 openssh-5.9p0/audit.h
--- openssh-5.9p0/audit.h.audit2 2011-08-30 10:55:35.723122290 +0200
+++ openssh-5.9p0/audit.h 2011-08-30 10:55:37.905212176 +0200
@@ -28,6 +28,7 @@
# define _SSH_AUDIT_H
#include "loginrec.h"
+#include "key.h"
enum ssh_audit_event_type {
SSH_LOGIN_EXCEED_MAXTRIES,
@@ -55,5 +56,7 @@ void audit_session_close(struct logininf
int audit_run_command(const char *);
void audit_end_command(int, const char *);
ssh_audit_event_t audit_classify_auth(const char *);
+int audit_keyusage(int, const char *, unsigned, char *, int);
+void audit_key(int, int *, const Key *);
#endif /* _SSH_AUDIT_H */
diff -up openssh-5.9p0/auth-rsa.c.audit2 openssh-5.9p0/auth-rsa.c
--- openssh-5.9p0/auth-rsa.c.audit2 2011-08-30 10:55:33.120097071 +0200
+++ openssh-5.9p0/auth-rsa.c 2011-08-30 10:55:38.729025376 +0200
@@ -92,7 +92,10 @@ auth_rsa_verify_response(Key *key, BIGNU
{
u_char buf[32], mdbuf[16];
MD5_CTX md;
- int len;
+ int len, rv;
+#ifdef SSH_AUDIT_EVENTS
+ char *fp;
+#endif
/* don't allow short keys */
if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
@@ -113,12 +116,18 @@ auth_rsa_verify_response(Key *key, BIGNU
MD5_Final(mdbuf, &md);
/* Verify that the response is the original challenge. */
- if (timingsafe_bcmp(response, mdbuf, 16) != 0) {
- /* Wrong answer. */
- return (0);
+ rv = timingsafe_bcmp(response, mdbuf, 16) == 0;
+
+#ifdef SSH_AUDIT_EVENTS
+ fp = key_selected_fingerprint(key, SSH_FP_HEX);
+ if (audit_keyusage(1, "ssh-rsa1", RSA_size(key->rsa) * 8, fp, rv) == 0) {
+ debug("unsuccessful audit");
+ rv = 0;
}
- /* Correct answer. */
- return (1);
+ xfree(fp);
+#endif
+
+ return rv;
}
/*
diff -up openssh-5.9p0/auth.h.audit2 openssh-5.9p0/auth.h
--- openssh-5.9p0/auth.h.audit2 2011-05-29 13:39:38.000000000 +0200
+++ openssh-5.9p0/auth.h 2011-08-30 10:57:43.238087347 +0200
@@ -170,6 +170,7 @@ void abandon_challenge_response(Authctxt
char *expand_authorized_keys(const char *, struct passwd *pw);
char *authorized_principals_file(struct passwd *);
+int user_key_verify(const Key *, const u_char *, u_int, const u_char *, u_int);
FILE *auth_openkeyfile(const char *, struct passwd *, int);
FILE *auth_openprincipals(const char *, struct passwd *, int);
@@ -185,6 +186,7 @@ Key *get_hostkey_public_by_type(int);
Key *get_hostkey_private_by_type(int);
int get_hostkey_index(Key *);
int ssh1_session_key(BIGNUM *);
+int hostbased_key_verify(const Key *, const u_char *, u_int, const u_char *, u_int);
/* debug messages during authentication */
void auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2)));
diff -up openssh-5.9p0/auth2-hostbased.c.audit2 openssh-5.9p0/auth2-hostbased.c
--- openssh-5.9p0/auth2-hostbased.c.audit2 2011-08-30 10:55:32.696212587 +0200
+++ openssh-5.9p0/auth2-hostbased.c 2011-08-30 10:55:38.120068864 +0200
@@ -119,7 +119,7 @@ userauth_hostbased(Authctxt *authctxt)
/* test for allowed key and correct signature */
authenticated = 0;
if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) &&
- PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
+ PRIVSEP(hostbased_key_verify(key, sig, slen, buffer_ptr(&b),
buffer_len(&b))) == 1)
authenticated = 1;
@@ -136,6 +136,18 @@ done:
return authenticated;
}
+int
+hostbased_key_verify(const Key *key, const u_char *sig, u_int slen, const u_char *data, u_int datalen)
+{
+ int rv;
+
+ rv = key_verify(key, sig, slen, data, datalen);
+#ifdef SSH_AUDIT_EVENTS
+ audit_key(0, &rv, key);
+#endif
+ return rv;
+}
+
/* return 1 if given hostkey is allowed */
int
hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
diff -up openssh-5.9p0/auth2-pubkey.c.audit2 openssh-5.9p0/auth2-pubkey.c
--- openssh-5.9p0/auth2-pubkey.c.audit2 2011-08-30 10:55:32.803126151 +0200
+++ openssh-5.9p0/auth2-pubkey.c 2011-08-30 10:55:38.426108672 +0200
@@ -140,7 +140,7 @@ userauth_pubkey(Authctxt *authctxt)
/* test for correct signature */
authenticated = 0;
if (PRIVSEP(user_key_allowed(authctxt->pw, key)) &&
- PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
+ PRIVSEP(user_key_verify(key, sig, slen, buffer_ptr(&b),
buffer_len(&b))) == 1)
authenticated = 1;
buffer_free(&b);
@@ -177,6 +177,18 @@ done:
return authenticated;
}
+int
+user_key_verify(const Key *key, const u_char *sig, u_int slen, const u_char *data, u_int datalen)
+{
+ int rv;
+
+ rv = key_verify(key, sig, slen, data, datalen);
+#ifdef SSH_AUDIT_EVENTS
+ audit_key(1, &rv, key);
+#endif
+ return rv;
+}
+
static int
match_principals_option(const char *principal_list, struct KeyCert *cert)
{
diff -up openssh-5.9p0/monitor.c.audit2 openssh-5.9p0/monitor.c
--- openssh-5.9p0/monitor.c.audit2 2011-08-30 10:55:35.849023496 +0200
+++ openssh-5.9p0/monitor.c 2011-08-30 10:55:38.848024600 +0200
@@ -1318,9 +1318,11 @@ mm_answer_keyverify(int sock, Buffer *m)
Key *key;
u_char *signature, *data, *blob;
u_int signaturelen, datalen, bloblen;
+ int type = 0;
int verified = 0;
int valid_data = 0;
+ type = buffer_get_int(m);
blob = buffer_get_string(m, &bloblen);
signature = buffer_get_string(m, &signaturelen);
data = buffer_get_string(m, &datalen);
@@ -1328,6 +1330,8 @@ mm_answer_keyverify(int sock, Buffer *m)
if (hostbased_cuser == NULL || hostbased_chost == NULL ||
!monitor_allowed_key(blob, bloblen))
fatal("%s: bad key, not previously allowed", __func__);
+ if (type != key_blobtype)
+ fatal("%s: bad key type", __func__);
key = key_from_blob(blob, bloblen);
if (key == NULL)
@@ -1348,7 +1352,17 @@ mm_answer_keyverify(int sock, Buffer *m)
if (!valid_data)
fatal("%s: bad signature data blob", __func__);
- verified = key_verify(key, signature, signaturelen, data, datalen);
+ switch (key_blobtype) {
+ case MM_USERKEY:
+ verified = user_key_verify(key, signature, signaturelen, data, datalen);
+ break;
+ case MM_HOSTKEY:
+ verified = hostbased_key_verify(key, signature, signaturelen, data, datalen);
+ break;
+ default:
+ verified = 0;
+ break;
+ }
debug3("%s: key %p signature %s",
__func__, key, (verified == 1) ? "verified" : "unverified");
diff -up openssh-5.9p0/monitor_wrap.c.audit2 openssh-5.9p0/monitor_wrap.c
--- openssh-5.9p0/monitor_wrap.c.audit2 2011-08-30 10:55:36.431043533 +0200
+++ openssh-5.9p0/monitor_wrap.c 2011-08-30 10:55:39.074038187 +0200
@@ -431,7 +431,7 @@ mm_key_allowed(enum mm_keytype type, cha
*/
int
-mm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen)
+mm_key_verify(enum mm_keytype type, Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen)
{
Buffer m;
u_char *blob;
@@ -445,6 +445,7 @@ mm_key_verify(Key *key, u_char *sig, u_i
return (0);
buffer_init(&m);
+ buffer_put_int(&m, type);
buffer_put_string(&m, blob, len);
buffer_put_string(&m, sig, siglen);
buffer_put_string(&m, data, datalen);
@@ -462,6 +463,19 @@ mm_key_verify(Key *key, u_char *sig, u_i
return (verified);
}
+int
+mm_hostbased_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen)
+{
+ return mm_key_verify(MM_HOSTKEY, key, sig, siglen, data, datalen);
+}
+
+int
+mm_user_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen)
+{
+ return mm_key_verify(MM_USERKEY, key, sig, siglen, data, datalen);
+}
+
+
/* Export key state after authentication */
Newkeys *
mm_newkeys_from_blob(u_char *blob, int blen)
diff -up openssh-5.9p0/monitor_wrap.h.audit2 openssh-5.9p0/monitor_wrap.h
--- openssh-5.9p0/monitor_wrap.h.audit2 2011-08-30 10:55:36.550088263 +0200
+++ openssh-5.9p0/monitor_wrap.h 2011-08-30 10:55:39.282151179 +0200
@@ -49,7 +49,8 @@ int mm_key_allowed(enum mm_keytype, char
int mm_user_key_allowed(struct passwd *, Key *);
int mm_hostbased_key_allowed(struct passwd *, char *, char *, Key *);
int mm_auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *);
-int mm_key_verify(Key *, u_char *, u_int, u_char *, u_int);
+int mm_hostbased_key_verify(Key *, u_char *, u_int, u_char *, u_int);
+int mm_user_key_verify(Key *, u_char *, u_int, u_char *, u_int);
int mm_auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **);
int mm_auth_rsa_verify_response(Key *, BIGNUM *, u_char *);
BIGNUM *mm_auth_rsa_generate_challenge(Key *);

528
openssh-5.9p1-audit3.patch Normal file
View File

@ -0,0 +1,528 @@
diff -up openssh-5.9p1/Makefile.in.audit3 openssh-5.9p1/Makefile.in
--- openssh-5.9p1/Makefile.in.audit3 2011-08-05 22:15:18.000000000 +0200
+++ openssh-5.9p1/Makefile.in 2011-09-14 07:05:58.337520327 +0200
@@ -71,7 +71,7 @@ LIBSSH_OBJS=acss.o authfd.o authfile.o b
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 \
msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o jpake.o \
- schnorr.o ssh-pkcs11.o
+ schnorr.o ssh-pkcs11.o auditstub.o
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
sshconnect.o sshconnect1.o sshconnect2.o mux.o \
diff -up openssh-5.9p1/audit-bsm.c.audit3 openssh-5.9p1/audit-bsm.c
--- openssh-5.9p1/audit-bsm.c.audit3 2011-09-14 07:05:56.719459048 +0200
+++ openssh-5.9p1/audit-bsm.c 2011-09-14 07:05:58.430520147 +0200
@@ -396,4 +396,16 @@ audit_event(ssh_audit_event_t event)
debug("%s: unhandled event %d", __func__, event);
}
}
+
+void
+audit_unsupported_body(int what)
+{
+ /* not implemented */
+}
+
+void
+audit_kex_body(int ctos, char *enc, char *mac, char *compress, pid_t pid, uid_t uid)
+{
+ /* not implemented */
+}
#endif /* BSM */
diff -up openssh-5.9p1/audit-linux.c.audit3 openssh-5.9p1/audit-linux.c
--- openssh-5.9p1/audit-linux.c.audit3 2011-09-14 07:05:56.820460613 +0200
+++ openssh-5.9p1/audit-linux.c 2011-09-14 07:07:29.651459660 +0200
@@ -40,6 +40,8 @@
#include "auth.h"
#include "servconf.h"
#include "canohost.h"
+#include "packet.h"
+#include "cipher.h"
#define AUDIT_LOG_SIZE 128
@@ -269,4 +271,60 @@ audit_event(ssh_audit_event_t event)
}
}
+void
+audit_unsupported_body(int what)
+{
+#ifdef AUDIT_CRYPTO_SESSION
+ char buf[AUDIT_LOG_SIZE];
+ const static char *name[] = { "cipher", "mac", "comp" };
+ char *s;
+ int audit_fd;
+
+ snprintf(buf, sizeof(buf), "op=unsupported-%s direction=? cipher=? ksize=? rport=%d laddr=%s lport=%d ",
+ name[what], get_remote_port(), (s = get_local_ipaddr(packet_get_connection_in())),
+ get_local_port());
+ xfree(s);
+ audit_fd = audit_open();
+ if (audit_fd < 0)
+ /* no problem, the next instruction will be fatal() */
+ return;
+ audit_log_user_message(audit_fd, AUDIT_CRYPTO_SESSION,
+ buf, NULL, get_remote_ipaddr(), NULL, 0);
+ audit_close(audit_fd);
+#endif
+}
+
+void
+audit_kex_body(int ctos, char *enc, char *mac, char *compress, pid_t pid,
+ uid_t uid)
+{
+#ifdef AUDIT_CRYPTO_SESSION
+ char buf[AUDIT_LOG_SIZE];
+ int audit_fd, audit_ok;
+ const static char *direction[] = { "from-server", "from-client", "both" };
+ Cipher *cipher = cipher_by_name(enc);
+ char *s;
+
+ snprintf(buf, sizeof(buf), "op=start direction=%s cipher=%s ksize=%d spid=%jd suid=%jd rport=%d laddr=%s lport=%d ",
+ direction[ctos], enc, cipher ? 8 * cipher->key_len : 0,
+ (intmax_t)pid, (intmax_t)uid,
+ get_remote_port(), (s = get_local_ipaddr(packet_get_connection_in())), get_local_port());
+ xfree(s);
+ audit_fd = audit_open();
+ if (audit_fd < 0) {
+ if (errno == EINVAL || errno == EPROTONOSUPPORT ||
+ errno == EAFNOSUPPORT)
+ return; /* No audit support in kernel */
+ else
+ fatal("cannot open audit"); /* Must prevent login */
+ }
+ audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_SESSION,
+ buf, NULL, get_remote_ipaddr(), NULL, 1);
+ audit_close(audit_fd);
+ /* do not abort if the error is EPERM and sshd is run as non root user */
+ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0)))
+ fatal("cannot write into audit"); /* Must prevent login */
+#endif
+}
+
#endif /* USE_LINUX_AUDIT */
diff -up openssh-5.9p1/audit.c.audit3 openssh-5.9p1/audit.c
--- openssh-5.9p1/audit.c.audit3 2011-09-14 07:05:56.937585272 +0200
+++ openssh-5.9p1/audit.c 2011-09-14 07:05:58.646521393 +0200
@@ -28,6 +28,7 @@
#include <stdarg.h>
#include <string.h>
+#include <unistd.h>
#ifdef SSH_AUDIT_EVENTS
@@ -36,6 +37,8 @@
#include "key.h"
#include "hostfile.h"
#include "auth.h"
+#include "ssh-gss.h"
+#include "monitor_wrap.h"
#include "xmalloc.h"
/*
@@ -128,6 +131,18 @@ audit_key(int host_user, int *rv, const
xfree(fp);
}
+void
+audit_unsupported(int what)
+{
+ PRIVSEP(audit_unsupported_body(what));
+}
+
+void
+audit_kex(int ctos, char *enc, char *mac, char *comp)
+{
+ PRIVSEP(audit_kex_body(ctos, enc, mac, comp, getpid(), getuid()));
+}
+
# ifndef CUSTOM_SSH_AUDIT_EVENTS
/*
* Null implementations of audit functions.
@@ -238,5 +253,26 @@ audit_keyusage(int host_user, const char
host_user ? "pubkey" : "hostbased", geteuid(), audit_username(), type, bits,
key_fingerprint_prefix(), fp, rv);
}
+
+/*
+ * This will be called when the protocol negotiation fails.
+ */
+void
+audit_unsupported_body(int what)
+{
+ debug("audit unsupported protocol euid %d type %d", geteuid(), what);
+}
+
+/*
+ * This will be called on succesfull protocol negotiation.
+ */
+void
+audit_kex_body(int ctos, char *enc, char *mac, char *compress, pid_t pid,
+ uid_t uid)
+{
+ debug("audit protocol negotiation euid %d direction %d cipher %s mac %s compresion %s from pid %ld uid %u",
+ (unsigned)geteuid(), ctos, enc, mac, compress, (long)pid,
+ (unsigned)uid);
+}
# endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */
#endif /* SSH_AUDIT_EVENTS */
diff -up openssh-5.9p1/audit.h.audit3 openssh-5.9p1/audit.h
--- openssh-5.9p1/audit.h.audit3 2011-09-14 07:05:57.391522394 +0200
+++ openssh-5.9p1/audit.h 2011-09-14 07:05:58.766586362 +0200
@@ -58,5 +58,9 @@ void audit_end_command(int, const char
ssh_audit_event_t audit_classify_auth(const char *);
int audit_keyusage(int, const char *, unsigned, char *, int);
void audit_key(int, int *, const Key *);
+void audit_unsupported(int);
+void audit_kex(int, char *, char *, char *);
+void audit_unsupported_body(int);
+void audit_kex_body(int, char *, char *, char *, pid_t, uid_t);
#endif /* _SSH_AUDIT_H */
diff -up openssh-5.9p1/auditstub.c.audit3 openssh-5.9p1/auditstub.c
--- openssh-5.9p1/auditstub.c.audit3 2011-09-14 07:05:58.866461077 +0200
+++ openssh-5.9p1/auditstub.c 2011-09-14 07:05:58.870569033 +0200
@@ -0,0 +1,39 @@
+/* $Id: auditstub.c,v 1.1 jfch Exp $ */
+
+/*
+ * Copyright 2010 Red Hat, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * 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, this list of conditions and the following disclaimer.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
+ *
+ * Red Hat author: Jan F. Chadima <jchadima@redhat.com>
+ */
+
+void
+audit_unsupported(int n)
+{
+}
+
+void
+audit_kex(int ctos, char *enc, char *mac, char *comp)
+{
+}
+
diff -up openssh-5.9p1/cipher.c.audit3 openssh-5.9p1/cipher.c
--- openssh-5.9p1/cipher.c.audit3 2011-09-07 15:05:09.000000000 +0200
+++ openssh-5.9p1/cipher.c 2011-09-14 07:05:58.955582581 +0200
@@ -60,15 +60,7 @@ extern void ssh1_3des_iv(EVP_CIPHER_CTX
extern const EVP_CIPHER *evp_aes_128_ctr(void);
extern void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, u_int);
-struct Cipher {
- char *name;
- int number; /* for ssh1 only */
- u_int block_size;
- u_int key_len;
- u_int discard_len;
- u_int cbc_mode;
- const EVP_CIPHER *(*evptype)(void);
-} ciphers[] = {
+struct Cipher ciphers[] = {
{ "none", SSH_CIPHER_NONE, 8, 0, 0, 0, EVP_enc_null },
{ "des", SSH_CIPHER_DES, 8, 8, 0, 1, EVP_des_cbc },
{ "3des", SSH_CIPHER_3DES, 8, 16, 0, 1, evp_ssh1_3des },
diff -up openssh-5.9p1/cipher.h.audit3 openssh-5.9p1/cipher.h
--- openssh-5.9p1/cipher.h.audit3 2009-01-28 06:38:41.000000000 +0100
+++ openssh-5.9p1/cipher.h 2011-09-14 07:05:59.063459363 +0200
@@ -61,7 +61,16 @@
typedef struct Cipher Cipher;
typedef struct CipherContext CipherContext;
-struct Cipher;
+struct Cipher {
+ char *name;
+ int number; /* for ssh1 only */
+ u_int block_size;
+ u_int key_len;
+ u_int discard_len;
+ u_int cbc_mode;
+ const EVP_CIPHER *(*evptype)(void);
+};
+
struct CipherContext {
int plaintext;
EVP_CIPHER_CTX evp;
diff -up openssh-5.9p1/kex.c.audit3 openssh-5.9p1/kex.c
--- openssh-5.9p1/kex.c.audit3 2010-09-24 14:11:14.000000000 +0200
+++ openssh-5.9p1/kex.c 2011-09-14 07:05:59.171457800 +0200
@@ -49,6 +49,7 @@
#include "dispatch.h"
#include "monitor.h"
#include "roaming.h"
+#include "audit.h"
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
# if defined(HAVE_EVP_SHA256)
@@ -286,9 +287,13 @@ static void
choose_enc(Enc *enc, char *client, char *server)
{
char *name = match_list(client, server, NULL);
- if (name == NULL)
+ if (name == NULL) {
+#ifdef SSH_AUDIT_EVENTS
+ audit_unsupported(0);
+#endif
fatal("no matching cipher found: client %s server %s",
client, server);
+ }
if ((enc->cipher = cipher_by_name(name)) == NULL)
fatal("matching cipher is not supported: %s", name);
enc->name = name;
@@ -303,9 +308,13 @@ static void
choose_mac(Mac *mac, char *client, char *server)
{
char *name = match_list(client, server, NULL);
- if (name == NULL)
+ if (name == NULL) {
+#ifdef SSH_AUDIT_EVENTS
+ audit_unsupported(1);
+#endif
fatal("no matching mac found: client %s server %s",
client, server);
+ }
if (mac_setup(mac, name) < 0)
fatal("unsupported mac %s", name);
/* truncate the key */
@@ -320,8 +329,12 @@ static void
choose_comp(Comp *comp, char *client, char *server)
{
char *name = match_list(client, server, NULL);
- if (name == NULL)
+ if (name == NULL) {
+#ifdef SSH_AUDIT_EVENTS
+ audit_unsupported(2);
+#endif
fatal("no matching comp found: client %s server %s", client, server);
+ }
if (strcmp(name, "zlib@openssh.com") == 0) {
comp->type = COMP_DELAYED;
} else if (strcmp(name, "zlib") == 0) {
@@ -446,6 +459,9 @@ kex_choose_conf(Kex *kex)
newkeys->enc.name,
newkeys->mac.name,
newkeys->comp.name);
+#ifdef SSH_AUDIT_EVENTS
+ audit_kex(ctos, newkeys->enc.name, newkeys->mac.name, newkeys->comp.name);
+#endif
}
choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]);
choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
diff -up openssh-5.9p1/monitor.c.audit3 openssh-5.9p1/monitor.c
--- openssh-5.9p1/monitor.c.audit3 2011-09-14 07:05:57.952459820 +0200
+++ openssh-5.9p1/monitor.c 2011-09-14 07:05:59.272520466 +0200
@@ -97,6 +97,7 @@
#include "ssh2.h"
#include "jpake.h"
#include "roaming.h"
+#include "audit.h"
#ifdef GSSAPI
static Gssctxt *gsscontext = NULL;
@@ -187,6 +188,8 @@ int mm_answer_gss_checkmic(int, Buffer *
int mm_answer_audit_event(int, Buffer *);
int mm_answer_audit_command(int, Buffer *);
int mm_answer_audit_end_command(int, Buffer *);
+int mm_answer_audit_unsupported_body(int, Buffer *);
+int mm_answer_audit_kex_body(int, Buffer *);
#endif
static int monitor_read_log(struct monitor *);
@@ -237,6 +240,8 @@ struct mon_table mon_dispatch_proto20[]
#endif
#ifdef SSH_AUDIT_EVENTS
{MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
+ {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body},
+ {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body},
#endif
#ifdef BSD_AUTH
{MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery},
@@ -275,6 +280,8 @@ struct mon_table mon_dispatch_postauth20
{MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
{MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command},
{MONITOR_REQ_AUDIT_END_COMMAND, MON_PERMIT, mm_answer_audit_end_command},
+ {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body},
+ {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body},
#endif
{0, 0, NULL}
};
@@ -306,6 +313,8 @@ struct mon_table mon_dispatch_proto15[]
#endif
#ifdef SSH_AUDIT_EVENTS
{MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
+ {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body},
+ {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body},
#endif
{0, 0, NULL}
};
@@ -318,6 +327,8 @@ struct mon_table mon_dispatch_postauth15
{MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
{MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT|MON_ONCE, mm_answer_audit_command},
{MONITOR_REQ_AUDIT_END_COMMAND, MON_PERMIT, mm_answer_audit_end_command},
+ {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body},
+ {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body},
#endif
{0, 0, NULL}
};
@@ -2383,3 +2394,47 @@ mm_answer_jpake_check_confirm(int sock,
}
#endif /* JPAKE */
+
+#ifdef SSH_AUDIT_EVENTS
+int
+mm_answer_audit_unsupported_body(int sock, Buffer *m)
+{
+ int what;
+
+ what = buffer_get_int(m);
+
+ audit_unsupported_body(what);
+
+ buffer_clear(m);
+
+ mm_request_send(sock, MONITOR_ANS_AUDIT_UNSUPPORTED, m);
+ return 0;
+}
+
+int
+mm_answer_audit_kex_body(int sock, Buffer *m)
+{
+ int ctos, len;
+ char *cipher, *mac, *compress;
+ pid_t pid;
+ uid_t uid;
+
+ ctos = buffer_get_int(m);
+ cipher = buffer_get_string(m, &len);
+ mac = buffer_get_string(m, &len);
+ compress = buffer_get_string(m, &len);
+ pid = buffer_get_int64(m);
+ uid = buffer_get_int64(m);
+
+ audit_kex_body(ctos, cipher, mac, compress, pid, uid);
+
+ xfree(cipher);
+ xfree(mac);
+ xfree(compress);
+ buffer_clear(m);
+
+ mm_request_send(sock, MONITOR_ANS_AUDIT_KEX, m);
+ return 0;
+}
+
+#endif /* SSH_AUDIT_EVENTS */
diff -up openssh-5.9p1/monitor.h.audit3 openssh-5.9p1/monitor.h
--- openssh-5.9p1/monitor.h.audit3 2011-09-14 07:05:55.510580908 +0200
+++ openssh-5.9p1/monitor.h 2011-09-14 07:05:59.378647273 +0200
@@ -61,6 +61,8 @@ enum monitor_reqtype {
MONITOR_REQ_PAM_FREE_CTX, MONITOR_ANS_PAM_FREE_CTX,
MONITOR_REQ_AUDIT_EVENT, MONITOR_REQ_AUDIT_COMMAND,
MONITOR_ANS_AUDIT_COMMAND, MONITOR_REQ_AUDIT_END_COMMAND,
+ MONITOR_REQ_AUDIT_UNSUPPORTED, MONITOR_ANS_AUDIT_UNSUPPORTED,
+ MONITOR_REQ_AUDIT_KEX, MONITOR_ANS_AUDIT_KEX,
MONITOR_REQ_TERM,
MONITOR_REQ_JPAKE_STEP1, MONITOR_ANS_JPAKE_STEP1,
MONITOR_REQ_JPAKE_GET_PWDATA, MONITOR_ANS_JPAKE_GET_PWDATA,
diff -up openssh-5.9p1/monitor_wrap.c.audit3 openssh-5.9p1/monitor_wrap.c
--- openssh-5.9p1/monitor_wrap.c.audit3 2011-09-14 07:05:58.059501118 +0200
+++ openssh-5.9p1/monitor_wrap.c 2011-09-14 07:05:59.511503364 +0200
@@ -1505,3 +1505,41 @@ mm_jpake_check_confirm(const BIGNUM *k,
return success;
}
#endif /* JPAKE */
+
+#ifdef SSH_AUDIT_EVENTS
+void
+mm_audit_unsupported_body(int what)
+{
+ Buffer m;
+
+ buffer_init(&m);
+ buffer_put_int(&m, what);
+
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_UNSUPPORTED, &m);
+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_UNSUPPORTED,
+ &m);
+
+ buffer_free(&m);
+}
+
+void
+mm_audit_kex_body(int ctos, char *cipher, char *mac, char *compress, pid_t pid,
+ uid_t uid)
+{
+ Buffer m;
+
+ buffer_init(&m);
+ buffer_put_int(&m, ctos);
+ buffer_put_cstring(&m, cipher);
+ buffer_put_cstring(&m, mac);
+ buffer_put_cstring(&m, compress);
+ buffer_put_int64(&m, pid);
+ buffer_put_int64(&m, uid);
+
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_KEX, &m);
+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_KEX,
+ &m);
+
+ buffer_free(&m);
+}
+#endif /* SSH_AUDIT_EVENTS */
diff -up openssh-5.9p1/monitor_wrap.h.audit3 openssh-5.9p1/monitor_wrap.h
--- openssh-5.9p1/monitor_wrap.h.audit3 2011-09-14 07:05:58.171521245 +0200
+++ openssh-5.9p1/monitor_wrap.h 2011-09-14 07:05:59.624646515 +0200
@@ -78,6 +78,8 @@ void mm_sshpam_free_ctx(void *);
void mm_audit_event(ssh_audit_event_t);
int mm_audit_run_command(const char *);
void mm_audit_end_command(int, const char *);
+void mm_audit_unsupported_body(int);
+void mm_audit_kex_body(int, char *, char *, char *, pid_t, uid_t);
#endif
struct Session;
diff -up openssh-5.9p1/sshd.c.audit3 openssh-5.9p1/sshd.c
--- openssh-5.9p1/sshd.c.audit3 2011-09-14 07:05:56.554583874 +0200
+++ openssh-5.9p1/sshd.c 2011-09-14 07:05:59.828466112 +0200
@@ -118,6 +118,7 @@
#endif
#include "monitor_wrap.h"
#include "roaming.h"
+#include "audit.h"
#include "ssh-sandbox.h"
#include "version.h"
@@ -2209,6 +2210,10 @@ do_ssh1_kex(void)
if (cookie[i] != packet_get_char())
packet_disconnect("IP Spoofing check bytes do not match.");
+#ifdef SSH_AUDIT_EVENTS
+ audit_kex(2, cipher_name(cipher_type), "crc", "none");
+#endif
+
debug("Encryption type: %.200s", cipher_name(cipher_type));
/* Get the encrypted integer. */

View File

@ -0,0 +1,12 @@
diff -up openssh-5.9p1/contrib/ssh-copy-id.restorecon openssh-5.9p1/contrib/ssh-copy-id
--- openssh-5.9p1/contrib/ssh-copy-id.restorecon 2011-08-17 04:05:49.000000000 +0200
+++ openssh-5.9p1/contrib/ssh-copy-id 2011-11-21 08:40:56.000000000 +0100
@@ -41,7 +41,7 @@ fi
# strip any trailing colon
host=`echo $1 | sed 's/:$//'`
-{ eval "$GET_ID" ; } | ssh $host "umask 077; test -d ~/.ssh || mkdir ~/.ssh ; cat >> ~/.ssh/authorized_keys" || exit 1
+{ eval "$GET_ID" ; } | ssh $host "umask 077; test -d ~/.ssh || mkdir ~/.ssh ; cat >> ~/.ssh/authorized_keys && (test -x /sbin/restorecon && /sbin/restorecon ~/.ssh ~/.ssh/authorized_keys >/dev/null 2>&1 || true)" || exit 1
cat <<EOF
Now try logging into the machine, with "ssh '$host'", and check in:

View File

@ -1,45 +1,7 @@
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
SFTP_SERVER=$(libexecdir)/sftp-server
SSH_KEYSIGN=$(libexecdir)/ssh-keysign
SSH_KEYCAT=$(libexecdir)/ssh-keycat
+CTR_CAVSTEST=$(libexecdir)/ctr-cavstest
SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
SSH_SK_HELPER=$(libexecdir)/ssh-sk-helper
PRIVSEP_PATH=@PRIVSEP_PATH@
@@ -66,7 +67,7 @@ EXEEXT=@EXEEXT@
.SUFFIXES: .lo
-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT) 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-sk-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 $(KEYCATLIBS) $(LIBS)
+ctr-cavstest$(EXEEXT): $(LIBCOMPAT) libssh.a ctr-cavstest.o
+ $(LD) -o $@ ctr-cavstest.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
+
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYSCAN_OBJS)
$(LD) -o $@ $(SSHKEYSCAN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
@@ -326,6 +330,7 @@ install-files:
$(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) ssh-sk-helper$(EXEEXT) $(DESTDIR)$(SSH_SK_HELPER)$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) ssh-keycat$(EXEEXT) $(DESTDIR)$(libexecdir)/ssh-keycat$(EXEEXT)
+ $(INSTALL) -m 0755 $(STRIP_OPT) 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 @@
diff -up openssh-5.9p1/ctr-cavstest.c.ctr-cavs openssh-5.9p1/ctr-cavstest.c
--- openssh-5.9p1/ctr-cavstest.c.ctr-cavs 2012-01-13 15:59:06.584283289 +0100
+++ openssh-5.9p1/ctr-cavstest.c 2012-01-13 18:21:33.791941027 +0100
@@ -0,0 +1,208 @@
+/*
+ *
+ * invocation (all of the following are equal):
@ -60,7 +22,6 @@ diff -up openssh-6.8p1/ctr-cavstest.c.ctr-cavs openssh-6.8p1/ctr-cavstest.c
+
+#include "xmalloc.h"
+#include "log.h"
+#include "ssherr.h"
+#include "cipher.h"
+
+/* compatibility with old or broken OpenSSL versions */
@ -134,7 +95,7 @@ diff -up openssh-6.8p1/ctr-cavstest.c.ctr-cavs openssh-6.8p1/ctr-cavstest.c
+ break;
+
+ total += n;
+ buf = xreallocarray(buf, total + READ_CHUNK, 1);
+ buf = xrealloc(buf, total + READ_CHUNK, 1);
+ } while(total < MAX_READ_SIZE);
+ return buf;
+}
@ -142,14 +103,14 @@ diff -up openssh-6.8p1/ctr-cavstest.c.ctr-cavs openssh-6.8p1/ctr-cavstest.c
+int main (int argc, char *argv[])
+{
+
+ const struct sshcipher *c;
+ struct sshcipher_ctx *cc;
+ Cipher *c;
+ CipherContext cc;
+ char *algo = "aes128-ctr";
+ char *hexkey = NULL;
+ char *hexiv = "00000000000000000000000000000000";
+ char *hexdata = NULL;
+ char *p;
+ int i, r;
+ int i;
+ int encrypt = 1;
+ void *key;
+ size_t keylen;
@ -187,7 +148,7 @@ diff -up openssh-6.8p1/ctr-cavstest.c.ctr-cavs openssh-6.8p1/ctr-cavstest.c
+ usage();
+ }
+
+ OpenSSL_add_all_algorithms();
+ SSLeay_add_all_algorithms();
+
+ c = cipher_by_name(algo);
+ if (c == NULL) {
@ -222,13 +183,10 @@ diff -up openssh-6.8p1/ctr-cavstest.c.ctr-cavs openssh-6.8p1/ctr-cavstest.c
+ 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;
+ }
+ cipher_init(&cc, c, key, keylen, iv, ivlen, encrypt);
+
+ free(key);
+ free(iv);
+ xfree(key);
+ xfree(iv);
+
+ outdata = malloc(datalen);
+ if(outdata == NULL) {
@ -236,22 +194,57 @@ diff -up openssh-6.8p1/ctr-cavstest.c.ctr-cavs openssh-6.8p1/ctr-cavstest.c
+ 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;
+ }
+ cipher_crypt(&cc, outdata, data, datalen);
+
+ free(data);
+ xfree(data);
+
+ cipher_free(cc);
+ cipher_cleanup(&cc);
+
+ for (p = outdata; datalen > 0; ++p, --datalen) {
+ printf("%02X", (unsigned char)*p);
+ }
+
+ free(outdata);
+ xfree(outdata);
+
+ printf("\n");
+ return 0;
+}
+
diff -up openssh-5.9p1/Makefile.in.ctr-cavs openssh-5.9p1/Makefile.in
--- openssh-5.9p1/Makefile.in.ctr-cavs 2012-01-13 15:59:06.539282357 +0100
+++ openssh-5.9p1/Makefile.in 2012-01-13 15:59:06.588283373 +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@
@@ -63,7 +64,7 @@ EXEEXT=@EXEEXT@
MANFMT=@MANFMT@
INSTALL_SSH_LDAP_HELPER=@INSTALL_SSH_LDAP_HELPER@
-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT) ssh-keycat$(EXEEXT)
+TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT) ssh-keycat$(EXEEXT) ctr-cavstest$(EXEEXT)
LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \
canohost.o channels.o cipher.o cipher-acss.o cipher-aes.o \
@@ -171,6 +172,9 @@ ssh-ldap-helper$(EXEEXT): $(LIBCOMPAT) l
ssh-keycat$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keycat.o
$(LD) -o $@ ssh-keycat.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(SSHDLIBS)
+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 roaming_dummy.o
$(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS)
@@ -271,6 +275,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

View File

@ -97,5 +97,5 @@ diff -up openssh-5.9p1/cipher-ctr.c.ctr-evp openssh-5.9p1/cipher-ctr.c
if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
+ EVP_CIPHER_CTX_cleanup(&c->ecbctx);
memset(c, 0, sizeof(*c));
free(c);
xfree(c);
EVP_CIPHER_CTX_set_app_data(ctx, NULL);

72
openssh-5.9p1-edns.patch Normal file
View File

@ -0,0 +1,72 @@
diff -up openssh-5.9p1/dns.c.edns openssh-5.9p1/dns.c
--- openssh-5.9p1/dns.c.edns 2010-08-31 14:41:14.000000000 +0200
+++ openssh-5.9p1/dns.c 2011-09-09 08:05:27.782440497 +0200
@@ -177,6 +177,7 @@ verify_host_key_dns(const char *hostname
{
u_int counter;
int result;
+ unsigned int rrset_flags = 0;
struct rrsetinfo *fingerprints = NULL;
u_int8_t hostkey_algorithm;
@@ -200,8 +201,19 @@ verify_host_key_dns(const char *hostname
return -1;
}
+ /*
+ * Original getrrsetbyname function, found on OpenBSD for example,
+ * doesn't accept any flag and prerequisite for obtaining AD bit in
+ * DNS response is set by "options edns0" in resolv.conf.
+ *
+ * Our version is more clever and use RRSET_FORCE_EDNS0 flag.
+ */
+#ifndef HAVE_GETRRSETBYNAME
+ rrset_flags |= RRSET_FORCE_EDNS0;
+#endif
result = getrrsetbyname(hostname, DNS_RDATACLASS_IN,
- DNS_RDATATYPE_SSHFP, 0, &fingerprints);
+ DNS_RDATATYPE_SSHFP, rrset_flags, &fingerprints);
+
if (result) {
verbose("DNS lookup error: %s", dns_result_totext(result));
return -1;
diff -up openssh-5.9p1/openbsd-compat/getrrsetbyname.c.edns openssh-5.9p1/openbsd-compat/getrrsetbyname.c
--- openssh-5.9p1/openbsd-compat/getrrsetbyname.c.edns 2009-07-13 03:38:23.000000000 +0200
+++ openssh-5.9p1/openbsd-compat/getrrsetbyname.c 2011-09-09 15:03:39.930500801 +0200
@@ -209,8 +209,8 @@ getrrsetbyname(const char *hostname, uns
goto fail;
}
- /* don't allow flags yet, unimplemented */
- if (flags) {
+ /* Allow RRSET_FORCE_EDNS0 flag only. */
+ if ((flags & ~RRSET_FORCE_EDNS0) != 0) {
result = ERRSET_INVAL;
goto fail;
}
@@ -226,9 +226,9 @@ getrrsetbyname(const char *hostname, uns
#endif /* DEBUG */
#ifdef RES_USE_DNSSEC
- /* turn on DNSSEC if EDNS0 is configured */
- if (_resp->options & RES_USE_EDNS0)
- _resp->options |= RES_USE_DNSSEC;
+ /* turn on DNSSEC if required */
+ if (flags & RRSET_FORCE_EDNS0)
+ _resp->options |= (RES_USE_EDNS0|RES_USE_DNSSEC);
#endif /* RES_USE_DNSEC */
/* make query */
diff -up openssh-5.9p1/openbsd-compat/getrrsetbyname.h.edns openssh-5.9p1/openbsd-compat/getrrsetbyname.h
--- openssh-5.9p1/openbsd-compat/getrrsetbyname.h.edns 2007-10-26 08:26:50.000000000 +0200
+++ openssh-5.9p1/openbsd-compat/getrrsetbyname.h 2011-09-09 08:05:27.965438689 +0200
@@ -72,6 +72,9 @@
#ifndef RRSET_VALIDATED
# define RRSET_VALIDATED 1
#endif
+#ifndef RRSET_FORCE_EDNS0
+# define RRSET_FORCE_EDNS0 0x0001
+#endif
/*
* Return codes for getrrsetbyname()

532
openssh-5.9p1-fips.patch Normal file
View File

@ -0,0 +1,532 @@
diff -up openssh-5.9p1/authfile.c.fips openssh-5.9p1/authfile.c
--- openssh-5.9p1/authfile.c.fips 2012-07-17 20:57:35.078155160 +0200
+++ openssh-5.9p1/authfile.c 2012-07-17 20:57:35.086155338 +0200
@@ -148,8 +148,14 @@ key_private_rsa1_to_blob(Key *key, Buffe
/* Allocate space for the private part of the key in the buffer. */
cp = buffer_append_space(&encrypted, buffer_len(&buffer));
- cipher_set_key_string(&ciphercontext, cipher, passphrase,
- CIPHER_ENCRYPT);
+ if (cipher_set_key_string(&ciphercontext, cipher, passphrase,
+ CIPHER_ENCRYPT) < 0) {
+ error("cipher_set_key_string failed.");
+ buffer_free(&encrypted);
+ buffer_free(&buffer);
+ return 0;
+ }
+
cipher_crypt(&ciphercontext, cp,
buffer_ptr(&buffer), buffer_len(&buffer));
cipher_cleanup(&ciphercontext);
@@ -472,8 +478,13 @@ key_parse_private_rsa1(Buffer *blob, con
cp = buffer_append_space(&decrypted, buffer_len(&copy));
/* Rest of the buffer is encrypted. Decrypt it using the passphrase. */
- cipher_set_key_string(&ciphercontext, cipher, passphrase,
- CIPHER_DECRYPT);
+ if (cipher_set_key_string(&ciphercontext, cipher, passphrase,
+ CIPHER_DECRYPT) < 0) {
+ error("cipher_set_key_string failed.");
+ buffer_free(&decrypted);
+ goto fail;
+ }
+
cipher_crypt(&ciphercontext, cp,
buffer_ptr(&copy), buffer_len(&copy));
cipher_cleanup(&ciphercontext);
diff -up openssh-5.9p1/cipher.c.fips openssh-5.9p1/cipher.c
--- openssh-5.9p1/cipher.c.fips 2012-07-17 20:57:34.988153164 +0200
+++ openssh-5.9p1/cipher.c 2012-07-17 20:57:35.086155338 +0200
@@ -40,6 +40,7 @@
#include <sys/types.h>
#include <openssl/md5.h>
+#include <openssl/fips.h>
#include <string.h>
#include <stdarg.h>
@@ -86,6 +87,22 @@ struct Cipher ciphers[] = {
{ NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, NULL }
};
+struct Cipher fips_ciphers[] = {
+ { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, EVP_enc_null },
+ { "3des", SSH_CIPHER_3DES, 8, 16, 0, 1, evp_ssh1_3des },
+
+ { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 1, EVP_des_ede3_cbc },
+ { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, 1, EVP_aes_128_cbc },
+ { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, 1, EVP_aes_192_cbc },
+ { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, 1, EVP_aes_256_cbc },
+ { "rijndael-cbc@lysator.liu.se",
+ SSH_CIPHER_SSH2, 16, 32, 0, 1, EVP_aes_256_cbc },
+ { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, evp_aes_128_ctr },
+ { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, evp_aes_128_ctr },
+ { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, evp_aes_128_ctr },
+ { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, NULL }
+};
+
/*--*/
u_int
@@ -128,7 +145,7 @@ Cipher *
cipher_by_name(const char *name)
{
Cipher *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;
@@ -138,7 +155,7 @@ Cipher *
cipher_by_number(int id)
{
Cipher *c;
- for (c = ciphers; c->name != NULL; c++)
+ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++)
if (c->number == id)
return c;
return NULL;
@@ -182,7 +199,7 @@ cipher_number(const char *name)
Cipher *c;
if (name == NULL)
return -1;
- for (c = ciphers; c->name != NULL; c++)
+ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++)
if (strcasecmp(c->name, name) == 0)
return c->number;
return -1;
@@ -289,14 +306,15 @@ cipher_cleanup(CipherContext *cc)
* passphrase and using the resulting 16 bytes as the key.
*/
-void
+int
cipher_set_key_string(CipherContext *cc, Cipher *cipher,
const char *passphrase, int do_encrypt)
{
MD5_CTX md;
u_char digest[16];
- MD5_Init(&md);
+ if (MD5_Init(&md) <= 0)
+ return -1;
MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase));
MD5_Final(digest, &md);
@@ -304,6 +322,7 @@ cipher_set_key_string(CipherContext *cc,
memset(digest, 0, sizeof(digest));
memset(&md, 0, sizeof(md));
+ return 0;
}
/*
diff -up openssh-5.9p1/cipher-ctr.c.fips openssh-5.9p1/cipher-ctr.c
--- openssh-5.9p1/cipher-ctr.c.fips 2010-10-07 13:06:42.000000000 +0200
+++ openssh-5.9p1/cipher-ctr.c 2012-07-17 20:57:35.086155338 +0200
@@ -140,7 +140,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-5.9p1/cipher.h.fips openssh-5.9p1/cipher.h
--- openssh-5.9p1/cipher.h.fips 2012-07-17 20:57:34.989153186 +0200
+++ openssh-5.9p1/cipher.h 2012-07-17 20:57:35.087155360 +0200
@@ -87,7 +87,7 @@ void cipher_init(CipherContext *, Ciphe
const u_char *, u_int, int);
void cipher_crypt(CipherContext *, u_char *, const u_char *, u_int);
void cipher_cleanup(CipherContext *);
-void cipher_set_key_string(CipherContext *, Cipher *, const char *, int);
+int cipher_set_key_string(CipherContext *, Cipher *, const char *, int);
u_int cipher_blocksize(const Cipher *);
u_int cipher_keylen(const Cipher *);
u_int cipher_is_cbc(const Cipher *);
diff -up openssh-5.9p1/key.c.fips openssh-5.9p1/key.c
--- openssh-5.9p1/key.c.fips 2012-07-17 20:57:35.007153585 +0200
+++ openssh-5.9p1/key.c 2012-07-17 20:57:35.087155360 +0200
@@ -40,6 +40,7 @@
#include <sys/types.h>
#include <openssl/evp.h>
+#include <openssl/fips.h>
#include <openbsd-compat/openssl-compat.h>
#include <stdarg.h>
@@ -602,9 +603,13 @@ key_fingerprint_selection(void)
char *env;
if (!rv_defined) {
- env = getenv("SSH_FINGERPRINT_TYPE");
- rv = (env && !strcmp (env, "sha")) ?
- SSH_FP_SHA1 : SSH_FP_MD5;
+ if (FIPS_mode())
+ rv = SSH_FP_SHA1;
+ else {
+ env = getenv("SSH_FINGERPRINT_TYPE");
+ rv = (env && !strcmp (env, "sha")) ?
+ SSH_FP_SHA1 : SSH_FP_MD5;
+ }
rv_defined = 1;
}
return rv;
diff -up openssh-5.9p1/mac.c.fips openssh-5.9p1/mac.c
--- openssh-5.9p1/mac.c.fips 2012-07-17 20:57:34.996153341 +0200
+++ openssh-5.9p1/mac.c 2012-07-17 20:58:35.584497499 +0200
@@ -28,6 +28,7 @@
#include <sys/types.h>
#include <openssl/hmac.h>
+#include <openssl/fips.h>
#include <stdarg.h>
#include <string.h>
@@ -47,14 +48,14 @@
#define SSH_EVP 1 /* OpenSSL EVP-based MAC */
#define SSH_UMAC 2 /* UMAC (not integrated with OpenSSL) */
-struct {
+struct Macs {
char *name;
int type;
const EVP_MD * (*mdfunc)(void);
int truncatebits; /* truncate digest if != 0 */
int key_len; /* just for UMAC */
int len; /* just for UMAC */
-} macs[] = {
+} all_macs[] = {
{ "hmac-sha1", SSH_EVP, EVP_sha1, 0, -1, -1 },
{ "hmac-sha1-96", SSH_EVP, EVP_sha1, 96, -1, -1 },
#ifdef HAVE_EVP_SHA256
@@ -71,9 +72,19 @@ struct {
{ NULL, 0, NULL, 0, -1, -1 }
};
+struct Macs fips_macs[] = {
+ { "hmac-sha1", SSH_EVP, EVP_sha1, 0, -1, -1 },
+#ifdef HAVE_EVP_SHA256
+ { "hmac-sha2-256", SSH_EVP, EVP_sha256, 0, -1, -1 },
+ { "hmac-sha2-512", SSH_EVP, EVP_sha512, 0, -1, -1 },
+#endif
+ { NULL, 0, NULL, 0, -1, -1 }
+};
+
static void
mac_setup_by_id(Mac *mac, int which)
{
+ struct Macs *macs = FIPS_mode() ? fips_macs : all_macs;
int evp_len;
mac->type = macs[which].type;
if (mac->type == SSH_EVP) {
@@ -94,6 +105,7 @@ int
mac_setup(Mac *mac, char *name)
{
int i;
+ struct Macs *macs = FIPS_mode() ? fips_macs : all_macs;
for (i = 0; macs[i].name; i++) {
if (strcmp(name, macs[i].name) == 0) {
diff -up openssh-5.9p1/Makefile.in.fips openssh-5.9p1/Makefile.in
--- openssh-5.9p1/Makefile.in.fips 2012-07-17 20:57:35.069154962 +0200
+++ openssh-5.9p1/Makefile.in 2012-07-17 20:57:35.086155338 +0200
@@ -142,25 +142,25 @@ libssh.a: $(LIBSSH_OBJS)
$(RANLIB) $@
ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS)
- $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHLIBS) $(LIBS)
+ $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(SSHLIBS) $(LIBS)
sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS)
- $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS)
+ $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(SSHDLIBS) $(LIBS)
scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o
$(LD) -o $@ scp.o progressmeter.o bufaux.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 roaming_dummy.o readconf.o
- $(LD) -o $@ ssh-keysign.o readconf.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+ $(LD) -o $@ ssh-keysign.o readconf.o roaming_dummy.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)
@@ -172,7 +172,7 @@ ssh-keycat$(EXEEXT): $(LIBCOMPAT) libssh
$(LD) -o $@ ssh-keycat.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(SSHDLIBS)
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o roaming_dummy.o
- $(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
+ $(LD) -o $@ ssh-keyscan.o roaming_dummy.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-5.9p1/myproposal.h.fips openssh-5.9p1/myproposal.h
--- openssh-5.9p1/myproposal.h.fips 2011-08-17 02:29:03.000000000 +0200
+++ openssh-5.9p1/myproposal.h 2012-07-17 21:01:12.685982807 +0200
@@ -97,6 +97,19 @@
#define KEX_DEFAULT_COMP "none,zlib@openssh.com,zlib"
#define KEX_DEFAULT_LANG ""
+#define KEX_FIPS_ENCRYPT \
+ "aes128-ctr,aes192-ctr,aes256-ctr," \
+ "aes128-cbc,3des-cbc," \
+ "aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se"
+#ifdef HAVE_EVP_SHA256
+#define KEX_FIPS_MAC \
+ "hmac-sha1," \
+ "hmac-sha2-256," \
+ "hmac-sha2-512"
+#else
+#define KEX_FIPS_MAC \
+ "hmac-sha1"
+#endif
static char *myproposal[PROPOSAL_MAX] = {
KEX_DEFAULT_KEX,
diff -up openssh-5.9p1/openbsd-compat/bsd-arc4random.c.fips openssh-5.9p1/openbsd-compat/bsd-arc4random.c
--- openssh-5.9p1/openbsd-compat/bsd-arc4random.c.fips 2010-03-25 22:52:02.000000000 +0100
+++ openssh-5.9p1/openbsd-compat/bsd-arc4random.c 2012-07-17 20:57:35.087155360 +0200
@@ -37,25 +37,18 @@
#define REKEY_BYTES (1 << 24)
static int rc4_ready = 0;
-static RC4_KEY rc4;
unsigned int
arc4random(void)
{
unsigned int r = 0;
- static int first_time = 1;
+ void *rp = &r;
- if (rc4_ready <= 0) {
- if (first_time)
- seed_rng();
- first_time = 0;
+ if (!rc4_ready) {
arc4random_stir();
}
+ RAND_bytes(rp, sizeof(r));
- RC4(&rc4, sizeof(r), (unsigned char *)&r, (unsigned char *)&r);
-
- rc4_ready -= sizeof(r);
-
return(r);
}
@@ -63,24 +56,11 @@ void
arc4random_stir(void)
{
unsigned char rand_buf[SEED_SIZE];
- int i;
- memset(&rc4, 0, sizeof(rc4));
if (RAND_bytes(rand_buf, sizeof(rand_buf)) <= 0)
fatal("Couldn't obtain random bytes (error %ld)",
ERR_get_error());
- RC4_set_key(&rc4, sizeof(rand_buf), rand_buf);
-
- /*
- * Discard early keystream, as per recommendations in:
- * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
- */
- for(i = 0; i <= 256; i += sizeof(rand_buf))
- RC4(&rc4, sizeof(rand_buf), rand_buf, rand_buf);
-
- memset(rand_buf, 0, sizeof(rand_buf));
-
- rc4_ready = REKEY_BYTES;
+ rc4_ready = 1;
}
#endif /* !HAVE_ARC4RANDOM */
diff -up openssh-5.9p1/ssh.c.fips openssh-5.9p1/ssh.c
--- openssh-5.9p1/ssh.c.fips 2011-08-05 22:18:16.000000000 +0200
+++ openssh-5.9p1/ssh.c 2012-07-17 20:57:35.088155382 +0200
@@ -73,6 +73,8 @@
#include <openssl/evp.h>
#include <openssl/err.h>
+#include <openssl/fips.h>
+#include <fipscheck.h>
#include "openbsd-compat/openssl-compat.h"
#include "openbsd-compat/sys-queue.h"
@@ -253,6 +255,10 @@ main(int ac, char **av)
sanitise_stdfd();
__progname = ssh_get_progname(av[0]);
+ SSLeay_add_all_algorithms();
+ if (FIPS_mode() && !FIPSCHECK_verify(NULL, NULL)) {
+ fatal("FIPS integrity verification test failed.");
+ }
#ifndef HAVE_SETPROCTITLE
/* Prepare for later setproctitle emulation */
@@ -329,6 +335,9 @@ main(int ac, char **av)
"ACD:F:I:KL:MNO:PR:S:TVw:W:XYy")) != -1) {
switch (opt) {
case '1':
+ if (FIPS_mode()) {
+ fatal("Protocol 1 not allowed in the FIPS mode.");
+ }
options.protocol = SSH_PROTO_1;
break;
case '2':
@@ -630,7 +639,6 @@ main(int ac, char **av)
if (!host)
usage();
- OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
/* Initialize the command to execute on remote host. */
@@ -721,6 +729,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);
@@ -789,6 +801,12 @@ main(int ac, char **av)
timeout_ms = options.connection_timeout * 1000;
+ if (FIPS_mode()) {
+ options.protocol &= SSH_PROTO_2;
+ if (options.protocol == 0)
+ fatal("Protocol 2 disabled by configuration but required in the FIPS mode.");
+ }
+
/* Open a connection to the remote host. */
if (ssh_connect(host, &hostaddr, options.port,
options.address_family, options.connection_attempts, &timeout_ms,
diff -up openssh-5.9p1/sshconnect2.c.fips openssh-5.9p1/sshconnect2.c
--- openssh-5.9p1/sshconnect2.c.fips 2012-07-17 20:57:34.955152432 +0200
+++ openssh-5.9p1/sshconnect2.c 2012-07-17 20:57:35.088155382 +0200
@@ -44,6 +44,8 @@
#include <vis.h>
#endif
+#include <openssl/fips.h>
+
#include "openbsd-compat/sys-queue.h"
#include "xmalloc.h"
@@ -170,6 +172,10 @@ ssh_kex2(char *host, struct sockaddr *ho
if (options.ciphers != NULL) {
myproposal[PROPOSAL_ENC_ALGS_CTOS] =
myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
+ } else if (FIPS_mode()) {
+ myproposal[PROPOSAL_ENC_ALGS_CTOS] =
+ myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_FIPS_ENCRYPT;
+
}
myproposal[PROPOSAL_ENC_ALGS_CTOS] =
compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]);
@@ -185,7 +191,11 @@ ssh_kex2(char *host, struct sockaddr *ho
if (options.macs != NULL) {
myproposal[PROPOSAL_MAC_ALGS_CTOS] =
myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
+ } else if (FIPS_mode()) {
+ myproposal[PROPOSAL_MAC_ALGS_CTOS] =
+ myproposal[PROPOSAL_MAC_ALGS_STOC] = KEX_FIPS_MAC;
}
+
if (options.hostkeyalgorithms != NULL)
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
options.hostkeyalgorithms;
diff -up openssh-5.9p1/sshd.c.fips openssh-5.9p1/sshd.c
--- openssh-5.9p1/sshd.c.fips 2012-07-17 20:57:35.049154517 +0200
+++ openssh-5.9p1/sshd.c 2012-07-17 20:57:35.089155405 +0200
@@ -76,6 +76,8 @@
#include <openssl/bn.h>
#include <openssl/md5.h>
#include <openssl/rand.h>
+#include <openssl/fips.h>
+#include <fipscheck.h>
#include "openbsd-compat/openssl-compat.h"
#ifdef HAVE_SECUREWARE
@@ -1395,6 +1397,11 @@ main(int ac, char **av)
#endif
__progname = ssh_get_progname(av[0]);
+ SSLeay_add_all_algorithms();
+ if (FIPS_mode() && !FIPSCHECK_verify(NULL, NULL)) {
+ fatal("FIPS integrity verification test failed.");
+ }
+
/* Save argv. Duplicate so setproctitle emulation doesn't clobber it */
saved_argc = ac;
rexec_argc = ac;
@@ -1554,8 +1561,6 @@ main(int ac, char **av)
else
closefrom(REEXEC_DEVCRYPTO_RESERVED_FD);
- OpenSSL_add_all_algorithms();
-
/*
* Force logging to stderr until we have loaded the private host
* key (unless started from inetd)
@@ -1673,6 +1678,10 @@ main(int ac, char **av)
debug("private host key: #%d type %d %s", i, key->type,
key_type(key));
}
+ if ((options.protocol & SSH_PROTO_1) && FIPS_mode()) {
+ logit("Disabling protocol version 1. Not allowed in the FIPS mode.");
+ options.protocol &= ~SSH_PROTO_1;
+ }
if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) {
logit("Disabling protocol version 1. Could not load host key");
options.protocol &= ~SSH_PROTO_1;
@@ -1837,6 +1846,10 @@ main(int ac, char **av)
/* Initialize the random number generator. */
arc4random_stir();
+ if (FIPS_mode()) {
+ logit("FIPS mode initialized");
+ }
+
/* Chdir to the root directory so that the current disk can be
unmounted if desired. */
(void) chdir("/");
@@ -2379,6 +2392,9 @@ do_ssh2_kex(void)
if (options.ciphers != NULL) {
myproposal[PROPOSAL_ENC_ALGS_CTOS] =
myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
+ } else if (FIPS_mode()) {
+ myproposal[PROPOSAL_ENC_ALGS_CTOS] =
+ myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_FIPS_ENCRYPT;
}
myproposal[PROPOSAL_ENC_ALGS_CTOS] =
compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]);
@@ -2388,6 +2404,9 @@ do_ssh2_kex(void)
if (options.macs != NULL) {
myproposal[PROPOSAL_MAC_ALGS_CTOS] =
myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
+ } else if (FIPS_mode()) {
+ myproposal[PROPOSAL_MAC_ALGS_CTOS] =
+ myproposal[PROPOSAL_MAC_ALGS_STOC] = KEX_FIPS_MAC;
}
if (options.compression == COMP_NONE) {
myproposal[PROPOSAL_COMP_ALGS_CTOS] =

View File

@ -1,24 +1,24 @@
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
diff -up openssh-6.1p1/auth2-pubkey.c.keycat openssh-6.1p1/auth2-pubkey.c
--- openssh-6.1p1/auth2-pubkey.c.keycat 2013-02-14 17:39:21.000000000 +0100
+++ openssh-6.1p1/auth2-pubkey.c 2013-02-14 17:40:42.600050510 +0100
@@ -571,6 +571,14 @@ user_key_command_allowed2(struct passwd
_exit(1);
}
+#ifdef WITH_SELINUX
+ if (sshd_selinux_setup_env_variables() < 0) {
+ if (ssh_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
execl(options.authorized_keys_command,
options.authorized_keys_command, user_pw->pw_name, NULL);
diff -up openssh-6.1p1/HOWTO.ssh-keycat.keycat openssh-6.1p1/HOWTO.ssh-keycat
--- openssh-6.1p1/HOWTO.ssh-keycat.keycat 2013-02-14 17:39:21.148382013 +0100
+++ openssh-6.1p1/HOWTO.ssh-keycat 2013-02-14 17:39:21.148382013 +0100
@@ -0,0 +1,12 @@
+The ssh-keycat retrieves the content of the ~/.ssh/authorized_keys
+of an user in any environment. This includes environments with
@ -32,106 +32,63 @@ diff -up openssh/HOWTO.ssh-keycat.keycat openssh/HOWTO.ssh-keycat
+ 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
diff -up openssh-6.1p1/Makefile.in.keycat openssh-6.1p1/Makefile.in
--- openssh-6.1p1/Makefile.in.keycat 2013-02-14 17:39:21.143382033 +0100
+++ openssh-6.1p1/Makefile.in 2013-02-14 17:39:21.148382013 +0100
@@ -27,6 +27,7 @@ SFTP_SERVER=$(libexecdir)/sftp-server
ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass
SFTP_SERVER=$(libexecdir)/sftp-server
SSH_KEYSIGN=$(libexecdir)/ssh-keysign
SSH_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
SSH_SK_HELPER=$(libexecdir)/ssh-sk-helper
PRIVSEP_PATH=@PRIVSEP_PATH@
@@ -52,6 +52,7 @@ K5LIBS=@K5LIBS@
K5LIBS=@K5LIBS@
GSSLIBS=@GSSLIBS@
SSHDLIBS=@SSHDLIBS@
+KEYCATLIBS=@KEYCATLIBS@
LIBEDIT=@LIBEDIT@
LIBFIDO2=@LIBFIDO2@
AR=@AR@
@@ -65,7 +66,7 @@ EXEEXT=@EXEEXT@
SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@
@@ -62,7 +63,7 @@ EXEEXT=@EXEEXT@
MANFMT=@MANFMT@
INSTALL_SSH_LDAP_HELPER=@INSTALL_SSH_LDAP_HELPER@
.SUFFIXES: .lo
-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT)
+TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT) ssh-keycat$(EXEEXT)
-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT)
+TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT) ssh-keycat$(EXEEXT)
LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \
canohost.o channels.o cipher.o cipher-acss.o cipher-aes.o \
@@ -168,6 +169,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 -lfipscheck $(LIBS)
XMSS_OBJS=\
ssh-xmss.o \
@@ -190,6 +191,9 @@ ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT)
ssh-sk-helper$(EXEEXT): $(LIBCOMPAT) libssh.a $(SKHELPER_OBJS)
$(LD) -o $@ $(SKHELPER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) $(LIBFIDO2)
+ssh-keycat$(EXEEXT): $(LIBCOMPAT) $(SSHDOBJS) libssh.a ssh-keycat.o uidswap.o
+ $(LD) -o $@ ssh-keycat.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat $(KEYCATLIBS) $(LIBS)
+ssh-keycat$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keycat.o
+ $(LD) -o $@ ssh-keycat.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(SSHDLIBS)
+
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYSCAN_OBJS)
$(LD) -o $@ $(SSHKEYSCAN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o roaming_dummy.o
$(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
@@ -321,6 +325,7 @@ install-files:
$(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) ssh-sk-helper$(EXEEXT) $(DESTDIR)$(SSH_SK_HELPER)$(EXEEXT)
@@ -267,6 +271,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,
diff -up openssh-6.1p1/openbsd-compat/port-linux.c.keycat openssh-6.1p1/openbsd-compat/port-linux.c
--- openssh-6.1p1/openbsd-compat/port-linux.c.keycat 2013-02-14 17:39:21.126382101 +0100
+++ openssh-6.1p1/openbsd-compat/port-linux.c 2013-02-14 17:39:21.149382009 +0100
@@ -315,7 +315,7 @@ ssh_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 *))
-ssh_selinux_setup_pam_variables(void)
+ssh_selinux_setup_variables(int(*set_it)(const char *, const char *))
{
const char *reqlvl;
char *role;
@@ -319,16 +333,16 @@ sshd_selinux_setup_pam_variables(void)
@@ -326,16 +326,16 @@ ssh_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 {
@ -144,66 +101,36 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.keycat openssh/openbsd-compat/
+ 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)
xfree(role);
@@ -343,6 +343,24 @@ ssh_selinux_setup_pam_variables(void)
return rv;
}
+static int
+sshd_selinux_setup_pam_variables(void)
+ssh_selinux_setup_pam_variables(void)
+{
+ return sshd_selinux_setup_variables(do_pam_putenv);
+ return ssh_selinux_setup_variables(do_pam_putenv);
+}
+
+static int
+do_setenv(char *name, const char *value)
+do_setenv(char *name, char *value)
+{
+ return setenv(name, value, 1);
+}
+
+int
+sshd_selinux_setup_env_variables(void)
+ssh_selinux_setup_env_variables(void)
+{
+ return sshd_selinux_setup_variables(do_setenv);
+ return ssh_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 @@
ssh_selinux_setup_exec_context(char *pwname)
diff -up openssh-6.1p1/ssh-keycat.c.keycat openssh-6.1p1/ssh-keycat.c
--- openssh-6.1p1/ssh-keycat.c.keycat 2013-02-14 17:39:21.149382009 +0100
+++ openssh-6.1p1/ssh-keycat.c 2013-02-14 17:39:21.149382009 +0100
@@ -0,0 +1,238 @@
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
@ -253,9 +180,6 @@ diff -up openssh/ssh-keycat.c.keycat openssh/ssh-keycat.c
+#include <pwd.h>
+#include <fcntl.h>
+#include <unistd.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#include <security/pam_appl.h>
+
@ -445,41 +369,3 @@ diff -up openssh/ssh-keycat.c.keycat openssh/ssh-keycat.c
+ }
+ return ev;
+}
diff --git a/configure.ac b/configure.ac
index 3bbccfd..6481f1f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2952,6 +2952,7 @@ AC_ARG_WITH([pam],
PAM_MSG="yes"
SSHDLIBS="$SSHDLIBS -lpam"
+ KEYCATLIBS="$KEYCATLIBS -lpam"
AC_DEFINE([USE_PAM], [1],
[Define if you want to enable PAM support])
@@ -3105,6 +3106,7 @@
;;
*)
SSHDLIBS="$SSHDLIBS -ldl"
+ KEYCATLIBS="$KEYCATLIBS -ldl"
;;
esac
fi
@@ -4042,6 +4044,7 @@ AC_ARG_WITH([selinux],
fi ]
)
AC_SUBST([SSHDLIBS])
+AC_SUBST([KEYCATLIBS])
# Check whether user wants Kerberos 5 support
KRB5_MSG="no"
@@ -5031,6 +5034,9 @@ fi
if test ! -z "${SSHDLIBS}"; then
echo " +for sshd: ${SSHDLIBS}"
fi
+if test ! -z "${KEYCATLIBS}"; then
+echo " +for ssh-keycat: ${KEYCATLIBS}"
+fi
echo ""

View File

@ -0,0 +1,80 @@
diff -up openssh-5.9p0/ssh-keygen.0.keygen openssh-5.9p0/ssh-keygen.0
--- openssh-5.9p0/ssh-keygen.0.keygen 2011-08-29 16:30:02.000000000 +0200
+++ openssh-5.9p0/ssh-keygen.0 2011-08-30 13:47:56.208087184 +0200
@@ -4,7 +4,7 @@ NAME
ssh-keygen - authentication key generation, management and conversion
SYNOPSIS
- ssh-keygen [-q] [-b bits] -t type [-N new_passphrase] [-C comment]
+ ssh-keygen [-q] [-o] [-b bits] -t type [-N new_passphrase] [-C comment]
[-f output_keyfile]
ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-f keyfile]
ssh-keygen -i [-m key_format] [-f input_keyfile]
@@ -181,6 +181,8 @@ DESCRIPTION
principals may be specified, separated by commas. Please see the
CERTIFICATES section for details.
+ -o Overwrite the key without prompting user.
+
-O option
Specify a certificate option when signing a key. This option may
be specified multiple times. Please see the CERTIFICATES section
diff -up openssh-5.9p0/ssh-keygen.1.keygen openssh-5.9p0/ssh-keygen.1
--- openssh-5.9p0/ssh-keygen.1.keygen 2011-08-30 13:32:30.787149917 +0200
+++ openssh-5.9p0/ssh-keygen.1 2011-08-30 13:46:42.638087171 +0200
@@ -45,6 +45,7 @@
.Bk -words
.Nm ssh-keygen
.Op Fl q
+.Op Fl o
.Op Fl b Ar bits
.Fl t Ar type
.Op Fl N Ar new_passphrase
@@ -339,6 +340,8 @@ Multiple principals may be specified, se
Please see the
.Sx CERTIFICATES
section for details.
+.It Fl o
+Overwrite the key without prompting user.
.It Fl O Ar option
Specify a certificate option when signing a key.
This option may be specified multiple times.
diff -up openssh-5.9p0/ssh-keygen.c.keygen openssh-5.9p0/ssh-keygen.c
--- openssh-5.9p0/ssh-keygen.c.keygen 2011-08-30 13:32:20.268149992 +0200
+++ openssh-5.9p0/ssh-keygen.c 2011-08-30 13:39:34.550214102 +0200
@@ -73,6 +73,7 @@ int change_passphrase = 0;
int change_comment = 0;
int quiet = 0;
+int overwrite = 0;
int log_level = SYSLOG_LEVEL_INFO;
@@ -1959,7 +1960,7 @@ main(int argc, char **argv)
exit(1);
}
- while ((opt = getopt(argc, argv, "AegiqpclBHLhvxXyF:b:f:t:D:I:P:m:N:n:"
+ while ((opt = getopt(argc, argv, "AegiqopclBHLhvxXyF:b:f:t:D:I:P:m:N:n:"
"O:C:r:g:R:T:G:M:S:s:a:V:W:z:")) != -1) {
switch (opt) {
case 'A':
@@ -2042,6 +2043,9 @@ main(int argc, char **argv)
case 'q':
quiet = 1;
break;
+ case 'o':
+ overwrite = 1;
+ break;
case 'e':
case 'x':
/* export key */
@@ -2278,7 +2282,7 @@ main(int argc, char **argv)
}
}
/* If the file already exists, ask the user to confirm. */
- if (stat(identity_file, &st) >= 0) {
+ if (!overwrite && stat(identity_file, &st) >= 0) {
char yesno[3];
printf("%s already exists.\n", identity_file);
printf("Overwrite (y/n)? ");

View File

@ -0,0 +1,13 @@
diff -up openssh-5.9p0/entropy.c.randclean openssh-5.9p0/entropy.c
--- openssh-5.9p0/entropy.c.randclean 2011-08-30 13:52:45.000000000 +0200
+++ openssh-5.9p0/entropy.c 2011-08-30 13:57:44.630111338 +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");

View File

@ -0,0 +1,321 @@
diff -up openssh-5.9p1/Makefile.in.sesandbox openssh-5.9p1/Makefile.in
--- openssh-5.9p1/Makefile.in.sesandbox 2011-09-19 04:10:05.706521484 +0200
+++ openssh-5.9p1/Makefile.in 2011-09-19 04:10:15.092646473 +0200
@@ -90,7 +90,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passw
loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
sftp-server.o sftp-common.o \
roaming_common.o roaming_serv.o \
- sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o
+ sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o sandbox-selinux.o
MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out
MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5
diff -up openssh-5.9p1/configure.ac.sesandbox openssh-5.9p1/configure.ac
--- openssh-5.9p1/configure.ac.sesandbox 2011-08-18 06:48:24.000000000 +0200
+++ openssh-5.9p1/configure.ac 2011-09-19 04:10:15.193521356 +0200
@@ -2476,7 +2476,7 @@ AC_SUBST([SSH_PRIVSEP_USER])
# Decide which sandbox style to use
sandbox_arg=""
AC_ARG_WITH([sandbox],
- [ --with-sandbox=style Specify privilege separation sandbox (no, darwin, rlimit, systrace)],
+ [ --with-sandbox=style Specify privilege separation sandbox (no, darwin, rlimit, systrace, selinux)],
[
if test "x$withval" = "xyes" ; then
sandbox_arg=""
@@ -2499,6 +2499,10 @@ elif test "x$sandbox_arg" = "xdarwin" ||
AC_MSG_ERROR([Darwin seatbelt sandbox requires sandbox.h and sandbox_init function])
SANDBOX_STYLE="darwin"
AC_DEFINE([SANDBOX_DARWIN], [1], [Sandbox using Darwin sandbox_init(3)])
+elif test "x$sandbox_arg" = "xselinux" || \
+ test "x$WITH_SELINUX" = "x1"; then
+ SANDBOX_STYLE="selinux"
+ AC_DEFINE([SANDBOX_SELINUX], [1], [Sandbox using selinux(8)])
elif test "x$sandbox_arg" = "xrlimit" || \
( test -z "$sandbox_arg" && test "x$ac_cv_func_setrlimit" = "xyes" ) ; then
test "x$ac_cv_func_setrlimit" != "xyes" && \
diff -up openssh-5.9p1/openbsd-compat/port-linux.c.sesandbox openssh-5.9p1/openbsd-compat/port-linux.c
--- openssh-5.9p1/openbsd-compat/port-linux.c.sesandbox 2011-09-19 04:10:14.731521450 +0200
+++ openssh-5.9p1/openbsd-compat/port-linux.c 2011-09-19 04:10:15.292521265 +0200
@@ -459,24 +459,24 @@ ssh_selinux_setup_pty(char *pwname, cons
debug3("%s: done", __func__);
}
-void
+int
ssh_selinux_change_context(const char *newname)
{
- int len, newlen;
+ int len, newlen, rv = -1;
char *oldctx, *newctx, *cx;
void (*switchlog) (const char *fmt,...) = logit;
if (!ssh_selinux_enabled())
- return;
+ return -2;
if (getcon((security_context_t *)&oldctx) < 0) {
logit("%s: getcon failed with %s", __func__, strerror(errno));
- return;
+ return -1;
}
if ((cx = index(oldctx, ':')) == NULL || (cx = index(cx + 1, ':')) ==
NULL) {
logit ("%s: unparseable context %s", __func__, oldctx);
- return;
+ return -1;
}
/*
@@ -484,8 +484,10 @@ ssh_selinux_change_context(const char *n
* security context.
*/
if (strncmp(cx, SSH_SELINUX_UNCONFINED_TYPE,
- sizeof(SSH_SELINUX_UNCONFINED_TYPE) - 1) == 0)
+ sizeof(SSH_SELINUX_UNCONFINED_TYPE) - 1) == 0) {
switchlog = debug3;
+ rv = -2;
+ }
newlen = strlen(oldctx) + strlen(newname) + 1;
newctx = xmalloc(newlen);
@@ -499,8 +501,11 @@ ssh_selinux_change_context(const char *n
if (setcon(newctx) < 0)
switchlog("%s: setcon %s from %s failed with %s", __func__,
newctx, oldctx, strerror(errno));
+ else
+ rv = 0;
xfree(oldctx);
xfree(newctx);
+ return rv;
}
void
diff -up openssh-5.9p1/openbsd-compat/port-linux.h.sesandbox openssh-5.9p1/openbsd-compat/port-linux.h
--- openssh-5.9p1/openbsd-compat/port-linux.h.sesandbox 2011-09-19 04:10:14.817647868 +0200
+++ openssh-5.9p1/openbsd-compat/port-linux.h 2011-09-19 04:10:15.401648009 +0200
@@ -23,7 +23,7 @@
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 *);
+int ssh_selinux_change_context(const char *);
void ssh_selinux_chopy_context(void);
void ssh_selinux_setfscreatecon(const char *);
#endif
diff -up openssh-5.9p1/sandbox-darwin.c.sesandbox openssh-5.9p1/sandbox-darwin.c
--- openssh-5.9p1/sandbox-darwin.c.sesandbox 2011-06-26 23:18:21.000000000 +0200
+++ openssh-5.9p1/sandbox-darwin.c 2011-09-19 04:10:15.490523231 +0200
@@ -83,6 +83,12 @@ ssh_sandbox_child(struct ssh_sandbox *bo
}
void
+ssh_sandbox_privileged_child(struct ssh_sandbox *box)
+{
+ /* empty */
+}
+
+void
ssh_sandbox_parent_finish(struct ssh_sandbox *box)
{
free(box);
diff -up openssh-5.9p1/sandbox-null.c.sesandbox openssh-5.9p1/sandbox-null.c
--- openssh-5.9p1/sandbox-null.c.sesandbox 2011-06-23 11:45:51.000000000 +0200
+++ openssh-5.9p1/sandbox-null.c 2011-09-19 04:10:15.599458687 +0200
@@ -58,6 +58,12 @@ ssh_sandbox_child(struct ssh_sandbox *bo
}
void
+ssh_sandbox_privileged_child(struct ssh_sandbox *box)
+{
+ /* empty */
+}
+
+void
ssh_sandbox_parent_finish(struct ssh_sandbox *box)
{
free(box);
diff -up openssh-5.9p1/sandbox-rlimit.c.sesandbox openssh-5.9p1/sandbox-rlimit.c
--- openssh-5.9p1/sandbox-rlimit.c.sesandbox 2011-06-23 11:45:51.000000000 +0200
+++ openssh-5.9p1/sandbox-rlimit.c 2011-09-19 04:10:16.077647289 +0200
@@ -78,6 +78,12 @@ ssh_sandbox_child(struct ssh_sandbox *bo
}
void
+ssh_sandbox_privileged_child(struct ssh_sandbox *box)
+{
+ /* empty */
+}
+
+void
ssh_sandbox_parent_finish(struct ssh_sandbox *box)
{
free(box);
diff -up openssh-5.9p1/sandbox-selinux.c.sesandbox openssh-5.9p1/sandbox-selinux.c
--- openssh-5.9p1/sandbox-selinux.c.sesandbox 2011-09-19 04:10:16.179526059 +0200
+++ openssh-5.9p1/sandbox-selinux.c 2011-09-19 04:39:00.058646230 +0200
@@ -0,0 +1,122 @@
+/* $Id: sandbox-selinux.c,v 1.0 2011/01/17 10:15:30 jfch Exp $ */
+
+/*
+ * Copyright 2011 Red Hat, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * 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, this list of conditions and the following disclaimer.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
+ *
+ * Red Hat author: Jan F. Chadima <jchadima@redhat.com>
+ */
+
+
+#include "includes.h"
+
+#ifdef SANDBOX_SELINUX
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/resource.h>
+
+#include "log.h"
+#include "ssh-sandbox.h"
+#include "xmalloc.h"
+#include "openbsd-compat/port-linux.h"
+
+/* selinux based sandbox */
+
+struct ssh_sandbox {
+ pid_t child_pid;
+};
+
+struct ssh_sandbox *
+ssh_sandbox_init(void)
+{
+ struct ssh_sandbox *box;
+
+ /*
+ * Strictly, we don't need to maintain any state here but we need
+ * to return non-NULL to satisfy the API.
+ */
+ debug3("selinux sandbox init");
+ box = xcalloc(1, sizeof(*box));
+ box->child_pid = 0;
+ return box;
+}
+
+void
+ssh_sandbox_child(struct ssh_sandbox *box)
+{
+ struct rlimit rl_zero;
+
+ rl_zero.rlim_cur = rl_zero.rlim_max = 0;
+
+ if (setrlimit(RLIMIT_FSIZE, &rl_zero) == -1)
+ fatal("%s: setrlimit(RLIMIT_FSIZE, { 0, 0 }): %s",
+ __func__, strerror(errno));
+ if (setrlimit(RLIMIT_NOFILE, &rl_zero) == -1)
+ fatal("%s: setrlimit(RLIMIT_NOFILE, { 0, 0 }): %s",
+ __func__, strerror(errno));
+#ifdef HAVE_RLIMIT_NPROC
+ if (setrlimit(RLIMIT_NPROC, &rl_zero) == -1)
+ fatal("%s: setrlimit(RLIMIT_NPROC, { 0, 0 }): %s",
+ __func__, strerror(errno));
+#endif
+}
+
+void
+ssh_sandbox_privileged_child(struct ssh_sandbox *box)
+{
+ switch (ssh_selinux_change_context("sshd_sandbox_t")) {
+ case 0:
+ debug3("selinux sandbox child sucessfully enabled");
+ break;
+ case -2:
+ logit("selinux sandbox not useful");
+ break;
+ case -1:
+ fatal("cannot set up selinux sandbox");
+ default:
+ fatal("inmternal error in selinux sandbox");
+ }
+}
+
+void
+ssh_sandbox_parent_finish(struct ssh_sandbox *box)
+{
+ free(box);
+ debug3("%s: finished", __func__);
+}
+
+void
+ssh_sandbox_parent_preauth(struct ssh_sandbox *box, pid_t child_pid)
+{
+ debug3("selinux sandbox parent sucessfully enabled");
+ box->child_pid = child_pid;
+}
+
+#endif /* SANDBOX_NULL */
diff -up openssh-5.9p1/sandbox-systrace.c.sesandbox openssh-5.9p1/sandbox-systrace.c
--- openssh-5.9p1/sandbox-systrace.c.sesandbox 2011-08-05 22:16:23.000000000 +0200
+++ openssh-5.9p1/sandbox-systrace.c 2011-09-19 04:10:16.268646532 +0200
@@ -109,6 +109,12 @@ ssh_sandbox_child(struct ssh_sandbox *bo
close(box->child_sock);
}
+void
+ssh_sandbox_privileged_child(struct ssh_sandbox *box)
+{
+ /* empty */
+}
+
static void
ssh_sandbox_parent(struct ssh_sandbox *box, pid_t child_pid,
const struct sandbox_policy *allowed_syscalls)
diff -up openssh-5.9p1/ssh-sandbox.h.sesandbox openssh-5.9p1/ssh-sandbox.h
--- openssh-5.9p1/ssh-sandbox.h.sesandbox 2011-06-23 11:45:51.000000000 +0200
+++ openssh-5.9p1/ssh-sandbox.h 2011-09-19 04:10:16.392523931 +0200
@@ -19,5 +19,6 @@ struct ssh_sandbox;
struct ssh_sandbox *ssh_sandbox_init(void);
void ssh_sandbox_child(struct ssh_sandbox *);
+void ssh_sandbox_privileged_child(struct ssh_sandbox *);
void ssh_sandbox_parent_finish(struct ssh_sandbox *);
void ssh_sandbox_parent_preauth(struct ssh_sandbox *, pid_t);
diff -up openssh-5.9p1/sshd.c.sesandbox openssh-5.9p1/sshd.c
--- openssh-5.9p1/sshd.c.sesandbox 2011-09-19 04:10:14.564467584 +0200
+++ openssh-5.9p1/sshd.c 2011-09-19 04:36:43.324520132 +0200
@@ -728,10 +730,12 @@ privsep_preauth(Authctxt *authctxt)
set_log_handler(mm_log_handler, pmonitor);
/* Demote the child */
- if (getuid() == 0 || geteuid() == 0)
+ if (getuid() == 0 || geteuid() == 0) {
+ ssh_sandbox_privileged_child(box);
privsep_preauth_child();
+ }
setproctitle("%s", "[net]");
if (box != NULL) {
ssh_sandbox_child(box);
xfree(box);
}

View File

@ -0,0 +1,63 @@
diff -up openssh-5.9p0/openbsd-compat/port-linux.c.sftp-chroot openssh-5.9p0/openbsd-compat/port-linux.c
--- openssh-5.9p0/openbsd-compat/port-linux.c.sftp-chroot 2011-09-01 04:12:22.743024608 +0200
+++ openssh-5.9p0/openbsd-compat/port-linux.c 2011-09-01 04:12:23.069088065 +0200
@@ -503,6 +503,23 @@ ssh_selinux_change_context(const char *n
xfree(newctx);
}
+void
+ssh_selinux_copy_context(void)
+{
+ char *ctx;
+
+ if (!ssh_selinux_enabled())
+ return;
+
+ if (getexeccon((security_context_t *)&ctx) < 0) {
+ logit("%s: getcon failed with %s", __func__, strerror (errno));
+ return;
+ }
+ if (setcon(ctx) < 0)
+ logit("%s: setcon failed with %s", __func__, strerror (errno));
+ xfree(ctx);
+}
+
#endif /* WITH_SELINUX */
#ifdef LINUX_OOM_ADJUST
diff -up openssh-5.9p0/openbsd-compat/port-linux.h.sftp-chroot openssh-5.9p0/openbsd-compat/port-linux.h
--- openssh-5.9p0/openbsd-compat/port-linux.h.sftp-chroot 2011-01-25 02:16:18.000000000 +0100
+++ openssh-5.9p0/openbsd-compat/port-linux.h 2011-09-01 04:12:23.163088777 +0200
@@ -24,6 +24,7 @@ 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_chopy_context(void);
void ssh_selinux_setfscreatecon(const char *);
#endif
diff -up openssh-5.9p0/session.c.sftp-chroot openssh-5.9p0/session.c
--- openssh-5.9p0/session.c.sftp-chroot 2011-09-01 04:12:19.698049195 +0200
+++ openssh-5.9p0/session.c 2011-09-01 04:40:03.598148719 +0200
@@ -1519,6 +1519,9 @@ do_setusercontext(struct passwd *pw)
pw->pw_uid);
chroot_path = percent_expand(tmp, "h", pw->pw_dir,
"u", pw->pw_name, (char *)NULL);
+#ifdef WITH_SELINUX
+ ssh_selinux_change_context("chroot_user_t");
+#endif
safely_chroot(chroot_path, pw->pw_uid);
free(tmp);
free(chroot_path);
@@ -1788,7 +1791,10 @@ do_child(Session *s, const char *command
optind = optreset = 1;
__progname = argv[0];
#ifdef WITH_SELINUX
- ssh_selinux_change_context("sftpd_t");
+ if (options.chroot_directory == NULL ||
+ strcasecmp(options.chroot_directory, "none") == 0) {
+ ssh_selinux_copy_context();
+ }
#endif
exit(sftp_server_main(i, argv, s->pw));
}

78
openssh-5.9p1-wIm.patch Normal file
View 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());
+}
+
+

641
openssh-6.0p1-audit1.patch Normal file
View File

@ -0,0 +1,641 @@
diff -up openssh-6.0p1/audit-bsm.c.audit1 openssh-6.0p1/audit-bsm.c
--- openssh-6.0p1/audit-bsm.c.audit1 2012-02-24 00:40:43.000000000 +0100
+++ openssh-6.0p1/audit-bsm.c 2012-08-06 20:33:24.416382804 +0200
@@ -375,10 +375,23 @@ audit_connection_from(const char *host,
#endif
}
-void
+int
audit_run_command(const char *command)
{
/* not implemented */
+ return 0;
+}
+
+void
+audit_end_command(int handle, const char *command)
+{
+ /* not implemented */
+}
+
+void
+audit_count_session_open(void)
+{
+ /* not necessary */
}
void
diff -up openssh-6.0p1/audit.c.audit1 openssh-6.0p1/audit.c
--- openssh-6.0p1/audit.c.audit1 2011-01-17 11:15:30.000000000 +0100
+++ openssh-6.0p1/audit.c 2012-08-06 20:33:24.417382801 +0200
@@ -140,6 +140,17 @@ audit_event(ssh_audit_event_t event)
}
/*
+ * Called when a child process has called, or will soon call,
+ * audit_session_open.
+ */
+void
+audit_count_session_open(void)
+{
+ debug("audit count session open euid %d user %s", geteuid(),
+ audit_username());
+}
+
+/*
* Called when a user session is started. Argument is the tty allocated to
* the session, or NULL if no tty was allocated.
*
@@ -174,13 +185,29 @@ audit_session_close(struct logininfo *li
/*
* This will be called when a user runs a non-interactive command. Note that
* it may be called multiple times for a single connection since SSH2 allows
- * multiple sessions within a single connection.
+ * multiple sessions within a single connection. Returns a "handle" for
+ * audit_end_command.
*/
-void
+int
audit_run_command(const char *command)
{
debug("audit run command euid %d user %s command '%.200s'", geteuid(),
audit_username(), command);
+ return 0;
+}
+
+/*
+ * This will be called when the non-interactive command finishes. Note that
+ * it may be called multiple times for a single connection since SSH2 allows
+ * multiple sessions within a single connection. "handle" should come from
+ * the corresponding audit_run_command.
+ */
+void
+audit_end_command(int handle, const char *command)
+{
+ debug("audit end nopty exec euid %d user %s command '%.200s'", geteuid(),
+ audit_username(), command);
}
+
# endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */
#endif /* SSH_AUDIT_EVENTS */
diff -up openssh-6.0p1/audit.h.audit1 openssh-6.0p1/audit.h
--- openssh-6.0p1/audit.h.audit1 2011-01-17 11:15:30.000000000 +0100
+++ openssh-6.0p1/audit.h 2012-08-06 20:33:24.417382801 +0200
@@ -49,9 +49,11 @@ typedef enum ssh_audit_event_type ssh_au
void audit_connection_from(const char *, int);
void audit_event(ssh_audit_event_t);
+void audit_count_session_open(void);
void audit_session_open(struct logininfo *);
void audit_session_close(struct logininfo *);
-void audit_run_command(const char *);
+int audit_run_command(const char *);
+void audit_end_command(int, const char *);
ssh_audit_event_t audit_classify_auth(const char *);
#endif /* _SSH_AUDIT_H */
diff -up openssh-6.0p1/audit-linux.c.audit1 openssh-6.0p1/audit-linux.c
--- openssh-6.0p1/audit-linux.c.audit1 2011-01-17 11:15:30.000000000 +0100
+++ openssh-6.0p1/audit-linux.c 2012-08-06 20:33:24.416382804 +0200
@@ -35,13 +35,20 @@
#include "log.h"
#include "audit.h"
+#include "key.h"
+#include "hostfile.h"
+#include "auth.h"
+#include "servconf.h"
#include "canohost.h"
+extern ServerOptions options;
+extern Authctxt *the_authctxt;
+extern u_int utmp_len;
const char* audit_username(void);
-int
-linux_audit_record_event(int uid, const char *username,
- const char *hostname, const char *ip, const char *ttyn, int success)
+static void
+linux_audit_user_logxxx(int uid, const char *username,
+ const char *hostname, const char *ip, const char *ttyn, int success, int event)
{
int audit_fd, rc, saved_errno;
@@ -49,11 +56,11 @@ linux_audit_record_event(int uid, const
if (audit_fd < 0) {
if (errno == EINVAL || errno == EPROTONOSUPPORT ||
errno == EAFNOSUPPORT)
- return 1; /* No audit support in kernel */
+ return; /* No audit support in kernel */
else
- return 0; /* Must prevent login */
+ goto fatal_report; /* Must prevent login */
}
- rc = audit_log_acct_message(audit_fd, AUDIT_USER_LOGIN,
+ rc = audit_log_acct_message(audit_fd, event,
NULL, "login", username ? username : "(unknown)",
username == NULL ? uid : -1, hostname, ip, ttyn, success);
saved_errno = errno;
@@ -65,35 +72,119 @@ linux_audit_record_event(int uid, const
if ((rc == -EPERM) && (geteuid() != 0))
rc = 0;
errno = saved_errno;
- return (rc >= 0);
+ if (rc < 0) {
+fatal_report:
+ fatal("linux_audit_write_entry failed: %s", strerror(errno));
+ }
+}
+
+static void
+linux_audit_user_auth(int uid, const char *username,
+ const char *hostname, const char *ip, const char *ttyn, int success, int event)
+{
+ int audit_fd, rc, saved_errno;
+ static const char *event_name[] = {
+ "maxtries exceeded",
+ "root denied",
+ "success",
+ "none",
+ "password",
+ "challenge-response",
+ "pubkey",
+ "hostbased",
+ "gssapi",
+ "invalid user",
+ "nologin",
+ "connection closed",
+ "connection abandoned",
+ "unknown"
+ };
+
+ audit_fd = audit_open();
+ if (audit_fd < 0) {
+ if (errno == EINVAL || errno == EPROTONOSUPPORT ||
+ errno == EAFNOSUPPORT)
+ return; /* No audit support in kernel */
+ else
+ goto fatal_report; /* Must prevent login */
+ }
+
+ if ((event < 0) || (event > SSH_AUDIT_UNKNOWN))
+ event = SSH_AUDIT_UNKNOWN;
+
+ rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH,
+ NULL, event_name[event], username ? username : "(unknown)",
+ username == NULL ? uid : -1, hostname, ip, ttyn, success);
+ saved_errno = errno;
+ close(audit_fd);
+ /*
+ * Do not report error if the error is EPERM and sshd is run as non
+ * root user.
+ */
+ if ((rc == -EPERM) && (geteuid() != 0))
+ rc = 0;
+ errno = saved_errno;
+ if (rc < 0) {
+fatal_report:
+ fatal("linux_audit_write_entry failed: %s", strerror(errno));
+ }
}
+static int user_login_count = 0;
+
/* Below is the sshd audit API code */
void
audit_connection_from(const char *host, int port)
{
-}
/* not implemented */
+}
-void
+int
audit_run_command(const char *command)
{
- /* not implemented */
+ if (!user_login_count++)
+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns),
+ NULL, "ssh", 1, AUDIT_USER_LOGIN);
+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns),
+ NULL, "ssh", 1, AUDIT_USER_START);
+ return 0;
+}
+
+void
+audit_end_command(int handle, const char *command)
+{
+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns),
+ NULL, "ssh", 1, AUDIT_USER_END);
+ if (user_login_count && !--user_login_count)
+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns),
+ NULL, "ssh", 1, AUDIT_USER_LOGOUT);
+}
+
+void
+audit_count_session_open(void)
+{
+ user_login_count++;
}
void
audit_session_open(struct logininfo *li)
{
- if (linux_audit_record_event(li->uid, NULL, li->hostname,
- NULL, li->line, 1) == 0)
- fatal("linux_audit_write_entry failed: %s", strerror(errno));
+ if (!user_login_count++)
+ linux_audit_user_logxxx(li->uid, NULL, li->hostname,
+ NULL, li->line, 1, AUDIT_USER_LOGIN);
+ linux_audit_user_logxxx(li->uid, NULL, li->hostname,
+ NULL, li->line, 1, AUDIT_USER_START);
}
void
audit_session_close(struct logininfo *li)
{
- /* not implemented */
+ linux_audit_user_logxxx(li->uid, NULL, li->hostname,
+ NULL, li->line, 1, AUDIT_USER_END);
+ if (user_login_count && !--user_login_count)
+ linux_audit_user_logxxx(li->uid, NULL, li->hostname,
+ NULL, li->line, 1, AUDIT_USER_LOGOUT);
}
void
@@ -101,21 +192,43 @@ audit_event(ssh_audit_event_t event)
{
switch(event) {
case SSH_AUTH_SUCCESS:
- case SSH_CONNECTION_CLOSE:
+ linux_audit_user_auth(-1, audit_username(), NULL,
+ get_remote_ipaddr(), "ssh", 1, event);
+ break;
+
case SSH_NOLOGIN:
- case SSH_LOGIN_EXCEED_MAXTRIES:
case SSH_LOGIN_ROOT_DENIED:
+ linux_audit_user_auth(-1, audit_username(), NULL,
+ get_remote_ipaddr(), "ssh", 0, event);
+ linux_audit_user_logxxx(-1, audit_username(), NULL,
+ get_remote_ipaddr(), "ssh", 0, AUDIT_USER_LOGIN);
break;
+ case SSH_LOGIN_EXCEED_MAXTRIES:
case SSH_AUTH_FAIL_NONE:
case SSH_AUTH_FAIL_PASSWD:
case SSH_AUTH_FAIL_KBDINT:
case SSH_AUTH_FAIL_PUBKEY:
case SSH_AUTH_FAIL_HOSTBASED:
case SSH_AUTH_FAIL_GSSAPI:
+ linux_audit_user_auth(-1, audit_username(), NULL,
+ get_remote_ipaddr(), "ssh", 0, event);
+ break;
+
+ case SSH_CONNECTION_CLOSE:
+ if (user_login_count) {
+ while (user_login_count--)
+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns),
+ NULL, "ssh", 1, AUDIT_USER_END);
+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns),
+ NULL, "ssh", 1, AUDIT_USER_LOGOUT);
+ }
+ break;
+
+ case SSH_CONNECTION_ABANDON:
case SSH_INVALID_USER:
- linux_audit_record_event(-1, audit_username(), NULL,
- get_remote_ipaddr(), "sshd", 0);
+ linux_audit_user_logxxx(-1, audit_username(), NULL,
+ get_remote_ipaddr(), "ssh", 0, AUDIT_USER_LOGIN);
break;
default:
diff -up openssh-6.0p1/monitor.c.audit1 openssh-6.0p1/monitor.c
--- openssh-6.0p1/monitor.c.audit1 2012-08-06 20:33:24.410382828 +0200
+++ openssh-6.0p1/monitor.c 2012-08-06 20:33:24.418382797 +0200
@@ -185,6 +185,7 @@ int mm_answer_gss_checkmic(int, Buffer *
#ifdef SSH_AUDIT_EVENTS
int mm_answer_audit_event(int, Buffer *);
int mm_answer_audit_command(int, Buffer *);
+int mm_answer_audit_end_command(int, Buffer *);
#endif
static int monitor_read_log(struct monitor *);
@@ -272,6 +273,7 @@ struct mon_table mon_dispatch_postauth20
#ifdef SSH_AUDIT_EVENTS
{MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
{MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command},
+ {MONITOR_REQ_AUDIT_END_COMMAND, MON_PERMIT, mm_answer_audit_end_command},
#endif
{0, 0, NULL}
};
@@ -314,6 +316,7 @@ struct mon_table mon_dispatch_postauth15
#ifdef SSH_AUDIT_EVENTS
{MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
{MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT|MON_ONCE, mm_answer_audit_command},
+ {MONITOR_REQ_AUDIT_END_COMMAND, MON_PERMIT, mm_answer_audit_end_command},
#endif
{0, 0, NULL}
};
@@ -1427,6 +1430,12 @@ mm_session_close(Session *s)
debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd);
session_pty_cleanup2(s);
}
+#ifdef SSH_AUDIT_EVENTS
+ if (s->command != NULL) {
+ debug3("%s: command %d", __func__, s->command_handle);
+ session_end_command2(s);
+ }
+#endif
session_unused(s->self);
}
@@ -1751,11 +1760,44 @@ mm_answer_audit_command(int socket, Buff
{
u_int len;
char *cmd;
+ Session *s;
debug3("%s entering", __func__);
cmd = buffer_get_string(m, &len);
+
/* sanity check command, if so how? */
- audit_run_command(cmd);
+ s = session_new();
+ if (s == NULL)
+ fatal("%s: error allocating a session", __func__);
+ s->command = cmd;
+ s->command_handle = audit_run_command(cmd);
+
+ buffer_clear(m);
+ buffer_put_int(m, s->self);
+
+ mm_request_send(socket, MONITOR_ANS_AUDIT_COMMAND, m);
+
+ return (0);
+}
+
+int
+mm_answer_audit_end_command(int socket, Buffer *m)
+{
+ int handle;
+ u_int len;
+ char *cmd;
+ Session *s;
+
+ debug3("%s entering", __func__);
+ handle = buffer_get_int(m);
+ cmd = buffer_get_string(m, &len);
+
+ s = session_by_id(handle);
+ if (s == NULL || s->ttyfd != -1 || s->command == NULL ||
+ strcmp(s->command, cmd) != 0)
+ fatal("%s: invalid handle", __func__);
+ mm_session_close(s);
+
xfree(cmd);
return (0);
}
diff -up openssh-6.0p1/monitor.h.audit1 openssh-6.0p1/monitor.h
--- openssh-6.0p1/monitor.h.audit1 2011-06-20 06:42:23.000000000 +0200
+++ openssh-6.0p1/monitor.h 2012-08-06 20:33:24.418382797 +0200
@@ -60,6 +60,7 @@ enum monitor_reqtype {
MONITOR_REQ_PAM_RESPOND, MONITOR_ANS_PAM_RESPOND,
MONITOR_REQ_PAM_FREE_CTX, MONITOR_ANS_PAM_FREE_CTX,
MONITOR_REQ_AUDIT_EVENT, MONITOR_REQ_AUDIT_COMMAND,
+ MONITOR_ANS_AUDIT_COMMAND, MONITOR_REQ_AUDIT_END_COMMAND,
MONITOR_REQ_TERM,
MONITOR_REQ_JPAKE_STEP1, MONITOR_ANS_JPAKE_STEP1,
MONITOR_REQ_JPAKE_GET_PWDATA, MONITOR_ANS_JPAKE_GET_PWDATA,
diff -up openssh-6.0p1/monitor_wrap.c.audit1 openssh-6.0p1/monitor_wrap.c
--- openssh-6.0p1/monitor_wrap.c.audit1 2012-08-06 20:33:24.384382930 +0200
+++ openssh-6.0p1/monitor_wrap.c 2012-08-06 20:33:24.419382793 +0200
@@ -1188,10 +1188,11 @@ mm_audit_event(ssh_audit_event_t event)
buffer_free(&m);
}
-void
+int
mm_audit_run_command(const char *command)
{
Buffer m;
+ int handle;
debug3("%s entering command %s", __func__, command);
@@ -1199,6 +1200,26 @@ mm_audit_run_command(const char *command
buffer_put_cstring(&m, command);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, &m);
+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_COMMAND, &m);
+
+ handle = buffer_get_int(&m);
+ buffer_free(&m);
+
+ return (handle);
+}
+
+void
+mm_audit_end_command(int handle, const char *command)
+{
+ Buffer m;
+
+ debug3("%s entering command %s", __func__, command);
+
+ buffer_init(&m);
+ buffer_put_int(&m, handle);
+ buffer_put_cstring(&m, command);
+
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_END_COMMAND, &m);
buffer_free(&m);
}
#endif /* SSH_AUDIT_EVENTS */
diff -up openssh-6.0p1/monitor_wrap.h.audit1 openssh-6.0p1/monitor_wrap.h
--- openssh-6.0p1/monitor_wrap.h.audit1 2011-06-20 06:42:23.000000000 +0200
+++ openssh-6.0p1/monitor_wrap.h 2012-08-06 20:33:24.419382793 +0200
@@ -74,7 +74,8 @@ void mm_sshpam_free_ctx(void *);
#ifdef SSH_AUDIT_EVENTS
#include "audit.h"
void mm_audit_event(ssh_audit_event_t);
-void mm_audit_run_command(const char *);
+int mm_audit_run_command(const char *);
+void mm_audit_end_command(int, const char *);
#endif
struct Session;
diff -up openssh-6.0p1/session.c.audit1 openssh-6.0p1/session.c
--- openssh-6.0p1/session.c.audit1 2011-11-04 00:55:24.000000000 +0100
+++ openssh-6.0p1/session.c 2012-08-06 20:33:24.420382789 +0200
@@ -742,6 +742,14 @@ do_exec_pty(Session *s, const char *comm
/* Parent. Close the slave side of the pseudo tty. */
close(ttyfd);
+#ifndef HAVE_OSF_SIA
+ /* do_login in the child did not affect state in this process,
+ compensate. From an architectural standpoint, this is extremely
+ ugly. */
+ if (!(options.use_login && command == NULL))
+ audit_count_session_open();
+#endif
+
/* Enter interactive session. */
s->ptymaster = ptymaster;
packet_set_interactive(1,
@@ -813,15 +821,19 @@ do_exec(Session *s, const char *command)
}
#ifdef SSH_AUDIT_EVENTS
+ if (s->command != NULL || s->command_handle != -1)
+ fatal("do_exec: command already set");
if (command != NULL)
- PRIVSEP(audit_run_command(command));
+ s->command = xstrdup(command);
else if (s->ttyfd == -1) {
char *shell = s->pw->pw_shell;
if (shell[0] == '\0') /* empty shell means /bin/sh */
shell =_PATH_BSHELL;
- PRIVSEP(audit_run_command(shell));
+ s->command = xstrdup(shell);
}
+ if (s->command != NULL)
+ s->command_handle = PRIVSEP(audit_run_command(s->command));
#endif
if (s->ttyfd != -1)
ret = do_exec_pty(s, command);
@@ -1848,6 +1860,7 @@ session_unused(int id)
sessions[id].ttyfd = -1;
sessions[id].ptymaster = -1;
sessions[id].x11_chanids = NULL;
+ sessions[id].command_handle = -1;
sessions[id].next_unused = sessions_first_unused;
sessions_first_unused = id;
}
@@ -1930,6 +1943,19 @@ session_open(Authctxt *authctxt, int cha
}
Session *
+session_by_id(int id)
+{
+ if (id >= 0 && id < sessions_nalloc) {
+ Session *s = &sessions[id];
+ if (s->used)
+ return s;
+ }
+ debug("session_by_id: unknown id %d", id);
+ session_dump();
+ return NULL;
+}
+
+Session *
session_by_tty(char *tty)
{
int i;
@@ -2455,6 +2481,30 @@ session_exit_message(Session *s, int sta
chan_write_failed(c);
}
+#ifdef SSH_AUDIT_EVENTS
+void
+session_end_command2(Session *s)
+{
+ if (s->command != NULL) {
+ audit_end_command(s->command_handle, s->command);
+ xfree(s->command);
+ s->command = NULL;
+ s->command_handle = -1;
+ }
+}
+
+static void
+session_end_command(Session *s)
+{
+ if (s->command != NULL) {
+ PRIVSEP(audit_end_command(s->command_handle, s->command));
+ xfree(s->command);
+ s->command = NULL;
+ s->command_handle = -1;
+ }
+}
+#endif
+
void
session_close(Session *s)
{
@@ -2463,6 +2513,10 @@ session_close(Session *s)
debug("session_close: session %d pid %ld", s->self, (long)s->pid);
if (s->ttyfd != -1)
session_pty_cleanup(s);
+#ifdef SSH_AUDIT_EVENTS
+ if (s->command)
+ session_end_command(s);
+#endif
if (s->term)
xfree(s->term);
if (s->display)
@@ -2682,6 +2736,15 @@ do_authenticated2(Authctxt *authctxt)
server_loop2(authctxt);
}
+static void
+do_cleanup_one_session(Session *s)
+{
+ session_pty_cleanup2(s);
+#ifdef SSH_AUDIT_EVENTS
+ session_end_command2(s);
+#endif
+}
+
void
do_cleanup(Authctxt *authctxt)
{
@@ -2730,5 +2793,5 @@ do_cleanup(Authctxt *authctxt)
* or if running in monitor.
*/
if (!use_privsep || mm_is_monitor())
- session_destroy_all(session_pty_cleanup2);
+ session_destroy_all(do_cleanup_one_session);
}
diff -up openssh-6.0p1/session.h.audit1 openssh-6.0p1/session.h
--- openssh-6.0p1/session.h.audit1 2008-05-19 07:34:50.000000000 +0200
+++ openssh-6.0p1/session.h 2012-08-06 20:33:24.420382789 +0200
@@ -60,6 +60,12 @@ struct Session {
char *name;
char *val;
} *env;
+
+ /* exec */
+#ifdef SSH_AUDIT_EVENTS
+ int command_handle;
+ char *command;
+#endif
};
void do_authenticated(Authctxt *);
@@ -72,8 +78,10 @@ void session_close_by_pid(pid_t, int);
void session_close_by_channel(int, void *);
void session_destroy_all(void (*)(Session *));
void session_pty_cleanup2(Session *);
+void session_end_command2(Session *);
Session *session_new(void);
+Session *session_by_id(int);
Session *session_by_tty(char *);
void session_close(Session *);
void do_setusercontext(struct passwd *);
diff -up openssh-6.0p1/sshd.c.audit1 openssh-6.0p1/sshd.c
--- openssh-6.0p1/sshd.c.audit1 2012-08-06 20:33:24.392382898 +0200
+++ openssh-6.0p1/sshd.c 2012-08-06 20:33:24.421382785 +0200
@@ -2381,7 +2381,8 @@ cleanup_exit(int i)
}
#ifdef SSH_AUDIT_EVENTS
/* done after do_cleanup so it can cancel the PAM auth 'thread' */
- if (!use_privsep || mm_is_monitor())
+ if ((the_authctxt == NULL || !the_authctxt->authenticated) &&
+ (!use_privsep || mm_is_monitor()))
audit_event(SSH_CONNECTION_ABANDON);
#endif
_exit(i);

486
openssh-6.0p1-audit5.patch Normal file
View File

@ -0,0 +1,486 @@
diff -up openssh-6.0p1/audit-bsm.c.audit5 openssh-6.0p1/audit-bsm.c
--- openssh-6.0p1/audit-bsm.c.audit5 2012-08-06 20:37:50.036345216 +0200
+++ openssh-6.0p1/audit-bsm.c 2012-08-06 20:37:50.046345177 +0200
@@ -491,4 +491,22 @@ audit_session_key_free_body(int ctos, pi
{
/* not implemented */
}
+
+void
+audit_destroy_sensitive_data(const char *fp)
+{
+ /* not implemented */
+}
+
+void
+audit_destroy_sensitive_data(const char *fp, pid_t pid, uid_t uid)
+{
+ /* not implemented */
+}
+
+void
+audit_generate_ephemeral_server_key(const char *fp)
+{
+ /* not implemented */
+}
#endif /* BSM */
diff -up openssh-6.0p1/audit.c.audit5 openssh-6.0p1/audit.c
--- openssh-6.0p1/audit.c.audit5 2012-08-06 20:37:50.036345216 +0200
+++ openssh-6.0p1/audit.c 2012-08-06 20:37:50.047345173 +0200
@@ -290,5 +290,24 @@ audit_session_key_free_body(int ctos, pi
debug("audit session key discard euid %u direction %d from pid %ld uid %u",
(unsigned)geteuid(), ctos, (long)pid, (unsigned)uid);
}
+
+/*
+ * This will be called on destroy private part of the server key
+ */
+void
+audit_destroy_sensitive_data(const char *fp, pid_t pid, uid_t uid)
+{
+ debug("audit destroy sensitive data euid %d fingerprint %s from pid %ld uid %u",
+ geteuid(), fp, (long)pid, (unsigned)uid);
+}
+
+/*
+ * This will be called on generation of the ephemeral server key
+ */
+void
+audit_generate_ephemeral_server_key(const char *)
+{
+ debug("audit create ephemeral server key euid %d fingerprint %s", geteuid(), fp);
+}
# endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */
#endif /* SSH_AUDIT_EVENTS */
diff -up openssh-6.0p1/audit.h.audit5 openssh-6.0p1/audit.h
--- openssh-6.0p1/audit.h.audit5 2012-08-06 20:37:50.037345212 +0200
+++ openssh-6.0p1/audit.h 2012-08-06 20:37:50.047345173 +0200
@@ -48,6 +48,8 @@ enum ssh_audit_event_type {
};
typedef enum ssh_audit_event_type ssh_audit_event_t;
+int listening_for_clients(void);
+
void audit_connection_from(const char *, int);
void audit_event(ssh_audit_event_t);
void audit_count_session_open(void);
@@ -64,5 +66,7 @@ void audit_unsupported_body(int);
void audit_kex_body(int, char *, char *, char *, pid_t, uid_t);
void audit_session_key_free(int ctos);
void audit_session_key_free_body(int ctos, pid_t, uid_t);
+void audit_destroy_sensitive_data(const char *, pid_t, uid_t);
+void audit_generate_ephemeral_server_key(const char *);
#endif /* _SSH_AUDIT_H */
diff -up openssh-6.0p1/audit-linux.c.audit5 openssh-6.0p1/audit-linux.c
--- openssh-6.0p1/audit-linux.c.audit5 2012-08-06 20:37:50.037345212 +0200
+++ openssh-6.0p1/audit-linux.c 2012-08-06 20:37:50.046345177 +0200
@@ -356,4 +356,50 @@ audit_session_key_free_body(int ctos, pi
error("cannot write into audit");
}
+void
+audit_destroy_sensitive_data(const char *fp, pid_t pid, uid_t uid)
+{
+ char buf[AUDIT_LOG_SIZE];
+ int audit_fd, audit_ok;
+
+ snprintf(buf, sizeof(buf), "op=destroy kind=server fp=%s direction=? spid=%jd suid=%jd ",
+ fp, (intmax_t)pid, (intmax_t)uid);
+ audit_fd = audit_open();
+ if (audit_fd < 0) {
+ if (errno != EINVAL && errno != EPROTONOSUPPORT &&
+ errno != EAFNOSUPPORT)
+ error("cannot open audit");
+ return;
+ }
+ audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER,
+ buf, NULL,
+ listening_for_clients() ? NULL : get_remote_ipaddr(),
+ NULL, 1);
+ audit_close(audit_fd);
+ /* do not abort if the error is EPERM and sshd is run as non root user */
+ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0)))
+ error("cannot write into audit");
+}
+
+void
+audit_generate_ephemeral_server_key(const char *fp)
+{
+ char buf[AUDIT_LOG_SIZE];
+ int audit_fd, audit_ok;
+
+ snprintf(buf, sizeof(buf), "op=create kind=server fp=%s direction=? ", fp);
+ audit_fd = audit_open();
+ if (audit_fd < 0) {
+ if (errno != EINVAL && errno != EPROTONOSUPPORT &&
+ errno != EAFNOSUPPORT)
+ error("cannot open audit");
+ return;
+ }
+ audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER,
+ buf, NULL, 0, NULL, 1);
+ audit_close(audit_fd);
+ /* do not abort if the error is EPERM and sshd is run as non root user */
+ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0)))
+ error("cannot write into audit");
+}
#endif /* USE_LINUX_AUDIT */
diff -up openssh-6.0p1/key.c.audit5 openssh-6.0p1/key.c
--- openssh-6.0p1/key.c.audit5 2012-08-06 20:37:49.992345388 +0200
+++ openssh-6.0p1/key.c 2012-08-06 20:37:50.048345169 +0200
@@ -1794,6 +1794,30 @@ key_demote(const Key *k)
}
int
+key_is_private(const Key *k)
+{
+ switch (k->type) {
+ case KEY_RSA_CERT_V00:
+ case KEY_RSA_CERT:
+ case KEY_RSA1:
+ case KEY_RSA:
+ return k->rsa->d != NULL;
+ case KEY_DSA_CERT_V00:
+ case KEY_DSA_CERT:
+ case KEY_DSA:
+ return k->dsa->priv_key != NULL;
+#ifdef OPENSSL_HAS_ECC
+ case KEY_ECDSA_CERT:
+ case KEY_ECDSA:
+ return EC_KEY_get0_private_key(k->ecdsa) != NULL;
+#endif
+ default:
+ fatal("key_is_private: bad key type %d", k->type);
+ return 1;
+ }
+}
+
+int
key_is_cert(const Key *k)
{
if (k == NULL)
diff -up openssh-6.0p1/key.h.audit5 openssh-6.0p1/key.h
--- openssh-6.0p1/key.h.audit5 2012-08-06 20:37:49.993345384 +0200
+++ openssh-6.0p1/key.h 2012-08-06 20:37:50.049345165 +0200
@@ -109,6 +109,7 @@ Key *key_generate(int, u_int);
Key *key_from_private(const Key *);
int key_type_from_name(char *);
int key_is_cert(const Key *);
+int key_is_private(const Key *k);
int key_type_plain(int);
int key_to_certified(Key *, int);
int key_drop_cert(Key *);
diff -up openssh-6.0p1/monitor.c.audit5 openssh-6.0p1/monitor.c
--- openssh-6.0p1/monitor.c.audit5 2012-08-06 20:37:50.040345200 +0200
+++ openssh-6.0p1/monitor.c 2012-08-06 20:37:50.049345165 +0200
@@ -114,6 +114,8 @@ extern Buffer auth_debug;
extern int auth_debug_init;
extern Buffer loginmsg;
+extern void destroy_sensitive_data(int);
+
/* State exported from the child */
struct {
@@ -190,6 +192,7 @@ int mm_answer_audit_end_command(int, Buf
int mm_answer_audit_unsupported_body(int, Buffer *);
int mm_answer_audit_kex_body(int, Buffer *);
int mm_answer_audit_session_key_free_body(int, Buffer *);
+int mm_answer_audit_server_key_free(int, Buffer *);
#endif
static int monitor_read_log(struct monitor *);
@@ -244,6 +247,7 @@ struct mon_table mon_dispatch_proto20[]
{MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body},
{MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body},
{MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body},
+ {MONITOR_REQ_AUDIT_SERVER_KEY_FREE, MON_PERMIT, mm_answer_audit_server_key_free},
#endif
#ifdef BSD_AUTH
{MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery},
@@ -284,6 +288,7 @@ struct mon_table mon_dispatch_postauth20
{MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body},
{MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body},
{MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body},
+ {MONITOR_REQ_AUDIT_SERVER_KEY_FREE, MON_PERMIT, mm_answer_audit_server_key_free},
#endif
{0, 0, NULL}
};
@@ -318,6 +323,7 @@ struct mon_table mon_dispatch_proto15[]
{MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body},
{MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body},
{MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body},
+ {MONITOR_REQ_AUDIT_SERVER_KEY_FREE, MON_PERMIT, mm_answer_audit_server_key_free},
#endif
{0, 0, NULL}
};
@@ -333,6 +339,7 @@ struct mon_table mon_dispatch_postauth15
{MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body},
{MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body},
{MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body},
+ {MONITOR_REQ_AUDIT_SERVER_KEY_FREE, MON_PERMIT, mm_answer_audit_server_key_free},
#endif
{0, 0, NULL}
};
@@ -1744,6 +1751,8 @@ mm_answer_term(int sock, Buffer *req)
sshpam_cleanup();
#endif
+ destroy_sensitive_data(0);
+
while (waitpid(pmonitor->m_pid, &status, 0) == -1)
if (errno != EINTR)
exit(1);
@@ -2485,4 +2494,25 @@ mm_answer_audit_session_key_free_body(in
mm_request_send(sock, MONITOR_ANS_AUDIT_SESSION_KEY_FREE, m);
return 0;
}
+
+int
+mm_answer_audit_server_key_free(int sock, Buffer *m)
+{
+ int len;
+ char *fp;
+ pid_t pid;
+ uid_t uid;
+
+ fp = buffer_get_string(m, &len);
+ pid = buffer_get_int64(m);
+ uid = buffer_get_int64(m);
+
+ audit_destroy_sensitive_data(fp, pid, uid);
+
+ xfree(fp);
+ buffer_clear(m);
+
+ mm_request_send(sock, MONITOR_ANS_AUDIT_SERVER_KEY_FREE, m);
+ return 0;
+}
#endif /* SSH_AUDIT_EVENTS */
diff -up openssh-6.0p1/monitor.h.audit5 openssh-6.0p1/monitor.h
--- openssh-6.0p1/monitor.h.audit5 2012-08-06 20:37:50.040345200 +0200
+++ openssh-6.0p1/monitor.h 2012-08-06 20:37:50.050345161 +0200
@@ -64,6 +64,7 @@ enum monitor_reqtype {
MONITOR_REQ_AUDIT_UNSUPPORTED, MONITOR_ANS_AUDIT_UNSUPPORTED,
MONITOR_REQ_AUDIT_KEX, MONITOR_ANS_AUDIT_KEX,
MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MONITOR_ANS_AUDIT_SESSION_KEY_FREE,
+ MONITOR_REQ_AUDIT_SERVER_KEY_FREE, MONITOR_ANS_AUDIT_SERVER_KEY_FREE,
MONITOR_REQ_TERM,
MONITOR_REQ_JPAKE_STEP1, MONITOR_ANS_JPAKE_STEP1,
MONITOR_REQ_JPAKE_GET_PWDATA, MONITOR_ANS_JPAKE_GET_PWDATA,
diff -up openssh-6.0p1/monitor_wrap.c.audit5 openssh-6.0p1/monitor_wrap.c
--- openssh-6.0p1/monitor_wrap.c.audit5 2012-08-06 20:37:50.041345196 +0200
+++ openssh-6.0p1/monitor_wrap.c 2012-08-06 20:37:50.050345161 +0200
@@ -1539,4 +1539,20 @@ mm_audit_session_key_free_body(int ctos,
&m);
buffer_free(&m);
}
+
+void
+mm_audit_destroy_sensitive_data(const char *fp, pid_t pid, uid_t uid)
+{
+ Buffer m;
+
+ buffer_init(&m);
+ buffer_put_cstring(&m, fp);
+ buffer_put_int64(&m, pid);
+ buffer_put_int64(&m, uid);
+
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_SERVER_KEY_FREE, &m);
+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_SERVER_KEY_FREE,
+ &m);
+ buffer_free(&m);
+}
#endif /* SSH_AUDIT_EVENTS */
diff -up openssh-6.0p1/monitor_wrap.h.audit5 openssh-6.0p1/monitor_wrap.h
--- openssh-6.0p1/monitor_wrap.h.audit5 2012-08-06 20:37:50.041345196 +0200
+++ openssh-6.0p1/monitor_wrap.h 2012-08-06 20:37:50.051345157 +0200
@@ -80,6 +80,7 @@ void mm_audit_end_command(int, const cha
void mm_audit_unsupported_body(int);
void mm_audit_kex_body(int, 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);
#endif
struct Session;
diff -up openssh-6.0p1/session.c.audit5 openssh-6.0p1/session.c
--- openssh-6.0p1/session.c.audit5 2012-08-06 20:37:50.043345189 +0200
+++ openssh-6.0p1/session.c 2012-08-06 20:37:50.052345153 +0200
@@ -136,7 +136,7 @@ extern int log_stderr;
extern int debug_flag;
extern u_int utmp_len;
extern int startup_pipe;
-extern void destroy_sensitive_data(void);
+extern void destroy_sensitive_data(int);
extern Buffer loginmsg;
/* original command from peer. */
@@ -1633,7 +1633,7 @@ do_child(Session *s, const char *command
int r = 0;
/* remove hostkey from the child's memory */
- destroy_sensitive_data();
+ destroy_sensitive_data(1);
/* Don't audit this - both us and the parent would be talking to the
monitor over a single socket, with no synchronization. */
packet_destroy_all(0, 1);
diff -up openssh-6.0p1/sshd.c.audit5 openssh-6.0p1/sshd.c
--- openssh-6.0p1/sshd.c.audit5 2012-08-06 20:37:50.044345185 +0200
+++ openssh-6.0p1/sshd.c 2012-08-06 20:37:50.053345149 +0200
@@ -255,7 +255,7 @@ Buffer loginmsg;
struct passwd *privsep_pw = NULL;
/* Prototypes for various functions defined later in this file. */
-void destroy_sensitive_data(void);
+void destroy_sensitive_data(int);
void demote_sensitive_data(void);
static void do_ssh1_kex(void);
@@ -274,6 +274,15 @@ close_listen_socks(void)
num_listen_socks = -1;
}
+/*
+ * Is this process listening for clients (i.e. not specific to any specific
+ * client connection?)
+ */
+int listening_for_clients(void)
+{
+ return num_listen_socks > 0;
+}
+
static void
close_startup_pipes(void)
{
@@ -534,22 +543,47 @@ sshd_exchange_identification(int sock_in
}
}
-/* Destroy the host and server keys. They will no longer be needed. */
+/*
+ * Destroy the host and server keys. They will no longer be needed. Careful,
+ * this can be called from cleanup_exit() - i.e. from just about anywhere.
+ */
void
-destroy_sensitive_data(void)
+destroy_sensitive_data(int privsep)
{
int i;
+ pid_t pid;
+ uid_t uid;
if (sensitive_data.server_key) {
key_free(sensitive_data.server_key);
sensitive_data.server_key = NULL;
}
+ pid = getpid();
+ uid = getuid();
for (i = 0; i < options.num_host_key_files; i++) {
if (sensitive_data.host_keys[i]) {
+ char *fp;
+
+ if (key_is_private(sensitive_data.host_keys[i]))
+ fp = key_fingerprint(sensitive_data.host_keys[i],
+ FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5,
+ SSH_FP_HEX);
+ else
+ fp = NULL;
key_free(sensitive_data.host_keys[i]);
sensitive_data.host_keys[i] = NULL;
+ if (fp != NULL) {
+ if (privsep)
+ PRIVSEP(audit_destroy_sensitive_data(fp,
+ pid, uid));
+ else
+ audit_destroy_sensitive_data(fp,
+ pid, uid);
+ xfree(fp);
+ }
}
- if (sensitive_data.host_certificates[i]) {
+ if (sensitive_data.host_certificates
+ && sensitive_data.host_certificates[i]) {
key_free(sensitive_data.host_certificates[i]);
sensitive_data.host_certificates[i] = NULL;
}
@@ -563,6 +597,8 @@ void
demote_sensitive_data(void)
{
Key *tmp;
+ pid_t pid;
+ uid_t uid;
int i;
if (sensitive_data.server_key) {
@@ -571,13 +607,27 @@ demote_sensitive_data(void)
sensitive_data.server_key = tmp;
}
+ pid = getpid();
+ uid = getuid();
for (i = 0; i < options.num_host_key_files; i++) {
if (sensitive_data.host_keys[i]) {
+ char *fp;
+
+ if (key_is_private(sensitive_data.host_keys[i]))
+ fp = key_fingerprint(sensitive_data.host_keys[i],
+ FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5,
+ SSH_FP_HEX);
+ else
+ fp = NULL;
tmp = key_demote(sensitive_data.host_keys[i]);
key_free(sensitive_data.host_keys[i]);
sensitive_data.host_keys[i] = tmp;
if (tmp->type == KEY_RSA1)
sensitive_data.ssh1_host_key = tmp;
+ if (fp != NULL) {
+ audit_destroy_sensitive_data(fp, pid, uid);
+ xfree(fp);
+ }
}
/* Certs do not need demotion */
}
@@ -1149,6 +1199,7 @@ server_accept_loop(int *sock_in, int *so
if (received_sigterm) {
logit("Received signal %d; terminating.",
(int) received_sigterm);
+ destroy_sensitive_data(0);
close_listen_socks();
unlink(options.pid_file);
exit(received_sigterm == SIGTERM ? 0 : 255);
@@ -2054,7 +2105,7 @@ main(int ac, char **av)
privsep_postauth(authctxt);
/* the monitor process [priv] will not return */
if (!compat20)
- destroy_sensitive_data();
+ destroy_sensitive_data(0);
}
packet_set_timeout(options.client_alive_interval,
@@ -2065,6 +2116,7 @@ main(int ac, char **av)
/* The connection has been terminated. */
packet_destroy_all(1, 1);
+ destroy_sensitive_data(1);
packet_get_state(MODE_IN, NULL, NULL, NULL, &ibytes);
packet_get_state(MODE_OUT, NULL, NULL, NULL, &obytes);
@@ -2293,7 +2345,7 @@ do_ssh1_kex(void)
session_id[i] = session_key[i] ^ session_key[i + 16];
}
/* Destroy the private and public keys. No longer. */
- destroy_sensitive_data();
+ destroy_sensitive_data(0);
if (use_privsep)
mm_ssh1_session_id(session_id);
@@ -2404,6 +2456,8 @@ cleanup_exit(int i)
}
}
is_privsep_child = use_privsep && pmonitor != NULL && !mm_is_monitor();
+ if (sensitive_data.host_keys != NULL)
+ destroy_sensitive_data(is_privsep_child);
packet_destroy_all(1, is_privsep_child);
#ifdef SSH_AUDIT_EVENTS
/* done after do_cleanup so it can cancel the PAM auth 'thread' */

272
openssh-6.0p1-entropy.patch Normal file
View File

@ -0,0 +1,272 @@
diff -up openssh-6.0p1/entropy.c.entropy openssh-6.0p1/entropy.c
--- openssh-6.0p1/entropy.c.entropy 2012-08-06 20:51:59.131033413 +0200
+++ openssh-6.0p1/entropy.c 2012-08-06 20:51:59.171033257 +0200
@@ -237,6 +237,9 @@ seed_rng(void)
memset(buf, '\0', sizeof(buf));
#endif /* OPENSSL_PRNG_ONLY */
+#ifdef __linux__
+ linux_seed();
+#endif /* __linux__ */
if (RAND_status() != 1)
fatal("PRNG is not seeded");
}
diff -up openssh-6.0p1/openbsd-compat/Makefile.in.entropy openssh-6.0p1/openbsd-compat/Makefile.in
--- openssh-6.0p1/openbsd-compat/Makefile.in.entropy 2012-08-06 20:51:59.100033534 +0200
+++ openssh-6.0p1/openbsd-compat/Makefile.in 2012-08-06 20:51:59.171033257 +0200
@@ -20,7 +20,7 @@ OPENBSD=base64.o basename.o bindresvport
COMPAT=bsd-arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o getrrsetbyname-ldns.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xmmap.o xcrypt.o
-PORTS=port-aix.o port-irix.o port-linux.o port-linux_part_2.o port-solaris.o port-tun.o port-uw.o
+PORTS=port-aix.o port-irix.o port-linux.o port-linux_part_2.o port-linux-prng.o port-solaris.o port-tun.o port-uw.o
.c.o:
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
diff -up openssh-6.0p1/openbsd-compat/port-linux-prng.c.entropy openssh-6.0p1/openbsd-compat/port-linux-prng.c
--- openssh-6.0p1/openbsd-compat/port-linux-prng.c.entropy 2012-08-06 20:51:59.171033257 +0200
+++ openssh-6.0p1/openbsd-compat/port-linux-prng.c 2012-08-06 20:51:59.171033257 +0200
@@ -0,0 +1,59 @@
+/* $Id: port-linux.c,v 1.11.4.2 2011/02/04 00:43:08 djm Exp $ */
+
+/*
+ * Copyright (c) 2011 Jan F. Chadima <jchadima@redhat.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Linux-specific portability code - prng support
+ */
+
+#include "includes.h"
+
+#include <errno.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <openssl/rand.h>
+
+#include "log.h"
+#include "xmalloc.h"
+#include "servconf.h"
+#include "port-linux.h"
+#include "key.h"
+#include "hostfile.h"
+#include "auth.h"
+
+void
+linux_seed(void)
+{
+ int len;
+ char *env = getenv("SSH_USE_STRONG_RNG");
+ char *random = "/dev/random";
+ size_t ienv, randlen = 6;
+
+ if (!env || !strcmp(env, "0"))
+ random = "/dev/urandom";
+ else if ((ienv = atoi(env)) > 6)
+ randlen = ienv;
+
+ errno = 0;
+ if ((len = RAND_load_file(random, randlen)) != randlen) {
+ if (errno)
+ fatal ("cannot read from %s, %s", random, strerror(errno));
+ else
+ fatal ("EOF reading %s", random);
+ }
+}
diff -up openssh-6.0p1/ssh.1.entropy openssh-6.0p1/ssh.1
--- openssh-6.0p1/ssh.1.entropy 2012-08-06 20:51:59.139033382 +0200
+++ openssh-6.0p1/ssh.1 2012-08-06 20:51:59.174033245 +0200
@@ -1269,6 +1269,23 @@ For more information, see the
.Cm PermitUserEnvironment
option in
.Xr sshd_config 5 .
+.Sh ENVIRONMENT
+.Bl -tag -width Ds -compact
+.It Ev SSH_USE_STRONG_RNG
+The reseeding of the OpenSSL random generator is usually done from
+.Cm /dev/urandom .
+If the
+.Cm SSH_USE_STRONG_RNG
+environment variable is set to value other than
+.Cm 0
+the OpenSSL random generator is reseeded from
+.Cm /dev/random .
+The number of bytes read is defined by the SSH_USE_STRONG_RNG value.
+Minimum is 6 bytes.
+This setting is not recommended on the computers without the hardware
+random generator because insufficient entropy causes the connection to
+be blocked until enough entropy is available.
+.El
.Sh FILES
.Bl -tag -width Ds -compact
.It Pa ~/.rhosts
diff -up openssh-6.1p1/ssh-add.0.entropy openssh-6.1p1/ssh-add.0
--- openssh-6.1p1/ssh-add.0.entropy 2012-11-12 13:11:42.717393364 +0100
+++ openssh-6.1p1/ssh-add.0 2012-11-12 13:12:46.288108790 +0100
@@ -81,6 +81,16 @@ ENVIRONMENT
Identifies the path of a UNIX-domain socket used to communicate
with the agent.
+ SSH_USE_STRONG_RNG
+ The reseeding of the OpenSSL random generator is usually done
+ from /dev/urandom. If the SSH_USE_STRONG_RNG environment vari-
+ able is set to value other than 0 the OpenSSL random generator is
+ reseeded from /dev/random. The number of bytes read is defined
+ by the SSH_USE_STRONG_RNG value. Minimum is 6 bytes. This set-
+ ting is not recommended on the computers without the hardware
+ random generator because insufficient entropy causes the connec-
+ tion to be blocked until enough entropy is available.
+
FILES
~/.ssh/identity
Contains the protocol version 1 RSA authentication identity of
diff -up openssh-6.1p1/ssh-add.1.entropy openssh-6.1p1/ssh-add.1
--- openssh-6.1p1/ssh-add.1.entropy 2011-10-18 07:06:33.000000000 +0200
+++ openssh-6.1p1/ssh-add.1 2012-11-12 13:11:24.711476108 +0100
@@ -160,6 +160,20 @@ to make this work.)
Identifies the path of a
.Ux Ns -domain
socket used to communicate with the agent.
+.It Ev SSH_USE_STRONG_RNG
+The reseeding of the OpenSSL random generator is usually done from
+.Cm /dev/urandom .
+If the
+.Cm SSH_USE_STRONG_RNG
+environment variable is set to value other than
+.Cm 0
+the OpenSSL random generator is reseeded from
+.Cm /dev/random .
+The number of bytes read is defined by the SSH_USE_STRONG_RNG value.
+Minimum is 6 bytes.
+This setting is not recommended on the computers without the hardware
+random generator because insufficient entropy causes the connection to
+be blocked until enough entropy is available.
.El
.Sh FILES
.Bl -tag -width Ds
.It Pa ~/.ssh/identity
diff -up openssh-6.0p1/ssh-agent.1.entropy openssh-6.0p1/ssh-agent.1
--- openssh-6.0p1/ssh-agent.1.entropy 2010-12-01 01:50:35.000000000 +0100
+++ openssh-6.0p1/ssh-agent.1 2012-08-06 20:51:59.172033253 +0200
@@ -198,6 +198,24 @@ sockets used to contain the connection t
These sockets should only be readable by the owner.
The sockets should get automatically removed when the agent exits.
.El
+.Sh ENVIRONMENT
+.Bl -tag -width Ds -compact
+.Pp
+.It Pa SSH_USE_STRONG_RNG
+The reseeding of the OpenSSL random generator is usually done from
+.Cm /dev/urandom .
+If the
+.Cm SSH_USE_STRONG_RNG
+environment variable is set to value other than
+.Cm 0
+the OpenSSL random generator is reseeded from
+.Cm /dev/random .
+The number of bytes read is defined by the SSH_USE_STRONG_RNG value.
+Minimum is 6 bytes.
+This setting is not recommended on the computers without the hardware
+random generator because insufficient entropy causes the connection to
+be blocked until enough entropy is available.
+.El
.Sh SEE ALSO
.Xr ssh 1 ,
.Xr ssh-add 1 ,
diff -up openssh-6.0p1/sshd.8.entropy openssh-6.0p1/sshd.8
--- openssh-6.0p1/sshd.8.entropy 2012-08-06 20:51:59.139033382 +0200
+++ openssh-6.0p1/sshd.8 2012-08-06 20:51:59.174033245 +0200
@@ -943,6 +943,24 @@ concurrently for different ports, this c
started last).
The content of this file is not sensitive; it can be world-readable.
.El
+.Sh ENVIRONMENT
+.Bl -tag -width Ds -compact
+.Pp
+.It Pa SSH_USE_STRONG_RNG
+The reseeding of the OpenSSL random generator is usually done from
+.Cm /dev/urandom .
+If the
+.Cm SSH_USE_STRONG_RNG
+environment variable is set to value other than
+.Cm 0
+the OpenSSL random generator is reseeded from
+.Cm /dev/random .
+The number of bytes read is defined by the SSH_USE_STRONG_RNG value.
+Minimum is 6 bytes.
+This setting is not recommended on the computers without the hardware
+random generator because insufficient entropy causes the connection to
+be blocked until enough entropy is available.
+.El
.Sh IPV6
IPv6 address can be used everywhere where IPv4 address. In all entries must be the IPv6 address enclosed in square brackets. Note: The square brackets are metacharacters for the shell and must be escaped in shell.
.Sh SEE ALSO
diff -up openssh-6.0p1/ssh-keygen.1.entropy openssh-6.0p1/ssh-keygen.1
--- openssh-6.0p1/ssh-keygen.1.entropy 2011-10-18 07:05:21.000000000 +0200
+++ openssh-6.0p1/ssh-keygen.1 2012-08-06 20:51:59.173033249 +0200
@@ -675,6 +675,24 @@ Contains Diffie-Hellman groups used for
The file format is described in
.Xr moduli 5 .
.El
+.Sh ENVIRONMENT
+.Bl -tag -width Ds -compact
+.Pp
+.It Pa SSH_USE_STRONG_RNG
+The reseeding of the OpenSSL random generator is usually done from
+.Cm /dev/urandom .
+If the
+.Cm SSH_USE_STRONG_RNG
+environment variable is set to value other than
+.Cm 0
+the OpenSSL random generator is reseeded from
+.Cm /dev/random .
+The number of bytes read is defined by the SSH_USE_STRONG_RNG value.
+Minimum is 6 bytes.
+This setting is not recommended on the computers without the hardware
+random generator because insufficient entropy causes the connection to
+be blocked until enough entropy is available.
+.El
.Sh SEE ALSO
.Xr ssh 1 ,
.Xr ssh-add 1 ,
diff -up openssh-6.0p1/ssh-keysign.8.entropy openssh-6.0p1/ssh-keysign.8
--- openssh-6.0p1/ssh-keysign.8.entropy 2010-08-31 14:41:14.000000000 +0200
+++ openssh-6.0p1/ssh-keysign.8 2012-08-06 20:51:59.173033249 +0200
@@ -78,6 +78,24 @@ must be set-uid root if host-based authe
If these files exist they are assumed to contain public certificate
information corresponding with the private keys above.
.El
+.Sh ENVIRONMENT
+.Bl -tag -width Ds -compact
+.Pp
+.It Pa SSH_USE_STRONG_RNG
+The reseeding of the OpenSSL random generator is usually done from
+.Cm /dev/urandom .
+If the
+.Cm SSH_USE_STRONG_RNG
+environment variable is set to value other than
+.Cm 0
+the OpenSSL random generator is reseeded from
+.Cm /dev/random .
+The number of bytes read is defined by the SSH_USE_STRONG_RNG value.
+Minimum is 6 bytes.
+This setting is not recommended on the computers without the hardware
+random generator because insufficient entropy causes the connection to
+be blocked until enough entropy is available.
+.El
.Sh SEE ALSO
.Xr ssh 1 ,
.Xr ssh-keygen 1 ,

2596
openssh-6.0p1-ldap.patch Normal file

File diff suppressed because it is too large Load Diff

579
openssh-6.1p1-akc.patch Normal file
View File

@ -0,0 +1,579 @@
diff -up openssh-6.1p1/auth2-pubkey.c.akc openssh-6.1p1/auth2-pubkey.c
--- openssh-6.1p1/auth2-pubkey.c.akc 2013-02-14 17:46:45.259546968 +0100
+++ openssh-6.1p1/auth2-pubkey.c 2013-02-14 17:48:19.072137541 +0100
@@ -27,9 +27,13 @@
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/wait.h>
+#include <errno.h>
#include <fcntl.h>
+#include <paths.h>
#include <pwd.h>
+#include <signal.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
@@ -260,7 +264,7 @@ match_principals_file(char *file, struct
if (strcmp(cp, cert->principals[i]) == 0) {
debug3("matched principal \"%.100s\" "
"from file \"%s\" on line %lu",
- cert->principals[i], file, linenum);
+ cert->principals[i], file, linenum);
if (auth_parse_options(pw, line_opts,
file, linenum) != 1)
continue;
@@ -273,31 +277,22 @@ match_principals_file(char *file, struct
fclose(f);
restore_uid();
return 0;
-}
+}
-/* return 1 if user allows given key */
+/*
+ * Checks whether key is allowed in authorized_keys-format file,
+ * returns 1 if the key is allowed or 0 otherwise.
+ */
static int
-user_key_allowed2(struct passwd *pw, Key *key, char *file)
+check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
{
char line[SSH_MAX_PUBKEY_BYTES];
const char *reason;
int found_key = 0;
- FILE *f;
u_long linenum = 0;
Key *found;
char *fp;
- /* Temporarily use the user's uid. */
- temporarily_use_uid(pw);
-
- debug("trying public key file %s", file);
- f = auth_openkeyfile(file, pw, options.strict_modes);
-
- if (!f) {
- restore_uid();
- return 0;
- }
-
found_key = 0;
found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
@@ -390,8 +385,6 @@ user_key_allowed2(struct passwd *pw, Key
break;
}
}
- restore_uid();
- fclose(f);
key_free(found);
if (!found_key)
debug2("key not found");
@@ -453,7 +446,180 @@ user_cert_trusted_ca(struct passwd *pw,
return ret;
}
-/* check whether given key is in .ssh/authorized_keys* */
+/*
+ * Checks whether key is allowed in file.
+ * returns 1 if the key is allowed or 0 otherwise.
+ */
+static int
+user_key_allowed2(struct passwd *pw, Key *key, char *file)
+{
+ FILE *f;
+ int found_key = 0;
+
+ /* Temporarily use the user's uid. */
+ temporarily_use_uid(pw);
+
+ debug("trying public key file %s", file);
+ if ((f = auth_openkeyfile(file, pw, options.strict_modes)) != NULL) {
+ found_key = check_authkeys_file(f, file, key, pw);
+ fclose(f);
+ }
+
+ restore_uid();
+ return found_key;
+}
+
+/*
+ * Checks whether key is allowed in output of command.
+ * returns 1 if the key is allowed or 0 otherwise.
+ */
+static int
+user_key_command_allowed2(struct passwd *user_pw, Key *key)
+{
+ FILE *f;
+ int ok, found_key = 0;
+ struct passwd *pw;
+ struct stat st;
+ int status, devnull, p[2], i;
+ pid_t pid;
+ char *username, errmsg[512];
+
+ if (options.authorized_keys_command == NULL ||
+ options.authorized_keys_command[0] != '/')
+ return 0;
+
+ if (options.authorized_keys_command_user == NULL) {
+ pw = user_pw;
+ }
+ else {
+ username = percent_expand(options.authorized_keys_command_user,
+ "u", user_pw->pw_name, (char *)NULL);
+ pw = getpwnam(username);
+ if (pw == NULL) {
+ error("AuthorizedKeyCommandUser \"%s\" not found: %s",
+ username, strerror(errno));
+ free(username);
+ return 0;
+ }
+ free(username);
+ }
+
+ temporarily_use_uid(pw);
+
+ if (stat(options.authorized_keys_command, &st) < 0) {
+ error("Could not stat AuthorizedKeysCommand \"%s\": %s",
+ options.authorized_keys_command, strerror(errno));
+ goto out;
+ }
+ if (auth_secure_path(options.authorized_keys_command, &st, NULL, 0,
+ errmsg, sizeof(errmsg)) != 0) {
+ error("Unsafe AuthorizedKeysCommand: %s", errmsg);
+ goto out;
+ }
+
+ if (pipe(p) != 0) {
+ error("%s: pipe: %s", __func__, strerror(errno));
+ goto out;
+ }
+
+ debug3("Running AuthorizedKeysCommand: \"%s %s\" as \"%s\"",
+ options.authorized_keys_command, user_pw->pw_name, pw->pw_name);
+
+ /*
+ * Don't want to call this in the child, where it can fatal() and
+ * run cleanup_exit() code.
+ */
+ restore_uid();
+
+ switch ((pid = fork())) {
+ case -1: /* error */
+ error("%s: fork: %s", __func__, strerror(errno));
+ close(p[0]);
+ close(p[1]);
+ return 0;
+ case 0: /* child */
+ for (i = 0; i < NSIG; i++)
+ signal(i, SIG_DFL);
+
+ if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
+ error("%s: open %s: %s", __func__, _PATH_DEVNULL,
+ strerror(errno));
+ _exit(1);
+ }
+ /* Keep stderr around a while longer to catch errors */
+ if (dup2(devnull, STDIN_FILENO) == -1 ||
+ dup2(p[1], STDOUT_FILENO) == -1) {
+ error("%s: dup2: %s", __func__, strerror(errno));
+ _exit(1);
+ }
+ closefrom(STDERR_FILENO + 1);
+
+ /* Don't use permanently_set_uid() here to avoid fatal() */
+ if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) {
+ error("setresgid %u: %s", (u_int)pw->pw_gid,
+ strerror(errno));
+ _exit(1);
+ }
+ if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) {
+ error("setresuid %u: %s", (u_int)pw->pw_uid,
+ strerror(errno));
+ _exit(1);
+ }
+ /* stdin is pointed to /dev/null at this point */
+ if (dup2(STDIN_FILENO, STDERR_FILENO) == -1) {
+ error("%s: dup2: %s", __func__, strerror(errno));
+ _exit(1);
+ }
+
+ execl(options.authorized_keys_command,
+ options.authorized_keys_command, user_pw->pw_name, NULL);
+
+ error("AuthorizedKeysCommand %s exec failed: %s",
+ options.authorized_keys_command, strerror(errno));
+ _exit(127);
+ default: /* parent */
+ break;
+ }
+
+ temporarily_use_uid(pw);
+
+ close(p[1]);
+ if ((f = fdopen(p[0], "r")) == NULL) {
+ error("%s: fdopen: %s", __func__, strerror(errno));
+ close(p[0]);
+ /* Don't leave zombie child */
+ kill(pid, SIGTERM);
+ while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
+ ;
+ goto out;
+ }
+ ok = check_authkeys_file(f, options.authorized_keys_command, key, pw);
+ fclose(f);
+
+ while (waitpid(pid, &status, 0) == -1) {
+ if (errno != EINTR) {
+ error("%s: waitpid: %s", __func__, strerror(errno));
+ goto out;
+ }
+ }
+ if (WIFSIGNALED(status)) {
+ error("AuthorizedKeysCommand %s exited on signal %d",
+ options.authorized_keys_command, WTERMSIG(status));
+ goto out;
+ } else if (WEXITSTATUS(status) != 0) {
+ error("AuthorizedKeysCommand %s returned status %d",
+ options.authorized_keys_command, WEXITSTATUS(status));
+ goto out;
+ }
+ found_key = ok;
+ out:
+ restore_uid();
+ return found_key;
+}
+
+/*
+ * Check whether key authenticates and authorises the user.
+ */
int
user_key_allowed(struct passwd *pw, Key *key)
{
@@ -469,9 +635,17 @@ user_key_allowed(struct passwd *pw, Key
if (success)
return success;
+ success = user_key_command_allowed2(pw, key);
+ if (success > 0)
+ return success;
+
for (i = 0; !success && i < options.num_authkeys_files; i++) {
+
+ if (strcasecmp(options.authorized_keys_files[i], "none") == 0)
+ continue;
file = expand_authorized_keys(
options.authorized_keys_files[i], pw);
+
success = user_key_allowed2(pw, key, file);
xfree(file);
}
diff -up openssh-6.1p1/auth.c.akc openssh-6.1p1/auth.c
--- openssh-6.1p1/auth.c.akc 2013-02-14 17:46:45.189547274 +0100
+++ openssh-6.1p1/auth.c 2013-02-14 17:46:45.273546907 +0100
@@ -415,39 +415,41 @@ check_key_in_hostfiles(struct passwd *pw
/*
- * Check a given file for security. This is defined as all components
+ * Check a given path for security. This is defined as all components
* of the path to the file must be owned by either the owner of
* of the file or root and no directories must be group or world writable.
*
* XXX Should any specific check be done for sym links ?
*
- * Takes an open file descriptor, the file name, a uid and and
+ * Takes an the file name, its stat information (preferably from fstat() to
+ * avoid races), the uid of the expected owner, their home directory and an
* error buffer plus max size as arguments.
*
* Returns 0 on success and -1 on failure
*/
-static int
-secure_filename(FILE *f, const char *file, struct passwd *pw,
- char *err, size_t errlen)
+int
+auth_secure_path(const char *name, struct stat *stp, const char *pw_dir,
+ uid_t uid, char *err, size_t errlen)
{
- uid_t uid = pw->pw_uid;
char buf[MAXPATHLEN], homedir[MAXPATHLEN];
char *cp;
int comparehome = 0;
struct stat st;
- if (realpath(file, buf) == NULL) {
- snprintf(err, errlen, "realpath %s failed: %s", file,
+ if (realpath(name, buf) == NULL) {
+ snprintf(err, errlen, "realpath %s failed: %s", name,
strerror(errno));
return -1;
}
- if (realpath(pw->pw_dir, homedir) != NULL)
+ if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL)
comparehome = 1;
- /* check the open file to avoid races */
- if (fstat(fileno(f), &st) < 0 ||
- (st.st_uid != 0 && st.st_uid != uid) ||
- (st.st_mode & 022) != 0) {
+ if (!S_ISREG(stp->st_mode)) {
+ snprintf(err, errlen, "%s is not a regular file", buf);
+ return -1;
+ }
+ if ((stp->st_uid != 0 && stp->st_uid != uid) ||
+ (stp->st_mode & 022) != 0) {
snprintf(err, errlen, "bad ownership or modes for file %s",
buf);
return -1;
@@ -483,6 +485,31 @@ secure_filename(FILE *f, const char *fil
return 0;
}
+/*
+ * Version of secure_path() that accepts an open file descriptor to
+ * avoid races.
+ *
+ * Returns 0 on success and -1 on failure
+ */
+static int
+secure_filename(FILE *f, const char *file, struct passwd *pw,
+ char *err, size_t errlen)
+{
+ uid_t uid = pw->pw_uid;
+ char buf[MAXPATHLEN], homedir[MAXPATHLEN];
+ char *cp;
+ int comparehome = 0;
+ struct stat st;
+
+ /* check the open file to avoid races */
+ if (fstat(fileno(f), &st) < 0) {
+ snprintf(err, errlen, "cannot stat file %s: %s",
+ buf, strerror(errno));
+ return -1;
+ }
+ return auth_secure_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen);
+}
+
static FILE *
auth_openfile(const char *file, struct passwd *pw, int strict_modes,
int log_missing, char *file_type)
diff -up openssh-6.1p1/auth.h.akc openssh-6.1p1/auth.h
--- openssh-6.1p1/auth.h.akc 2013-02-14 17:46:45.259546968 +0100
+++ openssh-6.1p1/auth.h 2013-02-14 17:46:45.274546903 +0100
@@ -125,6 +125,10 @@ int auth_rhosts_rsa_key_allowed(struct
int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
int user_key_allowed(struct passwd *, Key *);
+struct stat;
+int auth_secure_path(const char *, struct stat *, const char *, uid_t,
+ char *, size_t);
+
#ifdef KRB5
int auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client, krb5_data *);
int auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt);
diff -up openssh-6.1p1/servconf.c.akc openssh-6.1p1/servconf.c
--- openssh-6.1p1/servconf.c.akc 2013-02-14 17:46:45.193547257 +0100
+++ openssh-6.1p1/servconf.c 2013-02-14 17:46:45.274546903 +0100
@@ -137,6 +137,8 @@ initialize_server_options(ServerOptions
options->num_permitted_opens = -1;
options->adm_forced_command = NULL;
options->chroot_directory = NULL;
+ options->authorized_keys_command = NULL;
+ options->authorized_keys_command_user = NULL;
options->zero_knowledge_password_authentication = -1;
options->revoked_keys_file = NULL;
options->trusted_user_ca_keys = NULL;
@@ -331,6 +333,7 @@ typedef enum {
sZeroKnowledgePasswordAuthentication, sHostCertificate,
sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
sKexAlgorithms, sIPQoS, sVersionAddendum,
+ sAuthorizedKeysCommand, sAuthorizedKeysCommandUser,
sAuthenticationMethods,
sDeprecated, sUnsupported
} ServerOpCodes;
@@ -457,6 +460,9 @@ static struct {
{ "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL },
{ "ipqos", sIPQoS, SSHCFG_ALL },
{ "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL },
+ { "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL },
+ { "authorizedkeyscommandrunas", sAuthorizedKeysCommandUser, SSHCFG_ALL },
+ { "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL },
{ "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL },
{ NULL, sBadOption, 0 }
};
@@ -1520,6 +1526,26 @@ process_server_config_line(ServerOptions
}
return 0;
+ case sAuthorizedKeysCommand:
+ len = strspn(cp, WHITESPACE);
+ if (*activep && options->authorized_keys_command == NULL) {
+ options->authorized_keys_command = xstrdup(cp + len);
+ if (*options->authorized_keys_command != '/') {
+ fatal("%.200s line %d: AuthorizedKeysCommand "
+ "must be an absolute path",
+ filename, linenum);
+ }
+ }
+ return 0;
+
+ case sAuthorizedKeysCommandUser:
+ charptr = &options->authorized_keys_command_user;
+
+ arg = strdelim(&cp);
+ if (*activep && *charptr == NULL)
+ *charptr = xstrdup(arg);
+ break;
+
case sDeprecated:
logit("%s line %d: Deprecated option %s",
filename, linenum, arg);
@@ -1670,6 +1696,8 @@ copy_set_server_options(ServerOptions *d
M_CP_INTOPT(hostbased_uses_name_from_packet_only);
M_CP_INTOPT(kbd_interactive_authentication);
M_CP_INTOPT(zero_knowledge_password_authentication);
+ M_CP_STROPT(authorized_keys_command);
+ M_CP_STROPT(authorized_keys_command_user);
M_CP_INTOPT(permit_root_login);
M_CP_INTOPT(permit_empty_passwd);
@@ -1930,6 +1958,8 @@ dump_config(ServerOptions *o)
dump_cfg_string(sAuthorizedPrincipalsFile,
o->authorized_principals_file);
dump_cfg_string(sVersionAddendum, o->version_addendum);
+ dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command);
+ dump_cfg_string(sAuthorizedKeysCommandUser, o->authorized_keys_command_user);
/* string arguments requiring a lookup */
dump_cfg_string(sLogLevel, log_level_name(o->log_level));
diff -up openssh-6.1p1/servconf.h.akc openssh-6.1p1/servconf.h
--- openssh-6.1p1/servconf.h.akc 2013-02-14 17:46:45.194547252 +0100
+++ openssh-6.1p1/servconf.h 2013-02-14 17:46:45.275546898 +0100
@@ -167,6 +167,8 @@ typedef struct {
char *revoked_keys_file;
char *trusted_user_ca_keys;
char *authorized_principals_file;
+ char *authorized_keys_command;
+ char *authorized_keys_command_user;
char *version_addendum; /* Appended to SSH banner */
diff -up openssh-6.1p1/sshd.c.akc openssh-6.1p1/sshd.c
--- openssh-6.1p1/sshd.c.akc 2013-02-14 17:46:45.270546920 +0100
+++ openssh-6.1p1/sshd.c 2013-02-14 17:46:45.276546894 +0100
@@ -366,9 +366,20 @@ main_sigchld_handler(int sig)
static void
grace_alarm_handler(int sig)
{
+ pid_t pgid;
+
if (use_privsep && pmonitor != NULL && pmonitor->m_pid > 0)
kill(pmonitor->m_pid, SIGALRM);
+ /*
+ * Try to kill any processes that we have spawned, E.g. authorized
+ * keys command helpers.
+ */
+ if ((pgid = getpgid(0)) == getpid()) {
+ signal(SIGTERM, SIG_IGN);
+ killpg(pgid, SIGTERM);
+ }
+
/* Log error and exit. */
sigdie("Timeout before authentication for %s", get_remote_ipaddr());
}
diff -up openssh-6.1p1/sshd_config.0.akc openssh-6.1p1/sshd_config.0
--- openssh-6.1p1/sshd_config.0.akc 2012-08-29 02:53:04.000000000 +0200
+++ openssh-6.1p1/sshd_config.0 2013-02-14 17:46:45.276546894 +0100
@@ -71,6 +71,23 @@ DESCRIPTION
See PATTERNS in ssh_config(5) for more information on patterns.
+ AuthorizedKeysCommand
+
+ Specifies a program to be used for lookup of the user's
+ public keys. The program will be invoked with its first
+ argument the name of the user being authorized, and should produce
+ on standard output AuthorizedKeys lines (see AUTHORIZED_KEYS
+ in sshd(8)). By default (or when set to the empty string) there is no
+ AuthorizedKeysCommand run. If the AuthorizedKeysCommand does not successfully
+ authorize the user, authorization falls through to the
+ AuthorizedKeysFile. Note that this option has an effect
+ only with PubkeyAuthentication turned on.
+
+ AuthorizedKeysCommandRunAs
+ Specifies the user under whose account the AuthorizedKeysCommand is run.
+ Empty string (the default value) means the user being authorized
+ is used.
+
AuthorizedKeysFile
Specifies the file that contains the public keys that can be used
for user authentication. The format is described in the
@@ -402,7 +419,8 @@ DESCRIPTION
Only a subset of keywords may be used on the lines following a
Match keyword. Available keywords are AcceptEnv,
AllowAgentForwarding, AllowGroups, AllowTcpForwarding,
- AllowUsers, AuthorizedKeysFile, AuthorizedPrincipalsFile, Banner,
+ AllowUsers, AuthorizedKeysFile, AuthorizedKeysCommand,
+ AuthorizedKeysCommandRunAs, AuthorizedPrincipalsFile, Banner,
ChrootDirectory, DenyGroups, DenyUsers, ForceCommand,
GatewayPorts, GSSAPIAuthentication, HostbasedAuthentication,
HostbasedUsesNameFromPacketOnly, KbdInteractiveAuthentication,
diff -up openssh-6.1p1/sshd_config.5.akc openssh-6.1p1/sshd_config.5
--- openssh-6.1p1/sshd_config.5.akc 2013-02-14 17:46:45.195547248 +0100
+++ openssh-6.1p1/sshd_config.5 2013-02-14 17:46:45.277546890 +0100
@@ -173,6 +173,20 @@ Note that each authentication method lis
in the configuration.
The default is not to require multiple authentication; successful completion
of a single authentication method is sufficient.
+.It Cm AuthorizedKeysCommand
+Specifies a program to be used for lookup of the user's public keys.
+The program will be invoked with a single argument of the username
+being authenticated, and should produce on standard output zero or
+more lines of authorized_keys output (see AUTHORIZED_KEYS in
+.Xr sshd 8 )
+If a key supplied by AuthorizedKeysCommand does not successfully authenticate
+and authorize the user then public key authentication continues using the usual
+.Cm AuthorizedKeysFile
+files.
+By default, no AuthorizedKeysCommand is run.
+.It Cm AuthorizedKeysCommandUser
+Specifies the user under whose account the AuthorizedKeysCommand is run.
+The default is the user being authenticated.
.It Cm AuthorizedKeysFile
Specifies the file that contains the public keys that can be used
for user authentication.
@@ -734,6 +748,8 @@ Available keywords are
.Cm AllowTcpForwarding ,
.Cm AllowUsers ,
.Cm AuthenticationMethods ,
+.Cm AuthorizedKeysCommand ,
+.Cm AuthorizedKeysCommandUser ,
.Cm AuthorizedKeysFile ,
.Cm AuthorizedPrincipalsFile ,
.Cm Banner ,
@@ -749,6 +765,7 @@ Available keywords are
.Cm KerberosAuthentication ,
.Cm MaxAuthTries ,
.Cm MaxSessions ,
+.Cm PubkeyAuthentication ,
.Cm PasswordAuthentication ,
.Cm PermitEmptyPasswords ,
.Cm PermitOpen ,
diff -up openssh-6.1p1/sshd_config.akc openssh-6.1p1/sshd_config
--- openssh-6.1p1/sshd_config.akc 2012-07-31 04:21:34.000000000 +0200
+++ openssh-6.1p1/sshd_config 2013-02-14 17:46:45.277546890 +0100
@@ -49,6 +49,9 @@
# but this is overridden so installations will only check .ssh/authorized_keys
AuthorizedKeysFile .ssh/authorized_keys
+#AuthorizedKeysCommand none
+#AuthorizedKeysCommandUser nobody
+
#AuthorizedPrincipalsFile none
# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts

View File

@ -0,0 +1,18 @@
diff -up openssh-6.1p1/contrib/Makefile.askpass-ld openssh-6.1p1/contrib/Makefile
--- openssh-6.1p1/contrib/Makefile.askpass-ld 2012-05-19 07:24:37.000000000 +0200
+++ openssh-6.1p1/contrib/Makefile 2012-09-14 20:35:47.565704718 +0200
@@ -4,12 +4,12 @@ all:
@echo "Valid targets: gnome-ssh-askpass1 gnome-ssh-askpass2"
gnome-ssh-askpass1: gnome-ssh-askpass1.c
- $(CC) `gnome-config --cflags gnome gnomeui` \
+ $(CC) ${CFLAGS} `gnome-config --cflags gnome gnomeui` \
gnome-ssh-askpass1.c -o gnome-ssh-askpass1 \
`gnome-config --libs gnome gnomeui`
gnome-ssh-askpass2: gnome-ssh-askpass2.c
- $(CC) `$(PKG_CONFIG) --cflags gtk+-2.0` \
+ $(CC) ${CFLAGS} `$(PKG_CONFIG) --cflags gtk+-2.0` \
gnome-ssh-askpass2.c -o gnome-ssh-askpass2 \
`$(PKG_CONFIG) --libs gtk+-2.0 x11`

672
openssh-6.1p1-audit4.patch Normal file
View File

@ -0,0 +1,672 @@
diff -up openssh-6.1p1/audit-bsm.c.audit4 openssh-6.1p1/audit-bsm.c
--- openssh-6.1p1/audit-bsm.c.audit4 2012-11-28 14:20:38.990185823 +0100
+++ openssh-6.1p1/audit-bsm.c 2012-11-28 14:20:38.995185800 +0100
@@ -485,4 +485,10 @@ audit_kex_body(int ctos, char *enc, char
{
/* not implemented */
}
+
+void
+audit_session_key_free_body(int ctos, pid_t pid, uid_t uid)
+{
+ /* not implemented */
+}
#endif /* BSM */
diff -up openssh-6.1p1/audit.c.audit4 openssh-6.1p1/audit.c
--- openssh-6.1p1/audit.c.audit4 2012-11-28 14:20:38.990185823 +0100
+++ openssh-6.1p1/audit.c 2012-11-28 14:20:38.995185800 +0100
@@ -143,6 +143,12 @@ audit_kex(int ctos, char *enc, char *mac
PRIVSEP(audit_kex_body(ctos, enc, mac, comp, getpid(), getuid()));
}
+void
+audit_session_key_free(int ctos)
+{
+ PRIVSEP(audit_session_key_free_body(ctos, getpid(), getuid()));
+}
+
# ifndef CUSTOM_SSH_AUDIT_EVENTS
/*
* Null implementations of audit functions.
@@ -274,5 +280,15 @@ audit_kex_body(int ctos, char *enc, char
(unsigned)geteuid(), ctos, enc, mac, compress, (long)pid,
(unsigned)uid);
}
+
+/*
+ * This will be called on succesfull session key discard
+ */
+void
+audit_session_key_free_body(int ctos, pid_t pid, uid_t uid)
+{
+ debug("audit session key discard euid %u direction %d from pid %ld uid %u",
+ (unsigned)geteuid(), ctos, (long)pid, (unsigned)uid);
+}
# endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */
#endif /* SSH_AUDIT_EVENTS */
diff -up openssh-6.1p1/audit.h.audit4 openssh-6.1p1/audit.h
--- openssh-6.1p1/audit.h.audit4 2012-11-28 14:20:38.990185823 +0100
+++ openssh-6.1p1/audit.h 2012-11-28 14:20:38.995185800 +0100
@@ -62,5 +62,7 @@ void audit_unsupported(int);
void audit_kex(int, char *, char *, char *);
void audit_unsupported_body(int);
void audit_kex_body(int, char *, char *, char *, pid_t, uid_t);
+void audit_session_key_free(int ctos);
+void audit_session_key_free_body(int ctos, pid_t, uid_t);
#endif /* _SSH_AUDIT_H */
diff -up openssh-6.1p1/audit-linux.c.audit4 openssh-6.1p1/audit-linux.c
--- openssh-6.1p1/audit-linux.c.audit4 2012-11-28 14:20:38.990185823 +0100
+++ openssh-6.1p1/audit-linux.c 2012-11-28 14:20:38.995185800 +0100
@@ -294,6 +294,8 @@ audit_unsupported_body(int what)
#endif
}
+const static char *direction[] = { "from-server", "from-client", "both" };
+
void
audit_kex_body(int ctos, char *enc, char *mac, char *compress, pid_t pid,
uid_t uid)
@@ -301,7 +303,6 @@ audit_kex_body(int ctos, char *enc, char
#ifdef AUDIT_CRYPTO_SESSION
char buf[AUDIT_LOG_SIZE];
int audit_fd, audit_ok;
- const static char *direction[] = { "from-server", "from-client", "both" };
Cipher *cipher = cipher_by_name(enc);
char *s;
@@ -327,4 +328,32 @@ audit_kex_body(int ctos, char *enc, char
#endif
}
+void
+audit_session_key_free_body(int ctos, pid_t pid, uid_t uid)
+{
+ char buf[AUDIT_LOG_SIZE];
+ int audit_fd, audit_ok;
+ char *s;
+
+ snprintf(buf, sizeof(buf), "op=destroy kind=session fp=? direction=%s spid=%jd suid=%jd rport=%d laddr=%s lport=%d ",
+ direction[ctos], (intmax_t)pid, (intmax_t)uid,
+ get_remote_port(),
+ (s = get_local_ipaddr(packet_get_connection_in())),
+ get_local_port());
+ xfree(s);
+ audit_fd = audit_open();
+ if (audit_fd < 0) {
+ if (errno != EINVAL && errno != EPROTONOSUPPORT &&
+ errno != EAFNOSUPPORT)
+ error("cannot open audit");
+ return;
+ }
+ audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER,
+ buf, NULL, get_remote_ipaddr(), NULL, 1);
+ audit_close(audit_fd);
+ /* do not abort if the error is EPERM and sshd is run as non root user */
+ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0)))
+ error("cannot write into audit");
+}
+
#endif /* USE_LINUX_AUDIT */
diff -up openssh-6.1p1/auditstub.c.audit4 openssh-6.1p1/auditstub.c
--- openssh-6.1p1/auditstub.c.audit4 2012-11-28 14:20:38.990185823 +0100
+++ openssh-6.1p1/auditstub.c 2012-11-28 14:20:38.995185800 +0100
@@ -27,6 +27,8 @@
* Red Hat author: Jan F. Chadima <jchadima@redhat.com>
*/
+#include <sys/types.h>
+
void
audit_unsupported(int n)
{
@@ -37,3 +39,12 @@ audit_kex(int ctos, char *enc, char *mac
{
}
+void
+audit_session_key_free(int ctos)
+{
+}
+
+void
+audit_session_key_free_body(int ctos, pid_t pid, uid_t uid)
+{
+}
diff -up openssh-6.1p1/kex.c.audit4 openssh-6.1p1/kex.c
--- openssh-6.1p1/kex.c.audit4 2012-11-28 14:20:38.991185818 +0100
+++ openssh-6.1p1/kex.c 2012-11-28 14:20:38.995185800 +0100
@@ -624,3 +624,34 @@ dump_digest(char *msg, u_char *digest, i
fprintf(stderr, "\n");
}
#endif
+
+static void
+enc_destroy(Enc *enc)
+{
+ if (enc == NULL)
+ return;
+
+ if (enc->key) {
+ memset(enc->key, 0, enc->key_len);
+ xfree(enc->key);
+ }
+
+ if (enc->iv) {
+ memset(enc->iv, 0, enc->block_size);
+ xfree(enc->iv);
+ }
+
+ memset(enc, 0, sizeof(*enc));
+}
+
+void
+newkeys_destroy(Newkeys *newkeys)
+{
+ if (newkeys == NULL)
+ return;
+
+ enc_destroy(&newkeys->enc);
+ mac_destroy(&newkeys->mac);
+ memset(&newkeys->comp, 0, sizeof(newkeys->comp));
+}
+
diff -up openssh-6.1p1/kex.h.audit4 openssh-6.1p1/kex.h
--- openssh-6.1p1/kex.h.audit4 2010-09-24 14:11:14.000000000 +0200
+++ openssh-6.1p1/kex.h 2012-11-28 14:20:38.996185795 +0100
@@ -156,6 +156,8 @@ void kexgex_server(Kex *);
void kexecdh_client(Kex *);
void kexecdh_server(Kex *);
+void newkeys_destroy(Newkeys *newkeys);
+
void
kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int,
BIGNUM *, BIGNUM *, BIGNUM *, u_char **, u_int *);
diff -up openssh-6.1p1/mac.c.audit4 openssh-6.1p1/mac.c
--- openssh-6.1p1/mac.c.audit4 2012-06-30 00:34:59.000000000 +0200
+++ openssh-6.1p1/mac.c 2012-11-28 14:20:38.996185795 +0100
@@ -169,6 +169,20 @@ mac_clear(Mac *mac)
mac->umac_ctx = NULL;
}
+void
+mac_destroy(Mac *mac)
+{
+ if (mac == NULL)
+ return;
+
+ if (mac->key) {
+ memset(mac->key, 0, mac->key_len);
+ xfree(mac->key);
+ }
+
+ memset(mac, 0, sizeof(*mac));
+}
+
/* XXX copied from ciphers_valid */
#define MAC_SEP ","
int
diff -up openssh-6.1p1/mac.h.audit4 openssh-6.1p1/mac.h
--- openssh-6.1p1/mac.h.audit4 2007-06-11 06:01:42.000000000 +0200
+++ openssh-6.1p1/mac.h 2012-11-28 14:20:38.996185795 +0100
@@ -28,3 +28,4 @@ int mac_setup(Mac *, char *);
int mac_init(Mac *);
u_char *mac_compute(Mac *, u_int32_t, u_char *, int);
void mac_clear(Mac *);
+void mac_destroy(Mac *);
diff -up openssh-6.1p1/monitor.c.audit4 openssh-6.1p1/monitor.c
--- openssh-6.1p1/monitor.c.audit4 2012-11-28 14:20:38.992185813 +0100
+++ openssh-6.1p1/monitor.c 2012-11-28 17:02:17.677045093 +0100
@@ -189,6 +189,7 @@ int mm_answer_audit_command(int, Buffer
int mm_answer_audit_end_command(int, Buffer *);
int mm_answer_audit_unsupported_body(int, Buffer *);
int mm_answer_audit_kex_body(int, Buffer *);
+int mm_answer_audit_session_key_free_body(int, Buffer *);
#endif
static int monitor_read_log(struct monitor *);
@@ -241,6 +242,7 @@ struct mon_table mon_dispatch_proto20[]
{MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
{MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body},
{MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body},
+ {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body},
#endif
#ifdef BSD_AUTH
{MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery},
@@ -280,6 +282,7 @@ struct mon_table mon_dispatch_postauth20
{MONITOR_REQ_AUDIT_END_COMMAND, MON_PERMIT, mm_answer_audit_end_command},
{MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body},
{MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body},
+ {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body},
#endif
{0, 0, NULL}
};
@@ -313,6 +316,7 @@ struct mon_table mon_dispatch_proto15[]
{MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
{MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body},
{MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body},
+ {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body},
#endif
{0, 0, NULL}
};
@@ -327,6 +331,7 @@ struct mon_table mon_dispatch_postauth15
{MONITOR_REQ_AUDIT_END_COMMAND, MON_PERMIT, mm_answer_audit_end_command},
{MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body},
{MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body},
+ {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body},
#endif
{0, 0, NULL}
};
@@ -448,10 +453,6 @@ monitor_child_preauth(Authctxt *_authctx
#endif
}
- /* Drain any buffered messages from the child */
- while (pmonitor->m_log_recvfd >= 0 && monitor_read_log(pmonitor) == 0)
- ;
-
if (!authctxt->valid)
fatal("%s: authenticated invalid user", __func__);
if (strcmp(auth_method, "unknown") == 0)
@@ -1950,11 +1951,13 @@ mm_get_keystate(struct monitor *pmonitor
blob = buffer_get_string(&m, &bloblen);
current_keys[MODE_OUT] = mm_newkeys_from_blob(blob, bloblen);
+ memset(blob, 0, bloblen);
xfree(blob);
debug3("%s: Waiting for second key", __func__);
blob = buffer_get_string(&m, &bloblen);
current_keys[MODE_IN] = mm_newkeys_from_blob(blob, bloblen);
+ memset(blob, 0, bloblen);
xfree(blob);
/* Now get sequence numbers for the packets */
@@ -2000,6 +2003,21 @@ mm_get_keystate(struct monitor *pmonitor
}
buffer_free(&m);
+
+#ifdef SSH_AUDIT_EVENTS
+ if (compat20) {
+ buffer_init(&m);
+ mm_request_receive_expect(pmonitor->m_sendfd,
+ MONITOR_REQ_AUDIT_SESSION_KEY_FREE, &m);
+ mm_answer_audit_session_key_free_body(pmonitor->m_sendfd, &m);
+ buffer_free(&m);
+ }
+#endif
+
+ /* Drain any buffered messages from the child */
+ while (pmonitor->m_log_recvfd >= 0 && monitor_read_log(pmonitor) == 0)
+ ;
+
}
@@ -2444,4 +2462,22 @@ mm_answer_audit_kex_body(int sock, Buffe
return 0;
}
+int
+mm_answer_audit_session_key_free_body(int sock, Buffer *m)
+{
+ int ctos;
+ pid_t pid;
+ uid_t uid;
+
+ ctos = buffer_get_int(m);
+ pid = buffer_get_int64(m);
+ uid = buffer_get_int64(m);
+
+ audit_session_key_free_body(ctos, pid, uid);
+
+ buffer_clear(m);
+
+ mm_request_send(sock, MONITOR_ANS_AUDIT_SESSION_KEY_FREE, m);
+ return 0;
+}
#endif /* SSH_AUDIT_EVENTS */
diff -up openssh-6.1p1/monitor.h.audit4 openssh-6.1p1/monitor.h
--- openssh-6.1p1/monitor.h.audit4 2012-11-28 14:20:38.992185813 +0100
+++ openssh-6.1p1/monitor.h 2012-11-28 14:20:38.997185790 +0100
@@ -63,6 +63,7 @@ enum monitor_reqtype {
MONITOR_ANS_AUDIT_COMMAND, MONITOR_REQ_AUDIT_END_COMMAND,
MONITOR_REQ_AUDIT_UNSUPPORTED, MONITOR_ANS_AUDIT_UNSUPPORTED,
MONITOR_REQ_AUDIT_KEX, MONITOR_ANS_AUDIT_KEX,
+ MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MONITOR_ANS_AUDIT_SESSION_KEY_FREE,
MONITOR_REQ_TERM,
MONITOR_REQ_JPAKE_STEP1, MONITOR_ANS_JPAKE_STEP1,
MONITOR_REQ_JPAKE_GET_PWDATA, MONITOR_ANS_JPAKE_GET_PWDATA,
diff -up openssh-6.1p1/monitor_wrap.c.audit4 openssh-6.1p1/monitor_wrap.c
--- openssh-6.1p1/monitor_wrap.c.audit4 2012-11-28 14:20:38.992185813 +0100
+++ openssh-6.1p1/monitor_wrap.c 2012-11-28 14:20:38.997185790 +0100
@@ -653,12 +653,14 @@ mm_send_keystate(struct monitor *monitor
fatal("%s: conversion of newkeys failed", __func__);
buffer_put_string(&m, blob, bloblen);
+ memset(blob, 0, bloblen);
xfree(blob);
if (!mm_newkeys_to_blob(MODE_IN, &blob, &bloblen))
fatal("%s: conversion of newkeys failed", __func__);
buffer_put_string(&m, blob, bloblen);
+ memset(blob, 0, bloblen);
xfree(blob);
packet_get_state(MODE_OUT, &seqnr, &blocks, &packets, &bytes);
@@ -1522,4 +1524,19 @@ mm_audit_kex_body(int ctos, char *cipher
buffer_free(&m);
}
+
+void
+mm_audit_session_key_free_body(int ctos, pid_t pid, uid_t uid)
+{
+ Buffer m;
+
+ buffer_init(&m);
+ buffer_put_int(&m, ctos);
+ buffer_put_int64(&m, pid);
+ buffer_put_int64(&m, uid);
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_SESSION_KEY_FREE, &m);
+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_SESSION_KEY_FREE,
+ &m);
+ buffer_free(&m);
+}
#endif /* SSH_AUDIT_EVENTS */
diff -up openssh-6.1p1/monitor_wrap.h.audit4 openssh-6.1p1/monitor_wrap.h
--- openssh-6.1p1/monitor_wrap.h.audit4 2012-11-28 14:20:38.992185813 +0100
+++ openssh-6.1p1/monitor_wrap.h 2012-11-28 14:20:38.997185790 +0100
@@ -79,6 +79,7 @@ int mm_audit_run_command(const char *);
void mm_audit_end_command(int, const char *);
void mm_audit_unsupported_body(int);
void mm_audit_kex_body(int, char *, char *, char *, pid_t, uid_t);
+void mm_audit_session_key_free_body(int, pid_t, uid_t);
#endif
struct Session;
diff -up openssh-6.1p1/packet.c.audit4 openssh-6.1p1/packet.c
--- openssh-6.1p1/packet.c.audit4 2012-11-28 14:20:38.973185902 +0100
+++ openssh-6.1p1/packet.c 2012-11-28 14:20:38.998185785 +0100
@@ -60,6 +60,7 @@
#include <signal.h>
#include "xmalloc.h"
+#include "audit.h"
#include "buffer.h"
#include "packet.h"
#include "crc32.h"
@@ -470,6 +471,13 @@ packet_get_connection_out(void)
return active_state->connection_out;
}
+static int
+packet_state_has_keys (const struct session_state *state)
+{
+ return state != NULL &&
+ (state->newkeys[MODE_IN] != NULL || state->newkeys[MODE_OUT] != NULL);
+}
+
/* Closes the connection and clears and frees internal data structures. */
void
@@ -478,13 +486,6 @@ packet_close(void)
if (!active_state->initialized)
return;
active_state->initialized = 0;
- if (active_state->connection_in == active_state->connection_out) {
- shutdown(active_state->connection_out, SHUT_RDWR);
- close(active_state->connection_out);
- } else {
- close(active_state->connection_in);
- close(active_state->connection_out);
- }
buffer_free(&active_state->input);
buffer_free(&active_state->output);
buffer_free(&active_state->outgoing_packet);
@@ -493,8 +494,18 @@ packet_close(void)
buffer_free(&active_state->compression_buffer);
buffer_compress_uninit();
}
- cipher_cleanup(&active_state->send_context);
- cipher_cleanup(&active_state->receive_context);
+ if (packet_state_has_keys(active_state)) {
+ cipher_cleanup(&active_state->send_context);
+ cipher_cleanup(&active_state->receive_context);
+ audit_session_key_free(2);
+ }
+ if (active_state->connection_in == active_state->connection_out) {
+ shutdown(active_state->connection_out, SHUT_RDWR);
+ close(active_state->connection_out);
+ } else {
+ close(active_state->connection_in);
+ close(active_state->connection_out);
+ }
}
/* Sets remote side protocol flags. */
@@ -729,6 +740,23 @@ packet_send1(void)
*/
}
+static void
+newkeys_destroy_and_free(Newkeys *newkeys)
+{
+ if (newkeys == NULL)
+ return;
+
+ xfree(newkeys->enc.name);
+
+ mac_clear(&newkeys->mac);
+ xfree(newkeys->mac.name);
+
+ xfree(newkeys->comp.name);
+
+ newkeys_destroy(newkeys);
+ xfree(newkeys);
+}
+
void
set_newkeys(int mode)
{
@@ -754,18 +782,9 @@ set_newkeys(int mode)
}
if (active_state->newkeys[mode] != NULL) {
debug("set_newkeys: rekeying");
+ audit_session_key_free(mode);
cipher_cleanup(cc);
- enc = &active_state->newkeys[mode]->enc;
- mac = &active_state->newkeys[mode]->mac;
- comp = &active_state->newkeys[mode]->comp;
- mac_clear(mac);
- xfree(enc->name);
- xfree(enc->iv);
- xfree(enc->key);
- xfree(mac->name);
- xfree(mac->key);
- xfree(comp->name);
- xfree(active_state->newkeys[mode]);
+ newkeys_destroy_and_free(active_state->newkeys[mode]);
}
active_state->newkeys[mode] = kex_get_newkeys(mode);
if (active_state->newkeys[mode] == NULL)
@@ -1921,6 +1940,47 @@ packet_get_newkeys(int mode)
return (void *)active_state->newkeys[mode];
}
+static void
+packet_destroy_state(struct session_state *state)
+{
+ if (state == NULL)
+ return;
+
+ cipher_cleanup(&state->receive_context);
+ cipher_cleanup(&state->send_context);
+
+ buffer_free(&state->input);
+ buffer_free(&state->output);
+ buffer_free(&state->outgoing_packet);
+ buffer_free(&state->incoming_packet);
+ buffer_free(&state->compression_buffer);
+ newkeys_destroy_and_free(state->newkeys[MODE_IN]);
+ state->newkeys[MODE_IN] = NULL;
+ newkeys_destroy_and_free(state->newkeys[MODE_OUT]);
+ state->newkeys[MODE_OUT] = NULL;
+ mac_destroy(state->packet_discard_mac);
+// TAILQ_HEAD(, packet) outgoing;
+// memset(state, 0, sizeof(state));
+}
+
+void
+packet_destroy_all(int audit_it, int privsep)
+{
+ if (audit_it)
+ audit_it = packet_state_has_keys (active_state) ||
+ packet_state_has_keys (backup_state);
+ packet_destroy_state(active_state);
+ packet_destroy_state(backup_state);
+ if (audit_it) {
+#ifdef SSH_AUDIT_EVENTS
+ if (privsep)
+ audit_session_key_free(2);
+ else
+ audit_session_key_free_body(2, getpid(), getuid());
+#endif
+ }
+}
+
/*
* Save the state for the real connection, and use a separate state when
* resuming a suspended connection.
@@ -1928,18 +1988,12 @@ packet_get_newkeys(int mode)
void
packet_backup_state(void)
{
- struct session_state *tmp;
-
close(active_state->connection_in);
active_state->connection_in = -1;
close(active_state->connection_out);
active_state->connection_out = -1;
- if (backup_state)
- tmp = backup_state;
- else
- tmp = alloc_session_state();
backup_state = active_state;
- active_state = tmp;
+ active_state = alloc_session_state();
}
/*
@@ -1956,9 +2010,7 @@ packet_restore_state(void)
backup_state = active_state;
active_state = tmp;
active_state->connection_in = backup_state->connection_in;
- backup_state->connection_in = -1;
active_state->connection_out = backup_state->connection_out;
- backup_state->connection_out = -1;
len = buffer_len(&backup_state->input);
if (len > 0) {
buf = buffer_ptr(&backup_state->input);
@@ -1966,4 +2018,10 @@ packet_restore_state(void)
buffer_clear(&backup_state->input);
add_recv_bytes(len);
}
+ backup_state->connection_in = -1;
+ backup_state->connection_out = -1;
+ packet_destroy_state(backup_state);
+ xfree(backup_state);
+ backup_state = NULL;
}
+
diff -up openssh-6.1p1/packet.h.audit4 openssh-6.1p1/packet.h
--- openssh-6.1p1/packet.h.audit4 2012-02-10 22:19:21.000000000 +0100
+++ openssh-6.1p1/packet.h 2012-11-28 14:20:38.998185785 +0100
@@ -123,4 +123,5 @@ void packet_restore_state(void);
void *packet_get_input(void);
void *packet_get_output(void);
+void packet_destroy_all(int, int);
#endif /* PACKET_H */
diff -up openssh-6.1p1/session.c.audit4 openssh-6.1p1/session.c
--- openssh-6.1p1/session.c.audit4 2012-11-28 14:20:38.983185855 +0100
+++ openssh-6.1p1/session.c 2012-11-28 14:20:38.998185785 +0100
@@ -1634,6 +1634,9 @@ do_child(Session *s, const char *command
/* remove hostkey from the child's memory */
destroy_sensitive_data();
+ /* 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) {
diff -up openssh-6.1p1/sshd.c.audit4 openssh-6.1p1/sshd.c
--- openssh-6.1p1/sshd.c.audit4 2012-11-28 14:20:38.993185808 +0100
+++ openssh-6.1p1/sshd.c 2012-11-28 14:20:38.999185780 +0100
@@ -692,6 +692,8 @@ privsep_preauth(Authctxt *authctxt)
}
}
+extern Newkeys *current_keys[];
+
static void
privsep_postauth(Authctxt *authctxt)
{
@@ -716,6 +718,10 @@ privsep_postauth(Authctxt *authctxt)
else if (pmonitor->m_pid != 0) {
verbose("User child is on pid %ld", (long)pmonitor->m_pid);
buffer_clear(&loginmsg);
+ newkeys_destroy(current_keys[MODE_OUT]);
+ newkeys_destroy(current_keys[MODE_IN]);
+ audit_session_key_free_body(2, getpid(), getuid());
+ packet_destroy_all(0, 0);
monitor_child_postauth(pmonitor);
/* NEVERREACHED */
@@ -2016,6 +2022,7 @@ main(int ac, char **av)
*/
if (use_privsep) {
mm_send_keystate(pmonitor);
+ packet_destroy_all(1, 1);
exit(0);
}
@@ -2068,6 +2075,8 @@ main(int ac, char **av)
do_authenticated(authctxt);
/* The connection has been terminated. */
+ packet_destroy_all(1, 1);
+
packet_get_state(MODE_IN, NULL, NULL, NULL, &ibytes);
packet_get_state(MODE_OUT, NULL, NULL, NULL, &obytes);
verbose("Transferred: sent %llu, received %llu bytes",
@@ -2385,6 +2394,16 @@ do_ssh2_kex(void)
void
cleanup_exit(int i)
{
+ static int in_cleanup = 0;
+ int is_privsep_child;
+
+ /* cleanup_exit can be called at the very least from the privsep
+ wrappers used for auditing. Make sure we don't recurse
+ indefinitely. */
+ if (in_cleanup)
+ _exit(i);
+ in_cleanup = 1;
+
if (the_authctxt) {
do_cleanup(the_authctxt);
if (use_privsep && privsep_is_preauth && pmonitor->m_pid > 1) {
@@ -2395,6 +2414,8 @@ cleanup_exit(int i)
pmonitor->m_pid, strerror(errno));
}
}
+ is_privsep_child = use_privsep && pmonitor != NULL && !mm_is_monitor();
+ packet_destroy_all(1, is_privsep_child);
#ifdef SSH_AUDIT_EVENTS
/* done after do_cleanup so it can cancel the PAM auth 'thread' */
if ((the_authctxt == NULL || !the_authctxt->authenticated) &&

View File

@ -0,0 +1,841 @@
diff --git a/auth.c b/auth.c
index ee0cb05..1b2fc2b 100644
--- a/auth.c
+++ b/auth.c
@@ -251,7 +251,8 @@ allowed_user(struct passwd * pw)
}
void
-auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
+auth_log(Authctxt *authctxt, int authenticated, int partial,
+ const char *method, const char *submethod, const char *info)
{
void (*authlog) (const char *fmt,...) = verbose;
char *authmsg;
@@ -268,12 +269,15 @@ auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
if (authctxt->postponed)
authmsg = "Postponed";
+ else if (partial)
+ authmsg = "Partial";
else
authmsg = authenticated ? "Accepted" : "Failed";
- authlog("%s %s for %s%.100s from %.200s port %d%s",
+ authlog("%s %s%s%s for %s%.100s from %.200s port %d%s",
authmsg,
method,
+ submethod != NULL ? "/" : "", submethod == NULL ? "" : submethod,
authctxt->valid ? "" : "invalid user ",
authctxt->user,
get_remote_ipaddr(),
@@ -303,7 +307,7 @@ auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
* Check whether root logins are disallowed.
*/
int
-auth_root_allowed(char *method)
+auth_root_allowed(const char *method)
{
switch (options.permit_root_login) {
case PERMIT_YES:
diff --git a/auth.h b/auth.h
index 0d786c4..29823bb 100644
--- a/auth.h
+++ b/auth.h
@@ -64,6 +64,8 @@ struct Authctxt {
#ifdef BSD_AUTH
auth_session_t *as;
#endif
+ char **auth_methods; /* modified from server config */
+ u_int num_auth_methods;
#ifdef KRB5
krb5_context krb5_ctx;
krb5_ccache krb5_fwd_ccache;
@@ -142,12 +144,17 @@ void disable_forwarding(void);
void do_authentication(Authctxt *);
void do_authentication2(Authctxt *);
-void auth_log(Authctxt *, int, char *, char *);
-void userauth_finish(Authctxt *, int, char *);
+void auth_log(Authctxt *, int, int, const char *, const char *,
+ const char *);
+void userauth_finish(Authctxt *, int, const char *, const char *);
+int auth_root_allowed(const char *);
+
void userauth_send_banner(const char *);
-int auth_root_allowed(char *);
char *auth2_read_banner(void);
+int auth2_methods_valid(const char *, int);
+int auth2_update_methods_lists(Authctxt *, const char *);
+int auth2_setup_methods_lists(Authctxt *);
void privsep_challenge_enable(void);
diff --git a/auth1.c b/auth1.c
index cc85aec..458a110 100644
--- a/auth1.c
+++ b/auth1.c
@@ -253,7 +253,8 @@ do_authloop(Authctxt *authctxt)
if (options.use_pam && (PRIVSEP(do_pam_account())))
#endif
{
- auth_log(authctxt, 1, "without authentication", "");
+ auth_log(authctxt, 1, 0, "without authentication",
+ NULL, "");
return;
}
}
@@ -352,7 +353,8 @@ do_authloop(Authctxt *authctxt)
skip:
/* Log before sending the reply */
- auth_log(authctxt, authenticated, get_authname(type), info);
+ auth_log(authctxt, authenticated, 0, get_authname(type),
+ NULL, info);
if (client_user != NULL) {
xfree(client_user);
@@ -406,6 +408,11 @@ do_authentication(Authctxt *authctxt)
authctxt->pw = fakepw();
}
+ /* Configuration may have changed as a result of Match */
+ if (options.num_auth_methods != 0)
+ fatal("AuthenticationMethods is not supported with SSH "
+ "protocol 1");
+
setproctitle("%s%s", authctxt->valid ? user : "unknown",
use_privsep ? " [net]" : "");
diff --git a/auth2-chall.c b/auth2-chall.c
index e6dbffe..5f7ec6d 100644
--- a/auth2-chall.c
+++ b/auth2-chall.c
@@ -283,7 +283,7 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
KbdintAuthctxt *kbdintctxt;
int authenticated = 0, res;
u_int i, nresp;
- char **response = NULL, *method;
+ char *devicename = NULL, **response = NULL;
if (authctxt == NULL)
fatal("input_userauth_info_response: no authctxt");
@@ -329,9 +329,7 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
/* Failure! */
break;
}
-
- xasprintf(&method, "keyboard-interactive/%s", kbdintctxt->device->name);
-
+ devicename = kbdintctxt->device->name;
if (!authctxt->postponed) {
if (authenticated) {
auth2_challenge_stop(authctxt);
@@ -341,8 +339,8 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
auth2_challenge_start(authctxt);
}
}
- userauth_finish(authctxt, authenticated, method);
- xfree(method);
+ userauth_finish(authctxt, authenticated, "keyboard-interactive",
+ devicename);
}
void
diff --git a/auth2-gss.c b/auth2-gss.c
index 0d59b21..338c748 100644
--- a/auth2-gss.c
+++ b/auth2-gss.c
@@ -163,7 +163,7 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt)
}
authctxt->postponed = 0;
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
- userauth_finish(authctxt, 0, "gssapi-with-mic");
+ userauth_finish(authctxt, 0, "gssapi-with-mic", NULL);
} else {
if (send_tok.length != 0) {
packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
@@ -251,7 +251,7 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
- userauth_finish(authctxt, authenticated, "gssapi-with-mic");
+ userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL);
}
static void
@@ -291,7 +291,7 @@ input_gssapi_mic(int type, u_int32_t plen, void *ctxt)
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
- userauth_finish(authctxt, authenticated, "gssapi-with-mic");
+ userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL);
}
Authmethod method_gssapi = {
diff --git a/auth2-jpake.c b/auth2-jpake.c
index a460e82..e4ba9aa 100644
--- a/auth2-jpake.c
+++ b/auth2-jpake.c
@@ -556,7 +556,7 @@ input_userauth_jpake_client_confirm(int type, u_int32_t seq, void *ctxt)
authctxt->postponed = 0;
jpake_free(authctxt->jpake_ctx);
authctxt->jpake_ctx = NULL;
- userauth_finish(authctxt, authenticated, method_jpake.name);
+ userauth_finish(authctxt, authenticated, method_jpake.name, NULL);
}
#endif /* JPAKE */
diff --git a/auth2.c b/auth2.c
index b66bef6..ea0fd92 100644
--- a/auth2.c
+++ b/auth2.c
@@ -96,8 +96,10 @@ static void input_service_request(int, u_int32_t, void *);
static void input_userauth_request(int, u_int32_t, void *);
/* helper */
-static Authmethod *authmethod_lookup(const char *);
-static char *authmethods_get(void);
+static Authmethod *authmethod_lookup(Authctxt *, const char *);
+static char *authmethods_get(Authctxt *authctxt);
+static int method_allowed(Authctxt *, const char *);
+static int list_starts_with(const char *, const char *);
char *
auth2_read_banner(void)
@@ -255,6 +257,8 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
if (use_privsep)
mm_inform_authserv(service, style);
userauth_banner();
+ if (auth2_setup_methods_lists(authctxt) != 0)
+ packet_disconnect("no authentication methods enabled");
} else if (strcmp(user, authctxt->user) != 0 ||
strcmp(service, authctxt->service) != 0) {
packet_disconnect("Change of username or service not allowed: "
@@ -277,12 +281,12 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
authctxt->server_caused_failure = 0;
/* try to authenticate user */
- m = authmethod_lookup(method);
+ m = authmethod_lookup(authctxt, method);
if (m != NULL && authctxt->failures < options.max_authtries) {
debug2("input_userauth_request: try method %s", method);
authenticated = m->userauth(authctxt);
}
- userauth_finish(authctxt, authenticated, method);
+ userauth_finish(authctxt, authenticated, method, NULL);
xfree(service);
xfree(user);
@@ -290,13 +294,17 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
}
void
-userauth_finish(Authctxt *authctxt, int authenticated, char *method)
+userauth_finish(Authctxt *authctxt, int authenticated, const char *method,
+ const char *submethod)
{
char *methods;
+ int partial = 0;
if (!authctxt->valid && authenticated)
fatal("INTERNAL ERROR: authenticated invalid user %s",
authctxt->user);
+ if (authenticated && authctxt->postponed)
+ fatal("INTERNAL ERROR: authenticated and postponed");
/* Special handling for root */
if (authenticated && authctxt->pw->pw_uid == 0 &&
@@ -307,6 +315,19 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
#endif
}
+ if (authenticated && options.num_auth_methods != 0) {
+ if (!auth2_update_methods_lists(authctxt, method)) {
+ authenticated = 0;
+ partial = 1;
+ }
+ }
+
+ /* Log before sending the reply */
+ auth_log(authctxt, authenticated, partial, method, submethod, " ssh2");
+
+ if (authctxt->postponed)
+ return;
+
#ifdef USE_PAM
if (options.use_pam && authenticated) {
if (!PRIVSEP(do_pam_account())) {
@@ -325,17 +346,10 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
#ifdef _UNICOS
if (authenticated && cray_access_denied(authctxt->user)) {
authenticated = 0;
- fatal("Access denied for user %s.",authctxt->user);
+ fatal("Access denied for user %s.", authctxt->user);
}
#endif /* _UNICOS */
- /* Log before sending the reply */
- auth_log(authctxt, authenticated, method, " ssh2");
-
- if (authctxt->postponed)
- return;
-
- /* XXX todo: check if multiple auth methods are needed */
if (authenticated == 1) {
/* turn off userauth */
dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
@@ -348,7 +362,8 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
/* Allow initial try of "none" auth without failure penalty */
if (!authctxt->server_caused_failure &&
- (authctxt->attempt > 1 || strcmp(method, "none") != 0))
+ (authctxt->attempt > 1 || strcmp(method, "none") != 0) &&
+ partial == 0)
authctxt->failures++;
if (authctxt->failures >= options.max_authtries) {
#ifdef SSH_AUDIT_EVENTS
@@ -356,34 +371,61 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
#endif
packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
}
- methods = authmethods_get();
+ methods = authmethods_get(authctxt);
+ debug3("%s: failure partial=%d next methods=\"%s\"", __func__,
+ partial, methods);
packet_start(SSH2_MSG_USERAUTH_FAILURE);
packet_put_cstring(methods);
- packet_put_char(0); /* XXX partial success, unused */
+ packet_put_char(partial);
packet_send();
packet_write_wait();
xfree(methods);
}
}
+/*
+ * Checks whether method is allowed by at least one AuthenticationMethods
+ * methods list. Returns 1 if allowed, or no methods lists configured.
+ * 0 otherwise.
+ */
+static int
+method_allowed(Authctxt *authctxt, const char *method)
+{
+ u_int i;
+
+ /*
+ * NB. authctxt->num_auth_methods might be zero as a result of
+ * auth2_setup_methods_lists(), so check the configuration.
+ */
+ if (options.num_auth_methods == 0)
+ return 1;
+ for (i = 0; i < authctxt->num_auth_methods; i++) {
+ if (list_starts_with(authctxt->auth_methods[i], method))
+ return 1;
+ }
+ return 0;
+}
+
static char *
-authmethods_get(void)
+authmethods_get(Authctxt *authctxt)
{
Buffer b;
char *list;
- int i;
+ u_int i;
buffer_init(&b);
for (i = 0; authmethods[i] != NULL; i++) {
if (strcmp(authmethods[i]->name, "none") == 0)
continue;
- if (authmethods[i]->enabled != NULL &&
- *(authmethods[i]->enabled) != 0) {
- if (buffer_len(&b) > 0)
- buffer_append(&b, ",", 1);
- buffer_append(&b, authmethods[i]->name,
- strlen(authmethods[i]->name));
- }
+ if (authmethods[i]->enabled == NULL ||
+ *(authmethods[i]->enabled) == 0)
+ continue;
+ if (!method_allowed(authctxt, authmethods[i]->name))
+ continue;
+ if (buffer_len(&b) > 0)
+ buffer_append(&b, ",", 1);
+ buffer_append(&b, authmethods[i]->name,
+ strlen(authmethods[i]->name));
}
buffer_append(&b, "\0", 1);
list = xstrdup(buffer_ptr(&b));
@@ -392,7 +434,7 @@ authmethods_get(void)
}
static Authmethod *
-authmethod_lookup(const char *name)
+authmethod_lookup(Authctxt *authctxt, const char *name)
{
int i;
@@ -400,10 +442,152 @@ authmethod_lookup(const char *name)
for (i = 0; authmethods[i] != NULL; i++)
if (authmethods[i]->enabled != NULL &&
*(authmethods[i]->enabled) != 0 &&
- strcmp(name, authmethods[i]->name) == 0)
+ strcmp(name, authmethods[i]->name) == 0 &&
+ method_allowed(authctxt, authmethods[i]->name))
return authmethods[i];
debug2("Unrecognized authentication method name: %s",
name ? name : "NULL");
return NULL;
}
+/*
+ * Check a comma-separated list of methods for validity. Is need_enable is
+ * non-zero, then also require that the methods are enabled.
+ * Returns 0 on success or -1 if the methods list is invalid.
+ */
+int
+auth2_methods_valid(const char *_methods, int need_enable)
+{
+ char *methods, *omethods, *method;
+ u_int i, found;
+ int ret = -1;
+
+ if (*_methods == '\0') {
+ error("empty authentication method list");
+ return -1;
+ }
+ omethods = methods = xstrdup(_methods);
+ while ((method = strsep(&methods, ",")) != NULL) {
+ for (found = i = 0; !found && authmethods[i] != NULL; i++) {
+ if (strcmp(method, authmethods[i]->name) != 0)
+ continue;
+ if (need_enable) {
+ if (authmethods[i]->enabled == NULL ||
+ *(authmethods[i]->enabled) == 0) {
+ error("Disabled method \"%s\" in "
+ "AuthenticationMethods list \"%s\"",
+ method, _methods);
+ goto out;
+ }
+ }
+ found = 1;
+ break;
+ }
+ if (!found) {
+ error("Unknown authentication method \"%s\" in list",
+ method);
+ goto out;
+ }
+ }
+ ret = 0;
+ out:
+ free(omethods);
+ return ret;
+}
+
+/*
+ * Prune the AuthenticationMethods supplied in the configuration, removing
+ * any methods lists that include disabled methods. Note that this might
+ * leave authctxt->num_auth_methods == 0, even when multiple required auth
+ * has been requested. For this reason, all tests for whether multiple is
+ * enabled should consult options.num_auth_methods directly.
+ */
+int
+auth2_setup_methods_lists(Authctxt *authctxt)
+{
+ u_int i;
+
+ if (options.num_auth_methods == 0)
+ return 0;
+ debug3("%s: checking methods", __func__);
+ authctxt->auth_methods = xcalloc(options.num_auth_methods,
+ sizeof(*authctxt->auth_methods));
+ authctxt->num_auth_methods = 0;
+ for (i = 0; i < options.num_auth_methods; i++) {
+ if (auth2_methods_valid(options.auth_methods[i], 1) != 0) {
+ logit("Authentication methods list \"%s\" contains "
+ "disabled method, skipping",
+ options.auth_methods[i]);
+ continue;
+ }
+ debug("authentication methods list %d: %s",
+ authctxt->num_auth_methods, options.auth_methods[i]);
+ authctxt->auth_methods[authctxt->num_auth_methods++] =
+ xstrdup(options.auth_methods[i]);
+ }
+ if (authctxt->num_auth_methods == 0) {
+ error("No AuthenticationMethods left after eliminating "
+ "disabled methods");
+ return -1;
+ }
+ return 0;
+}
+
+static int
+list_starts_with(const char *methods, const char *method)
+{
+ size_t l = strlen(method);
+
+ if (strncmp(methods, method, l) != 0)
+ return 0;
+ if (methods[l] != ',' && methods[l] != '\0')
+ return 0;
+ return 1;
+}
+
+/*
+ * Remove method from the start of a comma-separated list of methods.
+ * Returns 0 if the list of methods did not start with that method or 1
+ * if it did.
+ */
+static int
+remove_method(char **methods, const char *method)
+{
+ char *omethods = *methods;
+ size_t l = strlen(method);
+
+ if (!list_starts_with(omethods, method))
+ return 0;
+ *methods = xstrdup(omethods + l + (omethods[l] == ',' ? 1 : 0));
+ free(omethods);
+ return 1;
+}
+
+/*
+ * Called after successful authentication. Will remove the successful method
+ * from the start of each list in which it occurs. If it was the last method
+ * in any list, then authentication is deemed successful.
+ * Returns 1 if the method completed any authentication list or 0 otherwise.
+ */
+int
+auth2_update_methods_lists(Authctxt *authctxt, const char *method)
+{
+ u_int i, found = 0;
+
+ debug3("%s: updating methods list after \"%s\"", __func__, method);
+ for (i = 0; i < authctxt->num_auth_methods; i++) {
+ if (!remove_method(&(authctxt->auth_methods[i]), method))
+ continue;
+ found = 1;
+ if (*authctxt->auth_methods[i] == '\0') {
+ debug2("authentication methods list %d complete", i);
+ return 1;
+ }
+ debug3("authentication methods list %d remaining: \"%s\"",
+ i, authctxt->auth_methods[i]);
+ }
+ /* This should not happen, but would be bad if it did */
+ if (!found)
+ fatal("%s: method not in AuthenticationMethods", __func__);
+ return 0;
+}
diff --git a/monitor.c b/monitor.c
index 1dc42f5..66f3eea 100644
--- a/monitor.c
+++ b/monitor.c
@@ -199,6 +199,7 @@ static int key_blobtype = MM_NOKEY;
static char *hostbased_cuser = NULL;
static char *hostbased_chost = NULL;
static char *auth_method = "unknown";
+static char *auth_submethod = NULL;
static u_int session_id2_len = 0;
static u_char *session_id2 = NULL;
static pid_t monitor_child_pid;
@@ -352,7 +353,7 @@ void
monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
{
struct mon_table *ent;
- int authenticated = 0;
+ int authenticated = 0, partial = 0;
debug3("preauth child monitor started");
@@ -379,8 +380,26 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
/* The first few requests do not require asynchronous access */
while (!authenticated) {
+ partial = 0;
auth_method = "unknown";
+ auth_submethod = NULL;
authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);
+
+ /* Special handling for multiple required authentications */
+ if (options.num_auth_methods != 0) {
+ if (!compat20)
+ fatal("AuthenticationMethods is not supported"
+ "with SSH protocol 1");
+ if (authenticated &&
+ !auth2_update_methods_lists(authctxt,
+ auth_method)) {
+ debug3("%s: method %s: partial", __func__,
+ auth_method);
+ authenticated = 0;
+ partial = 1;
+ }
+ }
+
if (authenticated) {
if (!(ent->flags & MON_AUTHDECIDE))
fatal("%s: unexpected authentication from %d",
@@ -403,9 +422,10 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
}
if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) {
- auth_log(authctxt, authenticated, auth_method,
+ auth_log(authctxt, authenticated, partial,
+ auth_method, auth_submethod,
compat20 ? " ssh2" : "");
- if (!authenticated)
+ if (!authenticated && !partial)
authctxt->failures++;
}
#ifdef JPAKE
@@ -781,7 +801,17 @@ mm_answer_pwnamallow(int sock, Buffer *m)
COPY_MATCH_STRING_OPTS();
#undef M_CP_STROPT
#undef M_CP_STRARRAYOPT
-
+
+ /* Create valid auth method lists */
+ if (compat20 && auth2_setup_methods_lists(authctxt) != 0) {
+ /*
+ * The monitor will continue long enough to let the child
+ * run to it's packet_disconnect(), but it must not allow any
+ * authentication to succeed.
+ */
+ debug("%s: no valid authentication method lists", __func__);
+ }
+
debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed);
mm_request_send(sock, MONITOR_ANS_PWNAM, m);
@@ -918,7 +948,11 @@ mm_answer_bsdauthrespond(int sock, Buffer *m)
debug3("%s: sending authenticated: %d", __func__, authok);
mm_request_send(sock, MONITOR_ANS_BSDAUTHRESPOND, m);
- auth_method = "bsdauth";
+ if (compat20)
+ auth_method = "keyboard-interactive"; /* XXX auth_submethod */
+ else
+ auth_method = "bsdauth";
+
return (authok != 0);
}
@@ -1057,7 +1091,9 @@ mm_answer_pam_query(int sock, Buffer *m)
xfree(prompts);
if (echo_on != NULL)
xfree(echo_on);
- auth_method = "keyboard-interactive/pam";
+ auth_method = "keyboard-interactive";
+ auth_submethod = "pam";
+
mm_request_send(sock, MONITOR_ANS_PAM_QUERY, m);
return (0);
}
@@ -1086,7 +1122,8 @@ mm_answer_pam_respond(int sock, Buffer *m)
buffer_clear(m);
buffer_put_int(m, ret);
mm_request_send(sock, MONITOR_ANS_PAM_RESPOND, m);
- auth_method = "keyboard-interactive/pam";
+ auth_method = "keyboard-interactive";
+ auth_submethod= "pam";
if (ret == 0)
sshpam_authok = sshpam_ctxt;
return (0);
@@ -1100,7 +1137,8 @@ mm_answer_pam_free_ctx(int sock, Buffer *m)
(sshpam_device.free_ctx)(sshpam_ctxt);
buffer_clear(m);
mm_request_send(sock, MONITOR_ANS_PAM_FREE_CTX, m);
- auth_method = "keyboard-interactive/pam";
+ auth_method = "keyboard-interactive";
+ auth_submethod = "pam";
return (sshpam_authok == sshpam_ctxt);
}
#endif
@@ -1178,7 +1216,8 @@ mm_answer_keyallowed(int sock, Buffer *m)
hostbased_chost = chost;
} else {
/* Log failed attempt */
- auth_log(authctxt, 0, auth_method, compat20 ? " ssh2" : "");
+ auth_log(authctxt, 0, 0, auth_method, NULL,
+ compat20 ? " ssh2" : "");
xfree(blob);
xfree(cuser);
xfree(chost);
diff --git a/servconf.c b/servconf.c
index 906778f..2c84993 100644
--- a/servconf.c
+++ b/servconf.c
@@ -48,6 +48,8 @@
#include "groupaccess.h"
#include "canohost.h"
#include "packet.h"
+#include "hostfile.h"
+#include "auth.h"
static void add_listen_addr(ServerOptions *, char *, int);
static void add_one_listen_addr(ServerOptions *, char *, int);
@@ -329,6 +331,7 @@ typedef enum {
sZeroKnowledgePasswordAuthentication, sHostCertificate,
sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
sKexAlgorithms, sIPQoS, sVersionAddendum,
+ sAuthenticationMethods,
sDeprecated, sUnsupported
} ServerOpCodes;
@@ -454,6 +457,7 @@ static struct {
{ "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL },
{ "ipqos", sIPQoS, SSHCFG_ALL },
{ "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL },
+ { "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL },
{ NULL, sBadOption, 0 }
};
@@ -1498,6 +1502,24 @@ process_server_config_line(ServerOptions *options, char *line,
}
return 0;
+ case sAuthenticationMethods:
+ if (*activep && options->num_auth_methods == 0) {
+ while ((arg = strdelim(&cp)) && *arg != '\0') {
+ if (options->num_auth_methods >=
+ MAX_AUTH_METHODS)
+ fatal("%s line %d: "
+ "too many authentication methods.",
+ filename, linenum);
+ if (auth2_methods_valid(arg, 0) != 0)
+ fatal("%s line %d: invalid "
+ "authentication method list.",
+ filename, linenum);
+ options->auth_methods[
+ options->num_auth_methods++] = xstrdup(arg);
+ }
+ }
+ return 0;
+
case sDeprecated:
logit("%s line %d: Deprecated option %s",
filename, linenum, arg);
@@ -1925,6 +1947,8 @@ dump_config(ServerOptions *o)
dump_cfg_strarray(sAllowGroups, o->num_allow_groups, o->allow_groups);
dump_cfg_strarray(sDenyGroups, o->num_deny_groups, o->deny_groups);
dump_cfg_strarray(sAcceptEnv, o->num_accept_env, o->accept_env);
+ dump_cfg_strarray_oneline(sAuthenticationMethods,
+ o->num_auth_methods, o->auth_methods);
/* other arguments */
for (i = 0; i < o->num_subsystems; i++)
diff --git a/servconf.h b/servconf.h
index 096d596..ef80eef 100644
--- a/servconf.h
+++ b/servconf.h
@@ -28,6 +28,7 @@
#define MAX_ACCEPT_ENV 256 /* Max # of env vars. */
#define MAX_MATCH_GROUPS 256 /* Max # of groups for Match. */
#define MAX_AUTHKEYS_FILES 256 /* Max # of authorized_keys files. */
+#define MAX_AUTH_METHODS 256 /* Max # of AuthenticationMethods. */
/* permit_root_login */
#define PERMIT_NOT_SET -1
@@ -168,6 +169,9 @@ typedef struct {
char *authorized_principals_file;
char *version_addendum; /* Appended to SSH banner */
+
+ u_int num_auth_methods;
+ char *auth_methods[MAX_AUTH_METHODS];
} ServerOptions;
/* Information about the incoming connection as used by Match */
@@ -197,6 +201,7 @@ struct connection_info {
M_CP_STRARRAYOPT(allow_groups, num_allow_groups); \
M_CP_STRARRAYOPT(deny_groups, num_deny_groups); \
M_CP_STRARRAYOPT(accept_env, num_accept_env); \
+ M_CP_STRARRAYOPT(auth_methods, num_auth_methods); \
} while (0)
struct connection_info *get_connection_info(int, int);
diff --git a/sshd.c b/sshd.c
index d5ec4e6..cb4bdd3 100644
--- a/sshd.c
+++ b/sshd.c
@@ -1333,6 +1333,7 @@ main(int ac, char **av)
int remote_port;
char *line;
int config_s[2] = { -1 , -1 };
+ u_int n;
u_int64_t ibytes, obytes;
mode_t new_umask;
Key *key;
@@ -1555,6 +1556,26 @@ main(int ac, char **av)
if (options.challenge_response_authentication)
options.kbd_interactive_authentication = 1;
+ /*
+ * Check whether there is any path through configured auth methods.
+ * Unfortunately it is not possible to verify this generally before
+ * daemonisation in the presence of Match block, but this catches
+ * and warns for trivial misconfigurations that could break login.
+ */
+ if (options.num_auth_methods != 0) {
+ if ((options.protocol & SSH_PROTO_1))
+ fatal("AuthenticationMethods is not supported with "
+ "SSH protocol 1");
+ for (n = 0; n < options.num_auth_methods; n++) {
+ if (auth2_methods_valid(options.auth_methods[n],
+ 1) == 0)
+ break;
+ }
+ if (n >= options.num_auth_methods)
+ fatal("AuthenticationMethods cannot be satisfied by "
+ "enabled authentication methods");
+ }
+
/* set default channel AF */
channel_set_af(options.address_family);
diff --git a/sshd_config.5 b/sshd_config.5
index 314ecfb..ed81ac8 100644
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -151,6 +151,28 @@ See
in
.Xr ssh_config 5
for more information on patterns.
+.It Cm AuthenticationMethods
+Specifies the authentication methods that must be successfully completed
+for a user to be granted access.
+This option must be followed by one or more comma-separated lists of
+authentication method names.
+Successful authentication requires completion of every method in at least
+one of these lists.
+.Pp
+For example, an argument of
+.Dq publickey,password publickey,keyboard-interactive
+would require the user to complete public key authentication, followed by
+either password or keyboard interactive authentication.
+Only methods that are next in one or more lists are offered at each stage,
+so for this example, it would not be possible to attempt password or
+keyboard-interactive authentication before public key.
+.Pp
+This option is only available for SSH protocol 2 and will yield a fatal
+error if enabled if protocol 1 is also enabled.
+Note that each authentication method listed should also be explicitly enabled
+in the configuration.
+The default is not to require multiple authentication; successful completion
+of a single authentication method is sufficient.
.It Cm AuthorizedKeysFile
Specifies the file that contains the public keys that can be used
for user authentication.
@@ -711,6 +733,7 @@ Available keywords are
.Cm AllowGroups ,
.Cm AllowTcpForwarding ,
.Cm AllowUsers ,
+.Cm AuthenticationMethods ,
.Cm AuthorizedKeysFile ,
.Cm AuthorizedPrincipalsFile ,
.Cm Banner ,

View File

@ -0,0 +1,45 @@
diff --git a/servconf.c b/servconf.c
index 684fbb4..a230c7b 100644
--- a/servconf.c
+++ b/servconf.c
@@ -267,11 +267,11 @@ fill_default_server_options(ServerOptions *options)
if (options->gateway_ports == -1)
options->gateway_ports = 0;
if (options->max_startups == -1)
- options->max_startups = 10;
+ options->max_startups = 100;
if (options->max_startups_rate == -1)
- options->max_startups_rate = 100; /* 100% */
+ options->max_startups_rate = 30; /* 30% */
if (options->max_startups_begin == -1)
- options->max_startups_begin = options->max_startups;
+ options->max_startups_begin = 10;
if (options->max_authtries == -1)
options->max_authtries = DEFAULT_AUTH_FAIL_MAX;
if (options->max_sessions == -1)
diff --git a/sshd_config b/sshd_config
index d1b85d0..5c03fd9 100644
--- a/sshd_config
+++ b/sshd_config
@@ -126,7 +126,7 @@ UsePrivilegeSeparation sandbox # Default for new installations.
#ShowPatchLevel no
#UseDNS yes
#PidFile /var/run/sshd.pid
-#MaxStartups 10
+#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
#VersionAddendum none
diff --git a/sshd_config.5 b/sshd_config.5
index fd0d35a..f02f6cc 100644
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -826,7 +826,7 @@ SSH daemon.
Additional connections will be dropped until authentication succeeds or the
.Cm LoginGraceTime
expires for a connection.
-The default is 10.
+The default is 10:30:100.
.Pp
Alternatively, random early drop can be enabled by specifying
the three colon separated values

View File

@ -0,0 +1,806 @@
diff -up openssh-6.1p1/auth-pam.c.coverity openssh-6.1p1/auth-pam.c
--- openssh-6.1p1/auth-pam.c.coverity 2009-07-12 14:07:21.000000000 +0200
+++ openssh-6.1p1/auth-pam.c 2012-09-14 21:16:41.264906486 +0200
@@ -216,7 +216,12 @@ pthread_join(sp_pthread_t thread, void *
if (sshpam_thread_status != -1)
return (sshpam_thread_status);
signal(SIGCHLD, sshpam_oldsig);
- waitpid(thread, &status, 0);
+ while (waitpid(thread, &status, 0) < 0) {
+ if (errno == EINTR)
+ continue;
+ fatal("%s: waitpid: %s", __func__,
+ strerror(errno));
+ }
return (status);
}
#endif
diff -up openssh-6.1p1/clientloop.c.coverity openssh-6.1p1/clientloop.c
--- openssh-6.1p1/clientloop.c.coverity 2012-06-20 14:31:27.000000000 +0200
+++ openssh-6.1p1/clientloop.c 2012-09-14 21:16:41.267906501 +0200
@@ -2006,14 +2006,15 @@ client_input_global_request(int type, u_
char *rtype;
int want_reply;
int success = 0;
+/* success is still 0 the packet is allways SSH2_MSG_REQUEST_FAILURE, isn't it? */
rtype = packet_get_string(NULL);
want_reply = packet_get_char();
debug("client_input_global_request: rtype %s want_reply %d",
rtype, want_reply);
if (want_reply) {
- packet_start(success ?
- SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE);
+ packet_start(/*success ?
+ SSH2_MSG_REQUEST_SUCCESS :*/ SSH2_MSG_REQUEST_FAILURE);
packet_send();
packet_write_wait();
}
diff -up openssh-6.1p1/channels.c.coverity openssh-6.1p1/channels.c
--- openssh-6.1p1/channels.c.coverity 2012-04-23 10:21:05.000000000 +0200
+++ openssh-6.1p1/channels.c 2012-09-14 21:16:41.272906528 +0200
@@ -232,11 +232,11 @@ channel_register_fds(Channel *c, int rfd
channel_max_fd = MAX(channel_max_fd, wfd);
channel_max_fd = MAX(channel_max_fd, efd);
- if (rfd != -1)
+ if (rfd >= 0)
fcntl(rfd, F_SETFD, FD_CLOEXEC);
- if (wfd != -1 && wfd != rfd)
+ if (wfd >= 0 && wfd != rfd)
fcntl(wfd, F_SETFD, FD_CLOEXEC);
- if (efd != -1 && efd != rfd && efd != wfd)
+ if (efd >= 0 && efd != rfd && efd != wfd)
fcntl(efd, F_SETFD, FD_CLOEXEC);
c->rfd = rfd;
@@ -251,11 +251,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-6.1p1/key.c.coverity openssh-6.1p1/key.c
--- openssh-6.1p1/key.c.coverity 2012-06-30 12:05:02.000000000 +0200
+++ openssh-6.1p1/key.c 2012-09-14 21:16:41.274906537 +0200
@@ -808,8 +808,10 @@ key_read(Key *ret, char **cpp)
success = 1;
/*XXXX*/
key_free(k);
+/*XXXX
if (success != 1)
break;
+XXXX*/
/* advance cp: skip whitespace and data */
while (*cp == ' ' || *cp == '\t')
cp++;
diff -up openssh-6.1p1/monitor.c.coverity openssh-6.1p1/monitor.c
--- openssh-6.1p1/monitor.c.coverity 2012-06-30 00:33:17.000000000 +0200
+++ openssh-6.1p1/monitor.c 2012-09-14 21:16:41.277906552 +0200
@@ -420,7 +420,7 @@ monitor_child_preauth(Authctxt *_authctx
}
/* 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 (!authctxt->valid)
@@ -1159,6 +1159,10 @@ mm_answer_keyallowed(int sock, Buffer *m
break;
}
}
+
+ debug3("%s: key %p is %s",
+ __func__, key, allowed ? "allowed" : "not allowed");
+
if (key != NULL)
key_free(key);
@@ -1180,9 +1184,6 @@ mm_answer_keyallowed(int sock, Buffer *m
xfree(chost);
}
- debug3("%s: key %p is %s",
- __func__, key, allowed ? "allowed" : "not allowed");
-
buffer_clear(m);
buffer_put_int(m, allowed);
buffer_put_int(m, forced_command != NULL);
diff -up openssh-6.1p1/monitor_wrap.c.coverity openssh-6.1p1/monitor_wrap.c
--- openssh-6.1p1/monitor_wrap.c.coverity 2011-06-20 06:42:23.000000000 +0200
+++ openssh-6.1p1/monitor_wrap.c 2012-09-14 21:16:41.280906568 +0200
@@ -707,10 +707,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-6.1p1/openbsd-compat/bindresvport.c.coverity openssh-6.1p1/openbsd-compat/bindresvport.c
--- openssh-6.1p1/openbsd-compat/bindresvport.c.coverity 2010-12-03 00:50:26.000000000 +0100
+++ openssh-6.1p1/openbsd-compat/bindresvport.c 2012-09-14 21:16:41.281906573 +0200
@@ -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-6.1p1/packet.c.coverity openssh-6.1p1/packet.c
--- openssh-6.1p1/packet.c.coverity 2012-03-09 00:28:07.000000000 +0100
+++ openssh-6.1p1/packet.c 2012-09-14 21:16:41.284906588 +0200
@@ -1177,6 +1177,7 @@ packet_read_poll1(void)
case DEATTACK_DETECTED:
packet_disconnect("crc32 compensation attack: "
"network attack detected");
+ break;
case DEATTACK_DOS_DETECTED:
packet_disconnect("deattack denial of "
"service detected");
@@ -1678,7 +1679,7 @@ void
packet_write_wait(void)
{
fd_set *setp;
- int ret, ms_remain;
+ int ret, ms_remain = 0;
struct timeval start, timeout, *timeoutp = NULL;
setp = (fd_set *)xcalloc(howmany(active_state->connection_out + 1,
diff -up openssh-6.1p1/progressmeter.c.coverity openssh-6.1p1/progressmeter.c
--- openssh-6.1p1/progressmeter.c.coverity 2006-08-05 04:39:40.000000000 +0200
+++ openssh-6.1p1/progressmeter.c 2012-09-14 21:16:41.285906593 +0200
@@ -65,7 +65,7 @@ static void update_progress_meter(int);
static time_t start; /* start progress */
static time_t last_update; /* last progress update */
-static char *file; /* name of the file being transferred */
+static const char *file; /* name of the file being transferred */
static off_t end_pos; /* ending position of transfer */
static off_t cur_pos; /* transfer position as of last refresh */
static volatile off_t *counter; /* progress counter */
@@ -247,7 +247,7 @@ update_progress_meter(int ignore)
}
void
-start_progress_meter(char *f, off_t filesize, off_t *ctr)
+start_progress_meter(const char *f, off_t filesize, off_t *ctr)
{
start = last_update = time(NULL);
file = f;
diff -up openssh-6.1p1/progressmeter.h.coverity openssh-6.1p1/progressmeter.h
--- openssh-6.1p1/progressmeter.h.coverity 2006-03-26 05:30:02.000000000 +0200
+++ openssh-6.1p1/progressmeter.h 2012-09-14 21:16:41.286906598 +0200
@@ -23,5 +23,5 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-void start_progress_meter(char *, off_t, off_t *);
+void start_progress_meter(const char *, off_t, off_t *);
void stop_progress_meter(void);
diff -up openssh-6.1p1/scp.c.coverity openssh-6.1p1/scp.c
--- openssh-6.1p1/scp.c.coverity 2011-09-22 13:38:01.000000000 +0200
+++ openssh-6.1p1/scp.c 2012-09-14 21:16:41.288906608 +0200
@@ -155,7 +155,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-6.1p1/servconf.c.coverity openssh-6.1p1/servconf.c
--- openssh-6.1p1/servconf.c.coverity 2012-07-31 04:22:38.000000000 +0200
+++ openssh-6.1p1/servconf.c 2012-09-14 21:16:41.291906623 +0200
@@ -1249,7 +1249,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++)
@@ -1340,8 +1340,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-6.1p1/serverloop.c.coverity openssh-6.1p1/serverloop.c
--- openssh-6.1p1/serverloop.c.coverity 2012-06-20 14:31:27.000000000 +0200
+++ openssh-6.1p1/serverloop.c 2012-09-14 21:16:41.294906638 +0200
@@ -147,13 +147,13 @@ notify_setup(void)
static void
notify_parent(void)
{
- if (notify_pipe[1] != -1)
+ if (notify_pipe[1] >= 0)
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
@@ -161,8 +161,8 @@ notify_done(fd_set *readset)
{
char c;
- if (notify_pipe[0] != -1 && FD_ISSET(notify_pipe[0], readset))
- while (read(notify_pipe[0], &c, 1) != -1)
+ if (notify_pipe[0] >= 0 && FD_ISSET(notify_pipe[0], readset))
+ while (read(notify_pipe[0], &c, 1) >= 0)
debug2("notify_done: reading");
}
@@ -336,7 +336,7 @@ wait_until_can_do_something(fd_set **rea
* If we have buffered data, try to write some of that data
* to the program.
*/
- if (fdin != -1 && buffer_len(&stdin_buffer) > 0)
+ if (fdin >= 0 && buffer_len(&stdin_buffer) > 0)
FD_SET(fdin, *writesetp);
}
notify_prepare(*readsetp);
@@ -476,7 +476,7 @@ process_output(fd_set *writeset)
int len;
/* Write buffered data to program stdin. */
- if (!compat20 && fdin != -1 && FD_ISSET(fdin, writeset)) {
+ if (!compat20 && fdin >= 0 && FD_ISSET(fdin, writeset)) {
data = buffer_ptr(&stdin_buffer);
dlen = buffer_len(&stdin_buffer);
len = write(fdin, data, dlen);
@@ -589,7 +589,7 @@ server_loop(pid_t pid, int fdin_arg, int
set_nonblock(fdin);
set_nonblock(fdout);
/* we don't have stderr for interactive terminal sessions, see below */
- if (fderr != -1)
+ if (fderr >= 0)
set_nonblock(fderr);
if (!(datafellows & SSH_BUG_IGNOREMSG) && isatty(fdin))
@@ -613,7 +613,7 @@ server_loop(pid_t pid, int fdin_arg, int
max_fd = MAX(connection_in, connection_out);
max_fd = MAX(max_fd, fdin);
max_fd = MAX(max_fd, fdout);
- if (fderr != -1)
+ if (fderr >= 0)
max_fd = MAX(max_fd, fderr);
#endif
@@ -643,7 +643,7 @@ server_loop(pid_t pid, int fdin_arg, int
* If we have received eof, and there is no more pending
* input data, cause a real eof by closing fdin.
*/
- if (stdin_eof && fdin != -1 && buffer_len(&stdin_buffer) == 0) {
+ if (stdin_eof && fdin >= 0 && buffer_len(&stdin_buffer) == 0) {
if (fdin != fdout)
close(fdin);
else
@@ -741,15 +741,15 @@ server_loop(pid_t pid, int fdin_arg, int
buffer_free(&stderr_buffer);
/* Close the file descriptors. */
- if (fdout != -1)
+ if (fdout >= 0)
close(fdout);
fdout = -1;
fdout_eof = 1;
- if (fderr != -1)
+ if (fderr >= 0)
close(fderr);
fderr = -1;
fderr_eof = 1;
- if (fdin != -1)
+ if (fdin >= 0)
close(fdin);
fdin = -1;
@@ -943,7 +943,7 @@ server_input_window_size(int type, u_int
debug("Window change received.");
packet_check_eom();
- if (fdin != -1)
+ if (fdin >= 0)
pty_change_window_size(fdin, row, col, xpixel, ypixel);
}
@@ -996,7 +996,7 @@ server_request_tun(void)
}
tun = packet_get_int();
- if (forced_tun_device != -1) {
+ if (forced_tun_device >= 0) {
if (tun != SSH_TUNID_ANY && forced_tun_device != tun)
goto done;
tun = forced_tun_device;
diff -up openssh-6.1p1/sftp.c.coverity openssh-6.1p1/sftp.c
--- openssh-6.1p1/sftp.c.coverity 2012-06-30 00:33:32.000000000 +0200
+++ openssh-6.1p1/sftp.c 2012-09-14 21:16:41.297906653 +0200
@@ -206,7 +206,7 @@ killchild(int signo)
{
if (sshpid > 1) {
kill(sshpid, SIGTERM);
- waitpid(sshpid, NULL, 0);
+ (void) waitpid(sshpid, NULL, 0);
}
_exit(1);
@@ -316,7 +316,7 @@ local_do_ls(const char *args)
/* Strip one path (usually the pwd) from the start of another */
static char *
-path_strip(char *path, char *strip)
+path_strip(const char *path, const char *strip)
{
size_t len;
@@ -334,7 +334,7 @@ path_strip(char *path, char *strip)
}
static char *
-make_absolute(char *p, char *pwd)
+make_absolute(char *p, const char *pwd)
{
char *abs_str;
@@ -482,7 +482,7 @@ parse_df_flags(const char *cmd, char **a
}
static int
-is_dir(char *path)
+is_dir(const char *path)
{
struct stat sb;
@@ -494,7 +494,7 @@ is_dir(char *path)
}
static int
-remote_is_dir(struct sftp_conn *conn, char *path)
+remote_is_dir(struct sftp_conn *conn, const char *path)
{
Attrib *a;
@@ -508,7 +508,7 @@ remote_is_dir(struct sftp_conn *conn, ch
/* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */
static int
-pathname_is_dir(char *pathname)
+pathname_is_dir(const char *pathname)
{
size_t l = strlen(pathname);
@@ -516,7 +516,7 @@ pathname_is_dir(char *pathname)
}
static int
-process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd,
+process_get(struct sftp_conn *conn, const char *src, const char *dst, const char *pwd,
int pflag, int rflag)
{
char *abs_src = NULL;
@@ -590,7 +590,7 @@ out:
}
static int
-process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd,
+process_put(struct sftp_conn *conn, const char *src, const char *dst, const char *pwd,
int pflag, int rflag)
{
char *tmp_dst = NULL;
@@ -695,7 +695,7 @@ sdirent_comp(const void *aa, const void
/* sftp ls.1 replacement for directories */
static int
-do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag)
+do_ls_dir(struct sftp_conn *conn, const char *path, const char *strip_path, int lflag)
{
int n;
u_int c = 1, colspace = 0, columns = 1;
@@ -780,7 +780,7 @@ do_ls_dir(struct sftp_conn *conn, char *
/* sftp ls.1 replacement which handles path globs */
static int
-do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
+do_globbed_ls(struct sftp_conn *conn, const char *path, const char *strip_path,
int lflag)
{
char *fname, *lname;
@@ -861,7 +861,7 @@ do_globbed_ls(struct sftp_conn *conn, ch
}
static int
-do_df(struct sftp_conn *conn, char *path, int hflag, int iflag)
+do_df(struct sftp_conn *conn, const char *path, int hflag, int iflag)
{
struct sftp_statvfs st;
char s_used[FMT_SCALED_STRSIZE];
diff -up openssh-6.1p1/sftp-client.c.coverity openssh-6.1p1/sftp-client.c
--- openssh-6.1p1/sftp-client.c.coverity 2012-07-02 14:15:39.000000000 +0200
+++ openssh-6.1p1/sftp-client.c 2012-09-14 21:18:16.891332281 +0200
@@ -149,7 +149,7 @@ get_msg(struct sftp_conn *conn, Buffer *
}
static void
-send_string_request(struct sftp_conn *conn, u_int id, u_int code, char *s,
+send_string_request(struct sftp_conn *conn, u_int id, u_int code, const char *s,
u_int len)
{
Buffer msg;
@@ -165,7 +165,7 @@ send_string_request(struct sftp_conn *co
static void
send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code,
- char *s, u_int len, Attrib *a)
+ const char *s, u_int len, Attrib *a)
{
Buffer msg;
@@ -422,7 +422,7 @@ sftp_proto_version(struct sftp_conn *con
}
int
-do_close(struct sftp_conn *conn, char *handle, u_int handle_len)
+do_close(struct sftp_conn *conn, const char *handle, u_int handle_len)
{
u_int id, status;
Buffer msg;
@@ -447,7 +447,7 @@ do_close(struct sftp_conn *conn, char *h
static int
-do_lsreaddir(struct sftp_conn *conn, char *path, int printflag,
+do_lsreaddir(struct sftp_conn *conn, const char *path, int printflag,
SFTP_DIRENT ***dir)
{
Buffer msg;
@@ -572,7 +572,7 @@ do_lsreaddir(struct sftp_conn *conn, cha
}
int
-do_readdir(struct sftp_conn *conn, char *path, SFTP_DIRENT ***dir)
+do_readdir(struct sftp_conn *conn, const char *path, SFTP_DIRENT ***dir)
{
return(do_lsreaddir(conn, path, 0, dir));
}
@@ -590,7 +590,7 @@ void free_sftp_dirents(SFTP_DIRENT **s)
}
int
-do_rm(struct sftp_conn *conn, char *path)
+do_rm(struct sftp_conn *conn, const char *path)
{
u_int status, id;
@@ -605,7 +605,7 @@ do_rm(struct sftp_conn *conn, char *path
}
int
-do_mkdir(struct sftp_conn *conn, char *path, Attrib *a, int printflag)
+do_mkdir(struct sftp_conn *conn, const char *path, Attrib *a, int printflag)
{
u_int status, id;
@@ -621,7 +621,7 @@ do_mkdir(struct sftp_conn *conn, char *p
}
int
-do_rmdir(struct sftp_conn *conn, char *path)
+do_rmdir(struct sftp_conn *conn, const char *path)
{
u_int status, id;
@@ -637,7 +637,7 @@ do_rmdir(struct sftp_conn *conn, char *p
}
Attrib *
-do_stat(struct sftp_conn *conn, char *path, int quiet)
+do_stat(struct sftp_conn *conn, const char *path, int quiet)
{
u_int id;
@@ -651,7 +651,7 @@ do_stat(struct sftp_conn *conn, char *pa
}
Attrib *
-do_lstat(struct sftp_conn *conn, char *path, int quiet)
+do_lstat(struct sftp_conn *conn, const char *path, int quiet)
{
u_int id;
@@ -685,7 +685,7 @@ do_fstat(struct sftp_conn *conn, char *h
#endif
int
-do_setstat(struct sftp_conn *conn, char *path, Attrib *a)
+do_setstat(struct sftp_conn *conn, const char *path, Attrib *a)
{
u_int status, id;
@@ -702,7 +702,7 @@ do_setstat(struct sftp_conn *conn, char
}
int
-do_fsetstat(struct sftp_conn *conn, char *handle, u_int handle_len,
+do_fsetstat(struct sftp_conn *conn, const char *handle, u_int handle_len,
Attrib *a)
{
u_int status, id;
@@ -719,7 +719,7 @@ do_fsetstat(struct sftp_conn *conn, char
}
char *
-do_realpath(struct sftp_conn *conn, char *path)
+do_realpath(struct sftp_conn *conn, const char *path)
{
Buffer msg;
u_int type, expected_id, count, id;
@@ -768,7 +768,7 @@ do_realpath(struct sftp_conn *conn, char
}
int
-do_rename(struct sftp_conn *conn, char *oldpath, char *newpath)
+do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath)
{
Buffer msg;
u_int status, id;
@@ -802,7 +802,7 @@ do_rename(struct sftp_conn *conn, char *
}
int
-do_hardlink(struct sftp_conn *conn, char *oldpath, char *newpath)
+do_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
{
Buffer msg;
u_int status, id;
@@ -835,7 +835,7 @@ do_hardlink(struct sftp_conn *conn, char
}
int
-do_symlink(struct sftp_conn *conn, char *oldpath, char *newpath)
+do_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
{
Buffer msg;
u_int status, id;
@@ -987,7 +987,7 @@ send_read_request(struct sftp_conn *conn
}
int
-do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
+do_download(struct sftp_conn *conn, const char *remote_path, const char *local_path,
Attrib *a, int pflag)
{
Attrib junk;
@@ -1226,7 +1226,7 @@ do_download(struct sftp_conn *conn, char
}
static int
-download_dir_internal(struct sftp_conn *conn, char *src, char *dst,
+download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
Attrib *dirattrib, int pflag, int printflag, int depth)
{
int i, ret = 0;
@@ -1316,7 +1316,7 @@ download_dir_internal(struct sftp_conn *
}
int
-download_dir(struct sftp_conn *conn, char *src, char *dst,
+download_dir(struct sftp_conn *conn, const char *src, const char *dst,
Attrib *dirattrib, int pflag, int printflag)
{
char *src_canon;
@@ -1334,7 +1334,7 @@ download_dir(struct sftp_conn *conn, cha
}
int
-do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
+do_upload(struct sftp_conn *conn, const char *local_path, const char *remote_path,
int pflag)
{
int local_fd;
@@ -1517,7 +1517,7 @@ do_upload(struct sftp_conn *conn, char *
}
static int
-upload_dir_internal(struct sftp_conn *conn, char *src, char *dst,
+upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
int pflag, int printflag, int depth)
{
int ret = 0, status;
@@ -1608,7 +1608,7 @@ upload_dir_internal(struct sftp_conn *co
}
int
-upload_dir(struct sftp_conn *conn, char *src, char *dst, int printflag,
+upload_dir(struct sftp_conn *conn, const char *src, const char *dst, int printflag,
int pflag)
{
char *dst_canon;
@@ -1625,7 +1625,7 @@ upload_dir(struct sftp_conn *conn, char
}
char *
-path_append(char *p1, char *p2)
+path_append(const char *p1, const char *p2)
{
char *ret;
size_t len = strlen(p1) + strlen(p2) + 2;
diff -up openssh-6.1p1/sftp-client.h.coverity openssh-6.1p1/sftp-client.h
--- openssh-6.1p1/sftp-client.h.coverity 2010-12-04 23:02:48.000000000 +0100
+++ openssh-6.1p1/sftp-client.h 2012-09-14 21:16:41.301906674 +0200
@@ -56,49 +56,49 @@ struct sftp_conn *do_init(int, int, u_in
u_int sftp_proto_version(struct sftp_conn *);
/* Close file referred to by 'handle' */
-int do_close(struct sftp_conn *, char *, u_int);
+int do_close(struct sftp_conn *, const char *, u_int);
/* Read contents of 'path' to NULL-terminated array 'dir' */
-int do_readdir(struct sftp_conn *, char *, SFTP_DIRENT ***);
+int do_readdir(struct sftp_conn *, const char *, SFTP_DIRENT ***);
/* Frees a NULL-terminated array of SFTP_DIRENTs (eg. from do_readdir) */
void free_sftp_dirents(SFTP_DIRENT **);
/* Delete file 'path' */
-int do_rm(struct sftp_conn *, char *);
+int do_rm(struct sftp_conn *, const char *);
/* Create directory 'path' */
-int do_mkdir(struct sftp_conn *, char *, Attrib *, int);
+int do_mkdir(struct sftp_conn *, const char *, Attrib *, int);
/* Remove directory 'path' */
-int do_rmdir(struct sftp_conn *, char *);
+int do_rmdir(struct sftp_conn *, const char *);
/* Get file attributes of 'path' (follows symlinks) */
-Attrib *do_stat(struct sftp_conn *, char *, int);
+Attrib *do_stat(struct sftp_conn *, const char *, int);
/* Get file attributes of 'path' (does not follow symlinks) */
-Attrib *do_lstat(struct sftp_conn *, char *, int);
+Attrib *do_lstat(struct sftp_conn *, const char *, int);
/* Set file attributes of 'path' */
-int do_setstat(struct sftp_conn *, char *, Attrib *);
+int do_setstat(struct sftp_conn *, const char *, Attrib *);
/* Set file attributes of open file 'handle' */
-int do_fsetstat(struct sftp_conn *, char *, u_int, Attrib *);
+int do_fsetstat(struct sftp_conn *, const char *, u_int, Attrib *);
/* Canonicalise 'path' - caller must free result */
-char *do_realpath(struct sftp_conn *, char *);
+char *do_realpath(struct sftp_conn *, const char *);
/* Get statistics for filesystem hosting file at "path" */
int do_statvfs(struct sftp_conn *, const char *, struct sftp_statvfs *, int);
/* Rename 'oldpath' to 'newpath' */
-int do_rename(struct sftp_conn *, char *, char *);
+int do_rename(struct sftp_conn *, const char *, const char *);
/* Link 'oldpath' to 'newpath' */
-int do_hardlink(struct sftp_conn *, char *, char *);
+int do_hardlink(struct sftp_conn *, const char *, const char *);
-/* Rename 'oldpath' to 'newpath' */
-int do_symlink(struct sftp_conn *, char *, char *);
+/* Symlink 'oldpath' to 'newpath' */
+int do_symlink(struct sftp_conn *, const char *, const char *);
/* XXX: add callbacks to do_download/do_upload so we can do progress meter */
@@ -106,27 +106,27 @@ int do_symlink(struct sftp_conn *, char
* Download 'remote_path' to 'local_path'. Preserve permissions and times
* if 'pflag' is set
*/
-int do_download(struct sftp_conn *, char *, char *, Attrib *, int);
+int do_download(struct sftp_conn *, const char *, const char *, Attrib *, int);
/*
* Recursively download 'remote_directory' to 'local_directory'. Preserve
* times if 'pflag' is set
*/
-int download_dir(struct sftp_conn *, char *, char *, Attrib *, int, int);
+int download_dir(struct sftp_conn *, const char *, const char *, Attrib *, int, int);
/*
* Upload 'local_path' to 'remote_path'. Preserve permissions and times
* if 'pflag' is set
*/
-int do_upload(struct sftp_conn *, char *, char *, int);
+int do_upload(struct sftp_conn *, const char *, const char *, int);
/*
* Recursively upload 'local_directory' to 'remote_directory'. Preserve
* times if 'pflag' is set
*/
-int upload_dir(struct sftp_conn *, char *, char *, int, int);
+int upload_dir(struct sftp_conn *, const char *, const char *, int, int);
/* Concatenate paths, taking care of slashes. Caller must free result. */
-char *path_append(char *, char *);
+char *path_append(const char *, const char *);
#endif
diff -up openssh-6.1p1/ssh-agent.c.coverity openssh-6.1p1/ssh-agent.c
--- openssh-6.1p1/ssh-agent.c.coverity 2011-06-03 06:14:16.000000000 +0200
+++ openssh-6.1p1/ssh-agent.c 2012-09-14 21:16:41.303906683 +0200
@@ -1147,8 +1147,8 @@ main(int ac, char **av)
sanitise_stdfd();
/* drop */
- setegid(getgid());
- setgid(getgid());
+ (void) setegid(getgid());
+ (void) setgid(getgid());
#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
/* Disable ptrace on Linux without sgid bit */
diff -up openssh-6.1p1/sshd.c.coverity openssh-6.1p1/sshd.c
--- openssh-6.1p1/sshd.c.coverity 2012-07-31 04:21:34.000000000 +0200
+++ openssh-6.1p1/sshd.c 2012-09-14 21:16:41.307906705 +0200
@@ -682,8 +682,10 @@ privsep_preauth(Authctxt *authctxt)
if (getuid() == 0 || geteuid() == 0)
privsep_preauth_child();
setproctitle("%s", "[net]");
- if (box != NULL)
+ if (box != NULL) {
ssh_sandbox_child(box);
+ xfree(box);
+ }
return 0;
}
@@ -1311,6 +1313,9 @@ server_accept_loop(int *sock_in, int *so
if (num_listen_socks < 0)
break;
}
+
+ if (fdset != NULL)
+ xfree(fdset);
}
@@ -1768,7 +1773,7 @@ main(int ac, char **av)
/* Chdir to the root directory so that the current disk can be
unmounted if desired. */
- chdir("/");
+ (void) chdir("/");
/* ignore SIGPIPE */
signal(SIGPIPE, SIG_IGN);

View File

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

3027
openssh-6.1p1-gsskex.patch Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,59 @@
diff -U0 openssh-6.2p2/ChangeLog.dh openssh-6.2p2/ChangeLog
--- openssh-6.2p2/ChangeLog.dh 2013-11-18 12:14:09.662240103 +0100
+++ openssh-6.2p2/ChangeLog 2013-11-18 12:14:09.665240089 +0100
@@ -0,0 +1,8 @@
+20131010
+ - dtucker@cvs.openbsd.org 2013/10/08 11:42:13
+ [dh.c dh.h]
+ Increase the size of the Diffie-Hellman groups requested for a each
+ symmetric key size. New values from NIST Special Publication 800-57 with
+ the upper limit specified by RFC4419. Pointed out by Peter Backes, ok
+ djm@.
+
diff -up openssh-6.2p2/dh.c.dh openssh-6.2p2/dh.c
--- openssh-6.2p2/dh.c.dh 2011-12-19 00:52:52.000000000 +0100
+++ openssh-6.2p2/dh.c 2013-11-18 12:14:09.665240089 +0100
@@ -332,17 +332,20 @@ dh_new_group14(void)
/*
* Estimates the group order for a Diffie-Hellman group that has an
- * attack complexity approximately the same as O(2**bits). Estimate
- * with: O(exp(1.9223 * (ln q)^(1/3) (ln ln q)^(2/3)))
+ * attack complexity approximately the same as O(2**bits).
+ * Values from NIST Special Publication 800-57: Recommendation for Key
+ * Management Part 1 (rev 3) limited by the recommended maximum value
+ * from RFC4419 section 3.
*/
int
dh_estimate(int bits)
{
-
+ if (bits <= 112)
+ return 2048;
if (bits <= 128)
- return (1024); /* O(2**86) */
+ return 3072;
if (bits <= 192)
- return (2048); /* O(2**116) */
- return (4096); /* O(2**156) */
+ return 7680;
+ return 8192;
}
diff -up openssh-6.2p2/dh.h.dh openssh-6.2p2/dh.h
--- openssh-6.2p2/dh.h.dh 2008-06-29 14:47:04.000000000 +0200
+++ openssh-6.2p2/dh.h 2013-11-18 12:14:09.665240089 +0100
@@ -1,4 +1,4 @@
-/* $OpenBSD: dh.h,v 1.10 2008/06/26 09:19:40 djm Exp $ */
+/* $OpenBSD: dh.h,v 1.11 2013/10/08 11:42:13 dtucker Exp $ */
/*
* Copyright (c) 2000 Niels Provos. All rights reserved.
@@ -43,6 +43,7 @@ int dh_pub_is_valid(DH *, BIGNUM *);
int dh_estimate(int);
+/* Min and max values from RFC4419. */
#define DH_GRP_MIN 1024
#define DH_GRP_MAX 8192

167
openssh-6.1p1-kuserok.patch Normal file
View File

@ -0,0 +1,167 @@
diff -up openssh-6.1p1/auth-krb5.c.kuserok openssh-6.1p1/auth-krb5.c
--- openssh-6.1p1/auth-krb5.c.kuserok 2012-09-14 21:08:16.941496194 +0200
+++ openssh-6.1p1/auth-krb5.c 2012-09-14 21:08:17.063496896 +0200
@@ -55,6 +55,20 @@
extern ServerOptions options;
+int
+ssh_krb5_kuserok(krb5_context krb5_ctx, krb5_principal krb5_user, const char *client)
+{
+ if (options.use_kuserok)
+ 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)
{
@@ -147,7 +161,7 @@ auth_krb5_password(Authctxt *authctxt, c
if (problem)
goto out;
- if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, client)) {
+ if (!ssh_krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, client)) {
problem = -1;
goto out;
}
diff -up openssh-6.1p1/gss-serv-krb5.c.kuserok openssh-6.1p1/gss-serv-krb5.c
--- openssh-6.1p1/gss-serv-krb5.c.kuserok 2012-09-14 21:08:17.019496642 +0200
+++ openssh-6.1p1/gss-serv-krb5.c 2012-09-14 21:08:17.065496906 +0200
@@ -68,6 +68,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 *);
/* Initialise the krb5 library, for the stuff that GSSAPI won't do */
@@ -115,7 +116,7 @@ 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, luser) && k5login_exists) {
+ if (ssh_krb5_kuserok(krb_context, princ, luser) && k5login_exists) {
retval = 1;
logit("Authorized to %s, krb5 principal %s (krb5_kuserok)",
luser, (char *)client->displayname.value);
diff -up openssh-6.1p1/servconf.c.kuserok openssh-6.1p1/servconf.c
--- openssh-6.1p1/servconf.c.kuserok 2012-09-14 21:08:16.989496471 +0200
+++ openssh-6.1p1/servconf.c 2012-09-14 21:09:30.864868698 +0200
@@ -152,6 +152,7 @@ initialize_server_options(ServerOptions
options->ip_qos_interactive = -1;
options->ip_qos_bulk = -1;
options->version_addendum = NULL;
+ options->use_kuserok = -1;
}
void
@@ -301,6 +302,8 @@ fill_default_server_options(ServerOption
options->version_addendum = xstrdup("");
if (options->show_patchlevel == -1)
options->show_patchlevel = 0;
+ if (options->use_kuserok == -1)
+ options->use_kuserok = 1;
/* Turn privilege separation on by default */
if (use_privsep == -1)
@@ -327,7 +330,7 @@ typedef enum {
sPermitRootLogin, sLogFacility, sLogLevel,
sRhostsRSAAuthentication, sRSAAuthentication,
sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
- sKerberosGetAFSToken,
+ sKerberosGetAFSToken, sKerberosUseKuserok,
sKerberosTgtPassing, sChallengeResponseAuthentication,
sPasswordAuthentication, sKbdInteractiveAuthentication,
sListenAddress, sAddressFamily,
@@ -399,11 +402,13 @@ static struct {
#else
{ "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
#endif
+ { "kerberosusekuserok", sKerberosUseKuserok, SSHCFG_ALL },
#else
{ "kerberosauthentication", sUnsupported, SSHCFG_ALL },
{ "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL },
{ "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
{ "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
+ { "kerberosusekuserok", sUnsupported, SSHCFG_ALL },
#endif
{ "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
{ "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
@@ -1486,6 +1491,10 @@ process_server_config_line(ServerOptions
*activep = value;
break;
+ case sKerberosUseKuserok:
+ intptr = &options->use_kuserok;
+ goto parse_flag;
+
case sPermitOpen:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
@@ -1769,6 +1778,7 @@ copy_set_server_options(ServerOptions *d
M_CP_INTOPT(max_authtries);
M_CP_INTOPT(ip_qos_interactive);
M_CP_INTOPT(ip_qos_bulk);
+ M_CP_INTOPT(use_kuserok);
/* See comment in servconf.h */
COPY_MATCH_STRING_OPTS();
@@ -2005,6 +2015,7 @@ dump_config(ServerOptions *o)
dump_cfg_fmtint(sUseDNS, o->use_dns);
dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding);
dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep);
+ dump_cfg_fmtint(sKerberosUseKuserok, o->use_kuserok);
/* string arguments */
dump_cfg_string(sPidFile, o->pid_file);
diff -up openssh-6.1p1/servconf.h.kuserok openssh-6.1p1/servconf.h
--- openssh-6.1p1/servconf.h.kuserok 2012-09-14 21:08:16.990496476 +0200
+++ openssh-6.1p1/servconf.h 2012-09-14 21:08:17.071496942 +0200
@@ -169,6 +169,7 @@ typedef struct {
int num_permitted_opens;
+ int use_kuserok;
char *chroot_directory;
char *revoked_keys_file;
char *trusted_user_ca_keys;
diff -up openssh-6.1p1/sshd_config.kuserok openssh-6.1p1/sshd_config
--- openssh-6.1p1/sshd_config.kuserok 2012-09-14 21:08:17.002496545 +0200
+++ openssh-6.1p1/sshd_config 2012-09-14 21:08:17.074496957 +0200
@@ -79,6 +79,7 @@ ChallengeResponseAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no
+#KerberosUseKuserok yes
# GSSAPI options
#GSSAPIAuthentication no
diff -up openssh-6.1p1/sshd_config.5.kuserok openssh-6.1p1/sshd_config.5
--- openssh-6.1p1/sshd_config.5.kuserok 2012-09-14 21:08:17.004496556 +0200
+++ openssh-6.1p1/sshd_config.5 2012-09-14 21:08:17.073496952 +0200
@@ -618,6 +618,10 @@ Specifies whether to automatically destr
file on logout.
The default is
.Dq yes .
+.It Cm KerberosUseKuserok
+Specifies whether to look at .k5login file for user's aliases.
+The default is
+.Dq yes .
.It Cm KexAlgorithms
Specifies the available KEX (Key Exchange) algorithms.
Multiple algorithms must be comma-separated.
@@ -767,6 +771,7 @@ Available keywords are
.Cm HostbasedUsesNameFromPacketOnly ,
.Cm KbdInteractiveAuthentication ,
.Cm KerberosAuthentication ,
+.Cm KerberosUseKuserok ,
.Cm MaxAuthTries ,
.Cm MaxSessions ,
.Cm PubkeyAuthentication ,

View File

@ -1,26 +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)
diff -up openssh-6.1p1/sshd.c.log-usepam-no openssh-6.1p1/sshd.c
--- openssh-6.1p1/sshd.c.log-usepam-no 2012-09-14 20:54:58.000000000 +0200
+++ openssh-6.1p1/sshd.c 2012-09-14 20:55:42.289477749 +0200
@@ -1617,6 +1617,10 @@ main(int ac, char **av)
parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name,
cfg, &includes, NULL);
&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.");
+
/* Fill in default values for those options not explicitly set. */
fill_default_server_options(&options);
seed_rng();
diff --git a/sshd_config b/sshd_config
--- a/sshd_config
+++ b/sshd_config
@@ -101,6 +101,8 @@ GSSAPICleanupCredentials no
/* Fill in default values for those options not explicitly set. */
diff -up openssh-6.1p1/sshd_config.log-usepam-no openssh-6.1p1/sshd_config
--- openssh-6.1p1/sshd_config.log-usepam-no 2012-09-14 20:54:58.514255748 +0200
+++ openssh-6.1p1/sshd_config 2012-09-14 20:54:58.551255954 +0200
@@ -95,6 +95,8 @@ GSSAPICleanupCredentials yes
# 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 no
UsePAM yes
#AllowAgentForwarding yes

View File

@ -0,0 +1,24 @@
diff -up openssh-6.1p1/moduli.0.man-moduli openssh-6.1p1/moduli.0
--- openssh-6.1p1/moduli.0.man-moduli 2012-11-06 09:42:13.677062887 +0100
+++ openssh-6.1p1/moduli.0 2012-11-06 09:42:58.693543381 +0100
@@ -25,7 +25,7 @@ DESCRIPTION
0 Unknown, not tested.
2 "Safe" prime; (p-1)/2 is also prime.
- 4 Sophie Germain; (p+1)*2 is also prime.
+ 4 Sophie Germain; (p*2)+1 is also prime.
Moduli candidates initially produced by ssh-keygen(1)
are Sophie Germain primes (type 4). Further primality
diff -up openssh-6.1p1/moduli.5.man-moduli openssh-6.1p1/moduli.5
--- openssh-6.1p1/moduli.5.man-moduli 2012-11-06 09:42:17.730035388 +0100
+++ openssh-6.1p1/moduli.5 2012-11-06 09:43:31.403180375 +0100
@@ -61,7 +61,7 @@ Unknown, not tested.
.It 2
"Safe" prime; (p-1)/2 is also prime.
.It 4
-Sophie Germain; (p+1)*2 is also prime.
+Sophie Germain; (p*2)+1 is also prime.
.El
.Pp
Moduli candidates initially produced by

View File

@ -0,0 +1,93 @@
diff -up openssh-6.1p1/openbsd-compat/port-linux.c.privsep-selinux openssh-6.1p1/openbsd-compat/port-linux.c
--- openssh-6.1p1/openbsd-compat/port-linux.c.privsep-selinux 2012-11-05 14:46:39.334809203 +0100
+++ openssh-6.1p1/openbsd-compat/port-linux.c 2012-11-05 14:54:32.614504884 +0100
@@ -505,6 +505,25 @@ ssh_selinux_change_context(const char *n
xfree(newctx);
}
+void
+ssh_selinux_copy_context(void)
+{
+ security_context_t *ctx;
+
+ if (!ssh_selinux_enabled())
+ return;
+
+ if (getexeccon((security_context_t *)&ctx) != 0) {
+ logit("%s: getcon failed with %s", __func__, strerror (errno));
+ return;
+ }
+ if (ctx != NULL) {
+ if (setcon(ctx) != 0)
+ logit("%s: setcon failed with %s", __func__, strerror (errno));
+ freecon(ctx);
+ }
+}
+
#endif /* WITH_SELINUX */
#ifdef LINUX_OOM_ADJUST
diff -up openssh-6.1p1/openbsd-compat/port-linux.h.privsep-selinux openssh-6.1p1/openbsd-compat/port-linux.h
--- openssh-6.1p1/openbsd-compat/port-linux.h.privsep-selinux 2011-01-25 02:16:18.000000000 +0100
+++ openssh-6.1p1/openbsd-compat/port-linux.h 2012-11-05 14:46:39.339809234 +0100
@@ -24,6 +24,7 @@ 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_copy_context(void);
void ssh_selinux_setfscreatecon(const char *);
#endif
diff -up openssh-6.1p1/session.c.privsep-selinux openssh-6.1p1/session.c
--- openssh-6.1p1/session.c.privsep-selinux 2012-12-03 09:43:11.727505761 +0100
+++ openssh-6.1p1/session.c 2012-12-03 09:54:50.455688902 +0100
@@ -1519,6 +1519,9 @@ do_setusercontext(struct passwd *pw)
pw->pw_uid);
chroot_path = percent_expand(tmp, "h", pw->pw_dir,
"u", pw->pw_name, (char *)NULL);
+#ifdef WITH_SELINUX
+ ssh_selinux_copy_context();
+#endif
safely_chroot(chroot_path, pw->pw_uid);
free(tmp);
free(chroot_path);
@@ -1533,6 +1536,12 @@ do_setusercontext(struct passwd *pw)
/* Permanently switch to the desired uid. */
permanently_set_uid(pw);
#endif
+
+#ifdef WITH_SELINUX
+ if (options.chroot_directory == NULL ||
+ strcasecmp(options.chroot_directory, "none") == 0)
+ ssh_selinux_copy_context();
+#endif
}
if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
@@ -1787,9 +1796,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-6.1p1/sshd.c.privsep-selinux openssh-6.1p1/sshd.c
--- openssh-6.1p1/sshd.c.privsep-selinux 2012-11-05 14:46:39.335809209 +0100
+++ openssh-6.1p1/sshd.c 2012-11-05 14:46:39.341809247 +0100
@@ -794,6 +794,13 @@ privsep_postauth(Authctxt *authctxt)
do_setusercontext(authctxt->pw);
skip:
+#ifdef WITH_SELINUX
+ /* switch SELinux content for root too */
+ if (authctxt->pw->pw_uid == 0) {
+ ssh_selinux_copy_context();
+ }
+#endif
+
/* It is safe now to apply the key state */
monitor_apply_keystate(pmonitor);

117
openssh-6.1p1-redhat.patch Normal file
View File

@ -0,0 +1,117 @@
diff -up openssh-6.1p1/ssh_config.redhat openssh-6.1p1/ssh_config
--- openssh-6.1p1/ssh_config.redhat 2010-01-12 09:40:27.000000000 +0100
+++ openssh-6.1p1/ssh_config 2012-10-26 16:28:51.820340584 +0200
@@ -45,3 +45,14 @@
# PermitLocalCommand no
# VisualHostKey no
# ProxyCommand ssh -q -W %h:%p gateway.example.com
+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-6.1p1/sshd_config.0.redhat openssh-6.1p1/sshd_config.0
--- openssh-6.1p1/sshd_config.0.redhat 2012-10-26 16:28:51.762340584 +0200
+++ openssh-6.1p1/sshd_config.0 2012-10-26 16:28:51.821340584 +0200
@@ -583,9 +583,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-6.1p1/sshd_config.5.redhat openssh-6.1p1/sshd_config.5
--- openssh-6.1p1/sshd_config.5.redhat 2012-10-26 16:28:51.763340584 +0200
+++ openssh-6.1p1/sshd_config.5 2012-10-26 16:28:51.822340584 +0200
@@ -1015,7 +1015,7 @@ Note that this option applies to protoco
.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-6.1p1/sshd_config.redhat openssh-6.1p1/sshd_config
--- openssh-6.1p1/sshd_config.redhat 2012-10-26 16:28:51.819340584 +0200
+++ openssh-6.1p1/sshd_config 2012-10-26 16:31:44.773340564 +0200
@@ -10,6 +10,10 @@
# 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
@@ -32,6 +36,7 @@
# Logging
# obsoletes QuietMode and FascistLogging
#SyslogFacility AUTH
+SyslogFacility AUTHPRIV
#LogLevel INFO
# Authentication:
@@ -67,9 +72,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
@@ -79,7 +86,9 @@ AuthorizedKeysFile .ssh/authorized_keys
# GSSAPI options
#GSSAPIAuthentication no
+GSSAPIAuthentication yes
#GSSAPICleanupCredentials yes
+GSSAPICleanupCredentials yes
# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
@@ -91,11 +100,13 @@ AuthorizedKeysFile .ssh/authorized_keys
# 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
#PrintMotd yes
@@ -117,6 +128,12 @@ UsePrivilegeSeparation sandbox # Defaul
# no default banner path
#Banner none
+# Accept locale-related environment variables
+AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
+AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
+AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
+AcceptEnv XMODIFIERS
+
# override default of no subsystems
Subsystem sftp /usr/libexec/sftp-server

View File

@ -0,0 +1,22 @@
diff -up openssh-6.1p1/servconf.c.required-authentication openssh-6.1p1/servconf.c
--- openssh-6.1p1/servconf.c.required-authentication 2012-11-30 21:13:14.375382453 +0100
+++ openssh-6.1p1/servconf.c 2012-11-30 21:33:56.972017545 +0100
@@ -495,6 +495,8 @@ static struct {
{ "authorizedkeyscommandrunas", sAuthorizedKeysCommandUser, SSHCFG_ALL },
{ "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL },
{ "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL },
+ { "requiredauthentications1", sAuthenticationMethods, SSHCFG_ALL },
+ { "requiredauthentications2", sAuthenticationMethods, SSHCFG_ALL },
{ NULL, sBadOption, 0 }
};
@@ -1560,6 +1562,9 @@ process_server_config_line(ServerOptions
return 0;
case sAuthenticationMethods:
+ if (strncasecmp(arg, "requiredauthentications", 23) == 0)
+ logit("%s line %d: Option %s is obsolete. Please use AuthenticationMethods",
+ filename, linenum, arg);
if (*activep && options->num_auth_methods == 0) {
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (options->num_auth_methods >=

View File

@ -0,0 +1,934 @@
diff -up openssh-6.1p1/auth1.c.role-mls openssh-6.1p1/auth1.c
--- openssh-6.1p1/auth1.c.role-mls 2012-11-28 17:06:43.657990103 +0100
+++ openssh-6.1p1/auth1.c 2012-11-28 17:06:43.699989959 +0100
@@ -384,6 +384,9 @@ do_authentication(Authctxt *authctxt)
{
u_int ulen;
char *user, *style = NULL;
+#ifdef WITH_SELINUX
+ char *role=NULL;
+#endif
/* Get the name of the user that we wish to log in as. */
packet_read_expect(SSH_CMSG_USER);
@@ -392,11 +395,24 @@ do_authentication(Authctxt *authctxt)
user = packet_get_cstring(&ulen);
packet_check_eom();
+#ifdef WITH_SELINUX
+ if ((role = strchr(user, '/')) != NULL)
+ *role++ = '\0';
+#endif
+
if ((style = strchr(user, ':')) != NULL)
*style++ = '\0';
+#ifdef WITH_SELINUX
+ else
+ if (role && (style = strchr(role, ':')) != NULL)
+ *style++ = '\0';
+#endif
authctxt->user = user;
authctxt->style = style;
+#ifdef WITH_SELINUX
+ authctxt->role = role;
+#endif
/* Verify that the user is a valid user. */
if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL)
diff -up openssh-6.1p1/auth2.c.role-mls openssh-6.1p1/auth2.c
--- openssh-6.1p1/auth2.c.role-mls 2012-11-28 17:06:43.661990089 +0100
+++ openssh-6.1p1/auth2.c 2012-11-28 17:11:09.058916613 +0100
@@ -218,6 +218,9 @@ input_userauth_request(int type, u_int32
Authctxt *authctxt = ctxt;
Authmethod *m = NULL;
char *user, *service, *method, *style = NULL;
+#ifdef WITH_SELINUX
+ char *role = NULL;
+#endif
int authenticated = 0;
if (authctxt == NULL)
@@ -229,6 +232,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;
@@ -251,8 +259,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-6.1p1/auth2-gss.c.role-mls openssh-6.1p1/auth2-gss.c
--- openssh-6.1p1/auth2-gss.c.role-mls 2011-05-05 06:04:11.000000000 +0200
+++ openssh-6.1p1/auth2-gss.c 2012-11-28 17:06:43.700989956 +0100
@@ -260,6 +260,7 @@ input_gssapi_mic(int type, u_int32_t ple
Authctxt *authctxt = ctxt;
Gssctxt *gssctxt;
int authenticated = 0;
+ char *micuser;
Buffer b;
gss_buffer_desc mic, gssbuf;
u_int len;
@@ -272,7 +273,13 @@ input_gssapi_mic(int type, u_int32_t ple
mic.value = packet_get_string(&len);
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");
gssbuf.value = buffer_ptr(&b);
@@ -284,6 +291,8 @@ input_gssapi_mic(int type, u_int32_t ple
logit("GSSAPI MIC check failed");
buffer_free(&b);
+ if (micuser != authctxt->user)
+ xfree(micuser);
xfree(mic.value);
authctxt->postponed = 0;
diff -up openssh-6.1p1/auth2-hostbased.c.role-mls openssh-6.1p1/auth2-hostbased.c
--- openssh-6.1p1/auth2-hostbased.c.role-mls 2012-11-28 17:06:43.669990062 +0100
+++ openssh-6.1p1/auth2-hostbased.c 2012-11-28 17:06:43.700989956 +0100
@@ -106,7 +106,15 @@ userauth_hostbased(Authctxt *authctxt)
buffer_put_string(&b, session_id2, session_id2_len);
/* reconstruct packet */
buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
- buffer_put_cstring(&b, authctxt->user);
+#ifdef WITH_SELINUX
+ if (authctxt->role) {
+ buffer_put_int(&b, strlen(authctxt->user)+strlen(authctxt->role)+1);
+ buffer_append(&b, authctxt->user, strlen(authctxt->user));
+ buffer_put_char(&b, '/');
+ buffer_append(&b, authctxt->role, strlen(authctxt->role));
+ } else
+#endif
+ buffer_put_cstring(&b, authctxt->user);
buffer_put_cstring(&b, service);
buffer_put_cstring(&b, "hostbased");
buffer_put_string(&b, pkalg, alen);
diff -up openssh-6.1p1/auth2-pubkey.c.role-mls openssh-6.1p1/auth2-pubkey.c
--- openssh-6.1p1/auth2-pubkey.c.role-mls 2012-11-28 17:06:43.669990062 +0100
+++ openssh-6.1p1/auth2-pubkey.c 2012-11-28 17:06:43.700989956 +0100
@@ -121,7 +121,15 @@ userauth_pubkey(Authctxt *authctxt)
}
/* reconstruct packet */
buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
- buffer_put_cstring(&b, authctxt->user);
+#ifdef WITH_SELINUX
+ if (authctxt->role) {
+ buffer_put_int(&b, strlen(authctxt->user)+strlen(authctxt->role)+1);
+ buffer_append(&b, authctxt->user, strlen(authctxt->user));
+ buffer_put_char(&b, '/');
+ buffer_append(&b, authctxt->role, strlen(authctxt->role));
+ } else
+#endif
+ buffer_put_cstring(&b, authctxt->user);
buffer_put_cstring(&b,
datafellows & SSH_BUG_PKSERVICE ?
"ssh-userauth" :
diff -up openssh-6.1p1/auth.h.role-mls openssh-6.1p1/auth.h
--- openssh-6.1p1/auth.h.role-mls 2012-11-28 17:06:43.669990062 +0100
+++ openssh-6.1p1/auth.h 2012-11-28 17:06:43.699989959 +0100
@@ -59,6 +59,9 @@ struct Authctxt {
char *service;
struct passwd *pw; /* set if 'valid' */
char *style;
+#ifdef WITH_SELINUX
+ char *role;
+#endif
void *kbdintctxt;
void *jpake_ctx;
#ifdef BSD_AUTH
diff -up openssh-6.1p1/auth-pam.c.role-mls openssh-6.1p1/auth-pam.c
--- openssh-6.1p1/auth-pam.c.role-mls 2012-11-28 17:06:43.638990168 +0100
+++ openssh-6.1p1/auth-pam.c 2012-11-28 17:06:43.699989959 +0100
@@ -1074,7 +1074,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-6.1p1/auth-pam.h.role-mls openssh-6.1p1/auth-pam.h
--- openssh-6.1p1/auth-pam.h.role-mls 2004-09-11 14:17:26.000000000 +0200
+++ openssh-6.1p1/auth-pam.h 2012-11-28 17:06:43.699989959 +0100
@@ -38,7 +38,7 @@ void do_pam_session(void);
void do_pam_set_tty(const char *);
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-6.1p1/misc.c.role-mls openssh-6.1p1/misc.c
--- openssh-6.1p1/misc.c.role-mls 2011-09-22 13:34:36.000000000 +0200
+++ openssh-6.1p1/misc.c 2012-11-28 17:06:43.701989952 +0100
@@ -427,6 +427,7 @@ char *
colon(char *cp)
{
int flag = 0;
+ int start = 1;
if (*cp == ':') /* Leading colon is part of file name. */
return NULL;
@@ -442,6 +443,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-6.1p1/monitor.c.role-mls openssh-6.1p1/monitor.c
--- openssh-6.1p1/monitor.c.role-mls 2012-11-28 17:06:43.686990004 +0100
+++ openssh-6.1p1/monitor.c 2012-11-28 17:06:43.701989952 +0100
@@ -148,6 +148,9 @@ int mm_answer_sign(int, Buffer *);
int mm_answer_pwnamallow(int, Buffer *);
int mm_answer_auth2_read_banner(int, Buffer *);
int mm_answer_authserv(int, Buffer *);
+#ifdef WITH_SELINUX
+int mm_answer_authrole(int, Buffer *);
+#endif
int mm_answer_authpassword(int, Buffer *);
int mm_answer_bsdauthquery(int, Buffer *);
int mm_answer_bsdauthrespond(int, Buffer *);
@@ -231,6 +234,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
@@ -838,6 +844,9 @@ mm_answer_pwnamallow(int sock, Buffer *m
else {
/* 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
@@ -881,6 +890,25 @@ mm_answer_authserv(int sock, Buffer *m)
return (0);
}
+#ifdef WITH_SELINUX
+int
+mm_answer_authrole(int sock, Buffer *m)
+{
+ monitor_permit_authentications(1);
+
+ authctxt->role = buffer_get_string(m, NULL);
+ debug3("%s: role=%s",
+ __func__, authctxt->role);
+
+ if (strlen(authctxt->role) == 0) {
+ xfree(authctxt->role);
+ authctxt->role = NULL;
+ }
+
+ return (0);
+}
+#endif
+
int
mm_answer_authpassword(int sock, Buffer *m)
{
@@ -1251,7 +1279,7 @@ static int
monitor_valid_userblob(u_char *data, u_int datalen)
{
Buffer b;
- char *p;
+ char *p, *r;
u_int len;
int fail = 0;
@@ -1277,6 +1305,8 @@ monitor_valid_userblob(u_char *data, u_i
if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
fail++;
p = buffer_get_string(&b, NULL);
+ if ((r = strchr(p, '/')) != NULL)
+ *r = '\0';
if (strcmp(authctxt->user, p) != 0) {
logit("wrong user name passed to monitor: expected %s != %.100s",
authctxt->user, p);
@@ -1308,7 +1338,7 @@ monitor_valid_hostbasedblob(u_char *data
char *chost)
{
Buffer b;
- char *p;
+ char *p, *r;
u_int len;
int fail = 0;
@@ -1325,6 +1355,8 @@ monitor_valid_hostbasedblob(u_char *data
if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
fail++;
p = buffer_get_string(&b, NULL);
+ if ((r = strchr(p, '/')) != NULL)
+ *r = '\0';
if (strcmp(authctxt->user, p) != 0) {
logit("wrong user name passed to monitor: expected %s != %.100s",
authctxt->user, p);
diff -up openssh-6.1p1/monitor.h.role-mls openssh-6.1p1/monitor.h
--- openssh-6.1p1/monitor.h.role-mls 2012-11-28 17:06:43.686990004 +0100
+++ openssh-6.1p1/monitor.h 2012-11-28 17:06:43.701989952 +0100
@@ -31,6 +31,9 @@
enum monitor_reqtype {
MONITOR_REQ_MODULI, MONITOR_ANS_MODULI,
MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV,
+#ifdef WITH_SELINUX
+ MONITOR_REQ_AUTHROLE,
+#endif
MONITOR_REQ_SIGN, MONITOR_ANS_SIGN,
MONITOR_REQ_PWNAM, MONITOR_ANS_PWNAM,
MONITOR_REQ_AUTH2_READ_BANNER, MONITOR_ANS_AUTH2_READ_BANNER,
diff -up openssh-6.1p1/monitor_wrap.c.role-mls openssh-6.1p1/monitor_wrap.c
--- openssh-6.1p1/monitor_wrap.c.role-mls 2012-11-28 17:06:43.686990004 +0100
+++ openssh-6.1p1/monitor_wrap.c 2012-11-28 17:06:43.702989948 +0100
@@ -336,6 +336,25 @@ mm_inform_authserv(char *service, char *
buffer_free(&m);
}
+/* Inform the privileged process about role */
+
+#ifdef WITH_SELINUX
+void
+mm_inform_authrole(char *role)
+{
+ Buffer m;
+
+ debug3("%s entering", __func__);
+
+ buffer_init(&m);
+ buffer_put_cstring(&m, role ? role : "");
+
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHROLE, &m);
+
+ buffer_free(&m);
+}
+#endif
+
/* Do the password authentication */
int
mm_auth_password(Authctxt *authctxt, char *password)
diff -up openssh-6.1p1/monitor_wrap.h.role-mls openssh-6.1p1/monitor_wrap.h
--- openssh-6.1p1/monitor_wrap.h.role-mls 2012-11-28 17:06:43.686990004 +0100
+++ openssh-6.1p1/monitor_wrap.h 2012-11-28 17:06:43.702989948 +0100
@@ -42,6 +42,9 @@ int mm_is_monitor(void);
DH *mm_choose_dh(int, int, int);
int mm_key_sign(Key *, u_char **, u_int *, u_char *, u_int);
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 Authctxt *, char *);
diff -up openssh-6.1p1/openbsd-compat/Makefile.in.role-mls openssh-6.1p1/openbsd-compat/Makefile.in
--- openssh-6.1p1/openbsd-compat/Makefile.in.role-mls 2011-11-04 01:25:25.000000000 +0100
+++ openssh-6.1p1/openbsd-compat/Makefile.in 2012-11-28 17:06:43.702989948 +0100
@@ -20,7 +20,7 @@ OPENBSD=base64.o basename.o bindresvport
COMPAT=bsd-arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o getrrsetbyname-ldns.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xmmap.o xcrypt.o
-PORTS=port-aix.o port-irix.o port-linux.o port-solaris.o port-tun.o port-uw.o
+PORTS=port-aix.o port-irix.o port-linux.o port-linux_part_2.o port-solaris.o port-tun.o port-uw.o
.c.o:
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
diff -up openssh-6.1p1/openbsd-compat/port-linux.c.role-mls openssh-6.1p1/openbsd-compat/port-linux.c
--- openssh-6.1p1/openbsd-compat/port-linux.c.role-mls 2012-03-09 00:25:18.000000000 +0100
+++ openssh-6.1p1/openbsd-compat/port-linux.c 2012-11-28 17:06:43.702989948 +0100
@@ -31,68 +31,271 @@
#include "log.h"
#include "xmalloc.h"
+#include "servconf.h"
#include "port-linux.h"
+#include "key.h"
+#include "hostfile.h"
+#include "auth.h"
#ifdef WITH_SELINUX
#include <selinux/selinux.h>
#include <selinux/flask.h>
+#include <selinux/context.h>
#include <selinux/get_context_list.h>
+#include <selinux/get_default_type.h>
+#include <selinux/av_permissions.h>
+
+#ifdef HAVE_LINUX_AUDIT
+#include <libaudit.h>
+#include <unistd.h>
+#endif
#ifndef SSH_SELINUX_UNCONFINED_TYPE
# define SSH_SELINUX_UNCONFINED_TYPE ":unconfined_t:"
#endif
-/* Wrapper around is_selinux_enabled() to log its return value once only */
-int
-ssh_selinux_enabled(void)
+extern ServerOptions options;
+extern Authctxt *the_authctxt;
+extern int inetd_flag;
+extern int rexeced_flag;
+
+/* Send audit message */
+static int
+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)
{
- static int enabled = -1;
+ struct av_decision avd;
+ int retval;
+ unsigned int bit = CONTEXT__CONTAINS;
+
+ debug("%s: src:%s dst:%s", __func__, src, dst);
+ retval = security_compute_av(src, dst, SECCLASS_CONTEXT, 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;
+ }
- if (enabled == -1) {
- enabled = (is_selinux_enabled() == 1);
- debug("SELinux support %s", enabled ? "enabled" : "disabled");
+ 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;
+}
- return (enabled);
+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 security_context_t
-ssh_selinux_getctxbyname(char *pwname)
+ssh_selinux_getctxbyname(char *pwname,
+ security_context_t *default_sc, security_context_t *user_sc)
{
- security_context_t sc = NULL;
- char *sename = NULL, *lvl = NULL;
- int r;
+ 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 (getseuserbyname(pwname, &sename, &lvl) != 0)
- return NULL;
+ if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) {
+ sename = NULL;
+ lvl = NULL;
+ }
#else
sename = pwname;
- lvl = NULL;
+ lvl = "";
#endif
+ if (r == 0) {
#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
- r = get_default_context_with_level(sename, lvl, NULL, &sc);
+ r = get_default_context_with_level(sename, lvl, NULL, default_sc);
#else
- r = get_default_context(sename, NULL, &sc);
+ 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 (r != 0) {
- switch (security_getenforce()) {
- case -1:
- fatal("%s: ssh_selinux_getctxbyname: "
- "security_getenforce() failed", __func__);
- case 0:
- error("%s: Failed to get default SELinux security "
- "context for %s", __func__, pwname);
- sc = NULL;
- break;
- default:
- fatal("%s: Failed to get default SELinux security "
- "context for %s (in enforcing mode)",
- __func__, pwname);
}
+
+ 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
@@ -102,7 +305,42 @@ ssh_selinux_getctxbyname(char *pwname)
xfree(lvl);
#endif
- return sc;
+ if (role != NULL)
+ xfree(role);
+ if (con)
+ context_free(con);
+
+ return (r);
+}
+
+/* Setup environment variables for pam_selinux */
+static int
+ssh_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)
+ xfree(role);
+
+ return rv;
}
/* Set the execution context to the default for the specified user */
@@ -110,28 +348,71 @@ void
ssh_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 (ssh_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__);
- user_ctx = ssh_selinux_getctxbyname(pwname);
- if (setexeccon(user_ctx) != 0) {
+ r = ssh_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 */
+ 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: Failed to set SELinux execution "
- "context for %s", __func__, pwname);
+ error("%s: SELinux failure. Continuing in permissive mode.",
+ __func__);
break;
default:
- fatal("%s: Failed to set SELinux execution context "
- "for %s (in enforcing mode)", __func__, pwname);
+ fatal("%s: SELinux failure. Aborting connection.",
+ __func__);
}
}
- if (user_ctx != NULL)
+ if (user_ctx != NULL && user_ctx != default_ctx)
freecon(user_ctx);
+ if (default_ctx != NULL)
+ freecon(default_ctx);
debug3("%s: done", __func__);
}
@@ -149,7 +430,10 @@ 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? */
@@ -221,21 +505,6 @@ ssh_selinux_change_context(const char *n
xfree(newctx);
}
-void
-ssh_selinux_setfscreatecon(const char *path)
-{
- security_context_t context;
-
- if (!ssh_selinux_enabled())
- return;
- if (path == NULL) {
- setfscreatecon(NULL);
- return;
- }
- if (matchpathcon(path, 0700, &context) == 0)
- setfscreatecon(context);
-}
-
#endif /* WITH_SELINUX */
#ifdef LINUX_OOM_ADJUST
diff -up openssh-6.1p1/openbsd-compat/port-linux_part_2.c.role-mls openssh-6.1p1/openbsd-compat/port-linux_part_2.c
--- openssh-6.1p1/openbsd-compat/port-linux_part_2.c.role-mls 2012-11-28 17:06:43.703989944 +0100
+++ openssh-6.1p1/openbsd-compat/port-linux_part_2.c 2012-11-28 17:06:43.703989944 +0100
@@ -0,0 +1,75 @@
+/* $Id: port-linux.c,v 1.11.4.2 2011/02/04 00:43:08 djm Exp $ */
+
+/*
+ * Copyright (c) 2005 Daniel Walsh <dwalsh@redhat.com>
+ * Copyright (c) 2006 Damien Miller <djm@openbsd.org>
+ *
+ * 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 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 "log.h"
+#include "xmalloc.h"
+#include "port-linux.h"
+#include "key.h"
+#include "hostfile.h"
+#include "auth.h"
+
+#ifdef WITH_SELINUX
+#include <selinux/selinux.h>
+#include <selinux/flask.h>
+#include <selinux/get_context_list.h>
+
+/* Wrapper around is_selinux_enabled() to log its return value once only */
+int
+ssh_selinux_enabled(void)
+{
+ static int enabled = -1;
+
+ if (enabled == -1) {
+ enabled = (is_selinux_enabled() == 1);
+ debug("SELinux support %s", enabled ? "enabled" : "disabled");
+ }
+
+ return (enabled);
+}
+
+void
+ssh_selinux_setfscreatecon(const char *path)
+{
+ security_context_t context;
+
+ if (!ssh_selinux_enabled())
+ return;
+ if (path == NULL) {
+ setfscreatecon(NULL);
+ return;
+ }
+ if (matchpathcon(path, 0700, &context) == 0)
+ setfscreatecon(context);
+}
+
+#endif /* WITH_SELINUX */
+
+#endif /* WITH_SELINUX || LINUX_OOM_ADJUST */
diff -up openssh-6.1p1/sshd.c.role-mls openssh-6.1p1/sshd.c
--- openssh-6.1p1/sshd.c.role-mls 2012-11-28 17:06:43.688989996 +0100
+++ openssh-6.1p1/sshd.c 2012-11-28 17:06:43.703989944 +0100
@@ -2101,6 +2101,9 @@ main(int ac, char **av)
restore_uid();
}
#endif
+#ifdef WITH_SELINUX
+ ssh_selinux_setup_exec_context(authctxt->pw->pw_name);
+#endif
#ifdef USE_PAM
if (options.use_pam) {
do_pam_setcred(1);

View File

@ -0,0 +1,59 @@
diff -U0 openssh-6.1p1/ChangeLog.sftp-multibyte openssh-6.1p1/ChangeLog
--- openssh-6.1p1/ChangeLog.sftp-multibyte 2013-06-19 17:32:22.527999462 +0200
+++ openssh-6.1p1/ChangeLog 2013-06-19 17:34:12.236533762 +0200
@@ -0,0 +1,8 @@
+20130605
+ - dtucker@cvs.openbsd.org 2013/06/04 20:42:36
+ [sftp.c]
+ Make sftp's libedit interface marginally multibyte aware by building up
+ the quoted string by character instead of by byte. Prevents failures
+ when linked against a libedit built with wide character support (bz#1990).
+ "looks ok" djm
+
diff -up openssh-6.1p1/sftp.c.sftp-multibyte openssh-6.1p1/sftp.c
--- openssh-6.1p1/sftp.c.sftp-multibyte 2013-06-19 17:32:22.353000206 +0200
+++ openssh-6.1p1/sftp.c 2013-06-19 17:36:46.947876920 +0200
@@ -38,6 +38,7 @@
#ifdef HAVE_LIBGEN_H
#include <libgen.h>
#endif
+#include <locale.h>
#ifdef USE_LIBEDIT
#include <histedit.h>
#else
@@ -1694,8 +1695,9 @@ complete_match(EditLine *el, struct sftp
char *file, int remote, int lastarg, char quote, int terminated)
{
glob_t g;
- char *tmp, *tmp2, ins[3];
+ char *tmp, *tmp2, ins[8];
u_int i, hadglob, pwdlen, len, tmplen, filelen;
+ int clen;
const LineInfo *lf;
/* Glob from "file" location */
@@ -1751,10 +1753,13 @@ complete_match(EditLine *el, struct sftp
tmp2 = tmp + filelen;
len = strlen(tmp2);
/* quote argument on way out */
- for (i = 0; i < len; i++) {
+ for (i = 0; i < len; i += clen) {
+ if ((clen = mblen(tmp2 + i, len - i)) < 0 ||
+ (size_t)clen > sizeof(ins) - 2)
+ fatal("invalid multibyte character");
ins[0] = '\\';
- ins[1] = tmp2[i];
- ins[2] = '\0';
+ memcpy(ins + 1, tmp2 + i, clen);
+ ins[clen + 1] = '\0';
switch (tmp2[i]) {
case '\'':
case '"':
@@ -2096,6 +2101,7 @@ main(int argc, char **argv)
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
+ setlocale(LC_CTYPE, "");
__progname = ssh_get_progname(argv[0]);
memset(&args, '\0', sizeof(args));

View File

@ -0,0 +1,23 @@
diff -U0 openssh-6.2p2/ChangeLog.ssh_gai_strerror openssh-6.2p2/ChangeLog
--- openssh-6.2p2/ChangeLog.ssh_gai_strerror 2013-07-23 12:03:41.467902339 +0200
+++ openssh-6.2p2/ChangeLog 2013-07-23 12:06:03.414281151 +0200
@@ -0,0 +1,7 @@
+20130718
+ - djm@cvs.openbsd.org 2013/07/12 00:43:50
+ [misc.c]
+ in ssh_gai_strerror() don't fallback to strerror for EAI_SYSTEM when
+ errno == 0. Avoids confusing error message in some broken resolver
+ cases. bz#2122 patch from plautrba AT redhat.com; ok dtucker
+
diff -up openssh-6.2p2/misc.c.ssh_gai_strerror openssh-6.2p2/misc.c
--- openssh-6.2p2/misc.c.ssh_gai_strerror 2013-07-23 12:03:41.321902978 +0200
+++ openssh-6.2p2/misc.c 2013-07-23 12:03:41.467902339 +0200
@@ -127,7 +127,7 @@ unset_nonblock(int fd)
const char *
ssh_gai_strerror(int gaierr)
{
- if (gaierr == EAI_SYSTEM)
+ if (gaierr == EAI_SYSTEM && errno != 0)
return strerror(errno);
return gai_strerror(gaierr);
}

158
openssh-6.1p1-vendor.patch Normal file
View File

@ -0,0 +1,158 @@
diff -up openssh-6.1p1/configure.ac.vendor openssh-6.1p1/configure.ac
--- openssh-6.1p1/configure.ac.vendor 2012-09-14 20:36:49.153085211 +0200
+++ openssh-6.1p1/configure.ac 2012-09-14 20:36:49.559088133 +0200
@@ -4303,6 +4303,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
@@ -4529,6 +4535,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-6.1p1/servconf.c.vendor openssh-6.1p1/servconf.c
--- openssh-6.1p1/servconf.c.vendor 2012-09-14 20:36:49.124085002 +0200
+++ openssh-6.1p1/servconf.c 2012-09-14 20:50:34.995972516 +0200
@@ -128,6 +128,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;
@@ -289,6 +290,9 @@ fill_default_server_options(ServerOption
options->ip_qos_bulk = IPTOS_THROUGHPUT;
if (options->version_addendum == NULL)
options->version_addendum = xstrdup("");
+ if (options->show_patchlevel == -1)
+ options->show_patchlevel = 0;
+
/* Turn privilege separation on by default */
if (use_privsep == -1)
use_privsep = PRIVSEP_NOSANDBOX;
@@ -326,7 +330,7 @@ typedef enum {
sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem,
sMaxStartups, sMaxAuthTries, sMaxSessions,
- sBanner, sUseDNS, sHostbasedAuthentication,
+ sBanner, sShowPatchLevel, sUseDNS, sHostbasedAuthentication,
sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
sClientAliveCountMax, sAuthorizedKeysFile,
sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
@@ -441,6 +445,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 },
@@ -1162,6 +1167,10 @@ process_server_config_line(ServerOptions
multistate_ptr = multistate_privsep;
goto parse_multistate;
+ case sShowPatchLevel:
+ intptr = &options->show_patchlevel;
+ goto parse_flag;
+
case sAllowUsers:
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (options->num_allow_users >= MAX_ALLOW_USERS)
@@ -1956,6 +1965,7 @@ dump_config(ServerOptions *o)
dump_cfg_fmtint(sUseLogin, o->use_login);
dump_cfg_fmtint(sCompression, o->compression);
dump_cfg_fmtint(sGatewayPorts, o->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(sUsePrivilegeSeparation, use_privsep);
diff -up openssh-6.1p1/servconf.h.vendor openssh-6.1p1/servconf.h
--- openssh-6.1p1/servconf.h.vendor 2012-09-14 20:36:49.125085009 +0200
+++ openssh-6.1p1/servconf.h 2012-09-14 20:36:49.564088168 +0200
@@ -140,6 +140,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-6.1p1/sshd_config.vendor openssh-6.1p1/sshd_config
--- openssh-6.1p1/sshd_config.vendor 2012-09-14 20:36:49.507087759 +0200
+++ openssh-6.1p1/sshd_config 2012-09-14 20:36:49.565088175 +0200
@@ -114,6 +114,7 @@ UsePrivilegeSeparation sandbox # Defaul
#Compression delayed
#ClientAliveInterval 0
#ClientAliveCountMax 3
+#ShowPatchLevel no
#UseDNS yes
#PidFile /var/run/sshd.pid
#MaxStartups 10
diff -up openssh-6.1p1/sshd_config.0.vendor openssh-6.1p1/sshd_config.0
--- openssh-6.1p1/sshd_config.0.vendor 2012-09-14 20:36:49.510087780 +0200
+++ openssh-6.1p1/sshd_config.0 2012-09-14 20:36:49.567088190 +0200
@@ -558,6 +558,11 @@ DESCRIPTION
Defines the number of bits in the ephemeral protocol version 1
server key. The minimum value is 512, and the default is 1024.
+ ShowPatchLevel
+ Specifies whether sshd will display the specific patch level of
+ the binary in the server identification string. The patch level
+ is set at compile-time. The default is M-bM-^@M-^\noM-bM-^@M-^].
+
StrictModes
Specifies whether sshd(8) should check file modes and ownership
of the user's files and home directory before accepting login.
diff -up openssh-6.1p1/sshd_config.5.vendor openssh-6.1p1/sshd_config.5
--- openssh-6.1p1/sshd_config.5.vendor 2012-09-14 20:36:49.512087794 +0200
+++ openssh-6.1p1/sshd_config.5 2012-09-14 20:36:49.568088198 +0200
@@ -978,6 +978,14 @@ This option applies to protocol version
.It Cm ServerKeyBits
Defines the number of bits in the ephemeral protocol version 1 server key.
The minimum value is 512, and the default is 1024.
+.It Cm ShowPatchLevel
+Specifies whether
+.Nm sshd
+will display the patch level of the binary in the identification string.
+The patch level is set at compile-time.
+The default is
+.Dq no .
+This option applies to protocol version 1 only.
.It Cm StrictModes
Specifies whether
.Xr sshd 8
diff -up openssh-6.1p1/sshd.c.vendor openssh-6.1p1/sshd.c
--- openssh-6.1p1/sshd.c.vendor 2012-09-14 20:36:49.399086981 +0200
+++ openssh-6.1p1/sshd.c 2012-09-14 20:47:30.696088744 +0200
@@ -433,7 +433,7 @@ sshd_exchange_identification(int sock_in
}
xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s%s",
- major, minor, SSH_VERSION,
+ major, minor, (options.show_patchlevel == 1) ? SSH_VENDOR_PATCHLEVEL : SSH_VERSION,
*options.version_addendum == '\0' ? "" : " ",
options.version_addendum, newline);
@@ -1635,7 +1635,8 @@ main(int ac, char **av)
exit(1);
}
- debug("sshd version %.100s", SSH_RELEASE);
+ debug("sshd version %.100s",
+ (options.show_patchlevel == 1) ? SSH_VENDOR_PATCHLEVEL : SSH_RELEASE);
/* Store privilege separation user for later use if required. */
if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) {

View File

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

View File

@ -1,263 +0,0 @@
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 *)ssh->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);
ssh_signal(SIGHUP, &monitor_child_handler);
ssh_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 ssh *, 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)
/* Stop directing logs to a high-numbered fd before we close it */
log_redirect_stderr_to(NULL);
-
- /*
- * Close any extra open file descriptors so that we don't have them
- * hanging around in clients. Note that we want to do this after
- * initgroups, because at least on Solaris 2.3 it leaves file
- * descriptors open.
- */
- closefrom(STDERR_FILENO + 1);
}
/*
@@ -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,
extern char *__progname;
__progname = ssh_get_progname(argv[0]);
- log_init(__progname, log_level, log_facility, log_stderr);
+ log_init_handler(__progname, log_level, log_facility, log_stderr, reset_handler);
pw = pwcopy(user_pw);
@@ -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();

View File

@ -1,14 +0,0 @@
--- a/scp.c
+++ a/scp.c
@@ -1084,6 +1084,10 @@ sink(int argc, char **argv)
free(vect[0]);
continue;
}
+ if (buf[0] == 'C' && ! exists && np[strlen(np)-1] == '/') {
+ errno = ENOTDIR;
+ goto bad;
+ }
omode = mode;
mode |= S_IWUSR;
if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) == -1) {
--

View File

@ -1,132 +0,0 @@
diff --git a/openbsd-compat/port-linux-sshd.c b/openbsd-compat/port-linux-sshd.c
index 8f32464..18a2ca4 100644
--- a/openbsd-compat/port-linux-sshd.c
+++ b/openbsd-compat/port-linux-sshd.c
@@ -32,6 +32,7 @@
#include "misc.h" /* servconf.h needs misc.h for struct ForwardOptions */
#include "servconf.h"
#include "port-linux.h"
+#include "misc.h"
#include "sshkey.h"
#include "hostfile.h"
#include "auth.h"
@@ -445,7 +446,7 @@ sshd_selinux_setup_exec_context(char *pwname)
void
sshd_selinux_copy_context(void)
{
- security_context_t *ctx;
+ char *ctx;
if (!sshd_selinux_enabled())
return;
@@ -461,6 +462,72 @@ sshd_selinux_copy_context(void)
}
}
+void
+sshd_selinux_change_privsep_preauth_context(void)
+{
+ int len;
+ char line[1024], *preauth_context = NULL, *cp, *arg;
+ const char *contexts_path;
+ FILE *contexts_file;
+ struct stat sb;
+
+ contexts_path = selinux_openssh_contexts_path();
+ if (contexts_path == NULL) {
+ debug3("%s: Failed to get the path to SELinux context", __func__);
+ return;
+ }
+
+ if ((contexts_file = fopen(contexts_path, "r")) == NULL) {
+ debug("%s: Failed to open SELinux context file", __func__);
+ return;
+ }
+
+ if (fstat(fileno(contexts_file), &sb) != 0 ||
+ sb.st_uid != 0 || (sb.st_mode & 022) != 0) {
+ logit("%s: SELinux context file needs to be owned by root"
+ " and not writable by anyone else", __func__);
+ fclose(contexts_file);
+ return;
+ }
+
+ while (fgets(line, sizeof(line), contexts_file)) {
+ /* Strip trailing whitespace */
+ for (len = strlen(line) - 1; len > 0; len--) {
+ if (strchr(" \t\r\n", line[len]) == NULL)
+ break;
+ line[len] = '\0';
+ }
+
+ if (line[0] == '\0')
+ continue;
+
+ cp = line;
+ arg = strdelim(&cp);
+ if (arg && *arg == '\0')
+ arg = strdelim(&cp);
+
+ if (arg && strcmp(arg, "privsep_preauth") == 0) {
+ arg = strdelim(&cp);
+ if (!arg || *arg == '\0') {
+ debug("%s: privsep_preauth is empty", __func__);
+ fclose(contexts_file);
+ return;
+ }
+ preauth_context = xstrdup(arg);
+ }
+ }
+ fclose(contexts_file);
+
+ if (preauth_context == NULL) {
+ debug("%s: Unable to find 'privsep_preauth' option in"
+ " SELinux context file", __func__);
+ return;
+ }
+
+ ssh_selinux_change_context(preauth_context);
+ free(preauth_context);
+}
+
#endif
#endif
diff --git a/openbsd-compat/port-linux.c b/openbsd-compat/port-linux.c
index 22ea8ef..1fc963d 100644
--- a/openbsd-compat/port-linux.c
+++ b/openbsd-compat/port-linux.c
@@ -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 */

View File

@ -1,131 +0,0 @@
diff -up openssh-7.4p1/gss-serv-krb5.c.GSSAPIEnablek5users openssh-7.4p1/gss-serv-krb5.c
--- openssh-7.4p1/gss-serv-krb5.c.GSSAPIEnablek5users 2016-12-23 15:18:40.615216100 +0100
+++ openssh-7.4p1/gss-serv-krb5.c 2016-12-23 15:18:40.628216102 +0100
@@ -279,7 +279,6 @@ ssh_gssapi_krb5_cmdok(krb5_principal pri
FILE *fp;
char file[MAXPATHLEN];
char *line = NULL;
- char kuser[65]; /* match krb5_kuserok() */
struct stat st;
struct passwd *pw = the_authctxt->pw;
int found_principal = 0;
@@ -288,7 +287,7 @@ ssh_gssapi_krb5_cmdok(krb5_principal pri
snprintf(file, sizeof(file), "%s/.k5users", pw->pw_dir);
/* If both .k5login and .k5users DNE, self-login is ok. */
- if (!k5login_exists && (access(file, F_OK) == -1)) {
+ if ( !options.enable_k5users || (!k5login_exists && (access(file, F_OK) == -1))) {
return ssh_krb5_kuserok(krb_context, principal, luser,
k5login_exists);
}
diff -up openssh-7.4p1/servconf.c.GSSAPIEnablek5users openssh-7.4p1/servconf.c
--- openssh-7.4p1/servconf.c.GSSAPIEnablek5users 2016-12-23 15:18:40.615216100 +0100
+++ openssh-7.4p1/servconf.c 2016-12-23 15:35:36.354401156 +0100
@@ -168,6 +168,7 @@ initialize_server_options(ServerOptions
options->gss_store_rekey = -1;
options->gss_kex_algorithms = NULL;
options->use_kuserok = -1;
+ options->enable_k5users = -1;
options->password_authentication = -1;
options->kbd_interactive_authentication = -1;
options->challenge_response_authentication = -1;
@@ -345,6 +346,8 @@ fill_default_server_options(ServerOption
#endif
if (options->use_kuserok == -1)
options->use_kuserok = 1;
+ if (options->enable_k5users == -1)
+ options->enable_k5users = 0;
if (options->password_authentication == -1)
options->password_authentication = 1;
if (options->kbd_interactive_authentication == -1)
@@ -418,7 +421,7 @@ typedef enum {
sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedKeyTypes,
sHostKeyAlgorithms,
sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
- sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
+ sGssAuthentication, sGssCleanupCreds, sGssEnablek5users, sGssStrictAcceptor,
sGssKeyEx, sGssKexAlgorithms, sGssStoreRekey,
sAcceptEnv, sSetEnv, sPermitTunnel,
sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory,
@@ -497,14 +500,16 @@ static struct {
{ "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL },
{ "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL },
{ "gssapikexalgorithms", sGssKexAlgorithms, SSHCFG_GLOBAL },
+ { "gssapienablek5users", sGssEnablek5users, SSHCFG_ALL },
#else
{ "gssapiauthentication", sUnsupported, SSHCFG_ALL },
{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
{ "gssapicleanupcreds", sUnsupported, SSHCFG_GLOBAL },
{ "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },
{ "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL },
{ "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL },
{ "gssapikexalgorithms", sUnsupported, SSHCFG_GLOBAL },
+ { "gssapienablek5users", sUnsupported, SSHCFG_ALL },
#endif
{ "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL },
{ "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL },
@@ -1653,6 +1658,10 @@ process_server_config_line(ServerOptions
intptr = &options->use_kuserok;
goto parse_flag;
+ case sGssEnablek5users:
+ intptr = &options->enable_k5users;
+ goto parse_flag;
+
case 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 yes
#GSSAPIStrictAcceptorCheck yes
#GSSAPIKeyExchange no
+#GSSAPIEnablek5users no
# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will

View File

@ -1,39 +0,0 @@
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 */

View File

@ -1,31 +0,0 @@
diff -up openssh-8.2p1/authfile.c.keyperm openssh-8.2p1/authfile.c
--- openssh-8.2p1/authfile.c.keyperm 2020-02-14 01:40:54.000000000 +0100
+++ openssh-8.2p1/authfile.c 2020-02-17 11:55:12.841729758 +0100
@@ -31,6 +31,7 @@
#include <errno.h>
#include <fcntl.h>
+#include <grp.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
@@ -101,7 +102,19 @@ sshkey_perm_ok(int fd, const char *filen
#ifdef HAVE_CYGWIN
if (check_ntsec(filename))
#endif
+
if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0) {
+ if (st.st_mode & 040) {
+ struct group *gr;
+
+ if ((gr = getgrnam("ssh_keys")) && (st.st_gid == gr->gr_gid)) {
+ /* The only additional bit is read
+ * for ssh_keys group, which is fine */
+ if ((st.st_mode & 077) == 040 ) {
+ return 0;
+ }
+ }
+ }
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @");
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");

View File

@ -1,289 +0,0 @@
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_strict_acceptor = -1;
options->gss_store_rekey = -1;
options->gss_kex_algorithms = NULL;
+ options->use_kuserok = -1;
options->password_authentication = -1;
options->kbd_interactive_authentication = -1;
options->challenge_response_authentication = -1;
@@ -278,6 +279,8 @@ fill_default_server_options(ServerOption
if (options->gss_kex_algorithms == NULL)
options->gss_kex_algorithms = strdup(GSS_KEX_DEFAULT_KEX);
#endif
+ if (options->use_kuserok == -1)
+ options->use_kuserok = 1;
if (options->password_authentication == -1)
options->password_authentication = 1;
if (options->kbd_interactive_authentication == -1)
@@ -399,7 +402,7 @@ typedef enum {
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
*inc_flags &= ~SSHCFG_MATCH_ONLY;
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 no

View File

@ -1,121 +0,0 @@
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: getexeccon 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

View File

@ -1,185 +0,0 @@
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(ssh, pmonitor);
/* Drain any buffered messages from the child */
- while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0)
+ while (pmonitor->m_log_recvfd >= 0 && monitor_read_log(pmonitor) == 0)
;
if (pmonitor->m_recvfd >= 0)
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)
debug("%s: invalid tun", __func__);
goto done;
}
- if (auth_opts->force_tun_device != -1) {
+ if (auth_opts->force_tun_device >= 0) {
if (tun != SSH_TUNID_ANY &&
auth_opts->force_tun_device != (int)tun)
goto done;
diff -up openssh-7.4p1/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)
pid = sshpid;
if (pid > 1) {
kill(pid, SIGTERM);
- waitpid(pid, NULL, 0);
+ (void) waitpid(pid, 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(ssh);
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
explicit_bzero(rnd, sizeof(rnd));
}
}
+
+ if (fdset != NULL)
+ free(fdset);
}
/*

View File

@ -1,618 +0,0 @@
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_KEYSIGN=$(libexecdir)/ssh-keysign
SSH_KEYCAT=$(libexecdir)/ssh-keycat
CTR_CAVSTEST=$(libexecdir)/ctr-cavstest
+SSH_CAVS=$(libexecdir)/ssh-cavs
SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
SSH_SK_HELPER=$(libexecdir)/ssh-sk-helper
PRIVSEP_PATH=@PRIVSEP_PATH@
@@ -67,7 +68,7 @@ EXEEXT=@EXEEXT@
.SUFFIXES: .lo
-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT) 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-sk-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 $(LIBS)
+ssh-cavs$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-cavs.o $(SKOBJS)
+ $(LD) -o $@ ssh-cavs.o $(SKOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYSCAN_OBJS)
$(LD) -o $@ $(SSHKEYSCAN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
@@ -331,6 +335,8 @@ install-files:
$(INSTALL) -m 0755 $(STRIP_OPT) ssh-sk-helper$(EXEEXT) $(DESTDIR)$(SSH_SK_HELPER)$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) ssh-keycat$(EXEEXT) $(DESTDIR)$(libexecdir)/ssh-keycat$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) 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,387 @@
+/*
+ * 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;
+ struct sshbuf *Kb = NULL;
+ 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;
+ }
+ Kb = sshbuf_new();
+ if (!Kb) {
+ printf("cannot convert K into sshbuf\n");
+ ret = 1;
+ goto out;
+ }
+ sshbuf_put_bignum2(Kb, Kbn);
+
+ 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(ssh, test->H, test->Hlen, Kb);
+
+ 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 (Kb)
+ sshbuf_free(Kb);
+ 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;

View File

@ -1,100 +0,0 @@
diff -up openssh-7.2p2/sftp-server.8.sftp-force-mode openssh-7.2p2/sftp-server.8
--- openssh-7.2p2/sftp-server.8.sftp-force-mode 2016-03-09 19:04:48.000000000 +0100
+++ openssh-7.2p2/sftp-server.8 2016-06-23 16:18:20.463854117 +0200
@@ -38,6 +38,7 @@
.Op Fl P Ar denied_requests
.Op Fl p Ar allowed_requests
.Op Fl u Ar umask
+.Op Fl m Ar force_file_perms
.Ek
.Nm
.Fl Q Ar protocol_feature
@@ -138,6 +139,12 @@ Sets an explicit
.Xr umask 2
to be applied to newly-created files and directories, instead of the
user's default mask.
+.It Fl m Ar force_file_perms
+Sets explicit file permissions to be applied to newly-created files instead
+of the default or client requested mode. Numeric values include:
+777, 755, 750, 666, 644, 640, etc. Using both -m and -u switches makes the
+umask (-u) effective only for newly created directories and explicit mode (-m)
+for newly created files.
.El
.Pp
On some systems,
diff -up openssh-7.2p2/sftp-server.c.sftp-force-mode openssh-7.2p2/sftp-server.c
--- openssh-7.2p2/sftp-server.c.sftp-force-mode 2016-06-23 16:18:20.446854128 +0200
+++ openssh-7.2p2/sftp-server.c 2016-06-23 16:20:37.950766082 +0200
@@ -69,6 +69,10 @@ struct sshbuf *oqueue;
/* Version of client */
static u_int version;
+/* Force file permissions */
+int permforce = 0;
+long permforcemode;
+
/* SSH2_FXP_INIT received */
static int init_done;
@@ -683,6 +687,7 @@ process_open(u_int32_t id)
Attrib a;
char *name;
int r, handle, fd, flags, mode, status = SSH2_FX_FAILURE;
+ mode_t old_umask = 0;
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
(r = sshbuf_get_u32(iqueue, &pflags)) != 0 || /* portable flags */
@@ -692,6 +697,10 @@ process_open(u_int32_t id)
debug3("request %u: open flags %d", id, pflags);
flags = flags_from_portable(pflags);
mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a.perm : 0666;
+ if (permforce == 1) { /* Force perm if -m is set */
+ mode = permforcemode;
+ old_umask = umask(0); /* so umask does not interfere */
+ }
logit("open \"%s\" flags %s mode 0%o",
name, string_from_portable(pflags), mode);
if (readonly &&
@@ -713,6 +722,8 @@ process_open(u_int32_t id)
}
}
}
+ if (permforce == 1)
+ (void) umask(old_umask); /* restore umask to something sane */
if (status != SSH2_FX_OK)
send_status(id, status);
free(name);
@@ -1494,7 +1505,7 @@ sftp_server_usage(void)
fprintf(stderr,
"usage: %s [-ehR] [-d start_directory] [-f log_facility] "
"[-l log_level]\n\t[-P denied_requests] "
- "[-p allowed_requests] [-u umask]\n"
+ "[-p allowed_requests] [-u umask] [-m force_file_perms]\n"
" %s -Q protocol_feature\n",
__progname, __progname);
exit(1);
@@ -1520,7 +1531,7 @@ sftp_server_main(int argc, char **argv,
pw = pwcopy(user_pw);
while (!skipargs && (ch = getopt(argc, argv,
- "d:f:l:P:p:Q:u:cehR")) != -1) {
+ "d:f:l:P:p:Q:u:m:cehR")) != -1) {
switch (ch) {
case 'Q':
if (strcasecmp(optarg, "requests") != 0) {
@@ -1580,6 +1591,15 @@ sftp_server_main(int argc, char **argv,
fatal("Invalid umask \"%s\"", optarg);
(void)umask((mode_t)mask);
break;
+ case 'm':
+ /* Force permissions on file received via sftp */
+ permforce = 1;
+ permforcemode = strtol(optarg, &cp, 8);
+ if (permforcemode < 0 || permforcemode > 0777 ||
+ *cp != '\0' || (permforcemode == 0 &&
+ errno != 0))
+ fatal("Invalid file mode \"%s\"", optarg);
+ break;
case 'h':
default:
sftp_server_usage();

View File

@ -1,12 +0,0 @@
diff -up openssh/servconf.c.sshdt openssh/servconf.c
--- openssh/servconf.c.sshdt 2015-06-24 11:42:29.041078704 +0200
+++ openssh/servconf.c 2015-06-24 11:44:39.734745802 +0200
@@ -2317,7 +2317,7 @@ dump_config(ServerOptions *o)
dump_cfg_string(sXAuthLocation, o->xauth_location);
dump_cfg_string(sCiphers, o->ciphers);
dump_cfg_string(sMacs, o->macs);
- dump_cfg_string(sBanner, o->banner);
+ dump_cfg_string(sBanner, o->banner != NULL ? o->banner : "none");
dump_cfg_string(sForceCommand, o->adm_forced_command);
dump_cfg_string(sChrootDirectory, o->chroot_directory);
dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys);

View File

@ -1,187 +0,0 @@
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(struct ssh *, int, char *, char *, char *, char *, pid_t, uid_t);
void mm_audit_session_key_free_body(struct ssh *, int, pid_t, uid_t);
void mm_audit_destroy_sensitive_data(struct ssh *, const char *, pid_t, uid_t);
+int mm_forward_audit_messages(int);
+void mm_set_monitor_pipe(int);
#endif
struct Session;
diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c
--- openssh-7.4p1/session.c.audit-race 2016-12-23 16:35:52.695685771 +0100
+++ openssh-7.4p1/session.c 2016-12-23 16:37:26.339730596 +0100
@@ -162,6 +162,10 @@ static Session *sessions = NULL;
login_cap_t *lc;
#endif
+#ifdef SSH_AUDIT_EVENTS
+int paudit[2];
+#endif
+
static int is_child = 0;
static int in_chroot = 0;
static int have_dev_log = 1;
@@ -289,6 +293,8 @@ xauth_valid_string(const char *s)
return 1;
}
+void child_destory_sensitive_data(struct ssh *ssh);
+
#define USE_PIPES 1
/*
* This is called to fork and execute a command when we have no tty. This
@@ -424,6 +430,8 @@ do_exec_no_pty(Session *s, const char *c
close(err[0]);
#endif
+ child_destory_sensitive_data(ssh);
+
/* Do processing for the child (exec command etc). */
do_child(ssh, s, command);
/* NOTREACHED */
@@ -547,6 +555,9 @@ do_exec_pty(Session *s, const char *comm
/* Close the extra descriptor for the pseudo tty. */
close(ttyfd);
+ /* Do this early, so we will not block large MOTDs */
+ child_destory_sensitive_data(ssh);
+
/* record login, etc. similar to login(1) */
#ifndef HAVE_OSF_SIA
do_login(ssh, s, command);
@@ -717,6 +728,8 @@ do_exec(Session *s, const char *command)
}
if (s->command != NULL && s->ptyfd == -1)
s->command_handle = PRIVSEP(audit_run_command(ssh, s->command));
+ if (pipe(paudit) < 0)
+ fatal("pipe: %s", strerror(errno));
#endif
if (s->ttyfd != -1)
ret = do_exec_pty(ssh, s, command);
@@ -732,6 +745,20 @@ do_exec(Session *s, const char *command)
*/
sshbuf_reset(loginmsg);
+#ifdef SSH_AUDIT_EVENTS
+ close(paudit[1]);
+ if (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)
log_redirect_stderr_to(NULL);
}
+void
+child_destory_sensitive_data(struct ssh *ssh)
+{
+#ifdef SSH_AUDIT_EVENTS
+ int pparent = paudit[1];
+ close(paudit[0]);
+ /* Hack the monitor pipe to avoid race condition with parent */
+ if (use_privsep)
+ mm_set_monitor_pipe(pparent);
+#endif
+
+ /* remove hostkey from the child's memory */
+ destroy_sensitive_data(ssh, 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(ssh, 0, 1);
+ /* XXX this will clean the rest but should not audit anymore */
+ /* packet_clear_keys(ssh); */
+
+#ifdef SSH_AUDIT_EVENTS
+ /* Notify parent that we are done */
+ close(pparent);
+#endif
+}
+
/*
* Performs common processing for the child, such as setting up the
* environment, closing extra file descriptors, setting the user and group
@@ -1554,13 +1608,6 @@ do_child(Session *s, const char *command
sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id));
- /* remove hostkey from the child's memory */
- destroy_sensitive_data(ssh, 1);
- ssh_packet_clear_keys(ssh);
- /* Don't audit this - both us and the parent would be talking to the
- monitor over a single socket, with no synchronization. */
- packet_destroy_all(ssh, 0, 1);
-
/* Force a password change */
if (s->authctxt->force_pwchange) {
do_setusercontext(pw);

View File

@ -1,87 +0,0 @@
diff --git a/auth-krb5.c b/auth-krb5.c
index 2b02a04..19b9364 100644
--- a/auth-krb5.c
+++ b/auth-krb5.c
@@ -375,5 +375,21 @@ cleanup:
return (krb5_cc_resolve(ctx, ccname, ccache));
}
}
+
+/*
+ * Reads k5login_directory option from the krb5.conf
+ */
+krb5_error_code
+ssh_krb5_get_k5login_directory(krb5_context ctx, char **k5login_directory) {
+ profile_t p;
+ int ret = 0;
+
+ ret = krb5_get_profile(ctx, &p);
+ if (ret)
+ return ret;
+
+ return profile_get_string(p, "libdefaults", "k5login_directory", NULL, NULL,
+ k5login_directory);
+}
#endif /* !HEIMDAL */
#endif /* KRB5 */
diff --git a/auth.h b/auth.h
index f9d191c..c432d2f 100644
--- a/auth.h
+++ b/auth.h
@@ -222,6 +222,8 @@ int sys_auth_passwd(Authctxt *, const char *);
#if defined(KRB5) && !defined(HEIMDAL)
krb5_error_code ssh_krb5_cc_new_unique(krb5_context, krb5_ccache *, int *);
+krb5_error_code ssh_krb5_get_k5login_directory(krb5_context ctx,
+ char **k5login_directory);
#endif
#endif /* AUTH_H */
diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c
index a7c0c5f..df8cc9a 100644
--- a/gss-serv-krb5.c
+++ b/gss-serv-krb5.c
@@ -244,8 +244,27 @@ ssh_gssapi_k5login_exists()
{
char file[MAXPATHLEN];
struct passwd *pw = the_authctxt->pw;
+ char *k5login_directory = NULL;
+ int ret = 0;
+
+ ret = ssh_krb5_get_k5login_directory(krb_context, &k5login_directory);
+ debug3("%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

View File

@ -1,52 +0,0 @@
Zseries only: Leave the hardware filedescriptors open.
All filedescriptors above 2 are getting closed when a new
sshd process to handle a new client connection is
spawned. As the process also chroot into an empty filesystem
without any device nodes, there is no chance to reopen the
files. This patch filters out the reqired fds in the
closefrom function so these are skipped in the close loop.
Author: Harald Freudenberger <freude@de.ibm.com>
---
openbsd-compat/bsd-closefrom.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
--- a/openbsd-compat/bsd-closefrom.c
+++ b/openbsd-compat/bsd-closefrom.c
@@ -82,7 +82,33 @@ closefrom(int lowfd)
fd = strtol(dent->d_name, &endp, 10);
if (dent->d_name != endp && *endp == '\0' &&
fd >= 0 && fd < INT_MAX && fd >= lowfd && fd != dirfd(dirp))
+#ifdef __s390__
+ {
+ /*
+ * the filedescriptors used to communicate with
+ * the device drivers to provide hardware support
+ * should survive. HF <freude@de.ibm.com>
+ */
+ char fpath[PATH_MAX], lpath[PATH_MAX];
+ len = snprintf(fpath, sizeof(fpath), "%s/%s",
+ fdpath, dent->d_name);
+ if (len > 0 && (size_t)len <= sizeof(fpath)) {
+ len = readlink(fpath, lpath, sizeof(lpath));
+ if (len > 0) {
+ lpath[len] = 0;
+ if (strstr(lpath, "dev/z90crypt")
+ || strstr(lpath, "dev/zcrypt")
+ || strstr(lpath, "dev/prandom")
+ || strstr(lpath, "dev/shm/icastats"))
+ fd = -1;
+ }
+ }
+ if (fd >= 0)
+ (void) close((int) fd);
+ }
+#else
(void) close((int) fd);
+#endif
}
(void) closedir(dirp);
return;

View File

@ -1,213 +0,0 @@
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) == -1) {
debug2("connect %.100s port %u: %.100s", buf,
- 6000 + display_number, strerror(errno));
+ X11_PORT_MIN + display_number, strerror(errno));
close(sock);
continue;
}
@@ -4466,8 +4472,8 @@ x11_connect_display(void)
}
freeaddrinfo(aitop);
if (!ai) {
- error("connect %.100s port %u: %.100s", buf,
- 6000 + display_number, strerror(errno));
+ error("connect %.100s port %u: %.100s", buf,
+ X11_PORT_MIN + display_number, strerror(errno));
return -1;
}
set_nodelay(sock);
diff -up openssh-7.4p1/channels.h.x11max openssh-7.4p1/channels.h
--- openssh-7.4p1/channels.h.x11max 2016-12-19 05:59:41.000000000 +0100
+++ openssh-7.4p1/channels.h 2016-12-23 15:46:32.139506636 +0100
@@ -293,7 +293,7 @@ int permitopen_port(const char *);
void channel_set_x11_refuse_time(struct ssh *, 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

View File

@ -1,98 +0,0 @@
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);

View File

@ -1,86 +0,0 @@
In order to use the OpenSSL-ibmpkcs11 engine it is needed to allow flock
and ipc calls, because this engine calls OpenCryptoki (a PKCS#11
implementation) which calls the libraries that will communicate with the
crypto cards. OpenCryptoki makes use of flock and ipc and, as of now,
this is only need on s390 architecture.
Signed-off-by: Eduardo Barretto <ebarretto@xxxxxxxxxxxxxxxxxx>
---
sandbox-seccomp-filter.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/sandbox-seccomp-filter.c b/sandbox-seccomp-filter.c
index ca75cc7..6e7de31 100644
--- a/sandbox-seccomp-filter.c
+++ b/sandbox-seccomp-filter.c
@@ -166,6 +166,9 @@ static const struct sock_filter preauth_insns[] = {
#ifdef __NR_exit_group
SC_ALLOW(__NR_exit_group),
#endif
+#if defined(__NR_flock) && defined(__s390__)
+ SC_ALLOW(__NR_flock),
+#endif
#ifdef __NR_futex
SC_ALLOW(__NR_futex),
#endif
@@ -178,6 +181,9 @@ static const struct sock_filter preauth_insns[] = {
#ifdef __NR_gettimeofday
SC_ALLOW(__NR_gettimeofday),
#endif
+#if defined(__NR_ipc) && defined(__s390__)
+ SC_ALLOW(__NR_ipc),
+#endif
#ifdef __NR_getuid
SC_ALLOW(__NR_getuid),
#endif
--
1.9.1
getuid and geteuid are needed when using an openssl engine that calls a
crypto card, e.g. ICA (libica).
Those syscalls are also needed by the distros for audit code.
Signed-off-by: Eduardo Barretto <ebarretto@xxxxxxxxxxxxxxxxxx>
---
sandbox-seccomp-filter.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/sandbox-seccomp-filter.c b/sandbox-seccomp-filter.c
index 6e7de31..e86aa2c 100644
--- a/sandbox-seccomp-filter.c
+++ b/sandbox-seccomp-filter.c
@@ -175,6 +175,18 @@ static const struct sock_filter preauth_insns[] = {
#ifdef __NR_getpid
SC_ALLOW(__NR_getpid),
#endif
+#ifdef __NR_getuid
+ SC_ALLOW(__NR_getuid),
+#endif
+#ifdef __NR_getuid32
+ SC_ALLOW(__NR_getuid32),
+#endif
+#ifdef __NR_geteuid
+ SC_ALLOW(__NR_geteuid),
+#endif
+#ifdef __NR_geteuid32
+ SC_ALLOW(__NR_geteuid32),
+#endif
#ifdef __NR_getrandom
SC_ALLOW(__NR_getrandom),
#endif
-- 1.9.1
1.9.1
diff -up openssh-7.6p1/sandbox-seccomp-filter.c.sandbox openssh-7.6p1/sandbox-seccomp-filter.c
--- openssh-7.6p1/sandbox-seccomp-filter.c.sandbox 2017-12-12 13:59:30.563874059 +0100
+++ openssh-7.6p1/sandbox-seccomp-filter.c 2017-12-12 13:59:14.842784083 +0100
@@ -190,6 +190,9 @@ static const struct sock_filter preauth_
#ifdef __NR_geteuid32
SC_ALLOW(__NR_geteuid32),
#endif
+#ifdef __NR_gettid
+ SC_ALLOW(__NR_gettid),
+#endif
#ifdef __NR_getrandom
SC_ALLOW(__NR_getrandom),
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,271 +0,0 @@
diff -up openssh/auth2-pubkey.c.refactor openssh/auth2-pubkey.c
--- openssh/auth2-pubkey.c.refactor 2019-04-04 13:19:12.188821236 +0200
+++ openssh/auth2-pubkey.c 2019-04-04 13:19:12.276822078 +0200
@@ -72,6 +72,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)
@@ -511,7 +514,8 @@ match_principals_command(struct ssh *ssh
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;
@@ -981,7 +985,8 @@ user_key_command_allowed2(struct ssh *ss
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 2019-04-04 13:19:12.235821686 +0200
+++ openssh/auth.c 2019-04-04 13:19:12.276822078 +0200
@@ -756,7 +756,8 @@ auth_get_canonical_hostname(struct ssh *
*/
pid_t
subprocess(const char *tag, 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;
@@ -872,7 +873,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 2019-04-04 13:19:12.251821839 +0200
+++ openssh/auth.h 2019-04-04 13:19:12.276822078 +0200
@@ -235,7 +235,7 @@ struct passwd *fakepw(void);
#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 2019-04-04 13:19:12.256821887 +0200
+++ openssh/openbsd-compat/port-linux.h 2019-04-04 13:19:12.276822078 +0200
@@ -26,8 +26,8 @@ void ssh_selinux_setfscreatecon(const ch
int sshd_selinux_enabled(void);
void sshd_selinux_copy_context(void);
-void sshd_selinux_setup_exec_context(char *);
-int sshd_selinux_setup_env_variables(void);
+void sshd_selinux_setup_exec_context(char *, int, int(char *, const char *), void *, int);
+int sshd_selinux_setup_env_variables(int inetd, void *);
void sshd_selinux_change_privsep_preauth_context(void);
#endif
diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compat/port-linux-sshd.c
--- openssh/openbsd-compat/port-linux-sshd.c.refactor 2019-04-04 13:19:12.256821887 +0200
+++ openssh/openbsd-compat/port-linux-sshd.c 2019-04-04 13:19:12.276822078 +0200
@@ -49,11 +49,6 @@
#include <unistd.h>
#endif
-extern ServerOptions options;
-extern Authctxt *the_authctxt;
-extern int inetd_flag;
-extern int rexeced_flag;
-
/* Wrapper around is_selinux_enabled() to log its return value once only */
int
sshd_selinux_enabled(void)
@@ -223,7 +218,8 @@ get_user_context(const char *sename, con
}
static void
-ssh_selinux_get_role_level(char **role, const char **level)
+ssh_selinux_get_role_level(char **role, const char **level,
+ Authctxt *the_authctxt)
{
*role = NULL;
*level = NULL;
@@ -241,8 +237,8 @@ ssh_selinux_get_role_level(char **role,
/* Return the default security context for the given username */
static int
-sshd_selinux_getctxbyname(char *pwname,
- security_context_t *default_sc, security_context_t *user_sc)
+sshd_selinux_getctxbyname(char *pwname, security_context_t *default_sc,
+ security_context_t *user_sc, int inetd, Authctxt *the_authctxt)
{
char *sename, *lvl;
char *role;
@@ -250,7 +246,7 @@ sshd_selinux_getctxbyname(char *pwname,
int r = 0;
context_t con = NULL;
- ssh_selinux_get_role_level(&role, &reqlvl);
+ ssh_selinux_get_role_level(&role, &reqlvl, the_authctxt);
#ifdef HAVE_GETSEUSERBYNAME
if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) {
@@ -272,7 +268,7 @@ sshd_selinux_getctxbyname(char *pwname,
if (r == 0) {
/* If launched from xinetd, we must use current level */
- if (inetd_flag && !rexeced_flag) {
+ if (inetd) {
security_context_t sshdsc=NULL;
if (getcon_raw(&sshdsc) < 0)
@@ -333,7 +329,8 @@ sshd_selinux_getctxbyname(char *pwname,
/* Setup environment variables for pam_selinux */
static int
-sshd_selinux_setup_variables(int(*set_it)(char *, const char *))
+sshd_selinux_setup_variables(int(*set_it)(char *, const char *), int inetd,
+ Authctxt *the_authctxt)
{
const char *reqlvl;
char *role;
@@ -342,11 +339,11 @@ sshd_selinux_setup_variables(int(*set_it
debug3("%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 = "";
@@ -362,9 +359,10 @@ sshd_selinux_setup_variables(int(*set_it
}
static int
-sshd_selinux_setup_pam_variables(void)
+sshd_selinux_setup_pam_variables(int inetd,
+ int(pam_setenv)(char *, const char *), Authctxt *the_authctxt)
{
- return sshd_selinux_setup_variables(do_pam_putenv);
+ return sshd_selinux_setup_variables(pam_setenv, inetd, the_authctxt);
}
static int
@@ -374,25 +372,28 @@ do_setenv(char *name, const char *value)
}
int
-sshd_selinux_setup_env_variables(void)
+sshd_selinux_setup_env_variables(int inetd, void *the_authctxt)
{
- return sshd_selinux_setup_variables(do_setenv);
+ Authctxt *authctxt = (Authctxt *) the_authctxt;
+ return sshd_selinux_setup_variables(do_setenv, inetd, authctxt);
}
/* Set the execution context to the default for the specified user */
void
-sshd_selinux_setup_exec_context(char *pwname)
+sshd_selinux_setup_exec_context(char *pwname, int inetd,
+ int(pam_setenv)(char *, const char *), void *the_authctxt, int use_pam)
{
security_context_t user_ctx = NULL;
int r = 0;
security_context_t default_ctx = NULL;
+ Authctxt *authctxt = (Authctxt *) the_authctxt;
if (!sshd_selinux_enabled())
return;
- if (options.use_pam) {
+ if (use_pam) {
/* do not compute context, just setup environment for pam_selinux */
- if (sshd_selinux_setup_pam_variables()) {
+ if (sshd_selinux_setup_pam_variables(inetd, pam_setenv, authctxt)) {
switch (security_getenforce()) {
case -1:
fatal("%s: security_getenforce() failed", __func__);
@@ -410,7 +411,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 2019-04-04 13:19:12.204821389 +0200
+++ openssh/platform.c 2019-04-04 13:19:12.277822088 +0200
@@ -32,6 +32,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)
@@ -183,7 +186,9 @@ platform_setusercontext_post_groups(stru
}
#endif /* HAVE_SETPCRED */
#ifdef WITH_SELINUX
- sshd_selinux_setup_exec_context(pw->pw_name);
+ sshd_selinux_setup_exec_context(pw->pw_name,
+ (inetd_flag && !rexeced_flag), do_pam_putenv, the_authctxt,
+ options.use_pam);
#endif
}
diff -up openssh/sshd.c.refactor openssh/sshd.c
--- openssh/sshd.c.refactor 2019-04-04 13:19:12.275822068 +0200
+++ openssh/sshd.c 2019-04-04 13:19:51.270195262 +0200
@@ -158,7 +158,7 @@ int debug_flag = 0;
static int test_flag = 0;
/* Flag indicating that the daemon is being started from inetd. */
-static int inetd_flag = 0;
+int inetd_flag = 0;
/* Flag indicating that sshd should not detach and become a daemon. */
static int no_daemon_flag = 0;
@@ -171,7 +171,7 @@ static char **saved_argv;
static int saved_argc;
/* re-exec */
-static int rexeced_flag = 0;
+int rexeced_flag = 0;
static int rexec_flag = 1;
static int rexec_argc = 0;
static char **rexec_argv;
@@ -2192,7 +2192,9 @@ main(int ac, char **av)
}
#endif
#ifdef WITH_SELINUX
- sshd_selinux_setup_exec_context(authctxt->pw->pw_name);
+ sshd_selinux_setup_exec_context(authctxt->pw->pw_name,
+ (inetd_flag && !rexeced_flag), do_pam_putenv, the_authctxt,
+ options.use_pam);
#endif
#ifdef USE_PAM
if (options.use_pam) {

View File

@ -1,457 +0,0 @@
diff -up openssh-8.0p1/cipher-ctr.c.fips openssh-8.0p1/cipher-ctr.c
--- openssh-8.0p1/cipher-ctr.c.fips 2019-07-23 14:55:45.326525641 +0200
+++ openssh-8.0p1/cipher-ctr.c 2019-07-23 14:55:45.401526401 +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-8.0p1/dh.c.fips openssh-8.0p1/dh.c
--- openssh-8.0p1/dh.c.fips 2019-04-18 00:52:57.000000000 +0200
+++ openssh-8.0p1/dh.c 2019-07-23 14:55:45.401526401 +0200
@@ -152,6 +152,12 @@ choose_dh(int min, int wantbits, int max
int best, bestcount, which, linenum;
struct dhgroup dhg;
+ if (FIPS_mode()) {
+ logit("Using arbitrary primes is not allowed in FIPS mode."
+ " Falling back to known groups.");
+ return (dh_new_group_fallback(max));
+ }
+
if ((f = fopen(_PATH_DH_MODULI, "r")) == NULL) {
logit("WARNING: could not open %s (%s), using fixed modulus",
_PATH_DH_MODULI, strerror(errno));
@@ -489,4 +495,38 @@ dh_estimate(int bits)
return 8192;
}
+/*
+ * Compares the received DH parameters with known-good groups,
+ * which might be either from group14, group16 or group18.
+ */
+int
+dh_is_known_group(const DH *dh)
+{
+ const BIGNUM *p, *g;
+ const BIGNUM *known_p, *known_g;
+ DH *known = NULL;
+ int bits = 0, rv = 0;
+
+ DH_get0_pqg(dh, &p, NULL, &g);
+ bits = BN_num_bits(p);
+
+ if (bits <= 3072) {
+ known = dh_new_group14();
+ } else if (bits <= 6144) {
+ known = dh_new_group16();
+ } else {
+ known = dh_new_group18();
+ }
+
+ DH_get0_pqg(known, &known_p, NULL, &known_g);
+
+ if (BN_cmp(g, known_g) == 0 &&
+ BN_cmp(p, known_p) == 0) {
+ rv = 1;
+ }
+
+ DH_free(known);
+ return rv;
+}
+
#endif /* WITH_OPENSSL */
diff -up openssh-8.0p1/dh.h.fips openssh-8.0p1/dh.h
--- openssh-8.0p1/dh.h.fips 2019-04-18 00:52:57.000000000 +0200
+++ openssh-8.0p1/dh.h 2019-07-23 14:55:45.401526401 +0200
@@ -43,6 +43,7 @@ DH *dh_new_group_fallback(int);
int dh_gen_key(DH *, int);
int dh_pub_is_valid(const DH *, const BIGNUM *);
+int dh_is_known_group(const DH *);
u_int dh_estimate(int);
diff -up openssh-8.0p1/kex.c.fips openssh-8.0p1/kex.c
--- openssh-8.0p1/kex.c.fips 2019-07-23 14:55:45.395526340 +0200
+++ openssh-8.0p1/kex.c 2019-07-23 14:55:45.402526411 +0200
@@ -199,7 +199,10 @@ kex_names_valid(const char *names)
for ((p = strsep(&cp, ",")); p && *p != '\0';
(p = strsep(&cp, ","))) {
if (kex_alg_by_name(p) == NULL) {
- error("Unsupported KEX algorithm \"%.100s\"", p);
+ if (FIPS_mode())
+ error("\"%.100s\" is not allowed in FIPS mode", p);
+ else
+ error("Unsupported KEX algorithm \"%.100s\"", p);
free(s);
return 0;
}
diff -up openssh-8.0p1/kexgexc.c.fips openssh-8.0p1/kexgexc.c
--- openssh-8.0p1/kexgexc.c.fips 2019-04-18 00:52:57.000000000 +0200
+++ openssh-8.0p1/kexgexc.c 2019-07-23 14:55:45.402526411 +0200
@@ -28,6 +28,7 @@
#ifdef WITH_OPENSSL
+#include <openssl/crypto.h>
#include <sys/types.h>
#include <openssl/dh.h>
@@ -113,6 +114,10 @@ input_kex_dh_gex_group(int type, u_int32
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
+ if (FIPS_mode() && dh_is_known_group(kex->dh) == 0) {
+ r = SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
p = g = NULL; /* belong to kex->dh now */
/* generate and send 'e', client DH public key */
diff -up openssh-8.0p1/myproposal.h.fips openssh-8.0p1/myproposal.h
--- openssh-8.0p1/myproposal.h.fips 2019-04-18 00:52:57.000000000 +0200
+++ openssh-8.0p1/myproposal.h 2019-07-23 14:55:45.402526411 +0200
@@ -111,6 +111,20 @@
"rsa-sha2-256," \
"ssh-rsa"
+#define KEX_FIPS_PK_ALG \
+ "ecdsa-sha2-nistp256-cert-v01@openssh.com," \
+ "ecdsa-sha2-nistp384-cert-v01@openssh.com," \
+ "ecdsa-sha2-nistp521-cert-v01@openssh.com," \
+ "rsa-sha2-512-cert-v01@openssh.com," \
+ "rsa-sha2-256-cert-v01@openssh.com," \
+ "ssh-rsa-cert-v01@openssh.com," \
+ "ecdsa-sha2-nistp256," \
+ "ecdsa-sha2-nistp384," \
+ "ecdsa-sha2-nistp521," \
+ "rsa-sha2-512," \
+ "rsa-sha2-256," \
+ "ssh-rsa"
+
#define KEX_SERVER_ENCRYPT \
"chacha20-poly1305@openssh.com," \
"aes128-ctr,aes192-ctr,aes256-ctr," \
@@ -134,6 +142,27 @@
#define KEX_CLIENT_MAC KEX_SERVER_MAC
+#define KEX_FIPS_ENCRYPT \
+ "aes128-ctr,aes192-ctr,aes256-ctr," \
+ "aes128-cbc,3des-cbc," \
+ "aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se," \
+ "aes128-gcm@openssh.com,aes256-gcm@openssh.com"
+#define KEX_DEFAULT_KEX_FIPS \
+ "ecdh-sha2-nistp256," \
+ "ecdh-sha2-nistp384," \
+ "ecdh-sha2-nistp521," \
+ "diffie-hellman-group-exchange-sha256," \
+ "diffie-hellman-group16-sha512," \
+ "diffie-hellman-group18-sha512," \
+ "diffie-hellman-group14-sha256"
+#define KEX_FIPS_MAC \
+ "hmac-sha1," \
+ "hmac-sha2-256," \
+ "hmac-sha2-512," \
+ "hmac-sha1-etm@openssh.com," \
+ "hmac-sha2-256-etm@openssh.com," \
+ "hmac-sha2-512-etm@openssh.com"
+
/* Not a KEX value, but here so all the algorithm defaults are together */
#define SSH_ALLOWED_CA_SIGALGS \
"ecdsa-sha2-nistp256," \
diff -up openssh-8.0p1/readconf.c.fips openssh-8.0p1/readconf.c
--- openssh-8.0p1/readconf.c.fips 2019-07-23 14:55:45.334525723 +0200
+++ openssh-8.0p1/readconf.c 2019-07-23 14:55:45.402526411 +0200
@@ -2179,11 +2179,16 @@ fill_default_options(Options * options)
all_key = sshkey_alg_list(0, 0, 1, ',');
all_sig = sshkey_alg_list(0, 1, 1, ',');
/* remove unsupported algos from default lists */
- def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher);
- def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac);
- def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex);
- def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
- def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig);
+ def_cipher = match_filter_allowlist((FIPS_mode() ?
+ KEX_FIPS_ENCRYPT : KEX_CLIENT_ENCRYPT), all_cipher);
+ def_mac = match_filter_allowlist((FIPS_mode() ?
+ KEX_FIPS_MAC : KEX_CLIENT_MAC), all_mac);
+ def_kex = match_filter_allowlist((FIPS_mode() ?
+ KEX_DEFAULT_KEX_FIPS : KEX_CLIENT_KEX), all_kex);
+ def_key = match_filter_allowlist((FIPS_mode() ?
+ KEX_FIPS_PK_ALG : KEX_DEFAULT_PK_ALG), all_key);
+ def_sig = match_filter_allowlist((FIPS_mode() ?
+ KEX_FIPS_PK_ALG : SSH_ALLOWED_CA_SIGALGS), all_sig);
#define ASSEMBLE(what, defaults, all) \
do { \
if ((r = kex_assemble_names(&options->what, \
diff -up openssh-8.0p1/sandbox-seccomp-filter.c.fips openssh-8.0p1/sandbox-seccomp-filter.c
--- openssh-8.0p1/sandbox-seccomp-filter.c.fips 2019-07-23 14:55:45.373526117 +0200
+++ openssh-8.0p1/sandbox-seccomp-filter.c 2019-07-23 14:55:45.402526411 +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-8.0p1/servconf.c.fips openssh-8.0p1/servconf.c
--- openssh-8.0p1/servconf.c.fips 2019-07-23 14:55:45.361525996 +0200
+++ openssh-8.0p1/servconf.c 2019-07-23 14:55:45.403526421 +0200
@@ -208,11 +208,16 @@ assemble_algorithms(ServerOptions *o)
all_key = sshkey_alg_list(0, 0, 1, ',');
all_sig = sshkey_alg_list(0, 1, 1, ',');
/* remove unsupported algos from default lists */
- def_cipher = match_filter_allowlist(KEX_SERVER_ENCRYPT, all_cipher);
- def_mac = match_filter_allowlist(KEX_SERVER_MAC, all_mac);
- def_kex = match_filter_allowlist(KEX_SERVER_KEX, all_kex);
- def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
- def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig);
+ def_cipher = match_filter_allowlist((FIPS_mode() ?
+ KEX_FIPS_ENCRYPT : KEX_SERVER_ENCRYPT), all_cipher);
+ def_mac = match_filter_allowlist((FIPS_mode() ?
+ KEX_FIPS_MAC : KEX_SERVER_MAC), all_mac);
+ def_kex = match_filter_allowlist((FIPS_mode() ?
+ KEX_DEFAULT_KEX_FIPS : KEX_SERVER_KEX), all_kex);
+ def_key = match_filter_allowlist((FIPS_mode() ?
+ KEX_FIPS_PK_ALG : KEX_DEFAULT_PK_ALG), all_key);
+ def_sig = match_filter_allowlist((FIPS_mode() ?
+ KEX_FIPS_PK_ALG : SSH_ALLOWED_CA_SIGALGS), all_sig);
#define ASSEMBLE(what, defaults, all) \
do { \
if ((r = kex_assemble_names(&o->what, defaults, all)) != 0) \
diff -up openssh-8.0p1/ssh.c.fips openssh-8.0p1/ssh.c
--- openssh-8.0p1/ssh.c.fips 2019-07-23 14:55:45.378526168 +0200
+++ openssh-8.0p1/ssh.c 2019-07-23 14:55:45.403526421 +0200
@@ -76,6 +76,7 @@
#include <openssl/evp.h>
#include <openssl/err.h>
#endif
+#include <openssl/crypto.h>
#include "openbsd-compat/openssl-compat.h"
#include "openbsd-compat/sys-queue.h"
@@ -614,6 +626,10 @@ main(int ac, char **av)
dump_client_config(&options, host);
exit(0);
}
+
+ if (FIPS_mode()) {
+ debug("FIPS mode initialized");
+ }
/* Expand SecurityKeyProvider if it refers to an environment variable */
if (options.sk_provider != NULL && *options.sk_provider == '$' &&
diff -up openssh-8.0p1/sshconnect2.c.fips openssh-8.0p1/sshconnect2.c
--- openssh-8.0p1/sshconnect2.c.fips 2019-07-23 14:55:45.336525743 +0200
+++ openssh-8.0p1/sshconnect2.c 2019-07-23 14:55:45.403526421 +0200
@@ -44,6 +44,8 @@
#include <vis.h>
#endif
+#include <openssl/crypto.h>
+
#include "openbsd-compat/sys-queue.h"
#include "xmalloc.h"
@@ -198,36 +203,41 @@ ssh_kex2(struct ssh *ssh, char *host, st
#if defined(GSSAPI) && defined(WITH_OPENSSL)
if (options.gss_keyex) {
- /* Add the GSSAPI mechanisms currently supported on this
- * client to the key exchange algorithm proposal */
- orig = myproposal[PROPOSAL_KEX_ALGS];
-
- if (options.gss_server_identity) {
- gss_host = xstrdup(options.gss_server_identity);
- } else if (options.gss_trust_dns) {
- gss_host = remote_hostname(ssh);
- /* Fall back to specified host if we are using proxy command
- * and can not use DNS on that socket */
- if (strcmp(gss_host, "UNKNOWN") == 0) {
- free(gss_host);
- gss_host = xstrdup(host);
- }
- } else {
- gss_host = xstrdup(host);
- }
-
- gss = ssh_gssapi_client_mechanisms(gss_host,
- options.gss_client_identity, options.gss_kex_algorithms);
- if (gss) {
- debug("Offering GSSAPI proposal: %s", gss);
- xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
- "%s,%s", gss, orig);
-
- /* If we've got GSSAPI algorithms, then we also support the
- * 'null' hostkey, as a last resort */
- orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
- xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
- "%s,null", orig);
+ if (FIPS_mode()) {
+ logit("Disabling GSSAPIKeyExchange. Not usable in FIPS mode");
+ options.gss_keyex = 0;
+ } else {
+ /* Add the GSSAPI mechanisms currently supported on this
+ * client to the key exchange algorithm proposal */
+ orig = myproposal[PROPOSAL_KEX_ALGS];
+
+ if (options.gss_server_identity) {
+ gss_host = xstrdup(options.gss_server_identity);
+ } else if (options.gss_trust_dns) {
+ gss_host = remote_hostname(ssh);
+ /* Fall back to specified host if we are using proxy command
+ * and can not use DNS on that socket */
+ if (strcmp(gss_host, "UNKNOWN") == 0) {
+ free(gss_host);
+ gss_host = xstrdup(host);
+ }
+ } else {
+ gss_host = xstrdup(host);
+ }
+
+ gss = ssh_gssapi_client_mechanisms(gss_host,
+ options.gss_client_identity, options.gss_kex_algorithms);
+ if (gss) {
+ debug("Offering GSSAPI proposal: %s", gss);
+ xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
+ "%s,%s", gss, orig);
+
+ /* If we've got GSSAPI algorithms, then we also support the
+ * 'null' hostkey, as a last resort */
+ orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
+ xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
+ "%s,null", orig);
+ }
}
}
#endif
diff -up openssh-8.0p1/sshd.c.fips openssh-8.0p1/sshd.c
--- openssh-8.0p1/sshd.c.fips 2019-07-23 14:55:45.398526371 +0200
+++ openssh-8.0p1/sshd.c 2019-07-23 14:55:45.403526421 +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,7 @@
#include <openssl/dh.h>
#include <openssl/bn.h>
#include <openssl/rand.h>
+#include <openssl/crypto.h>
#include "openbsd-compat/openssl-compat.h"
#endif
@@ -1529,6 +1532,7 @@ main(int ac, char **av)
#endif
__progname = ssh_get_progname(av[0]);
+ OpenSSL_add_all_algorithms();
/* Save argv. Duplicate so setproctitle emulation doesn't clobber it */
saved_argc = ac;
rexec_argc = ac;
@@ -1992,6 +2007,10 @@ main(int ac, char **av)
/* Reinitialize the log (because of the fork above). */
log_init(__progname, options.log_level, options.log_facility, log_stderr);
+ if (FIPS_mode()) {
+ debug("FIPS mode initialized");
+ }
+
/* Chdir to the root directory so that the current disk can be
unmounted if desired. */
if (chdir("/") == -1)
@@ -2382,10 +2401,14 @@ do_ssh2_kex(struct ssh *ssh)
if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0)
orig = NULL;
- if (options.gss_keyex)
- gss = ssh_gssapi_server_mechanisms();
- else
- gss = NULL;
+ if (options.gss_keyex) {
+ if (FIPS_mode()) {
+ logit("Disabling GSSAPIKeyExchange. Not usable in FIPS mode");
+ options.gss_keyex = 0;
+ } else {
+ gss = ssh_gssapi_server_mechanisms();
+ }
+ }
if (gss && orig)
xasprintf(&newstr, "%s,%s", gss, orig);
diff -up openssh-8.0p1/sshkey.c.fips openssh-8.0p1/sshkey.c
--- openssh-8.0p1/sshkey.c.fips 2019-07-23 14:55:45.398526371 +0200
+++ openssh-8.0p1/sshkey.c 2019-07-23 14:55:45.404526431 +0200
@@ -34,6 +34,7 @@
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/pem.h>
+#include <openssl/crypto.h>
#endif
#include "crypto_api.h"
@@ -57,6 +58,7 @@
#define SSHKEY_INTERNAL
#include "sshkey.h"
#include "match.h"
+#include "log.h"
#include "ssh-sk.h"
#ifdef WITH_XMSS
@@ -1591,6 +1593,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-8.0p1/ssh-keygen.c.fips openssh-8.0p1/ssh-keygen.c
--- openssh-8.0p1/ssh-keygen.c.fips 2019-07-23 14:55:45.391526300 +0200
+++ openssh-8.0p1/ssh-keygen.c 2019-07-23 14:57:54.118830056 +0200
@@ -199,6 +199,12 @@ type_bits_valid(int type, const char *na
#endif
}
#ifdef WITH_OPENSSL
+ if (FIPS_mode()) {
+ if (type == KEY_DSA)
+ fatal("DSA keys are not allowed in FIPS mode");
+ if (type == KEY_ED25519)
+ fatal("ED25519 keys are not allowed in FIPS mode");
+ }
switch (type) {
case KEY_DSA:
if (*bitsp != 1024)
@@ -1029,9 +1035,17 @@ do_gen_all_hostkeys(struct passwd *pw)
first = 1;
printf("%s: generating new host keys: ", __progname);
}
+ type = sshkey_type_from_name(key_types[i].key_type);
+
+ /* Skip the keys that are not supported in FIPS mode */
+ if (FIPS_mode() && (type == KEY_DSA || type == KEY_ED25519)) {
+ logit("Skipping %s key in FIPS mode",
+ key_types[i].key_type_display);
+ goto next;
+ }
+
printf("%s ", key_types[i].key_type_display);
fflush(stdout);
- type = sshkey_type_from_name(key_types[i].key_type);
if ((fd = mkstemp(prv_tmp)) == -1) {
error("Could not save your private key in %s: %s",
prv_tmp, strerror(errno));

View File

@ -1,647 +0,0 @@
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 +281,188 @@ krb5_cleanup_proc(Authctxt *authctxt)
}
}
-#ifndef HEIMDAL
+
+#if !defined(HEIMDAL)
+int
+ssh_asprintf_append(char **dsc, const char *fmt, ...) {
+ char *src, *old;
+ va_list ap;
+ int i;
+
+ va_start(ap, fmt);
+ i = vasprintf(&src, fmt, ap);
+ va_end(ap);
+
+ if (i == -1 || src == NULL)
+ return -1;
+
+ old = *dsc;
+
+ i = asprintf(dsc, "%s%s", *dsc, src);
+ if (i == -1 || src == NULL) {
+ free(src);
+ return -1;
+ }
+
+ free(old);
+ free(src);
+
+ return i;
+}
+
+int
+ssh_krb5_expand_template(char **result, const char *template) {
+ char *p_n, *p_o, *r, *tmp_template;
+
+ debug3("%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 (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_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
- int tmpfd, ret, oerrno;
- char ccname[40];
+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;
- ret = snprintf(ccname, sizeof(ccname),
- "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
- if (ret < 0 || (size_t)ret >= sizeof(ccname))
- return ENOMEM;
-
- old_umask = umask(0177);
- tmpfd = mkstemp(ccname + strlen("FILE:"));
- oerrno = errno;
- umask(old_umask);
- if (tmpfd == -1) {
- logit("mkstemp(): %.100s", strerror(oerrno));
- return oerrno;
- }
+ debug3("%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;
- if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) {
+ old_umask = umask(0177);
+ tmpfd = mkstemp(ccname + strlen("FILE:"));
oerrno = errno;
- logit("fchmod(): %.100s", strerror(oerrno));
+ umask(old_umask);
+ if (tmpfd == -1) {
+ logit("mkstemp(): %.100s", strerror(oerrno));
+ return oerrno;
+ }
+
+ if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) {
+ oerrno = errno;
+ logit("fchmod(): %.100s", strerror(oerrno));
+ close(tmpfd);
+ return oerrno;
+ }
+ /* make sure the KRB5CCNAME is set for non-standard location */
+ if (need_environment)
+ *need_environment = 1;
close(tmpfd);
- return oerrno;
}
- close(tmpfd);
- return (krb5_cc_resolve(ctx, ccname, ccache));
+ debug3("%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);
+ free(type);
+ 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
+ */
+ free(type);
+ 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;
@@ -238,7 +239,7 @@ int sys_auth_passwd(struct ssh *, const char *);
int sys_auth_passwd(struct ssh *, const char *);
#if defined(KRB5) && !defined(HEIMDAL)
-krb5_error_code ssh_krb5_cc_gen(krb5_context, krb5_ccache *);
+krb5_error_code ssh_krb5_cc_new_unique(krb5_context, krb5_ccache *, int *);
#endif
#endif /* AUTH_H */
diff -up openssh-7.9p1/gss-serv-krb5.c.ccache_name openssh-7.9p1/gss-serv-krb5.c
--- openssh-7.9p1/gss-serv-krb5.c.ccache_name 2019-03-01 15:17:42.708611802 +0100
+++ openssh-7.9p1/gss-serv-krb5.c 2019-03-01 15:17:42.713611844 +0100
@@ -267,7 +267,7 @@ ssh_gssapi_krb5_cmdok(krb5_principal pri
/* This writes out any forwarded credentials from the structure populated
* during userauth. Called after we have setuid to the user */
-static void
+static int
ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
{
krb5_ccache ccache;
@@ -276,14 +276,15 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
OM_uint32 maj_status, min_status;
const char *new_ccname, *new_cctype;
const char *errmsg;
+ int set_env = 0;
if (client->creds == NULL) {
debug("No credentials stored");
- return;
+ return 0;
}
if (ssh_gssapi_krb5_init() == 0)
- return;
+ return 0;
#ifdef HEIMDAL
# ifdef HAVE_KRB5_CC_NEW_UNIQUE
@@ -297,14 +298,14 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
krb5_get_err_text(krb_context, problem));
# endif
krb5_free_error_message(krb_context, errmsg);
- return;
+ return 0;
}
#else
- if ((problem = ssh_krb5_cc_gen(krb_context, &ccache))) {
+ if ((problem = ssh_krb5_cc_new_unique(krb_context, &ccache, &set_env)) != 0) {
errmsg = krb5_get_error_message(krb_context, problem);
- logit("ssh_krb5_cc_gen(): %.100s", errmsg);
+ logit("ssh_krb5_cc_new_unique(): %.100s", errmsg);
krb5_free_error_message(krb_context, errmsg);
- return;
+ return 0;
}
#endif /* #ifdef HEIMDAL */
@@ -313,7 +314,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
errmsg = krb5_get_error_message(krb_context, problem);
logit("krb5_parse_name(): %.100s", errmsg);
krb5_free_error_message(krb_context, errmsg);
- return;
+ return 0;
}
if ((problem = krb5_cc_initialize(krb_context, ccache, princ))) {
@@ -322,7 +323,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
krb5_free_error_message(krb_context, errmsg);
krb5_free_principal(krb_context, princ);
krb5_cc_destroy(krb_context, ccache);
- return;
+ return 0;
}
krb5_free_principal(krb_context, princ);
@@ -331,32 +332,21 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
client->creds, ccache))) {
logit("gss_krb5_copy_ccache() failed");
krb5_cc_destroy(krb_context, ccache);
- return;
+ return 0;
}
new_cctype = krb5_cc_get_type(krb_context, ccache);
new_ccname = krb5_cc_get_name(krb_context, ccache);
-
- client->store.envvar = "KRB5CCNAME";
-#ifdef USE_CCAPI
- xasprintf(&client->store.envval, "API:%s", new_ccname);
- client->store.filename = NULL;
-#else
- if (new_ccname[0] == ':')
- new_ccname++;
xasprintf(&client->store.envval, "%s:%s", new_cctype, new_ccname);
- if (strcmp(new_cctype, "DIR") == 0) {
- char *p;
- p = strrchr(client->store.envval, '/');
- if (p)
- *p = '\0';
+
+ if (set_env) {
+ client->store.envvar = "KRB5CCNAME";
}
if ((strcmp(new_cctype, "FILE") == 0) || (strcmp(new_cctype, "DIR") == 0))
client->store.filename = xstrdup(new_ccname);
-#endif
#ifdef USE_PAM
- if (options.use_pam)
+ if (options.use_pam && set_env)
do_pam_putenv(client->store.envvar, client->store.envval);
#endif
@@ -361,7 +355,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl
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 child's environment based
@@ -498,9 +500,7 @@ ssh_gssapi_rekey_creds() {
char *envstr;
#endif
- if (gssapi_client.store.filename == NULL &&
- gssapi_client.store.envval == NULL &&
- gssapi_client.store.envvar == NULL)
+ if (gssapi_client.store.envval == NULL)
return;
ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store));
diff -up openssh-7.9p1/servconf.c.ccache_name openssh-7.9p1/servconf.c
--- openssh-7.9p1/servconf.c.ccache_name 2019-03-01 15:17:42.704611768 +0100
+++ openssh-7.9p1/servconf.c 2019-03-01 15:17:42.713611844 +0100
@@ -123,6 +123,7 @@ initialize_server_options(ServerOptions
options->kerberos_or_local_passwd = -1;
options->kerberos_ticket_cleanup = -1;
options->kerberos_get_afs_token = -1;
+ options->kerberos_unique_ccache = -1;
options->gss_authentication=-1;
options->gss_keyex = -1;
options->gss_cleanup_creds = -1;
@@ -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 child's environment as they see fit
*/
- ssh_gssapi_do_child(&env, &envsize);
+ if (s->authctxt->krb5_set_env)
+ ssh_gssapi_do_child(&env, &envsize);
#endif
/* Set basic environment. */
@@ -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
@@ -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.

View File

@ -1,117 +0,0 @@
diff -up openssh/ssh_config.redhat openssh/ssh_config
--- openssh/ssh_config.redhat 2020-02-11 23:28:35.000000000 +0100
+++ openssh/ssh_config 2020-02-13 18:13:39.180641839 +0100
@@ -43,3 +43,10 @@
# ProxyCommand ssh -q -W %h:%p gateway.example.com
# RekeyLimit 1G 1h
# UserKnownHostsFile ~/.ssh/known_hosts.d/%k
+#
+# This system is following system-wide crypto policy.
+# To modify the crypto properties (Ciphers, MACs, ...), create a *.conf
+# file under /etc/ssh/ssh_config.d/ which will be automatically
+# included below. For more information, see manual page for
+# update-crypto-policies(8) and ssh_config(5).
+Include /etc/ssh/ssh_config.d/*.conf
diff -up openssh/ssh_config_redhat.redhat openssh/ssh_config_redhat
--- openssh/ssh_config_redhat.redhat 2020-02-13 18:13:39.180641839 +0100
+++ openssh/ssh_config_redhat 2020-02-13 18:13:39.180641839 +0100
@@ -0,0 +1,21 @@
+# The options here are in the "Match final block" to be applied as the last
+# options and could be potentially overwritten by the user configuration
+Match final all
+ # Follow system-wide Crypto Policy, if defined:
+ Include /etc/crypto-policies/back-ends/openssh.config
+
+ GSSAPIAuthentication yes
+
+# If this option is set to yes then remote X11 clients will have full access
+# to the original X11 display. As virtually no X11 client supports the untrusted
+# mode correctly we set this to yes.
+ ForwardX11Trusted yes
+
+# 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
+
+# Uncomment this if you want to use .local domain
+# Host *.local
diff -up openssh/sshd_config.0.redhat openssh/sshd_config.0
--- openssh/sshd_config.0.redhat 2020-02-12 14:30:04.000000000 +0100
+++ openssh/sshd_config.0 2020-02-13 18:13:39.181641855 +0100
@@ -970,9 +970,9 @@ DESCRIPTION
SyslogFacility
Gives the facility code that is used when logging messages from
- sshd(8). The possible values are: DAEMON, USER, AUTH, LOCAL0,
- LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The
- default is AUTH.
+ sshd(8). The possible values are: DAEMON, USER, AUTH, AUTHPRIV,
+ LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
+ The default is AUTH.
TCPKeepAlive
Specifies whether the system should send TCP keepalive messages
diff -up openssh/sshd_config.5.redhat openssh/sshd_config.5
--- openssh/sshd_config.5.redhat 2020-02-11 23:28:35.000000000 +0100
+++ openssh/sshd_config.5 2020-02-13 18:13:39.181641855 +0100
@@ -1614,7 +1614,7 @@ By default no subsystems are defined.
.It Cm SyslogFacility
Gives the facility code that is used when logging messages from
.Xr sshd 8 .
-The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2,
+The possible values are: DAEMON, USER, AUTH, AUTHPRIV, LOCAL0, LOCAL1, LOCAL2,
LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
The default is AUTH.
.It Cm TCPKeepAlive
diff -up openssh/sshd_config.redhat openssh/sshd_config
--- openssh/sshd_config.redhat 2020-02-11 23:28:35.000000000 +0100
+++ openssh/sshd_config 2020-02-13 18:20:16.349913681 +0100
@@ -10,6 +10,14 @@
# possible, but leave them commented. Uncommented options override the
# default value.
+# To modify the system-wide sshd configuration, create a *.conf file under
+# /etc/ssh/sshd_config.d/ which will be automatically included below
+Include /etc/ssh/sshd_config.d/*.conf
+
+# If you want to change the port on a SELinux system, you have to tell
+# SELinux about this change.
+# semanage port -a -t ssh_port_t -p tcp #PORTNUMBER
+#
#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
diff -up openssh/sshd_config_redhat.redhat openssh/sshd_config_redhat
--- openssh/sshd_config_redhat.redhat 2020-02-13 18:14:02.268006439 +0100
+++ openssh/sshd_config_redhat 2020-02-13 18:19:20.765035947 +0100
@@ -0,0 +1,28 @@
+# This system is following system-wide crypto policy. The changes to
+# crypto properties (Ciphers, MACs, ...) will not have any effect in
+# this or following included files. To override some configuration option,
+# write it before this block or include it before this file.
+# Please, see manual pages for update-crypto-policies(8) and sshd_config(5).
+Include /etc/crypto-policies/back-ends/opensshserver.config
+
+SyslogFacility AUTHPRIV
+
+ChallengeResponseAuthentication no
+
+GSSAPIAuthentication yes
+GSSAPICleanupCredentials no
+
+UsePAM yes
+
+X11Forwarding yes
+
+# It is recommended to use pam_motd in /etc/pam.d/sshd instead of PrintMotd,
+# as it is more configurable and versatile than the built-in version.
+PrintMotd no
+
+# 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
+

View File

@ -1,871 +0,0 @@
diff -up openssh/auth2.c.role-mls openssh/auth2.c
--- openssh/auth2.c.role-mls 2018-08-20 07:57:29.000000000 +0200
+++ openssh/auth2.c 2018-08-22 11:14:56.815430916 +0200
@@ -256,6 +256,9 @@ input_userauth_request(int type, u_int32
Authctxt *authctxt = ssh->authctxt;
Authmethod *m = NULL;
char *user = NULL, *service = NULL, *method = NULL, *style = NULL;
+#ifdef WITH_SELINUX
+ char *role = NULL;
+#endif
int r, authenticated = 0;
double tstart = monotime_double();
@@ -268,6 +271,11 @@ input_userauth_request(int type, u_int32
debug("userauth-request for user %s service %s method %s", user, service, method);
debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
+#ifdef WITH_SELINUX
+ if ((role = strchr(user, '/')) != NULL)
+ *role++ = 0;
+#endif
+
if ((style = strchr(user, ':')) != NULL)
*style++ = 0;
@@ -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(ssh);
if (auth2_setup_methods_lists(authctxt) != 0)
ssh_packet_disconnect(ssh,
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 && authctxt->role[0] != 0)
+ xasprintf(&micuser, "%s/%s", authctxt->user, authctxt->role);
+ else
+#endif
+ micuser = authctxt->user;
+ ssh_gssapi_buildmic(b, micuser, authctxt->service,
"gssapi-with-mic");
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;
char *compound;
diff -up openssh/auth-pam.h.role-mls openssh/auth-pam.h
--- openssh/auth-pam.h.role-mls 2018-08-20 07:57:29.000000000 +0200
+++ openssh/auth-pam.h 2018-08-22 11:14:56.817430932 +0200
@@ -33,7 +33,7 @@ u_int do_pam_account(void);
void do_pam_session(struct ssh *);
void do_pam_setcred(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/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(struct ssh *, int, struct sshbuf *);
int mm_answer_auth2_read_banner(struct ssh *, int, struct sshbuf *);
int mm_answer_authserv(struct ssh *, int, struct sshbuf *);
+#ifdef WITH_SELINUX
+int mm_answer_authrole(struct ssh *, int, struct sshbuf *);
+#endif
int mm_answer_authpassword(struct ssh *, int, struct sshbuf *);
int mm_answer_bsdauthquery(struct ssh *, int, struct sshbuf *);
int mm_answer_bsdauthrespond(struct ssh *, int, struct sshbuf *);
@@ -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 found;
}
+#ifdef WITH_SELINUX
+int
+mm_answer_authrole(struct ssh *ssh, int sock, struct sshbuf *m)
+{
+ int r;
+ monitor_permit_authentications(1);
+
+ if ((r = sshbuf_get_cstring(m, &authctxt->role, NULL)) != 0)
+ fatal("%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(struct ssh *ssh, 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);
const u_char *, size_t, const char *, const char *,
const char *, u_int compat);
void mm_inform_authserv(char *, char *);
+#ifdef WITH_SELINUX
+void mm_inform_authrole(char *);
+#endif
struct passwd *mm_getpwnamallow(struct ssh *, const char *);
char *mm_auth2_read_banner(void);
int mm_auth_password(struct ssh *, char *);
diff -up openssh/openbsd-compat/Makefile.in.role-mls openssh/openbsd-compat/Makefile.in
--- openssh/openbsd-compat/Makefile.in.role-mls 2018-08-20 07:57:29.000000000 +0200
+++ openssh/openbsd-compat/Makefile.in 2018-08-22 11:14:56.819430949 +0200
@@ -92,7 +92,8 @@ PORTS= port-aix.o \
port-linux.o \
port-solaris.o \
port-net.o \
- port-uw.o
+ port-uw.o \
+ port-linux-sshd.o
.c.o:
$(CC) $(CFLAGS_NOPIE) $(PICFLAG) $(CPPFLAGS) -c $<
diff -up openssh/openbsd-compat/port-linux.c.role-mls openssh/openbsd-compat/port-linux.c
--- openssh/openbsd-compat/port-linux.c.role-mls 2018-08-20 07:57:29.000000000 +0200
+++ openssh/openbsd-compat/port-linux.c 2018-08-22 11:14:56.819430949 +0200
@@ -100,37 +100,6 @@ ssh_selinux_getctxbyname(char *pwname)
return sc;
}
-/* Set the execution context to the default for the specified user */
-void
-ssh_selinux_setup_exec_context(char *pwname)
-{
- 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);

View File

@ -1,16 +0,0 @@
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)

View File

@ -1,27 +0,0 @@
From 22bfdcf060b632b5a6ff603f8f42ff166c211a66 Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Tue, 29 Sep 2020 10:02:45 +0000
Subject: [PATCH] Fail hard on the first failed attempt to write the
authorized_keys_file
---
ssh-copy-id | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/contrib/ssh-copy-id b/contrib/ssh-copy-id
index 392f64f..e69a23f 100755
--- a/contrib/ssh-copy-id
+++ b/contrib/ssh-copy-id
@@ -251,7 +251,7 @@ installkeys_sh() {
cd;
umask 077;
mkdir -p $(dirname "${AUTH_KEY_FILE}") &&
- { [ -z \`tail -1c ${AUTH_KEY_FILE} 2>/dev/null\` ] || echo >> ${AUTH_KEY_FILE}; } &&
+ { [ -z \`tail -1c ${AUTH_KEY_FILE} 2>/dev/null\` ] || echo >> ${AUTH_KEY_FILE} || exit 1; } &&
cat >> ${AUTH_KEY_FILE} ||
exit 1;
if type restorecon >/dev/null 2>&1; then
--
GitLab

View File

@ -1,502 +0,0 @@
diff -up openssh-8.2p1/ssh_config.5.crypto-policies openssh-8.2p1/ssh_config.5
--- openssh-8.2p1/ssh_config.5.crypto-policies 2020-03-26 14:40:44.546775605 +0100
+++ openssh-8.2p1/ssh_config.5 2020-03-26 14:52:20.700649727 +0100
@@ -359,17 +359,17 @@ or
.Qq *.c.example.com
domains.
.It Cm CASignatureAlgorithms
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+To see the defaults and how to modify this default, see manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies which algorithms are allowed for signing of certificates
by certificate authorities (CAs).
-The default is:
-.Bd -literal -offset indent
-ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
-ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
-.Ed
-.Pp
.Xr ssh 1
will not accept host certificates signed using algorithms other than those
specified.
+.Pp
.It Cm CertificateFile
Specifies a file from which the user's certificate is read.
A corresponding private key must be provided separately in order
@@ -424,20 +424,25 @@ If the option is set to
.Cm no ,
the check will not be executed.
.It Cm Ciphers
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+To see the defaults and how to modify this default, see manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies the ciphers allowed and their order of preference.
Multiple ciphers must be comma-separated.
If the specified list begins with a
.Sq +
-character, then the specified ciphers will be appended to the default set
-instead of replacing them.
+character, then the specified ciphers will be appended to the built-in
+openssh default set instead of replacing them.
If the specified list begins with a
.Sq -
character, then the specified ciphers (including wildcards) will be removed
-from the default set instead of replacing them.
+from the built-in openssh default set instead of replacing them.
If the specified list begins with a
.Sq ^
character, then the specified ciphers will be placed at the head of the
-default set.
+built-in openssh default set.
.Pp
The supported ciphers are:
.Bd -literal -offset indent
@@ -453,13 +458,6 @@ aes256-gcm@openssh.com
chacha20-poly1305@openssh.com
.Ed
.Pp
-The default is:
-.Bd -literal -offset indent
-chacha20-poly1305@openssh.com,
-aes128-ctr,aes192-ctr,aes256-ctr,
-aes128-gcm@openssh.com,aes256-gcm@openssh.com
-.Ed
-.Pp
The list of available ciphers may also be obtained using
.Qq ssh -Q cipher .
.It Cm ClearAllForwardings
@@ -812,6 +810,11 @@ command line will be passed untouched to
The default is
.Dq no .
.It Cm GSSAPIKexAlgorithms
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+To see the defaults and how to modify this default, see manual page
+.Xr update-crypto-policies 8 .
+.Pp
The list of key exchange algorithms that are offered for GSSAPI
key exchange. Possible values are
.Bd -literal -offset 3n
@@ -824,10 +827,8 @@ gss-nistp256-sha256-,
gss-curve25519-sha256-
.Ed
.Pp
-The default is
-.Dq gss-group14-sha256-,gss-group16-sha512-,gss-nistp256-sha256-,
-gss-curve25519-sha256-,gss-group14-sha1-,gss-gex-sha1- .
This option only applies to connections using GSSAPI.
+.Pp
.It Cm HashKnownHosts
Indicates that
.Xr ssh 1
@@ -1149,29 +1150,25 @@ it may be zero or more of:
and
.Cm pam .
.It Cm KexAlgorithms
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+To see the defaults and how to modify this default, see manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies the available KEX (Key Exchange) algorithms.
Multiple algorithms must be comma-separated.
If the specified list begins with a
.Sq +
-character, then the specified methods will be appended to the default set
-instead of replacing them.
+character, then the specified methods will be appended to the built-in
+openssh default set instead of replacing them.
If the specified list begins with a
.Sq -
character, then the specified methods (including wildcards) will be removed
-from the default set instead of replacing them.
+from the built-in openssh default set instead of replacing them.
If the specified list begins with a
.Sq ^
character, then the specified methods will be placed at the head of the
-default set.
-The default is:
-.Bd -literal -offset indent
-curve25519-sha256,curve25519-sha256@libssh.org,
-ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,
-diffie-hellman-group-exchange-sha256,
-diffie-hellman-group16-sha512,
-diffie-hellman-group18-sha512,
-diffie-hellman-group14-sha256
-.Ed
+built-in openssh default set.
.Pp
The list of available key exchange algorithms may also be obtained using
.Qq ssh -Q kex .
@@ -1231,37 +1228,33 @@ The default is INFO.
DEBUG and DEBUG1 are equivalent.
DEBUG2 and DEBUG3 each specify higher levels of verbose output.
.It Cm MACs
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+To see the defaults and how to modify this default, see manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies the MAC (message authentication code) algorithms
in order of preference.
The MAC algorithm is used for data integrity protection.
Multiple algorithms must be comma-separated.
If the specified list begins with a
.Sq +
-character, then the specified algorithms will be appended to the default set
-instead of replacing them.
+character, then the specified algorithms will be appended to the built-in
+openssh default set instead of replacing them.
If the specified list begins with a
.Sq -
character, then the specified algorithms (including wildcards) will be removed
-from the default set instead of replacing them.
+from the built-in openssh default set instead of replacing them.
If the specified list begins with a
.Sq ^
character, then the specified algorithms will be placed at the head of the
-default set.
+built-in openssh default set.
.Pp
The algorithms that contain
.Qq -etm
calculate the MAC after encryption (encrypt-then-mac).
These are considered safer and their use recommended.
.Pp
-The default is:
-.Bd -literal -offset indent
-umac-64-etm@openssh.com,umac-128-etm@openssh.com,
-hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,
-hmac-sha1-etm@openssh.com,
-umac-64@openssh.com,umac-128@openssh.com,
-hmac-sha2-256,hmac-sha2-512,hmac-sha1
-.Ed
-.Pp
The list of available MAC algorithms may also be obtained using
.Qq ssh -Q mac .
.It Cm NoHostAuthenticationForLocalhost
@@ -1394,36 +1387,25 @@ instead of continuing to execute and pas
The default is
.Cm no .
.It Cm PubkeyAcceptedKeyTypes
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+To see the defaults and how to modify this default, see manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies the key types that will be used for public key authentication
as a comma-separated list of patterns.
If the specified list begins with a
.Sq +
-character, then the key types after it will be appended to the default
-instead of replacing it.
+character, then the key types after it will be appended to the built-in
+openssh default instead of replacing it.
If the specified list begins with a
.Sq -
character, then the specified key types (including wildcards) will be removed
-from the default set instead of replacing them.
+from the built-in openssh default set instead of replacing them.
If the specified list begins with a
.Sq ^
character, then the specified key types will be placed at the head of the
-default set.
-The default for this option is:
-.Bd -literal -offset 3n
-ecdsa-sha2-nistp256-cert-v01@openssh.com,
-ecdsa-sha2-nistp384-cert-v01@openssh.com,
-ecdsa-sha2-nistp521-cert-v01@openssh.com,
-sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
-ssh-ed25519-cert-v01@openssh.com,
-sk-ssh-ed25519-cert-v01@openssh.com,
-rsa-sha2-512-cert-v01@openssh.com,
-rsa-sha2-256-cert-v01@openssh.com,
-ssh-rsa-cert-v01@openssh.com,
-ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
-sk-ecdsa-sha2-nistp256@openssh.com,
-ssh-ed25519,sk-ssh-ed25519@openssh.com,
-rsa-sha2-512,rsa-sha2-256,ssh-rsa
-.Ed
+built-in openssh default set.
.Pp
The list of available key types may also be obtained using
.Qq ssh -Q PubkeyAcceptedKeyTypes .
diff -up openssh-8.2p1/sshd_config.5.crypto-policies openssh-8.2p1/sshd_config.5
--- openssh-8.2p1/sshd_config.5.crypto-policies 2020-03-26 14:40:44.530775355 +0100
+++ openssh-8.2p1/sshd_config.5 2020-03-26 14:48:56.732468099 +0100
@@ -375,16 +375,16 @@ If the argument is
then no banner is displayed.
By default, no banner is displayed.
.It Cm CASignatureAlgorithms
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+To see the defaults and how to modify this default, see manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies which algorithms are allowed for signing of certificates
by certificate authorities (CAs).
-The default is:
-.Bd -literal -offset indent
-ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
-ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
-.Ed
-.Pp
Certificates signed using other algorithms will not be accepted for
public key or host-based authentication.
+.Pp
.It Cm ChallengeResponseAuthentication
Specifies whether challenge-response authentication is allowed (e.g. via
PAM or through authentication styles supported in
@@ -446,20 +446,25 @@ The default is
indicating not to
.Xr chroot 2 .
.It Cm Ciphers
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+To see the defaults and how to modify this default, see manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies the ciphers allowed.
Multiple ciphers must be comma-separated.
If the specified list begins with a
.Sq +
-character, then the specified ciphers will be appended to the default set
-instead of replacing them.
+character, then the specified ciphers will be appended to the built-in
+openssh default set instead of replacing them.
If the specified list begins with a
.Sq -
character, then the specified ciphers (including wildcards) will be removed
-from the default set instead of replacing them.
+from the built-in openssh default set instead of replacing them.
If the specified list begins with a
.Sq ^
character, then the specified ciphers will be placed at the head of the
-default set.
+built-in openssh default set.
.Pp
The supported ciphers are:
.Pp
@@ -486,13 +491,6 @@ aes256-gcm@openssh.com
chacha20-poly1305@openssh.com
.El
.Pp
-The default is:
-.Bd -literal -offset indent
-chacha20-poly1305@openssh.com,
-aes128-ctr,aes192-ctr,aes256-ctr,
-aes128-gcm@openssh.com,aes256-gcm@openssh.com
-.Ed
-.Pp
The list of available ciphers may also be obtained using
.Qq ssh -Q cipher .
.It Cm ClientAliveCountMax
@@ -681,22 +679,24 @@ For this to work
.Cm GSSAPIKeyExchange
needs to be enabled in the server and also used by the client.
.It Cm GSSAPIKexAlgorithms
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+To see the defaults and how to modify this default, see manual page
+.Xr update-crypto-policies 8 .
+.Pp
The list of key exchange algorithms that are accepted by GSSAPI
key exchange. Possible values are
.Bd -literal -offset 3n
-gss-gex-sha1-,
-gss-group1-sha1-,
-gss-group14-sha1-,
-gss-group14-sha256-,
-gss-group16-sha512-,
-gss-nistp256-sha256-,
+gss-gex-sha1-
+gss-group1-sha1-
+gss-group14-sha1-
+gss-group14-sha256-
+gss-group16-sha512-
+gss-nistp256-sha256-
gss-curve25519-sha256-
.Ed
-.Pp
-The default is
-.Dq gss-group14-sha256-,gss-group16-sha512-,gss-nistp256-sha256-,
-gss-curve25519-sha256-,gss-group14-sha1-,gss-gex-sha1- .
This option only applies to connections using GSSAPI.
+.Pp
.It Cm HostbasedAcceptedKeyTypes
Specifies the key types that will be accepted for hostbased authentication
as a list of comma-separated patterns.
@@ -793,25 +793,13 @@ is specified, the location of the socket
.Ev SSH_AUTH_SOCK
environment variable.
.It Cm HostKeyAlgorithms
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+To see the defaults and how to modify this default, see manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies the host key algorithms
that the server offers.
-The default for this option is:
-.Bd -literal -offset 3n
-ecdsa-sha2-nistp256-cert-v01@openssh.com,
-ecdsa-sha2-nistp384-cert-v01@openssh.com,
-ecdsa-sha2-nistp521-cert-v01@openssh.com,
-sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
-ssh-ed25519-cert-v01@openssh.com,
-sk-ssh-ed25519-cert-v01@openssh.com,
-rsa-sha2-512-cert-v01@openssh.com,
-rsa-sha2-256-cert-v01@openssh.com,
-ssh-rsa-cert-v01@openssh.com,
-ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
-sk-ecdsa-sha2-nistp256@openssh.com,
-ssh-ed25519,sk-ssh-ed25519@openssh.com,
-rsa-sha2-512,rsa-sha2-256,ssh-rsa
-.Ed
-.Pp
The list of available key types may also be obtained using
.Qq ssh -Q HostKeyAlgorithms .
.It Cm IgnoreRhosts
@@ -943,20 +931,25 @@ Specifies whether to look at .k5login fi
The default is
.Cm yes .
.It Cm KexAlgorithms
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+To see the defaults and how to modify this default, see manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies the available KEX (Key Exchange) algorithms.
Multiple algorithms must be comma-separated.
Alternately if the specified list begins with a
.Sq +
-character, then the specified methods will be appended to the default set
-instead of replacing them.
+character, then the specified methods will be appended to the built-in
+openssh default set instead of replacing them.
If the specified list begins with a
.Sq -
character, then the specified methods (including wildcards) will be removed
-from the default set instead of replacing them.
+from the built-in openssh default set instead of replacing them.
If the specified list begins with a
.Sq ^
character, then the specified methods will be placed at the head of the
-default set.
+built-in openssh default set.
The supported algorithms are:
.Pp
.Bl -item -compact -offset indent
@@ -988,15 +981,6 @@ ecdh-sha2-nistp521
sntrup4591761x25519-sha512@tinyssh.org
.El
.Pp
-The default is:
-.Bd -literal -offset indent
-curve25519-sha256,curve25519-sha256@libssh.org,
-ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,
-diffie-hellman-group-exchange-sha256,
-diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,
-diffie-hellman-group14-sha256
-.Ed
-.Pp
The list of available key exchange algorithms may also be obtained using
.Qq ssh -Q KexAlgorithms .
.It Cm ListenAddress
@@ -1065,21 +1049,26 @@ DEBUG and DEBUG1 are equivalent.
DEBUG2 and DEBUG3 each specify higher levels of debugging output.
Logging with a DEBUG level violates the privacy of users and is not recommended.
.It Cm MACs
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+To see the defaults and how to modify this default, see manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies the available MAC (message authentication code) algorithms.
The MAC algorithm is used for data integrity protection.
Multiple algorithms must be comma-separated.
If the specified list begins with a
.Sq +
-character, then the specified algorithms will be appended to the default set
-instead of replacing them.
+character, then the specified algorithms will be appended to the built-in
+openssh default set instead of replacing them.
If the specified list begins with a
.Sq -
character, then the specified algorithms (including wildcards) will be removed
-from the default set instead of replacing them.
+from the built-in openssh default set instead of replacing them.
If the specified list begins with a
.Sq ^
character, then the specified algorithms will be placed at the head of the
-default set.
+built-in openssh default set.
.Pp
The algorithms that contain
.Qq -etm
@@ -1122,15 +1111,6 @@ umac-64-etm@openssh.com
umac-128-etm@openssh.com
.El
.Pp
-The default is:
-.Bd -literal -offset indent
-umac-64-etm@openssh.com,umac-128-etm@openssh.com,
-hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,
-hmac-sha1-etm@openssh.com,
-umac-64@openssh.com,umac-128@openssh.com,
-hmac-sha2-256,hmac-sha2-512,hmac-sha1
-.Ed
-.Pp
The list of available MAC algorithms may also be obtained using
.Qq ssh -Q mac .
.It Cm Match
@@ -1480,36 +1460,25 @@ or equivalent.)
The default is
.Cm yes .
.It Cm PubkeyAcceptedKeyTypes
+The default is handled system-wide by
+.Xr crypto-policies 7 .
+To see the defaults and how to modify this default, see manual page
+.Xr update-crypto-policies 8 .
+.Pp
Specifies the key types that will be accepted for public key authentication
as a list of comma-separated patterns.
Alternately if the specified list begins with a
.Sq +
-character, then the specified key types will be appended to the default set
-instead of replacing them.
+character, then the specified key types will be appended to the built-in
+openssh default set instead of replacing them.
If the specified list begins with a
.Sq -
character, then the specified key types (including wildcards) will be removed
-from the default set instead of replacing them.
+from the built-in openssh default set instead of replacing them.
If the specified list begins with a
.Sq ^
character, then the specified key types will be placed at the head of the
-default set.
-The default for this option is:
-.Bd -literal -offset 3n
-ecdsa-sha2-nistp256-cert-v01@openssh.com,
-ecdsa-sha2-nistp384-cert-v01@openssh.com,
-ecdsa-sha2-nistp521-cert-v01@openssh.com,
-sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
-ssh-ed25519-cert-v01@openssh.com,
-sk-ssh-ed25519-cert-v01@openssh.com,
-rsa-sha2-512-cert-v01@openssh.com,
-rsa-sha2-256-cert-v01@openssh.com,
-ssh-rsa-cert-v01@openssh.com,
-ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
-sk-ecdsa-sha2-nistp256@openssh.com,
-ssh-ed25519,sk-ssh-ed25519@openssh.com,
-rsa-sha2-512,rsa-sha2-256,ssh-rsa
-.Ed
+built-in openssh default set.
.Pp
The list of available key types may also be obtained using
.Qq ssh -Q PubkeyAcceptedKeyTypes .

File diff suppressed because it is too large Load Diff

View File

@ -1,720 +0,0 @@
From ed7ec0cdf577ffbb0b15145340cf51596ca3eb89 Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Tue, 14 May 2019 10:45:45 +0200
Subject: [PATCH] Use high-level OpenSSL API for signatures
---
digest-openssl.c | 16 ++++
digest.h | 6 ++
ssh-dss.c | 65 ++++++++++------
ssh-ecdsa.c | 69 ++++++++++-------
ssh-rsa.c | 193 +++++++++--------------------------------------
sshkey.c | 77 +++++++++++++++++++
sshkey.h | 4 +
7 files changed, 221 insertions(+), 209 deletions(-)
diff --git a/digest-openssl.c b/digest-openssl.c
index da7ed72bc..6a21d8adb 100644
--- a/digest-openssl.c
+++ b/digest-openssl.c
@@ -63,6 +63,22 @@ const struct ssh_digest digests[] = {
{ -1, NULL, 0, NULL },
};
+const EVP_MD *
+ssh_digest_to_md(int digest_type)
+{
+ switch (digest_type) {
+ case SSH_DIGEST_SHA1:
+ return EVP_sha1();
+ case SSH_DIGEST_SHA256:
+ return EVP_sha256();
+ case SSH_DIGEST_SHA384:
+ return EVP_sha384();
+ case SSH_DIGEST_SHA512:
+ return EVP_sha512();
+ }
+ return NULL;
+}
+
static const struct ssh_digest *
ssh_digest_by_alg(int alg)
{
diff --git a/digest.h b/digest.h
index 274574d0e..c7ceeb36f 100644
--- a/digest.h
+++ b/digest.h
@@ -32,6 +32,12 @@
struct sshbuf;
struct ssh_digest_ctx;
+#ifdef WITH_OPENSSL
+#include <openssl/evp.h>
+/* Converts internal digest representation to the OpenSSL one */
+const EVP_MD *ssh_digest_to_md(int digest_type);
+#endif
+
/* Looks up a digest algorithm by name */
int ssh_digest_alg_by_name(const char *name);
diff --git a/ssh-dss.c b/ssh-dss.c
index a23c383dc..ea45e7275 100644
--- a/ssh-dss.c
+++ b/ssh-dss.c
@@ -52,11 +52,15 @@ int
ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, u_int compat)
{
+ EVP_PKEY *pkey = NULL;
DSA_SIG *sig = NULL;
const BIGNUM *sig_r, *sig_s;
- u_char digest[SSH_DIGEST_MAX_LENGTH], sigblob[SIGBLOB_LEN];
- size_t rlen, slen, len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1);
+ u_char sigblob[SIGBLOB_LEN];
+ size_t rlen, slen;
+ int len;
struct sshbuf *b = NULL;
+ u_char *sigb = NULL;
+ const u_char *psig = NULL;
int ret = SSH_ERR_INVALID_ARGUMENT;
if (lenp != NULL)
@@ -67,17 +71,24 @@ ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
if (key == NULL || key->dsa == NULL ||
sshkey_type_plain(key->type) != KEY_DSA)
return SSH_ERR_INVALID_ARGUMENT;
- if (dlen == 0)
- return SSH_ERR_INTERNAL_ERROR;
- if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen,
- digest, sizeof(digest))) != 0)
+ if ((pkey = EVP_PKEY_new()) == NULL ||
+ EVP_PKEY_set1_DSA(pkey, key->dsa) != 1)
+ return SSH_ERR_ALLOC_FAIL;
+ ret = sshkey_calculate_signature(pkey, SSH_DIGEST_SHA1, &sigb, &len,
+ data, datalen);
+ EVP_PKEY_free(pkey);
+ if (ret < 0) {
goto out;
+ }
- if ((sig = DSA_do_sign(digest, dlen, key->dsa)) == NULL) {
+ psig = sigb;
+ if ((sig = d2i_DSA_SIG(NULL, &psig, len)) == NULL) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
+ free(sigb);
+ sigb = NULL;
DSA_SIG_get0(sig, &sig_r, &sig_s);
rlen = BN_num_bytes(sig_r);
@@ -110,7 +121,7 @@ ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
*lenp = len;
ret = 0;
out:
- explicit_bzero(digest, sizeof(digest));
+ free(sigb);
DSA_SIG_free(sig);
sshbuf_free(b);
return ret;
@@ -121,20 +132,20 @@ ssh_dss_verify(const struct sshkey *key,
const u_char *signature, size_t signaturelen,
const u_char *data, size_t datalen, u_int compat)
{
+ EVP_PKEY *pkey = NULL;
DSA_SIG *sig = NULL;
BIGNUM *sig_r = NULL, *sig_s = NULL;
- u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob = NULL;
- size_t len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1);
+ u_char *sigblob = NULL;
+ size_t len, slen;
int ret = SSH_ERR_INTERNAL_ERROR;
struct sshbuf *b = NULL;
char *ktype = NULL;
+ u_char *sigb = NULL, *psig = NULL;
if (key == NULL || key->dsa == NULL ||
sshkey_type_plain(key->type) != KEY_DSA ||
signature == NULL || signaturelen == 0)
return SSH_ERR_INVALID_ARGUMENT;
- if (dlen == 0)
- return SSH_ERR_INTERNAL_ERROR;
/* fetch signature */
if ((b = sshbuf_from(signature, signaturelen)) == NULL)
@@ -176,25 +187,31 @@ ssh_dss_verify(const struct sshkey *key,
}
sig_r = sig_s = NULL; /* transferred */
- /* sha1 the data */
- if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen,
- digest, sizeof(digest))) != 0)
+ if ((slen = i2d_DSA_SIG(sig, NULL)) == 0) {
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
-
- switch (DSA_do_verify(digest, dlen, sig, key->dsa)) {
- case 1:
- ret = 0;
- break;
- case 0:
- ret = SSH_ERR_SIGNATURE_INVALID;
+ }
+ if ((sigb = malloc(slen)) == NULL) {
+ ret = SSH_ERR_ALLOC_FAIL;
goto out;
- default:
+ }
+ psig = sigb;
+ if ((slen = i2d_DSA_SIG(sig, &psig)) == 0) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
+ if ((pkey = EVP_PKEY_new()) == NULL ||
+ EVP_PKEY_set1_DSA(pkey, key->dsa) != 1) {
+ ret = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ ret = sshkey_verify_signature(pkey, SSH_DIGEST_SHA1, data, datalen,
+ sigb, slen);
+ EVP_PKEY_free(pkey);
+
out:
- explicit_bzero(digest, sizeof(digest));
+ free(sigb);
DSA_SIG_free(sig);
BN_clear_free(sig_r);
BN_clear_free(sig_s);
diff --git a/ssh-ecdsa.c b/ssh-ecdsa.c
index 599c7199d..b036796e8 100644
--- a/ssh-ecdsa.c
+++ b/ssh-ecdsa.c
@@ -50,11 +50,13 @@ int
ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, u_int compat)
{
+ EVP_PKEY *pkey = NULL;
ECDSA_SIG *sig = NULL;
+ unsigned char *sigb = NULL;
+ const unsigned char *psig;
const BIGNUM *sig_r, *sig_s;
int hash_alg;
- u_char digest[SSH_DIGEST_MAX_LENGTH];
- size_t len, dlen;
+ int len;
struct sshbuf *b = NULL, *bb = NULL;
int ret = SSH_ERR_INTERNAL_ERROR;
@@ -67,18 +69,24 @@ ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
sshkey_type_plain(key->type) != KEY_ECDSA)
return SSH_ERR_INVALID_ARGUMENT;
- if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 ||
- (dlen = ssh_digest_bytes(hash_alg)) == 0)
+ if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1)
return SSH_ERR_INTERNAL_ERROR;
- if ((ret = ssh_digest_memory(hash_alg, data, datalen,
- digest, sizeof(digest))) != 0)
+
+ if ((pkey = EVP_PKEY_new()) == NULL ||
+ EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa) != 1)
+ return SSH_ERR_ALLOC_FAIL;
+ ret = sshkey_calculate_signature(pkey, hash_alg, &sigb, &len, data,
+ datalen);
+ EVP_PKEY_free(pkey);
+ if (ret < 0) {
goto out;
+ }
- if ((sig = ECDSA_do_sign(digest, dlen, key->ecdsa)) == NULL) {
+ psig = sigb;
+ if ((sig = d2i_ECDSA_SIG(NULL, &psig, len)) == NULL) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
-
if ((bb = sshbuf_new()) == NULL || (b = sshbuf_new()) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
@@ -102,7 +110,7 @@ ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
*lenp = len;
ret = 0;
out:
- explicit_bzero(digest, sizeof(digest));
+ free(sigb);
sshbuf_free(b);
sshbuf_free(bb);
ECDSA_SIG_free(sig);
@@ -115,22 +123,21 @@ ssh_ecdsa_verify(const struct sshkey *key,
const u_char *signature, size_t signaturelen,
const u_char *data, size_t datalen, u_int compat)
{
+ EVP_PKEY *pkey = NULL;
ECDSA_SIG *sig = NULL;
BIGNUM *sig_r = NULL, *sig_s = NULL;
- int hash_alg;
- u_char digest[SSH_DIGEST_MAX_LENGTH];
- size_t dlen;
+ int hash_alg, len;
int ret = SSH_ERR_INTERNAL_ERROR;
struct sshbuf *b = NULL, *sigbuf = NULL;
char *ktype = NULL;
+ unsigned char *sigb = NULL, *psig = NULL;
if (key == NULL || key->ecdsa == NULL ||
sshkey_type_plain(key->type) != KEY_ECDSA ||
signature == NULL || signaturelen == 0)
return SSH_ERR_INVALID_ARGUMENT;
- if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 ||
- (dlen = ssh_digest_bytes(hash_alg)) == 0)
+ if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1)
return SSH_ERR_INTERNAL_ERROR;
/* fetch signature */
@@ -166,28 +173,36 @@ ssh_ecdsa_verify(const struct sshkey *key,
}
sig_r = sig_s = NULL; /* transferred */
- if (sshbuf_len(sigbuf) != 0) {
- ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
+ /* Figure out the length */
+ if ((len = i2d_ECDSA_SIG(sig, NULL)) == 0) {
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ if ((sigb = malloc(len)) == NULL) {
+ ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if ((ret = ssh_digest_memory(hash_alg, data, datalen,
- digest, sizeof(digest))) != 0)
+ psig = sigb;
+ if ((len = i2d_ECDSA_SIG(sig, &psig)) == 0) {
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
+ }
- switch (ECDSA_do_verify(digest, dlen, sig, key->ecdsa)) {
- case 1:
- ret = 0;
- break;
- case 0:
- ret = SSH_ERR_SIGNATURE_INVALID;
+ if (sshbuf_len(sigbuf) != 0) {
+ ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
goto out;
- default:
- ret = SSH_ERR_LIBCRYPTO_ERROR;
+ }
+
+ if ((pkey = EVP_PKEY_new()) == NULL ||
+ EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa) != 1) {
+ ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
+ ret = sshkey_verify_signature(pkey, hash_alg, data, datalen, sigb, len);
+ EVP_PKEY_free(pkey);
out:
- explicit_bzero(digest, sizeof(digest));
+ free(sigb);
sshbuf_free(sigbuf);
sshbuf_free(b);
ECDSA_SIG_free(sig);
diff --git a/ssh-rsa.c b/ssh-rsa.c
index 9b14f9a9a..8ef3a6aca 100644
--- a/ssh-rsa.c
+++ b/ssh-rsa.c
@@ -37,7 +37,7 @@
#include "openbsd-compat/openssl-compat.h"
-static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *);
+static int openssh_RSA_verify(int, const u_char *, size_t, u_char *, size_t, EVP_PKEY *);
static const char *
rsa_hash_alg_ident(int hash_alg)
@@ -90,21 +90,6 @@ rsa_hash_id_from_keyname(const char *alg)
return -1;
}
-static int
-rsa_hash_alg_nid(int type)
-{
- switch (type) {
- case SSH_DIGEST_SHA1:
- return NID_sha1;
- case SSH_DIGEST_SHA256:
- return NID_sha256;
- case SSH_DIGEST_SHA512:
- return NID_sha512;
- default:
- return -1;
- }
-}
-
int
ssh_rsa_complete_crt_parameters(struct sshkey *key, const BIGNUM *iqmp)
{
@@ -164,11 +149,10 @@ int
ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, const char *alg_ident)
{
- const BIGNUM *rsa_n;
- u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL;
- size_t slen = 0;
- u_int dlen, len;
- int nid, hash_alg, ret = SSH_ERR_INTERNAL_ERROR;
+ EVP_PKEY *pkey = NULL;
+ u_char *sig = NULL;
+ int len, slen = 0;
+ int hash_alg, ret = SSH_ERR_INTERNAL_ERROR;
struct sshbuf *b = NULL;
if (lenp != NULL)
@@ -180,33 +164,24 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
hash_alg = SSH_DIGEST_SHA1;
else
hash_alg = rsa_hash_id_from_keyname(alg_ident);
+
if (key == NULL || key->rsa == NULL || hash_alg == -1 ||
sshkey_type_plain(key->type) != KEY_RSA)
return SSH_ERR_INVALID_ARGUMENT;
- RSA_get0_key(key->rsa, &rsa_n, NULL, NULL);
- if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
- return SSH_ERR_KEY_LENGTH;
slen = RSA_size(key->rsa);
- if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM)
- return SSH_ERR_INVALID_ARGUMENT;
-
- /* hash the data */
- nid = rsa_hash_alg_nid(hash_alg);
- if ((dlen = ssh_digest_bytes(hash_alg)) == 0)
- return SSH_ERR_INTERNAL_ERROR;
- if ((ret = ssh_digest_memory(hash_alg, data, datalen,
- digest, sizeof(digest))) != 0)
- goto out;
+ if (RSA_bits(key->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE)
+ return SSH_ERR_KEY_LENGTH;
- if ((sig = malloc(slen)) == NULL) {
- ret = SSH_ERR_ALLOC_FAIL;
+ if ((pkey = EVP_PKEY_new()) == NULL ||
+ EVP_PKEY_set1_RSA(pkey, key->rsa) != 1)
+ return SSH_ERR_ALLOC_FAIL;
+ ret = sshkey_calculate_signature(pkey, hash_alg, &sig, &len, data,
+ datalen);
+ EVP_PKEY_free(pkey);
+ if (ret < 0) {
goto out;
}
- if (RSA_sign(nid, digest, dlen, sig, &len, key->rsa) != 1) {
- ret = SSH_ERR_LIBCRYPTO_ERROR;
- goto out;
- }
if (len < slen) {
size_t diff = slen - len;
memmove(sig + diff, sig, len);
@@ -215,6 +190,7 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
ret = SSH_ERR_INTERNAL_ERROR;
goto out;
}
+
/* encode signature */
if ((b = sshbuf_new()) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
@@ -235,7 +211,6 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
*lenp = len;
ret = 0;
out:
- explicit_bzero(digest, sizeof(digest));
freezero(sig, slen);
sshbuf_free(b);
return ret;
@@ -246,10 +221,10 @@ ssh_rsa_verify(const struct sshkey *key,
const u_char *sig, size_t siglen, const u_char *data, size_t datalen,
const char *alg)
{
- const BIGNUM *rsa_n;
+ EVP_PKEY *pkey = NULL;
char *sigtype = NULL;
int hash_alg, want_alg, ret = SSH_ERR_INTERNAL_ERROR;
- size_t len = 0, diff, modlen, dlen;
+ size_t len = 0, diff, modlen;
struct sshbuf *b = NULL;
u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL;
@@ -257,8 +232,7 @@ ssh_rsa_verify(const struct sshkey *key,
sshkey_type_plain(key->type) != KEY_RSA ||
sig == NULL || siglen == 0)
return SSH_ERR_INVALID_ARGUMENT;
- RSA_get0_key(key->rsa, &rsa_n, NULL, NULL);
- if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
+ if (RSA_bits(key->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE)
return SSH_ERR_KEY_LENGTH;
if ((b = sshbuf_from(sig, siglen)) == NULL)
@@ -310,16 +284,15 @@ ssh_rsa_verify(const struct sshkey *key,
explicit_bzero(sigblob, diff);
len = modlen;
}
- if ((dlen = ssh_digest_bytes(hash_alg)) == 0) {
- ret = SSH_ERR_INTERNAL_ERROR;
+
+ if ((pkey = EVP_PKEY_new()) == NULL ||
+ EVP_PKEY_set1_RSA(pkey, key->rsa) != 1) {
+ ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if ((ret = ssh_digest_memory(hash_alg, data, datalen,
- digest, sizeof(digest))) != 0)
- goto out;
+ ret = openssh_RSA_verify(hash_alg, data, datalen, sigblob, len, pkey);
+ EVP_PKEY_free(pkey);
- ret = openssh_RSA_verify(hash_alg, digest, dlen, sigblob, len,
- key->rsa);
out:
freezero(sigblob, len);
free(sigtype);
@@ -328,122 +301,26 @@ ssh_rsa_verify(const struct sshkey *key,
return ret;
}
-/*
- * See:
- * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/
- * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn
- */
-
-/*
- * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
- * oiw(14) secsig(3) algorithms(2) 26 }
- */
-static const u_char id_sha1[] = {
- 0x30, 0x21, /* type Sequence, length 0x21 (33) */
- 0x30, 0x09, /* type Sequence, length 0x09 */
- 0x06, 0x05, /* type OID, length 0x05 */
- 0x2b, 0x0e, 0x03, 0x02, 0x1a, /* id-sha1 OID */
- 0x05, 0x00, /* NULL */
- 0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */
-};
-
-/*
- * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html
- * id-sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840)
- * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2)
- * id-sha256(1) }
- */
-static const u_char id_sha256[] = {
- 0x30, 0x31, /* type Sequence, length 0x31 (49) */
- 0x30, 0x0d, /* type Sequence, length 0x0d (13) */
- 0x06, 0x09, /* type OID, length 0x09 */
- 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, /* id-sha256 */
- 0x05, 0x00, /* NULL */
- 0x04, 0x20 /* Octet string, length 0x20 (32), followed by sha256 hash */
-};
-
-/*
- * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html
- * id-sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840)
- * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2)
- * id-sha256(3) }
- */
-static const u_char id_sha512[] = {
- 0x30, 0x51, /* type Sequence, length 0x51 (81) */
- 0x30, 0x0d, /* type Sequence, length 0x0d (13) */
- 0x06, 0x09, /* type OID, length 0x09 */
- 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, /* id-sha512 */
- 0x05, 0x00, /* NULL */
- 0x04, 0x40 /* Octet string, length 0x40 (64), followed by sha512 hash */
-};
-
static int
-rsa_hash_alg_oid(int hash_alg, const u_char **oidp, size_t *oidlenp)
+openssh_RSA_verify(int hash_alg, const u_char *data, size_t datalen,
+ u_char *sigbuf, size_t siglen, EVP_PKEY *pkey)
{
- switch (hash_alg) {
- case SSH_DIGEST_SHA1:
- *oidp = id_sha1;
- *oidlenp = sizeof(id_sha1);
- break;
- case SSH_DIGEST_SHA256:
- *oidp = id_sha256;
- *oidlenp = sizeof(id_sha256);
- break;
- case SSH_DIGEST_SHA512:
- *oidp = id_sha512;
- *oidlenp = sizeof(id_sha512);
- break;
- default:
- return SSH_ERR_INVALID_ARGUMENT;
- }
- return 0;
-}
+ size_t rsasize = 0;
+ const RSA *rsa;
+ int ret;
-static int
-openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen,
- u_char *sigbuf, size_t siglen, RSA *rsa)
-{
- size_t rsasize = 0, oidlen = 0, hlen = 0;
- int ret, len, oidmatch, hashmatch;
- const u_char *oid = NULL;
- u_char *decrypted = NULL;
-
- if ((ret = rsa_hash_alg_oid(hash_alg, &oid, &oidlen)) != 0)
- return ret;
- ret = SSH_ERR_INTERNAL_ERROR;
- hlen = ssh_digest_bytes(hash_alg);
- if (hashlen != hlen) {
- ret = SSH_ERR_INVALID_ARGUMENT;
- goto done;
- }
+ rsa = EVP_PKEY_get0_RSA(pkey);
rsasize = RSA_size(rsa);
if (rsasize <= 0 || rsasize > SSHBUF_MAX_BIGNUM ||
siglen == 0 || siglen > rsasize) {
ret = SSH_ERR_INVALID_ARGUMENT;
goto done;
}
- if ((decrypted = malloc(rsasize)) == NULL) {
- ret = SSH_ERR_ALLOC_FAIL;
- goto done;
- }
- if ((len = RSA_public_decrypt(siglen, sigbuf, decrypted, rsa,
- RSA_PKCS1_PADDING)) < 0) {
- ret = SSH_ERR_LIBCRYPTO_ERROR;
- goto done;
- }
- if (len < 0 || (size_t)len != hlen + oidlen) {
- ret = SSH_ERR_INVALID_FORMAT;
- goto done;
- }
- oidmatch = timingsafe_bcmp(decrypted, oid, oidlen) == 0;
- hashmatch = timingsafe_bcmp(decrypted + oidlen, hash, hlen) == 0;
- if (!oidmatch || !hashmatch) {
- ret = SSH_ERR_SIGNATURE_INVALID;
- goto done;
- }
- ret = 0;
+
+ ret = sshkey_verify_signature(pkey, hash_alg, data, datalen,
+ sigbuf, siglen);
+
done:
- freezero(decrypted, rsasize);
return ret;
}
#endif /* WITH_OPENSSL */
diff --git a/sshkey.c b/sshkey.c
index ad1957762..b95ed0b10 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -358,6 +358,83 @@ sshkey_type_plain(int type)
}
#ifdef WITH_OPENSSL
+int
+sshkey_calculate_signature(EVP_PKEY *pkey, int hash_alg, u_char **sigp,
+ int *lenp, const u_char *data, size_t datalen)
+{
+ EVP_MD_CTX *ctx = NULL;
+ u_char *sig = NULL;
+ int ret, slen, len;
+
+ if (sigp == NULL || lenp == NULL) {
+ return SSH_ERR_INVALID_ARGUMENT;
+ }
+
+ slen = EVP_PKEY_size(pkey);
+ if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM)
+ return SSH_ERR_INVALID_ARGUMENT;
+
+ len = slen;
+ if ((sig = malloc(slen)) == NULL) {
+ return SSH_ERR_ALLOC_FAIL;
+ }
+
+ if ((ctx = EVP_MD_CTX_new()) == NULL) {
+ ret = SSH_ERR_ALLOC_FAIL;
+ goto error;
+ }
+ if (EVP_SignInit_ex(ctx, ssh_digest_to_md(hash_alg), NULL) <= 0 ||
+ EVP_SignUpdate(ctx, data, datalen) <= 0 ||
+ EVP_SignFinal(ctx, sig, &len, pkey) <= 0) {
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
+ goto error;
+ }
+
+ *sigp = sig;
+ *lenp = len;
+ /* Now owned by the caller */
+ sig = NULL;
+ ret = 0;
+
+error:
+ EVP_MD_CTX_free(ctx);
+ free(sig);
+ return ret;
+}
+
+int
+sshkey_verify_signature(EVP_PKEY *pkey, int hash_alg, const u_char *data,
+ size_t datalen, u_char *sigbuf, int siglen)
+{
+ EVP_MD_CTX *ctx = NULL;
+ int ret;
+
+ if ((ctx = EVP_MD_CTX_new()) == NULL) {
+ return SSH_ERR_ALLOC_FAIL;
+ }
+ if (EVP_VerifyInit_ex(ctx, ssh_digest_to_md(hash_alg), NULL) <= 0 ||
+ EVP_VerifyUpdate(ctx, data, datalen) <= 0) {
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
+ goto done;
+ }
+ ret = EVP_VerifyFinal(ctx, sigbuf, siglen, pkey);
+ switch (ret) {
+ case 1:
+ ret = 0;
+ break;
+ case 0:
+ ret = SSH_ERR_SIGNATURE_INVALID;
+ break;
+ default:
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
+ break;
+ }
+
+done:
+ EVP_MD_CTX_free(ctx);
+ return ret;
+}
+
/* XXX: these are really begging for a table-driven approach */
int
sshkey_curve_name_to_nid(const char *name)
diff --git a/sshkey.h b/sshkey.h
index a91e60436..270901a87 100644
--- a/sshkey.h
+++ b/sshkey.h
@@ -179,6 +179,10 @@ const char *sshkey_ssh_name(const struct sshkey *);
const char *sshkey_ssh_name_plain(const struct sshkey *);
int sshkey_names_valid2(const char *, int);
char *sshkey_alg_list(int, int, int, char);
+int sshkey_calculate_signature(EVP_PKEY*, int, u_char **,
+ int *, const u_char *, size_t);
+int sshkey_verify_signature(EVP_PKEY *, int, const u_char *,
+ size_t, u_char *, int);
int sshkey_from_blob(const u_char *, size_t, struct sshkey **);
int sshkey_fromb(struct sshbuf *, struct sshkey **);

View File

@ -1,137 +0,0 @@
commit 2c3ef499bfffce3cfd315edeebf202850ba4e00a
Author: Jakub Jelen <jjelen@redhat.com>
Date: Tue Apr 16 15:35:18 2019 +0200
Use the new OpenSSL KDF
diff --git a/configure.ac b/configure.ac
index 2a455e4e..e01c3d43 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2712,6 +2712,7 @@ if test "x$openssl" = "xyes" ; then
HMAC_CTX_init \
RSA_generate_key_ex \
RSA_get_default_method \
+ EVP_KDF_CTX_new_id \
])
# OpenSSL_add_all_algorithms may be a macro.
diff --git a/kex.c b/kex.c
index b6f041f4..1fbce2bb 100644
--- a/kex.c
+++ b/kex.c
@@ -38,6 +38,9 @@
#ifdef WITH_OPENSSL
#include <openssl/crypto.h>
#include <openssl/dh.h>
+# ifdef HAVE_EVP_KDF_CTX_NEW_ID
+# include <openssl/kdf.h>
+# endif
#endif
#include "ssh.h"
@@ -942,6 +945,95 @@ kex_choose_conf(struct ssh *ssh)
return r;
}
+#ifdef HAVE_EVP_KDF_CTX_NEW_ID
+static const EVP_MD *
+digest_to_md(int digest_type)
+{
+ switch (digest_type) {
+ case SSH_DIGEST_SHA1:
+ return EVP_sha1();
+ case SSH_DIGEST_SHA256:
+ return EVP_sha256();
+ case SSH_DIGEST_SHA384:
+ return EVP_sha384();
+ case SSH_DIGEST_SHA512:
+ return EVP_sha512();
+ }
+ return NULL;
+}
+
+static int
+derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen,
+ const struct sshbuf *shared_secret, u_char **keyp)
+{
+ struct kex *kex = ssh->kex;
+ EVP_KDF_CTX *ctx = NULL;
+ u_char *key = NULL;
+ int r, key_len;
+
+ if ((key_len = ssh_digest_bytes(kex->hash_alg)) == 0)
+ return SSH_ERR_INVALID_ARGUMENT;
+ key_len = ROUNDUP(need, key_len);
+ if ((key = calloc(1, key_len)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+
+ ctx = EVP_KDF_CTX_new_id(EVP_KDF_SSHKDF);
+ if (!ctx) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+
+ r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_MD, digest_to_md(kex->hash_alg));
+ if (r != 1) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY,
+ sshbuf_ptr(shared_secret), sshbuf_len(shared_secret));
+ if (r != 1) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_XCGHASH, hash, hashlen);
+ if (r != 1) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_TYPE, id);
+ if (r != 1) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_SESSION_ID,
+ kex->session_id, kex->session_id_len);
+ if (r != 1) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ r = EVP_KDF_derive(ctx, key, key_len);
+ if (r != 1) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+#ifdef DEBUG_KEX
+ fprintf(stderr, "key '%c'== ", id);
+ dump_digest("key", key, key_len);
+#endif
+ *keyp = key;
+ key = NULL;
+ r = 0;
+
+out:
+ free (key);
+ EVP_KDF_CTX_free(ctx);
+ if (r < 0) {
+ return r;
+ }
+ return 0;
+}
+#else
static int
derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen,
const struct sshbuf *shared_secret, u_char **keyp)
@@ -1004,6 +1096,7 @@ derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen,
ssh_digest_free(hashctx);
return r;
}
+#endif /* HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID */
#define NKEYS 6
int

File diff suppressed because it is too large Load Diff

View File

@ -1,40 +0,0 @@
diff --git a/regress/misc/sk-dummy/sk-dummy.c b/regress/misc/sk-dummy/sk-dummy.c
index dca158de..afdcb1d2 100644
--- a/regress/misc/sk-dummy/sk-dummy.c
+++ b/regress/misc/sk-dummy/sk-dummy.c
@@ -71,7 +71,7 @@ skdebug(const char *func, const char *fmt, ...)
#endif
}
-uint32_t
+uint32_t __attribute__((visibility("default")))
sk_api_version(void)
{
return SSH_SK_VERSION_MAJOR;
@@ -220,7 +220,7 @@ check_options(struct sk_option **options)
return 0;
}
-int
+int __attribute__((visibility("default")))
sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len,
const char *application, uint8_t flags, const char *pin,
struct sk_option **options, struct sk_enroll_response **enroll_response)
@@ -467,7 +467,7 @@ sig_ed25519(const uint8_t *message, size_t message_len,
return ret;
}
-int
+int __attribute__((visibility("default")))
sk_sign(uint32_t alg, const uint8_t *data, size_t datalen,
const char *application, const uint8_t *key_handle, size_t key_handle_len,
uint8_t flags, const char *pin, struct sk_option **options,
@@ -518,7 +518,7 @@ sk_sign(uint32_t alg, const uint8_t *message, size_t message_len,
return ret;
}
-int
+int __attribute__((visibility("default")))
sk_load_resident_keys(const char *pin, struct sk_option **options,
struct sk_resident_key ***rks, size_t *nrks)
{

View File

@ -1,30 +0,0 @@
diff --git a/channels.c b/channels.c
--- a/channels.c
+++ b/channels.c
@@ -3933,16 +3933,26 @@ x11_create_display_inet(int x11_display_
if (ai->ai_family == AF_INET6)
sock_set_v6only(sock);
if (x11_use_localhost)
set_reuseaddr(sock);
if (bind(sock, ai->ai_addr, ai->ai_addrlen) == -1) {
debug2("%s: bind port %d: %.100s", __func__,
port, strerror(errno));
close(sock);
+
+ /* do not remove successfully opened
+ * sockets if the request failed because
+ * the protocol IPv4/6 is not available
+ * (e.g. IPv6 may be disabled while being
+ * supported)
+ */
+ if (EADDRNOTAVAIL == errno)
+ continue;
+
for (n = 0; n < num_socks; n++)
close(socks[n]);
num_socks = 0;
break;
}
socks[num_socks++] = sock;
if (num_socks == NUM_SOCKS)
break;

View File

@ -1,57 +0,0 @@
--- compat.h.orig 2020-10-05 10:09:02.953505129 -0700
+++ compat.h 2020-10-05 10:10:17.587733113 -0700
@@ -34,7 +34,7 @@
#define SSH_BUG_UTF8TTYMODE 0x00000001
#define SSH_BUG_SIGTYPE 0x00000002
-/* #define unused 0x00000004 */
+#define SSH_BUG_SIGTYPE74 0x00000004
/* #define unused 0x00000008 */
#define SSH_OLD_SESSIONID 0x00000010
/* #define unused 0x00000020 */
--- compat.c.orig 2020-10-05 10:25:02.088720562 -0700
+++ compat.c 2020-10-05 10:13:11.637282492 -0700
@@ -65,11 +65,12 @@
{ "OpenSSH_6.5*,"
"OpenSSH_6.6*", SSH_NEW_OPENSSH|SSH_BUG_CURVE25519PAD|
SSH_BUG_SIGTYPE},
+ { "OpenSSH_7.4*", SSH_NEW_OPENSSH|SSH_BUG_SIGTYPE|
+ SSH_BUG_SIGTYPE74},
{ "OpenSSH_7.0*,"
"OpenSSH_7.1*,"
"OpenSSH_7.2*,"
"OpenSSH_7.3*,"
- "OpenSSH_7.4*,"
"OpenSSH_7.5*,"
"OpenSSH_7.6*,"
"OpenSSH_7.7*", SSH_NEW_OPENSSH|SSH_BUG_SIGTYPE},
--- sshconnect2.c.orig 2020-09-26 07:26:37.618010545 -0700
+++ sshconnect2.c 2020-10-05 10:47:22.116315148 -0700
@@ -1305,6 +1305,26 @@
break;
}
free(oallowed);
+ /*
+ * OpenSSH 7.4 supports SHA2 sig types, but fails to indicate its
+ * support. For that release, check the local policy against the
+ * SHA2 signature types.
+ */
+ if (alg == NULL &&
+ (key->type == KEY_RSA && (datafellows & SSH_BUG_SIGTYPE74))) {
+ oallowed = allowed = xstrdup(options.pubkey_key_types);
+ while ((cp = strsep(&allowed, ",")) != NULL) {
+ if (sshkey_type_from_name(cp) != key->type)
+ continue;
+ tmp = match_list(sshkey_sigalg_by_name(cp), "rsa-sha2-256,rsa-sha2-512", NULL);
+ if (tmp != NULL)
+ alg = xstrdup(cp);
+ free(tmp);
+ if (alg != NULL)
+ break;
+ }
+ free(oallowed);
+ }
return alg;
}

View File

@ -1,14 +0,0 @@
diff --git a/sandbox-seccomp-filter.c b/sandbox-seccomp-filter.c
index e0768c06..5065ae7e 100644
--- a/sandbox-seccomp-filter.c
+++ b/sandbox-seccomp-filter.c
@@ -267,6 +267,9 @@ static const struct sock_filter preauth_insns[] = {
#ifdef __NR_pselect6
SC_ALLOW(__NR_pselect6),
#endif
+#ifdef __NR_pselect6_time64
+ SC_ALLOW(__NR_pselect6_time64),
+#endif
#ifdef __NR_read
SC_ALLOW(__NR_read),
#endif

View File

@ -1,130 +0,0 @@
From 66f16e5425eb881570e82bfef7baeac2e7accc0a Mon Sep 17 00:00:00 2001
From: Oleg <Fallmay@users.noreply.github.com>
Date: Thu, 1 Oct 2020 12:09:08 +0300
Subject: [PATCH] Fix `EOF: command not found` error in ssh-copy-id
---
contrib/ssh-copy-id | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/contrib/ssh-copy-id b/contrib/ssh-copy-id
index 392f64f94..a76907717 100644
--- a/contrib/ssh-copy-id
+++ b/contrib/ssh-copy-id
@@ -247,7 +247,7 @@ installkeys_sh() {
# the -z `tail ...` checks for a trailing newline. The echo adds one if was missing
# the cat adds the keys we're getting via STDIN
# and if available restorecon is used to restore the SELinux context
- INSTALLKEYS_SH=$(tr '\t\n' ' ' <<-EOF)
+ INSTALLKEYS_SH=$(tr '\t\n' ' ' <<-EOF
cd;
umask 077;
mkdir -p $(dirname "${AUTH_KEY_FILE}") &&
@@ -258,6 +258,7 @@ installkeys_sh() {
restorecon -F .ssh ${AUTH_KEY_FILE};
fi
EOF
+ )
# to defend against quirky remote shells: use 'exec sh -c' to get POSIX;
printf "exec sh -c '%s'" "${INSTALLKEYS_SH}"
From de59a431cdec833e3ec15691dd950402b4c052cf Mon Sep 17 00:00:00 2001
From: Philip Hands <phil@hands.com>
Date: Sat, 3 Oct 2020 00:20:07 +0200
Subject: [PATCH] un-nest $() to make ksh cheerful
---
ssh-copy-id | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
From 02ac2c3c3db5478a440dfb1b90d15f686f2cbfc6 Mon Sep 17 00:00:00 2001
From: Philip Hands <phil@hands.com>
Date: Fri, 2 Oct 2020 21:30:10 +0200
Subject: [PATCH] ksh doesn't grok 'local'
and AFAICT it's not actually doing anything useful in the code, so let's
see how things go without it.
---
ssh-copy-id | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/contrib/ssh-copy-id b/contrib/ssh-copy-id
index a769077..11c9463 100755
--- a/contrib/ssh-copy-id
+++ b/contrib/ssh-copy-id
@@ -76,7 +76,7 @@ quote() {
}
use_id_file() {
- local L_ID_FILE="$1"
+ L_ID_FILE="$1"
if [ -z "$L_ID_FILE" ] ; then
printf '%s: ERROR: no ID file found\n' "$0"
@@ -94,7 +94,7 @@ use_id_file() {
# check that the files are readable
for f in "$PUB_ID_FILE" ${PRIV_ID_FILE:+"$PRIV_ID_FILE"} ; do
ErrMSG=$( { : < "$f" ; } 2>&1 ) || {
- local L_PRIVMSG=""
+ L_PRIVMSG=""
[ "$f" = "$PRIV_ID_FILE" ] && L_PRIVMSG=" (to install the contents of '$PUB_ID_FILE' anyway, look at the -f option)"
printf "\\n%s: ERROR: failed to open ID file '%s': %s\\n" "$0" "$f" "$(printf '%s\n%s\n' "$ErrMSG" "$L_PRIVMSG" | sed -e 's/.*: *//')"
exit 1
@@ -169,7 +169,7 @@ fi
# populate_new_ids() uses several global variables ($USER_HOST, $SSH_OPTS ...)
# and has the side effect of setting $NEW_IDS
populate_new_ids() {
- local L_SUCCESS="$1"
+ L_SUCCESS="$1"
# shellcheck disable=SC2086
if [ "$FORCED" ] ; then
@@ -181,13 +181,12 @@ populate_new_ids() {
eval set -- "$SSH_OPTS"
umask 0177
- local L_TMP_ID_FILE
L_TMP_ID_FILE=$(mktemp ~/.ssh/ssh-copy-id_id.XXXXXXXXXX)
if test $? -ne 0 || test "x$L_TMP_ID_FILE" = "x" ; then
printf '%s: ERROR: mktemp failed\n' "$0" >&2
exit 1
fi
- local L_CLEANUP="rm -f \"$L_TMP_ID_FILE\" \"${L_TMP_ID_FILE}.stderr\""
+ L_CLEANUP="rm -f \"$L_TMP_ID_FILE\" \"${L_TMP_ID_FILE}.stderr\""
# shellcheck disable=SC2064
trap "$L_CLEANUP" EXIT TERM INT QUIT
printf '%s: INFO: attempting to log in with the new key(s), to filter out any that are already installed\n' "$0" >&2
@@ -237,7 +236,7 @@ populate_new_ids() {
# produce a one-liner to add the keys to remote authorized_keys file
# optionally takes an alternative path for authorized_keys
installkeys_sh() {
- local AUTH_KEY_FILE=${1:-.ssh/authorized_keys}
+ AUTH_KEY_FILE=${1:-.ssh/authorized_keys}
# In setting INSTALLKEYS_SH:
# the tr puts it all on one line (to placate tcsh)
--
diff --git a/contrib/ssh-copy-id b/contrib/ssh-copy-id
index 11c9463..ee3f637 100755
--- a/contrib/ssh-copy-id
+++ b/contrib/ssh-copy-id
@@ -237,6 +237,7 @@ populate_new_ids() {
# optionally takes an alternative path for authorized_keys
installkeys_sh() {
AUTH_KEY_FILE=${1:-.ssh/authorized_keys}
+ AUTH_KEY_DIR=$(dirname "${AUTH_KEY_FILE}")
# In setting INSTALLKEYS_SH:
# the tr puts it all on one line (to placate tcsh)
@@ -249,7 +250,7 @@ installkeys_sh() {
INSTALLKEYS_SH=$(tr '\t\n' ' ' <<-EOF
cd;
umask 077;
- mkdir -p $(dirname "${AUTH_KEY_FILE}") &&
+ mkdir -p "${AUTH_KEY_DIR}" &&
{ [ -z \`tail -1c ${AUTH_KEY_FILE} 2>/dev/null\` ] || echo >> ${AUTH_KEY_FILE} || exit 1; } &&
cat >> ${AUTH_KEY_FILE} ||
exit 1;
--

21
openssh-nukeacss.sh Executable file
View File

@ -0,0 +1,21 @@
#!/bin/sh
#
# Remove the ACSS implementation from OpenSSH, and disable its use so that the
# rest of the package can still be built.
#
> acss.c
patch -sp0 << EOF
--- cipher.c.orig 2005-07-17 09:02:10.000000000 +0200
+++ cipher.c 2005-09-06 14:52:06.000000000 +0200
@@ -45,6 +45,9 @@
/* compatibility with old or broken OpenSSL versions */
#include "openbsd-compat/openssl-compat.h"
+#undef USE_CIPHER_ACSS
+#undef EVP_acss
+#define EVP_acss NULL
extern const EVP_CIPHER *evp_ssh1_bf(void);
extern const EVP_CIPHER *evp_ssh1_3des(void);
EOF
echo "Well done."

View File

@ -1,21 +0,0 @@
# I do not know about any better place where to put profile files
addFilter(r'openssh-askpass.x86_64: W: non-conffile-in-etc /etc/profile.d/gnome-ssh-askpass.c?sh')
# The ssh-keysign is not supposed to have standard permissions
addFilter(r'openssh.x86_64: E: non-standard-executable-perm /usr/libexec/openssh/ssh-keysign 2555')
addFilter(r'openssh.x86_64: E: setgid-binary /usr/libexec/openssh/ssh-keysign ssh_keys 2555')
addFilter(r'openssh.x86_64: W: non-standard-gid /usr/libexec/openssh/ssh-keysign ssh_keys')
# The -cavs subpackage is internal without documentation
# The -askpass is not intended to be used directly so it is missing documentation
addFilter(r'openssh-(askpass|cavs).x86_64: W: no-documentation')
# sshd config and sysconfig is not supposed to be world readable
addFilter(r'non-readable /etc/(ssh/sshd_config|sysconfig/sshd)')
# The /var/empty/sshd is supposed to have the given permissions
addFilter(r'non-standard-dir-perm /var/empty/sshd 711')
addFilter(r'non-standard-dir-in-var empty')
# Spelling false-positives
addFilter(r'spelling-error (Summary\(en_US\)|.* en_US) (mls|su|sudo|rlogin|rsh|untrusted) ')

File diff suppressed because it is too large Load Diff

View File

@ -1,36 +1,20 @@
authfd.c
authfd.h
atomicio.c
atomicio.h
bufaux.c
bufbn.c
authfd.h
buffer.h
buffer.c
cleanup.c
cipher.h
compat.h
entropy.c
defines.h
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

View File

@ -1,992 +0,0 @@
diff -up openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/get_command_line.c.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/get_command_line.c
--- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/get_command_line.c.psaa-compat 2019-07-08 18:36:13.000000000 +0200
+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/get_command_line.c 2020-09-23 10:52:16.424001475 +0200
@@ -27,6 +27,7 @@
* or implied, of Jamie Beverly.
*/
+#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
@@ -66,8 +67,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;
@@ -106,9 +107,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-pam_ssh_agent_auth-0.10.4/identity.h.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/identity.h
--- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/identity.h.psaa-compat 2019-07-08 18:36:13.000000000 +0200
+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/identity.h 2020-09-23 10:52:16.424001475 +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-pam_ssh_agent_auth-0.10.4/iterate_ssh_agent_keys.c.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/iterate_ssh_agent_keys.c
--- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/iterate_ssh_agent_keys.c.psaa-compat 2020-09-23 10:52:16.421001434 +0200
+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/iterate_ssh_agent_keys.c 2020-09-23 10:52:16.424001475 +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 +120,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;
@@ -144,7 +151,8 @@ pamsshagentauth_session_id2_gen(Buffer *
}
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 +169,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);
+ }
+ /* 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));
}
- /* 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("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 +290,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,9 +300,9 @@ 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;
@@ -299,31 +312,30 @@ pamsshagentauth_find_authorized_keys(con
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-pam_ssh_agent_auth-0.10.4/pam_ssh_agent_auth.c.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_ssh_agent_auth.c
--- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_ssh_agent_auth.c.psaa-compat 2020-09-23 10:52:16.423001461 +0200
+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_ssh_agent_auth.c 2020-09-23 10:53:10.631727657 +0200
@@ -106,7 +106,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--) {
@@ -132,11 +132,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);
@@ -151,12 +151,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);
@@ -165,11 +165,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;
}
@@ -179,8 +179,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");
}
/*
@@ -189,7 +189,7 @@ 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);
/*
* Attempt to read data from the sshd if we're being called as an auth agent.
@@ -197,10 +197,10 @@ pam_sm_authenticate(pam_handle_t * pamh,
const char* ssh_user_auth = pam_getenv(pamh, "SSH_AUTH_INFO_0");
int sshd_service = strncasecmp(servicename, sshd_service_name, sizeof(sshd_service_name) - 1);
if (sshd_service == 0 && ssh_user_auth != NULL) {
- pamsshagentauth_verbose("Got SSH_AUTH_INFO_0: `%.20s...'", ssh_user_auth);
+ verbose("Got SSH_AUTH_INFO_0: `%.20s...'", ssh_user_auth);
if (userauth_pubkey_from_pam(ruser, ssh_user_auth) > 0) {
retval = PAM_SUCCESS;
- pamsshagentauth_logit("Authenticated (sshd): `%s' as `%s' using %s", ruser, user, authorized_keys_file);
+ logit("Authenticated (sshd): `%s' as `%s' using %s", ruser, user, authorized_keys_file);
goto cleanexit;
}
}
@@ -208,13 +208,13 @@ pam_sm_authenticate(pam_handle_t * pamh,
* 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 (agent): `%s' as `%s' using %s", ruser, user, authorized_keys_file);
+ logit("Authenticated (agent): `%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-pam_ssh_agent_auth-0.10.4/pam_user_authorized_keys.c.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_authorized_keys.c
--- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_authorized_keys.c.psaa-compat 2019-07-08 18:36:13.000000000 +0200
+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_authorized_keys.c 2020-09-23 10:52:16.424001475 +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-pam_ssh_agent_auth-0.10.4/pam_user_authorized_keys.h.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_authorized_keys.h
--- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_authorized_keys.h.psaa-compat 2019-07-08 18:36:13.000000000 +0200
+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_authorized_keys.h 2020-09-23 10:52:16.424001475 +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-pam_ssh_agent_auth-0.10.4/pam_user_key_allowed2.c.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_key_allowed2.c
--- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_key_allowed2.c.psaa-compat 2019-07-08 18:36:13.000000000 +0200
+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_key_allowed2.c 2020-09-23 10:52:16.424001475 +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-pam_ssh_agent_auth-0.10.4/pam_user_key_allowed2.h.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_key_allowed2.h
--- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_key_allowed2.h.psaa-compat 2019-07-08 18:36:13.000000000 +0200
+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_key_allowed2.h 2020-09-23 10:52:16.424001475 +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-pam_ssh_agent_auth-0.10.4/secure_filename.c.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/secure_filename.c
--- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/secure_filename.c.psaa-compat 2019-07-08 18:36:13.000000000 +0200
+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/secure_filename.c 2020-09-23 10:52:16.424001475 +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-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.c.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.c
--- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.c.psaa-compat 2019-07-08 18:36:13.000000000 +0200
+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.c 2020-09-23 10:52:16.424001475 +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 +49,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;
- int authenticated = 0;
+ size_t blen = 0, slen = 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, NULL) == 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-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.h.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.h
--- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.h.psaa-compat 2019-07-08 18:36:13.000000000 +0200
+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.h 2020-09-23 10:52:16.424001475 +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-pam_ssh_agent_auth-0.10.4/uuencode.c.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/uuencode.c
--- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/uuencode.c.psaa-compat 2019-07-08 18:36:13.000000000 +0200
+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/uuencode.c 2020-09-23 10:52:16.424001475 +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);
}
--- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_pam.c.compat 2020-09-23 11:32:30.783695267 +0200
+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_pam.c 2020-09-23 11:33:21.383389036 +0200
@@ -33,7 +33,8 @@
#include <string.h>
#include "defines.h"
-#include "key.h"
+#include <includes.h>
+#include "sshkey.h"
#include "log.h"
#include "pam_user_authorized_keys.h"
@@ -42,28 +42,28 @@
int authenticated = 0;
const char method[] = "publickey ";
- char* ai = pamsshagentauth_xstrdup(ssh_auth_info);
+ char* ai = xstrdup(ssh_auth_info);
char* saveptr;
char* auth_line = strtok_r(ai, "\n", &saveptr);
while (auth_line != NULL) {
if (strncmp(auth_line, method, sizeof(method) - 1) == 0) {
char* key_str = auth_line + sizeof(method) - 1;
- Key* key = pamsshagentauth_key_new(KEY_UNSPEC);
+ struct sshkey* key = sshkey_new(KEY_UNSPEC);
if (key == NULL) {
continue;
}
- int r = pamsshagentauth_key_read(key, &key_str);
+ int r = sshkey_read(key, &key_str);
if (r == 1) {
if (pam_user_key_allowed(ruser, key)) {
authenticated = 1;
- pamsshagentauth_key_free(key);
+ sshkey_free(key);
break;
}
} else {
- pamsshagentauth_verbose("Failed to create key for %s: %d", auth_line, r);
+ verbose("Failed to create key for %s: %d", auth_line, r);
}
- pamsshagentauth_key_free(key);
+ sshkey_free(key);
}
auth_line = strtok_r(NULL, "\n", &saveptr);
}

View File

@ -1,20 +0,0 @@
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);

View File

@ -1,37 +0,0 @@
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;
}

View File

@ -0,0 +1,27 @@
diff -up pam_ssh_agent_auth-0.9.2/iterate_ssh_agent_keys.c.seteuid pam_ssh_agent_auth-0.9.2/iterate_ssh_agent_keys.c
--- pam_ssh_agent_auth-0.9.2/iterate_ssh_agent_keys.c.seteuid 2010-09-08 08:54:29.000000000 +0200
+++ pam_ssh_agent_auth-0.9.2/iterate_ssh_agent_keys.c 2010-11-22 08:38:05.000000000 +0100
@@ -131,13 +131,18 @@ 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 */
+ /* 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);
+ error("seteuid(%lu) failed", (unsigned long) uid);
+ return -1;
+ }
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;
+ 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 */

View File

@ -1,7 +1,7 @@
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;
diff -up pam_ssh_agent_auth-0.9.2/pam_ssh_agent_auth.c.visibility pam_ssh_agent_auth-0.9.2/pam_ssh_agent_auth.c
--- pam_ssh_agent_auth-0.9.2/pam_ssh_agent_auth.c.visibility 2009-12-21 20:57:34.000000000 +0100
+++ pam_ssh_agent_auth-0.9.2/pam_ssh_agent_auth.c 2012-06-21 20:01:31.356259429 +0200
@@ -68,7 +68,7 @@ char *__progname;
extern char *__progname;
#endif
@ -10,7 +10,7 @@ diff -up openssh-7.1p2/pam_ssh_agent_auth-0.10.2/pam_ssh_agent_auth.c.psaa-visib
pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char **argv)
{
char **argv_ptr;
@@ -214,7 +214,7 @@ cleanexit:
@@ -184,7 +184,7 @@ pam_sm_authenticate(pam_handle_t * pamh,
}
@ -18,4 +18,4 @@ diff -up openssh-7.1p2/pam_ssh_agent_auth-0.10.2/pam_ssh_agent_auth.c.psaa-visib
+PAM_EXTERN int __attribute__ ((visibility ("default")))
pam_sm_setcred(pam_handle_t * pamh, int flags, int argc, const char **argv)
{
UNUSED(pamh);
return PAM_SUCCESS;

View File

@ -1,96 +0,0 @@
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 */

View File

@ -1,11 +1,12 @@
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"
diff -up pam_ssh_agent_auth-0.9.3/iterate_ssh_agent_keys.c.psaa-build pam_ssh_agent_auth-0.9.3/iterate_ssh_agent_keys.c
--- pam_ssh_agent_auth-0.9.3/iterate_ssh_agent_keys.c.psaa-build 2010-01-13 03:17:01.000000000 +0100
+++ pam_ssh_agent_auth-0.9.3/iterate_ssh_agent_keys.c 2012-06-21 20:14:56.432527764 +0200
@@ -37,7 +37,16 @@
#include "buffer.h"
#include "key.h"
#include "authfd.h"
+#include "ssh.h"
#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
@ -14,11 +15,12 @@ diff -up openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-b
+#include <stdlib.h>
+#include <errno.h>
+#include <fcntl.h>
#include <openssl/evp.h>
#include "userauth_pubkey_from_id.h"
#include "identity.h"
#include "get_command_line.h"
extern char **environ;
@@ -69,6 +78,96 @@ session_id2_gen()
return cookie;
}
+/*
+ * Added by Jamie Beverly, ensure socket fd points to a socket owned by the user
@ -30,31 +32,7 @@ diff -up openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-b
+ * 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
+int
+ssh_get_authentication_socket_for_uid(uid_t uid)
+{
+ const char *authsocket;
@ -134,54 +112,56 @@ diff -up openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-b
+ return auth;
+}
+
+int
pamsshagentauth_find_authorized_keys(const char * user, const char * ruser, const char * servicename)
int
find_authorized_keys(uid_t uid)
{
Buffer session_id2 = { 0 };
@@ -190,7 +289,7 @@ pamsshagentauth_find_authorized_keys(con
@@ -81,7 +180,7 @@ find_authorized_keys(uid_t uid)
OpenSSL_add_all_digests();
pamsshagentauth_session_id2_gen(&session_id2, user, ruser, servicename);
session_id2 = session_id2_gen();
- 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);
verbose("Contacted ssh-agent of user %s (%u)", getpwuid(uid)->pw_name, 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=
@@ -109,3 +208,4 @@ find_authorized_keys(uid_t uid)
EVP_cleanup();
return retval;
}
+
diff -up pam_ssh_agent_auth-0.9.3/Makefile.in.psaa-build pam_ssh_agent_auth-0.9.3/Makefile.in
--- pam_ssh_agent_auth-0.9.3/Makefile.in.psaa-build 2009-10-27 21:19:41.000000000 +0100
+++ pam_ssh_agent_auth-0.9.3/Makefile.in 2012-06-21 20:14:56.432527764 +0200
@@ -28,7 +28,7 @@ PATHS=
CC=@CC@
LD=@LD@
CFLAGS=@CFLAGS@
-CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@
+CPPFLAGS=-I.. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@
+CPPFLAGS=-I.. -I$(srcdir) -I/usr/include/nss3 -I/usr/include/nspr4 @CPPFLAGS@ $(PATHS) @DEFS@
LIBS=@LIBS@
AR=@AR@
AWK=@AWK@
@@ -61,8 +61,8 @@ INSTALL=@INSTALL@
@@ -37,7 +37,7 @@ INSTALL=@INSTALL@
PERL=@PERL@
SED=@SED@
ENT=@ENT@
-LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@
-LDFLAGS_SHARED = @LDFLAGS_SHARED@
+LDFLAGS=-L.. -L../openbsd-compat/ @LDFLAGS@
+LDFLAGS_SHARED =-Wl,-z,defs @LDFLAGS_SHARED@
LDFLAGS_SHARED = @LDFLAGS_SHARED@
EXEEXT=@EXEEXT@
INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@
@@ -74,7 +74,7 @@ SSHOBJS=xmalloc.o atomicio.o authfd.o bu
@@ -48,7 +48,7 @@ PAM_MODULES=pam_ssh_agent_auth.so
ED25519OBJS=ed25519-donna/ed25519.o
SSHOBJS=xmalloc.o atomicio.o authfd.o bufaux.o bufbn.o buffer.o cleanup.o entropy.o fatal.o key.o log.o misc.o secure_filename.o ssh-dss.o ssh-rsa.o uuencode.o compat.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 userauth_pubkey_from_pam.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 userauth_pubkey_from_pam.o secure_filename.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
+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 secure_filename.o
MANPAGES_IN = pam_ssh_agent_auth.pod
@@ -94,13 +94,13 @@ $(PAM_MODULES): Makefile.in config.h
@@ -67,13 +67,13 @@ $(PAM_MODULES): Makefile.in config.h
.c.o:
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
-LIBCOMPAT=openbsd-compat/libopenbsd-compat.a
+LIBCOMPAT=../openbsd-compat/libopenbsd-compat.a
@ -189,10 +169,11 @@ diff -up openssh-7.4p1/pam_ssh_agent_auth-0.10.3/Makefile.in.psaa-build openssh-
(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 ../ssh-sk-client.o
+ $(LD) $(LDFLAGS_SHARED) -o $@ $(PAM_SSH_AGENT_AUTH_OBJS) ../ssh-sk-client.o $(LDFLAGS) -lssh -lopenbsd-compat pam_ssh_agent_auth.o ../uidswap.o $(LIBS) -lpam
-pam_ssh_agent_auth.so: $(LIBCOMPAT) $(SSHOBJS) $(PAM_SSH_AGENT_AUTH_OBJS) pam_ssh_agent_auth.o
- $(LD) $(LDFLAGS_SHARED) -o $@ $(SSHOBJS) $(PAM_SSH_AGENT_AUTH_OBJS) $(LDFLAGS) -lopenbsd-compat $(LIBS) -lpam pam_ssh_agent_auth.o
+pam_ssh_agent_auth.so: $(PAM_SSH_AGENT_AUTH_OBJS) pam_ssh_agent_auth.o
+ $(LD) $(LDFLAGS_SHARED) -o $@ $(PAM_SSH_AGENT_AUTH_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -lpam -lnss3 pam_ssh_agent_auth.o
$(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
pod2man --section=8 --release=v0.8 --name=pam_ssh_agent_auth --official --center "PAM" pam_ssh_agent_auth.pod > pam_ssh_agent_auth.8
diff -up pam_ssh_agent_auth-0.9.3/pam_user_authorized_keys.c.psaa-build pam_ssh_agent_auth-0.9.3/pam_user_authorized_keys.c

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