restore factory state, so we can fix bugs.

old stuff is still in the old revisions

OBS-URL: https://build.opensuse.org/package/show/network/openssh?expand=0&rev=98
This commit is contained in:
Marcus Meissner 2016-04-06 11:34:51 +00:00 committed by Git OBS Bridge
parent c818e705ca
commit 13651d3d21
40 changed files with 9926 additions and 4549 deletions

View File

@ -0,0 +1,34 @@
References: https://lists.mindrot.org/pipermail/openssh-unix-announce/2016-January/000124.html https://bugzilla.suse.com/show_bug.cgi?id=961645 https://bugzilla.suse.com/show_bug.cgi?id=961642
--- readconf.c 30 Jul 2015 00:01:34 -0000 1.239
+++ readconf.c 13 Jan 2016 23:17:23 -0000
@@ -1648,7 +1648,7 @@ initialize_options(Options * options)
options->tun_remote = -1;
options->local_command = NULL;
options->permit_local_command = -1;
- options->use_roaming = -1;
+ options->use_roaming = 0;
options->visual_host_key = -1;
options->ip_qos_interactive = -1;
options->ip_qos_bulk = -1;
@@ -1819,8 +1819,7 @@ fill_default_options(Options * options)
options->tun_remote = SSH_TUNID_ANY;
if (options->permit_local_command == -1)
options->permit_local_command = 0;
- if (options->use_roaming == -1)
- options->use_roaming = 1;
+ options->use_roaming = 0;
if (options->visual_host_key == -1)
options->visual_host_key = 0;
if (options->ip_qos_interactive == -1)
--- ssh.c 30 Jul 2015 00:01:34 -0000 1.420
+++ ssh.c 13 Jan 2016 23:17:23 -0000
@@ -1882,9 +1882,6 @@ ssh_session2(void)
fork_postauth();
}
- if (options.use_roaming)
- request_roaming();
-
return client_loop(tty_flag, tty_flag ?
options.escape_char : SSH_ESCAPECHAR_NONE, id);
}

View File

@ -1,4 +1,4 @@
This is OpenSSH version compiled for SUSE.
This is OpenSSH version 5.6p1.
There are following changes in default settings of ssh client:

View File

@ -0,0 +1,33 @@
# Don't audit SSH_INVALID_USER twice.
# PRIVSEP(getpwnamallow()) a few lines above already did this.
#
# based on:
# https://bugzilla.mindrot.org/show_bug.cgi?id=1402
# https://bugzilla.mindrot.org/attachment.cgi?id=2010
# by jchadima@redhat.com
#
# PRIVSEP(getpwnamallow()) a few lines above already did this.
diff --git a/openssh-6.6p1/auth2.c b/openssh-6.6p1/auth2.c
--- a/openssh-6.6p1/auth2.c
+++ b/openssh-6.6p1/auth2.c
@@ -236,19 +236,16 @@ input_userauth_request(int type, u_int32
authctxt->pw = PRIVSEP(getpwnamallow(user));
authctxt->user = xstrdup(user);
if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
authctxt->valid = 1;
debug2("input_userauth_request: setting up authctxt for %s", user);
} 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)
PRIVSEP(start_pam(authctxt));
#endif
setproctitle("%s%s", authctxt->valid ? user : "unknown",
use_privsep ? " [net]" : "");
authctxt->service = xstrdup(service);

View File

@ -0,0 +1,867 @@
# extended auditing of user actions
# based on:
# https://bugzilla.mindrot.org/show_bug.cgi?id=1402
# https://bugzilla.mindrot.org/attachment.cgi?id=2011
# by jchadima@redhat.com
diff --git a/openssh-6.6p1/audit-bsm.c b/openssh-6.6p1/audit-bsm.c
--- a/openssh-6.6p1/audit-bsm.c
+++ b/openssh-6.6p1/audit-bsm.c
@@ -370,20 +370,33 @@ audit_connection_from(const char *host,
/* this is used on IPv4-only machines */
tid->port = (dev_t)port;
tid->machine = inet_addr(host);
snprintf(buf, sizeof(buf), "%08x", tid->machine);
debug3("BSM audit: machine ID %s", buf);
#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
audit_session_open(struct logininfo *li)
{
/* not implemented */
}
diff --git a/openssh-6.6p1/audit-linux.c b/openssh-6.6p1/audit-linux.c
--- a/openssh-6.6p1/audit-linux.c
+++ b/openssh-6.6p1/audit-linux.c
@@ -30,97 +30,210 @@
#include "includes.h"
#if defined(USE_LINUX_AUDIT)
#include <libaudit.h>
#include <unistd.h>
#include <string.h>
#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;
audit_fd = audit_open();
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;
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;
- 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 */
}
- /* not implemented */
+
+int
+audit_run_command(const char *command)
+{
+ 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_run_command(const char *command)
+audit_end_command(int handle, const char *command)
{
- /* not implemented */
+ 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
audit_event(ssh_audit_event_t event)
{
switch(event) {
case SSH_AUTH_SUCCESS:
- case SSH_CONNECTION_CLOSE:
- 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", 1, event);
break;
+ case SSH_NOLOGIN:
+ 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:
debug("%s: unhandled event %d", __func__, event);
}
}
#endif /* USE_LINUX_AUDIT */
diff --git a/openssh-6.6p1/audit.c b/openssh-6.6p1/audit.c
--- a/openssh-6.6p1/audit.c
+++ b/openssh-6.6p1/audit.c
@@ -135,16 +135,27 @@ audit_connection_from(const char *host,
void
audit_event(ssh_audit_event_t event)
{
debug("audit event euid %d user %s event %d (%s)", geteuid(),
audit_username(), event, audit_event_lookup(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.
*
* Note that this may be called multiple times if multiple sessions are used
* within a single connection.
*/
void
audit_session_open(struct logininfo *li)
@@ -169,18 +180,34 @@ audit_session_close(struct logininfo *li
debug("audit session close euid %d user %s tty name %s", geteuid(),
audit_username(), t);
}
/*
* 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 --git a/openssh-6.6p1/audit.h b/openssh-6.6p1/audit.h
--- a/openssh-6.6p1/audit.h
+++ b/openssh-6.6p1/audit.h
@@ -44,14 +44,16 @@ enum ssh_audit_event_type {
SSH_CONNECTION_CLOSE, /* closed after attempting auth or session */
SSH_CONNECTION_ABANDON, /* closed without completing auth */
SSH_AUDIT_UNKNOWN
};
typedef enum ssh_audit_event_type ssh_audit_event_t;
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 --git a/openssh-6.6p1/monitor.c b/openssh-6.6p1/monitor.c
--- a/openssh-6.6p1/monitor.c
+++ b/openssh-6.6p1/monitor.c
@@ -175,16 +175,17 @@ int mm_answer_gss_setup_ctx(int, Buffer
int mm_answer_gss_accept_ctx(int, Buffer *);
int mm_answer_gss_userok(int, Buffer *);
int mm_answer_gss_checkmic(int, Buffer *);
#endif
#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 *);
static Authctxt *authctxt;
static BIGNUM *ssh1_challenge = NULL; /* used for ssh1 rsa auth */
/* local state for key verify */
@@ -255,16 +256,17 @@ struct mon_table mon_dispatch_postauth20
{MONITOR_REQ_MODULI, 0, mm_answer_moduli},
{MONITOR_REQ_SIGN, 0, mm_answer_sign},
{MONITOR_REQ_PTY, 0, mm_answer_pty},
{MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup},
{MONITOR_REQ_TERM, 0, mm_answer_term},
#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}
};
struct mon_table mon_dispatch_proto15[] = {
{MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
{MONITOR_REQ_SESSKEY, MON_ONCE, mm_answer_sesskey},
{MONITOR_REQ_SESSID, MON_ONCE, mm_answer_sessid},
@@ -297,16 +299,17 @@ struct mon_table mon_dispatch_proto15[]
struct mon_table mon_dispatch_postauth15[] = {
{MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty},
{MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup},
{MONITOR_REQ_TERM, 0, mm_answer_term},
#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}
};
struct mon_table *mon_dispatch;
/* Specifies if a certain message is allowed at the moment */
@@ -1420,16 +1423,22 @@ mm_record_login(Session *s, struct passw
static void
mm_session_close(Session *s)
{
debug3("%s: session %d pid %ld", __func__, s->self, (long)s->pid);
if (s->ttyfd != -1) {
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);
}
int
mm_answer_pty(int sock, Buffer *m)
{
extern struct monitor *pmonitor;
Session *s;
@@ -1742,21 +1751,53 @@ mm_answer_audit_event(int socket, Buffer
return (0);
}
int
mm_answer_audit_command(int socket, Buffer *m)
{
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);
+
free(cmd);
return (0);
}
#endif /* SSH_AUDIT_EVENTS */
void
monitor_apply_keystate(struct monitor *pmonitor)
{
diff --git a/openssh-6.6p1/monitor.h b/openssh-6.6p1/monitor.h
--- a/openssh-6.6p1/monitor.h
+++ b/openssh-6.6p1/monitor.h
@@ -59,16 +59,17 @@ enum monitor_reqtype {
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,
MONITOR_REQ_PAM_QUERY = 106, MONITOR_ANS_PAM_QUERY = 107,
MONITOR_REQ_PAM_RESPOND = 108, MONITOR_ANS_PAM_RESPOND = 109,
MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111,
MONITOR_REQ_AUDIT_EVENT = 112, MONITOR_REQ_AUDIT_COMMAND = 113,
+ MONITOR_ANS_AUDIT_COMMAND = 114, MONITOR_REQ_AUDIT_END_COMMAND = 115,
};
struct mm_master;
struct monitor {
int m_recvfd;
int m_sendfd;
int m_log_recvfd;
diff --git a/openssh-6.6p1/monitor_wrap.c b/openssh-6.6p1/monitor_wrap.c
--- a/openssh-6.6p1/monitor_wrap.c
+++ b/openssh-6.6p1/monitor_wrap.c
@@ -1184,27 +1184,48 @@ mm_audit_event(ssh_audit_event_t event)
buffer_init(&m);
buffer_put_int(&m, event);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_EVENT, &m);
buffer_free(&m);
}
-void
+int
mm_audit_run_command(const char *command)
{
Buffer m;
+ int handle;
debug3("%s entering command %s", __func__, command);
buffer_init(&m);
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 */
#ifdef GSSAPI
OM_uint32
mm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID goid)
{
diff --git a/openssh-6.6p1/monitor_wrap.h b/openssh-6.6p1/monitor_wrap.h
--- a/openssh-6.6p1/monitor_wrap.h
+++ b/openssh-6.6p1/monitor_wrap.h
@@ -69,17 +69,18 @@ void *mm_sshpam_init_ctx(struct Authctxt
int mm_sshpam_query(void *, char **, char **, u_int *, char ***, u_int **);
int mm_sshpam_respond(void *, u_int, char **);
void mm_sshpam_free_ctx(void *);
#endif
#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;
void mm_terminate(void);
int mm_pty_allocate(int *, int *, char *, size_t);
void mm_session_pty_cleanup2(struct Session *);
/* SSHv1 interfaces */
diff --git a/openssh-6.6p1/session.c b/openssh-6.6p1/session.c
--- a/openssh-6.6p1/session.c
+++ b/openssh-6.6p1/session.c
@@ -740,16 +740,24 @@ do_exec_pty(Session *s, const char *comm
cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
#endif
s->pid = pid;
/* 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,
options.ip_qos_interactive, options.ip_qos_bulk);
if (compat20) {
session_set_fds(s, ptyfd, fdout, -1, 1, 1);
} else {
server_loop(pid, ptyfd, fdout, -1);
@@ -834,25 +842,29 @@ do_exec(Session *s, const char *command)
session_type,
tty == NULL ? "" : " on ",
tty == NULL ? "" : tty,
s->pw->pw_name,
get_remote_ipaddr(),
get_remote_port());
#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);
else
ret = do_exec_no_pty(s, command);
original_command = NULL;
@@ -1908,16 +1920,17 @@ session_unused(int id)
memset(&sessions[id], 0, sizeof(*sessions));
sessions[id].self = id;
sessions[id].used = 0;
sessions[id].chanid = -1;
sessions[id].ptyfd = -1;
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;
}
Session *
session_new(void)
{
Session *s, *tmp;
@@ -1990,16 +2003,29 @@ session_open(Authctxt *authctxt, int cha
if (s->pw == NULL || !authctxt->valid)
fatal("no user for session %d", s->self);
debug("session_open: session %d: link with channel %d", s->self, chanid);
s->chanid = chanid;
return 1;
}
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;
for (i = 0; i < sessions_nalloc; i++) {
Session *s = &sessions[i];
if (s->used && s->ttyfd != -1 && strcmp(s->tty, tty) == 0) {
debug("session_by_tty: session %d tty %s", i, tty);
return s;
@@ -2506,16 +2532,40 @@ session_exit_message(Session *s, int sta
* interested in data we write.
* Note that we must not call 'chan_read_failed', since there could
* be some more data waiting in the pipe.
*/
if (c->ostate != CHAN_OUTPUT_CLOSED)
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);
+ free(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));
+ free(s->command);
+ s->command = NULL;
+ s->command_handle = -1;
+ }
+}
+#endif
+
void
session_close(Session *s)
{
u_int i;
int do_xauth;
debug("session_close: session %d pid %ld", s->self, (long)s->pid);
@@ -2546,16 +2596,20 @@ session_close(Session *s)
int status;
waitpid(pid, &status, 0);
}
}
if (s->ttyfd != -1)
session_pty_cleanup(s);
+#ifdef SSH_AUDIT_EVENTS
+ if (s->command)
+ session_end_command(s);
+#endif
free(s->term);
free(s->display);
free(s->x11_chanids);
free(s->auth_display);
free(s->auth_data);
free(s->auth_proto);
free(s->subsys);
if (s->env != NULL) {
@@ -2760,16 +2814,25 @@ session_setup_x11fwd(Session *s)
}
static void
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)
{
static int called = 0;
debug("do_cleanup");
/* no cleanup if we're in the child for login shell */
@@ -2808,10 +2871,10 @@ do_cleanup(Authctxt *authctxt)
/* remove agent socket */
auth_sock_cleanup_proc(authctxt->pw);
/*
* Cleanup ptys/utmp only if privsep is disabled,
* 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 --git a/openssh-6.6p1/session.h b/openssh-6.6p1/session.h
--- a/openssh-6.6p1/session.h
+++ b/openssh-6.6p1/session.h
@@ -56,29 +56,37 @@ struct Session {
int *x11_chanids;
int is_subsystem;
char *subsys;
u_int num_env;
struct {
char *name;
char *val;
} *env;
+
+ /* exec */
+#ifdef SSH_AUDIT_EVENTS
+ int command_handle;
+ char *command;
+#endif
};
void do_authenticated(Authctxt *);
void do_cleanup(Authctxt *);
int session_open(Authctxt *, int);
void session_unused(int);
int session_input_channel_req(Channel *, const char *);
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 *);
void child_set_env(char ***envp, u_int *envsizep, const char *name,
const char *value);
#endif
diff --git a/openssh-6.6p1/sshd.c b/openssh-6.6p1/sshd.c
--- a/openssh-6.6p1/sshd.c
+++ b/openssh-6.6p1/sshd.c
@@ -2532,13 +2532,14 @@ cleanup_exit(int i)
if (kill(pmonitor->m_pid, SIGKILL) != 0 &&
errno != ESRCH)
error("%s: kill(%d): %s", __func__,
pmonitor->m_pid, strerror(errno));
}
}
#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);
}

View File

@ -0,0 +1,61 @@
# HG changeset patch
# Parent 5482d21e8bd06309af51dea77a5f3668859fb2a0
diff --git a/openssh-6.6p1/auth-rsa.c b/openssh-6.6p1/auth-rsa.c
--- a/openssh-6.6p1/auth-rsa.c
+++ b/openssh-6.6p1/auth-rsa.c
@@ -94,16 +94,20 @@ int
auth_rsa_verify_response(Key *key, BIGNUM *challenge,
u_char response[SSH_DIGEST_MAX_LENGTH])
{
u_char buf[2 * SSH_DIGEST_MAX_LENGTH], mdbuf[SSH_DIGEST_MAX_LENGTH];
struct ssh_digest_ctx *md;
int len;
int dgst;
size_t dgst_len;
+ int 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) {
error("%s: RSA modulus too small: %d < minimum %d bits",
__func__,
BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE);
return (0);
}
@@ -121,22 +125,28 @@ auth_rsa_verify_response(Key *key, BIGNU
if ((md = ssh_digest_start(dgst)) == NULL ||
ssh_digest_update(md, buf, 2 * dgst_len) < 0 ||
ssh_digest_update(md, session_id, dgst_len) < 0 ||
ssh_digest_final(md, mdbuf, sizeof(mdbuf)) < 0)
fatal("%s: md5 failed", __func__);
ssh_digest_free(md);
/* Verify that the response is the original challenge. */
- if (timingsafe_bcmp(response, mdbuf, dgst_len) != 0) {
- /* Wrong answer. */
- return (0);
+ rv = timingsafe_bcmp(response, mdbuf, dgst_len) == 0;
+
+#ifdef SSH_AUDIT_EVENTS
+ fp = key_fingerprint(key, key_fp_type_select(), 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);
+ free(fp);
+#endif
+
+ return rv;
}
/*
* Performs the RSA authentication challenge-response dialog with the client,
* and returns true (non-zero) if the client gave the correct answer to
* our challenge; returns zero if the client gives a wrong answer.
*/

View File

@ -0,0 +1,506 @@
# auditing key-based authentication (both server and client)
# based on:
# https://bugzilla.mindrot.org/show_bug.cgi?id=1402
# https://bugzilla.mindrot.org/attachment.cgi?id=2012
# (replaces: https://bugzilla.mindrot.org/attachment.cgi?id=1975)
# by jchadima@redhat.com
diff --git a/openssh-6.6p1/audit-bsm.c b/openssh-6.6p1/audit-bsm.c
--- a/openssh-6.6p1/audit-bsm.c
+++ b/openssh-6.6p1/audit-bsm.c
@@ -401,16 +401,22 @@ audit_session_open(struct logininfo *li)
}
void
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)
{
char textbuf[BSM_TEXTBUFSZ];
static int logged_in = 0;
const char *user = the_authctxt ? the_authctxt->user : "(unknown user)";
if (cannot_audit(0))
diff --git a/openssh-6.6p1/audit-linux.c b/openssh-6.6p1/audit-linux.c
--- a/openssh-6.6p1/audit-linux.c
+++ b/openssh-6.6p1/audit-linux.c
@@ -36,16 +36,18 @@
#include "log.h"
#include "audit.h"
#include "key.h"
#include "hostfile.h"
#include "auth.h"
#include "servconf.h"
#include "canohost.h"
+#define AUDIT_LOG_SIZE 128
+
extern ServerOptions options;
extern Authctxt *the_authctxt;
extern u_int utmp_len;
const char* audit_username(void);
static void
linux_audit_user_logxxx(int uid, const char *username,
const char *hostname, const char *ip, const char *ttyn, int success, int event)
@@ -125,16 +127,47 @@ linux_audit_user_auth(int uid, const cha
rc = 0;
errno = saved_errno;
if (rc < 0) {
fatal_report:
fatal("linux_audit_write_entry failed: %s", strerror(errno));
}
}
+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 rport=%d",
+ type, bits, 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 */
void
audit_connection_from(const char *host, int port)
{
/* not implemented */
diff --git a/openssh-6.6p1/audit.c b/openssh-6.6p1/audit.c
--- a/openssh-6.6p1/audit.c
+++ b/openssh-6.6p1/audit.c
@@ -31,16 +31,17 @@
#ifdef SSH_AUDIT_EVENTS
#include "audit.h"
#include "log.h"
#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
* audit_connection_from() is called and MAY NOT be initialized when
* audit_event(CONNECTION_ABANDON) is called. Test for NULL before using.
*/
extern Authctxt *the_authctxt;
@@ -106,16 +107,32 @@ audit_event_lookup(ssh_audit_event_t ev)
};
for (i = 0; event_lookup[i].event != SSH_AUDIT_UNKNOWN; i++)
if (event_lookup[i].event == ev)
break;
return(event_lookup[i].name);
}
+void
+audit_key(int host_user, int *rv, const Key *key)
+{
+ char *fp;
+ const char *crypto_name;
+
+ fp = key_fingerprint(key, key_fp_type_select(), 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;
+ free(fp);
+}
+
# ifndef CUSTOM_SSH_AUDIT_EVENTS
/*
* Null implementations of audit functions.
* These get used if SSH_AUDIT_EVENTS is defined but no audit module is enabled.
*/
/*
* Called after a connection has been accepted but before any authentication
@@ -204,10 +221,22 @@ audit_run_command(const char *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);
}
+/*
+ * 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, result %d",
+ host_user ? "pubkey" : "hostbased", geteuid(), audit_username(), type, bits,
+ fp, rv);
+}
# endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */
#endif /* SSH_AUDIT_EVENTS */
diff --git a/openssh-6.6p1/audit.h b/openssh-6.6p1/audit.h
--- a/openssh-6.6p1/audit.h
+++ b/openssh-6.6p1/audit.h
@@ -23,16 +23,17 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SSH_AUDIT_H
# define _SSH_AUDIT_H
#include "loginrec.h"
+#include "key.h"
enum ssh_audit_event_type {
SSH_LOGIN_EXCEED_MAXTRIES,
SSH_LOGIN_ROOT_DENIED,
SSH_AUTH_SUCCESS,
SSH_AUTH_FAIL_NONE,
SSH_AUTH_FAIL_PASSWD,
SSH_AUTH_FAIL_KBDINT, /* keyboard-interactive or challenge-response */
@@ -50,10 +51,12 @@ 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 *);
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 --git a/openssh-6.6p1/auth.h b/openssh-6.6p1/auth.h
--- a/openssh-6.6p1/auth.h
+++ b/openssh-6.6p1/auth.h
@@ -178,16 +178,17 @@ int allowed_user(struct passwd *);
struct passwd * getpwnamallow(const char *user);
char *get_challenge(Authctxt *);
int verify_response(Authctxt *, const char *);
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);
int auth_key_is_revoked(Key *);
HostStatus
check_key_in_hostfiles(struct passwd *, Key *, const char *,
const char *, const char *);
@@ -195,16 +196,17 @@ check_key_in_hostfiles(struct passwd *,
/* hostkey handling */
Key *get_hostkey_by_index(int);
Key *get_hostkey_public_by_index(int);
Key *get_hostkey_public_by_type(int);
Key *get_hostkey_private_by_type(int);
int get_hostkey_index(Key *);
int ssh1_session_key(BIGNUM *);
void sshd_hostkey_sign(Key *, Key *, u_char **, u_int *, u_char *, u_int);
+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)));
void auth_debug_send(void);
void auth_debug_reset(void);
struct passwd *fakepw(void);
diff --git a/openssh-6.6p1/auth2-hostbased.c b/openssh-6.6p1/auth2-hostbased.c
--- a/openssh-6.6p1/auth2-hostbased.c
+++ b/openssh-6.6p1/auth2-hostbased.c
@@ -124,33 +124,45 @@ userauth_hostbased(Authctxt *authctxt)
#endif
pubkey_auth_info(authctxt, key,
"client user \"%.100s\", client host \"%.100s\"", cuser, chost);
/* 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;
buffer_free(&b);
done:
debug2("userauth_hostbased: authenticated %d", authenticated);
if (key != NULL)
key_free(key);
free(pkalg);
free(pkblob);
free(cuser);
free(chost);
free(sig);
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,
Key *key)
{
const char *resolvedname, *ipaddr, *lookup, *reason;
HostStatus host_status;
int len;
diff --git a/openssh-6.6p1/auth2-pubkey.c b/openssh-6.6p1/auth2-pubkey.c
--- a/openssh-6.6p1/auth2-pubkey.c
+++ b/openssh-6.6p1/auth2-pubkey.c
@@ -153,17 +153,17 @@ userauth_pubkey(Authctxt *authctxt)
#ifdef DEBUG_PK
buffer_dump(&b);
#endif
pubkey_auth_info(authctxt, key, NULL);
/* 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);
free(sig);
} else {
debug("test whether pkalg/pkblob are acceptable");
packet_check_eom();
@@ -190,16 +190,28 @@ done:
debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg);
if (key != NULL)
key_free(key);
free(pkalg);
free(pkblob);
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;
+}
+
void
pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...)
{
char *fp, *extra;
va_list ap;
int i;
extra = NULL;
diff --git a/openssh-6.6p1/monitor.c b/openssh-6.6p1/monitor.c
--- a/openssh-6.6p1/monitor.c
+++ b/openssh-6.6p1/monitor.c
@@ -1340,26 +1340,30 @@ monitor_valid_hostbasedblob(u_char *data
}
int
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);
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)
fatal("%s: bad public key blob", __func__);
switch (key_blobtype) {
case MM_USERKEY:
valid_data = monitor_valid_userblob(data, datalen);
@@ -1370,17 +1374,27 @@ mm_answer_keyverify(int sock, Buffer *m)
break;
default:
valid_data = 0;
break;
}
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");
key_free(key);
free(blob);
free(signature);
free(data);
diff --git a/openssh-6.6p1/monitor_wrap.c b/openssh-6.6p1/monitor_wrap.c
--- a/openssh-6.6p1/monitor_wrap.c
+++ b/openssh-6.6p1/monitor_wrap.c
@@ -426,30 +426,31 @@ mm_key_allowed(enum mm_keytype type, cha
/*
* This key verify needs to send the key type along, because the
* privileged parent makes the decision if the key is allowed
* for authentication.
*/
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;
u_int len;
int verified = 0;
debug3("%s entering", __func__);
/* Convert the key to a blob and the pass it over */
if (!key_to_blob(key, &blob, &len))
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);
free(blob);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, &m);
debug3("%s: waiting for MONITOR_ANS_KEYVERIFY", __func__);
@@ -457,16 +458,29 @@ mm_key_verify(Key *key, u_char *sig, u_i
verified = buffer_get_int(&m);
buffer_free(&m);
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)
{
Buffer b;
u_int len;
Newkeys *newkey = NULL;
Enc *enc;
diff --git a/openssh-6.6p1/monitor_wrap.h b/openssh-6.6p1/monitor_wrap.h
--- a/openssh-6.6p1/monitor_wrap.h
+++ b/openssh-6.6p1/monitor_wrap.h
@@ -44,17 +44,18 @@ int mm_key_sign(Key *, u_char **, u_int
void mm_inform_authserv(char *, char *);
struct passwd *mm_getpwnamallow(const char *);
char *mm_auth2_read_banner(void);
int mm_auth_password(struct Authctxt *, char *);
int mm_key_allowed(enum mm_keytype, char *, char *, Key *);
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 *);
#ifdef GSSAPI
OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *,
gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *);

View File

@ -0,0 +1,82 @@
# HG changeset patch
# Parent 274a545b591567f1378c1086ad3ba40c911a8bd6
diff --git a/openssh-6.6p1/Makefile.in b/openssh-6.6p1/Makefile.in
--- a/openssh-6.6p1/Makefile.in
+++ b/openssh-6.6p1/Makefile.in
@@ -72,17 +72,18 @@ LIBSSH_OBJS=authfd.o authfile.o bufaux.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 \
msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \
ssh-pkcs11.o krl.o smult_curve25519_ref.o \
kexc25519.o kexc25519c.o poly1305.o chacha.o cipher-chachapoly.o \
ssh-ed25519.o digest-openssl.o hmac.o \
sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o blocks.o \
- fips.o
+ fips.o \
+ auditstub.o
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
sshconnect.o sshconnect1.o sshconnect2.o mux.o \
roaming_common.o roaming_client.o
SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \
audit.o audit-bsm.o audit-linux.o platform.o \
sshpty.o sshlogin.o servconf.o serverloop.o \
diff --git a/openssh-6.6p1/cipher.c b/openssh-6.6p1/cipher.c
--- a/openssh-6.6p1/cipher.c
+++ b/openssh-6.6p1/cipher.c
@@ -54,30 +54,16 @@
/* compatibility with old or broken OpenSSL versions */
#include "openbsd-compat/openssl-compat.h"
extern const EVP_CIPHER *evp_ssh1_bf(void);
extern const EVP_CIPHER *evp_ssh1_3des(void);
extern void ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int);
-struct Cipher {
- char *name;
- int number; /* for ssh1 only */
- u_int block_size;
- u_int key_len;
- u_int iv_len; /* defaults to block_size */
- u_int auth_len;
- u_int discard_len;
- u_int flags;
-#define CFLAG_CBC (1<<0)
-#define CFLAG_CHACHAPOLY (1<<1)
- const EVP_CIPHER *(*evptype)(void);
-};
-
static const struct Cipher ciphers_all[] = {
{ "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null },
{ "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc },
{ "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des },
{ "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, 0, 0, 1, evp_ssh1_bf },
{ "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 0, 0, 1, EVP_des_ede3_cbc },
{ "blowfish-cbc",
diff --git a/openssh-6.6p1/sshd.c b/openssh-6.6p1/sshd.c
--- a/openssh-6.6p1/sshd.c
+++ b/openssh-6.6p1/sshd.c
@@ -119,16 +119,18 @@
#endif
#include "monitor_wrap.h"
#include "roaming.h"
#include "ssh-sandbox.h"
#include "version.h"
#include "fips.h"
+#include "audit.h"
+
#ifdef LIBWRAP
#include <tcpd.h>
#include <syslog.h>
int allow_severity;
int deny_severity;
#endif /* LIBWRAP */
#ifndef O_NOCTTY

View File

@ -0,0 +1,701 @@
# key exhange auditing
# based on:
# https://bugzilla.mindrot.org/show_bug.cgi?id=1402
# https://bugzilla.mindrot.org/attachment.cgi?id=2013
# (replaces: https://bugzilla.mindrot.org/attachment.cgi?id=1976)
# by jchadima@redhat.com
diff --git a/openssh-6.6p1/audit-bsm.c b/openssh-6.6p1/audit-bsm.c
--- a/openssh-6.6p1/audit-bsm.c
+++ b/openssh-6.6p1/audit-bsm.c
@@ -468,9 +468,21 @@ audit_event(ssh_audit_event_t event)
case SSH_AUTH_FAIL_KBDINT:
bsm_audit_bad_login("interactive password entry");
break;
default:
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 --git a/openssh-6.6p1/audit-linux.c b/openssh-6.6p1/audit-linux.c
--- a/openssh-6.6p1/audit-linux.c
+++ b/openssh-6.6p1/audit-linux.c
@@ -35,16 +35,18 @@
#include "log.h"
#include "audit.h"
#include "key.h"
#include "hostfile.h"
#include "auth.h"
#include "servconf.h"
#include "canohost.h"
+#include "packet.h"
+#include "cipher.h"
#define AUDIT_LOG_SIZE 128
extern ServerOptions options;
extern Authctxt *the_authctxt;
extern u_int utmp_len;
const char* audit_username(void);
@@ -264,9 +266,65 @@ audit_event(ssh_audit_event_t event)
get_remote_ipaddr(), "ssh", 0, AUDIT_USER_LOGIN);
break;
default:
debug("%s: unhandled event %d", __func__, 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());
+ free(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());
+ free(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 --git a/openssh-6.6p1/audit.c b/openssh-6.6p1/audit.c
--- a/openssh-6.6p1/audit.c
+++ b/openssh-6.6p1/audit.c
@@ -23,24 +23,27 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <stdarg.h>
#include <string.h>
+#include <unistd.h>
#ifdef SSH_AUDIT_EVENTS
#include "audit.h"
#include "log.h"
#include "key.h"
#include "hostfile.h"
#include "auth.h"
+#include "ssh-gss.h"
+#include "monitor_wrap.h"
#include "xmalloc.h"
/*
* Care must be taken when using this since it WILL NOT be initialized when
* audit_connection_from() is called and MAY NOT be initialized when
* audit_event(CONNECTION_ABANDON) is called. Test for NULL before using.
*/
extern Authctxt *the_authctxt;
@@ -123,16 +126,28 @@ audit_key(int host_user, int *rv, const
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;
free(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.
* These get used if SSH_AUDIT_EVENTS is defined but no audit module is enabled.
*/
/*
* Called after a connection has been accepted but before any authentication
@@ -233,10 +248,31 @@ audit_end_command(int handle, const char
*/
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, result %d",
host_user ? "pubkey" : "hostbased", geteuid(), audit_username(), type, bits,
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 --git a/openssh-6.6p1/audit.h b/openssh-6.6p1/audit.h
--- a/openssh-6.6p1/audit.h
+++ b/openssh-6.6p1/audit.h
@@ -53,10 +53,14 @@ 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 *);
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 *);
+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 --git a/openssh-6.6p1/auditstub.c b/openssh-6.6p1/auditstub.c
new file mode 100644
--- /dev/null
+++ b/openssh-6.6p1/auditstub.c
@@ -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 --git a/openssh-6.6p1/cipher.h b/openssh-6.6p1/cipher.h
--- a/openssh-6.6p1/cipher.h
+++ b/openssh-6.6p1/cipher.h
@@ -58,17 +58,30 @@
#define SSH_CIPHER_MAX 31
#define CIPHER_ENCRYPT 1
#define CIPHER_DECRYPT 0
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 iv_len; /* defaults to block_size */
+ u_int auth_len;
+ u_int discard_len;
+ u_int flags;
+#define CFLAG_CBC (1<<0)
+#define CFLAG_CHACHAPOLY (1<<1)
+ const EVP_CIPHER *(*evptype)(void);
+};
+
struct CipherContext {
int plaintext;
int encrypt;
EVP_CIPHER_CTX evp;
struct chachapoly_ctx cp_ctx; /* XXX union with evp? */
const Cipher *cipher;
};
diff --git a/openssh-6.6p1/kex.c b/openssh-6.6p1/kex.c
--- a/openssh-6.6p1/kex.c
+++ b/openssh-6.6p1/kex.c
@@ -45,16 +45,17 @@
#include "kex.h"
#include "log.h"
#include "mac.h"
#include "match.h"
#include "dispatch.h"
#include "monitor.h"
#include "roaming.h"
#include "digest.h"
+#include "audit.h"
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
# if defined(HAVE_EVP_SHA256)
# define evp_ssh_sha256 EVP_sha256
# else
extern const EVP_MD *evp_ssh_sha256(void);
# endif
#endif
@@ -346,53 +347,65 @@ kex_kexinit_finish(Kex *kex)
fatal("Unsupported key exchange %d", kex->kex_type);
}
}
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;
enc->enabled = 0;
enc->iv = NULL;
enc->iv_len = cipher_ivlen(enc->cipher);
enc->key = NULL;
enc->key_len = cipher_keylen(enc->cipher);
enc->block_size = cipher_blocksize(enc->cipher);
}
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 */
if (datafellows & SSH_BUG_HMAC)
mac->key_len = 16;
mac->name = name;
mac->key = NULL;
mac->enabled = 0;
}
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) {
comp->type = COMP_ZLIB;
} else if (strcmp(name, "none") == 0) {
comp->type = COMP_NONE;
} else {
fatal("unsupported comp %s", name);
@@ -497,16 +510,19 @@ kex_choose_conf(Kex *kex)
if (authlen == 0)
choose_mac(&newkeys->mac, cprop[nmac], sprop[nmac]);
choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp]);
debug("kex: %s %s %s %s",
ctos ? "client->server" : "server->client",
newkeys->enc.name,
authlen == 0 ? newkeys->mac.name : "<implicit>",
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],
sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]);
need = dh_need = 0;
for (mode = 0; mode < MODE_MAX; mode++) {
newkeys = kex->newkeys[mode];
need = MAX(need, newkeys->enc.key_len);
diff --git a/openssh-6.6p1/monitor.c b/openssh-6.6p1/monitor.c
--- a/openssh-6.6p1/monitor.c
+++ b/openssh-6.6p1/monitor.c
@@ -92,16 +92,17 @@
#endif
#include "monitor_wrap.h"
#include "monitor_fdpass.h"
#include "misc.h"
#include "compat.h"
#include "ssh2.h"
#include "roaming.h"
#include "authfd.h"
+#include "audit.h"
#ifdef GSSAPI
static Gssctxt *gsscontext = NULL;
#endif
/* Imports */
extern ServerOptions options;
extern u_int utmp_len;
@@ -176,16 +177,18 @@ int mm_answer_gss_accept_ctx(int, Buffer
int mm_answer_gss_userok(int, Buffer *);
int mm_answer_gss_checkmic(int, Buffer *);
#endif
#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 *);
+int mm_answer_audit_unsupported_body(int, Buffer *);
+int mm_answer_audit_kex_body(int, Buffer *);
#endif
static int monitor_read_log(struct monitor *);
static Authctxt *authctxt;
static BIGNUM *ssh1_challenge = NULL; /* used for ssh1 rsa auth */
/* local state for key verify */
@@ -227,16 +230,18 @@ struct mon_table mon_dispatch_proto20[]
{MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account},
{MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx},
{MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query},
{MONITOR_REQ_PAM_RESPOND, MON_ISAUTH, mm_answer_pam_respond},
{MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx},
#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},
{MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH, mm_answer_bsdauthrespond},
#endif
#ifdef SKEY
{MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
{MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},
@@ -257,16 +262,18 @@ struct mon_table mon_dispatch_postauth20
{MONITOR_REQ_SIGN, 0, mm_answer_sign},
{MONITOR_REQ_PTY, 0, mm_answer_pty},
{MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup},
{MONITOR_REQ_TERM, 0, mm_answer_term},
#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},
+ {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}
};
struct mon_table mon_dispatch_proto15[] = {
{MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
{MONITOR_REQ_SESSKEY, MON_ONCE, mm_answer_sesskey},
{MONITOR_REQ_SESSID, MON_ONCE, mm_answer_sessid},
@@ -288,28 +295,32 @@ struct mon_table mon_dispatch_proto15[]
{MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account},
{MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx},
{MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query},
{MONITOR_REQ_PAM_RESPOND, MON_ISAUTH, mm_answer_pam_respond},
{MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx},
#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}
};
struct mon_table mon_dispatch_postauth15[] = {
{MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty},
{MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup},
{MONITOR_REQ_TERM, 0, mm_answer_term},
#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},
+ {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}
};
struct mon_table *mon_dispatch;
/* Specifies if a certain message is allowed at the moment */
@@ -2187,8 +2198,52 @@ mm_answer_gss_userok(int sock, Buffer *m
auth_method = "gssapi-with-mic";
/* Monitor loop will terminate if authenticated */
return (authenticated);
}
#endif /* GSSAPI */
+#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);
+
+ free(cipher);
+ free(mac);
+ free(compress);
+ buffer_clear(m);
+
+ mm_request_send(sock, MONITOR_ANS_AUDIT_KEX, m);
+ return 0;
+}
+
+#endif /* SSH_AUDIT_EVENTS */
+
diff --git a/openssh-6.6p1/monitor.h b/openssh-6.6p1/monitor.h
--- a/openssh-6.6p1/monitor.h
+++ b/openssh-6.6p1/monitor.h
@@ -60,16 +60,18 @@ enum monitor_reqtype {
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,
MONITOR_REQ_PAM_QUERY = 106, MONITOR_ANS_PAM_QUERY = 107,
MONITOR_REQ_PAM_RESPOND = 108, MONITOR_ANS_PAM_RESPOND = 109,
MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111,
MONITOR_REQ_AUDIT_EVENT = 112, MONITOR_REQ_AUDIT_COMMAND = 113,
MONITOR_ANS_AUDIT_COMMAND = 114, MONITOR_REQ_AUDIT_END_COMMAND = 115,
+ MONITOR_REQ_AUDIT_UNSUPPORTED = 116, MONITOR_ANS_AUDIT_UNSUPPORTED = 117,
+ MONITOR_REQ_AUDIT_KEX = 118, MONITOR_ANS_AUDIT_KEX = 119,
};
struct mm_master;
struct monitor {
int m_recvfd;
int m_sendfd;
int m_log_recvfd;
diff --git a/openssh-6.6p1/monitor_wrap.c b/openssh-6.6p1/monitor_wrap.c
--- a/openssh-6.6p1/monitor_wrap.c
+++ b/openssh-6.6p1/monitor_wrap.c
@@ -1320,8 +1320,46 @@ mm_ssh_gssapi_userok(char *user)
authenticated = buffer_get_int(&m);
buffer_free(&m);
debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
return (authenticated);
}
#endif /* GSSAPI */
+#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 ? cipher : "");
+ buffer_put_cstring(&m, mac ? mac : "");
+ buffer_put_cstring(&m, compress ? 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 --git a/openssh-6.6p1/monitor_wrap.h b/openssh-6.6p1/monitor_wrap.h
--- a/openssh-6.6p1/monitor_wrap.h
+++ b/openssh-6.6p1/monitor_wrap.h
@@ -72,16 +72,18 @@ int mm_sshpam_respond(void *, u_int, cha
void mm_sshpam_free_ctx(void *);
#endif
#ifdef SSH_AUDIT_EVENTS
#include "audit.h"
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;
void mm_terminate(void);
int mm_pty_allocate(int *, int *, char *, size_t);
void mm_session_pty_cleanup2(struct Session *);
/* SSHv1 interfaces */
diff --git a/openssh-6.6p1/sshd.c b/openssh-6.6p1/sshd.c
--- a/openssh-6.6p1/sshd.c
+++ b/openssh-6.6p1/sshd.c
@@ -2325,16 +2325,20 @@ do_ssh1_kex(void)
packet_disconnect("Warning: client selects unsupported cipher.");
/* Get check bytes from the packet. These must match those we
sent earlier with the public key packet. */
for (i = 0; i < 8; i++)
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. */
if ((session_key_int = BN_new()) == NULL)
fatal("do_ssh1_kex: BN_new failed");
packet_get_bignum(session_key_int);
protocol_flags = packet_get_int();

View File

@ -0,0 +1,983 @@
# session key destruction and auditing
# based on:
# https://bugzilla.mindrot.org/show_bug.cgi?id=1402
# https://bugzilla.mindrot.org/attachment.cgi?id=2014
# by jchadima@redhat.com
diff --git a/openssh-6.6p1/audit-bsm.c b/openssh-6.6p1/audit-bsm.c
--- a/openssh-6.6p1/audit-bsm.c
+++ b/openssh-6.6p1/audit-bsm.c
@@ -480,9 +480,15 @@ 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 */
}
+
+void
+audit_session_key_free_body(int ctos, pid_t pid, uid_t uid)
+{
+ /* not implemented */
+}
#endif /* BSM */
diff --git a/openssh-6.6p1/audit-linux.c b/openssh-6.6p1/audit-linux.c
--- a/openssh-6.6p1/audit-linux.c
+++ b/openssh-6.6p1/audit-linux.c
@@ -289,24 +289,25 @@ audit_unsupported_body(int what)
/* 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
}
+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)
{
#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());
free(s);
@@ -322,9 +323,37 @@ audit_kex_body(int ctos, char *enc, char
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
}
+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());
+ free(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 --git a/openssh-6.6p1/audit.c b/openssh-6.6p1/audit.c
--- a/openssh-6.6p1/audit.c
+++ b/openssh-6.6p1/audit.c
@@ -138,16 +138,22 @@ audit_unsupported(int what)
}
void
audit_kex(int ctos, char *enc, char *mac, char *comp)
{
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.
* These get used if SSH_AUDIT_EVENTS is defined but no audit module is enabled.
*/
/*
* Called after a connection has been accepted but before any authentication
@@ -269,10 +275,20 @@ audit_unsupported_body(int what)
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);
}
+
+/*
+ * 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 --git a/openssh-6.6p1/audit.h b/openssh-6.6p1/audit.h
--- a/openssh-6.6p1/audit.h
+++ b/openssh-6.6p1/audit.h
@@ -57,10 +57,12 @@ 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 *);
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 --git a/openssh-6.6p1/auditstub.c b/openssh-6.6p1/auditstub.c
--- a/openssh-6.6p1/auditstub.c
+++ b/openssh-6.6p1/auditstub.c
@@ -22,18 +22,29 @@
* 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 <sys/types.h>
+
void
audit_unsupported(int n)
{
}
void
audit_kex(int ctos, char *enc, char *mac, char *comp)
{
}
+void
+audit_session_key_free(int ctos)
+{
+}
+
+void
+audit_session_key_free_body(int ctos, pid_t pid, uid_t uid)
+{
+}
diff --git a/openssh-6.6p1/kex.c b/openssh-6.6p1/kex.c
--- a/openssh-6.6p1/kex.c
+++ b/openssh-6.6p1/kex.c
@@ -700,8 +700,39 @@ dump_digest(char *msg, u_char *digest, i
if (i%32 == 31)
fprintf(stderr, "\n");
else if (i%8 == 7)
fprintf(stderr, " ");
}
fprintf(stderr, "\n");
}
#endif
+
+static void
+enc_destroy(Enc *enc)
+{
+ if (enc == NULL)
+ return;
+
+ if (enc->key) {
+ memset(enc->key, 0, enc->key_len);
+ free(enc->key);
+ }
+
+ if (enc->iv) {
+ memset(enc->iv, 0, enc->block_size);
+ free(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 --git a/openssh-6.6p1/kex.h b/openssh-6.6p1/kex.h
--- a/openssh-6.6p1/kex.h
+++ b/openssh-6.6p1/kex.h
@@ -162,16 +162,18 @@ void kexdh_client(Kex *);
void kexdh_server(Kex *);
void kexgex_client(Kex *);
void kexgex_server(Kex *);
void kexecdh_client(Kex *);
void kexecdh_server(Kex *);
void kexc25519_client(Kex *);
void kexc25519_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 *);
void
kexgex_hash(int, char *, char *, char *, int, char *,
int, u_char *, int, int, int, int, BIGNUM *, BIGNUM *, BIGNUM *,
BIGNUM *, BIGNUM *, u_char **, u_int *);
#ifdef OPENSSL_HAS_ECC
diff --git a/openssh-6.6p1/mac.c b/openssh-6.6p1/mac.c
--- a/openssh-6.6p1/mac.c
+++ b/openssh-6.6p1/mac.c
@@ -253,16 +253,30 @@ mac_clear(Mac *mac)
if (mac->umac_ctx != NULL)
umac128_delete(mac->umac_ctx);
} else if (mac->hmac_ctx != NULL)
ssh_hmac_free(mac->hmac_ctx);
mac->hmac_ctx = NULL;
mac->umac_ctx = NULL;
}
+void
+mac_destroy(Mac *mac)
+{
+ if (mac == NULL)
+ return;
+
+ if (mac->key) {
+ memset(mac->key, 0, mac->key_len);
+ free(mac->key);
+ }
+
+ memset(mac, 0, sizeof(*mac));
+}
+
/* XXX copied from ciphers_valid */
#define MAC_SEP ","
int
mac_valid(const char *names)
{
char *maclist, *cp, *p;
if (names == NULL || strcmp(names, "") == 0)
diff --git a/openssh-6.6p1/mac.h b/openssh-6.6p1/mac.h
--- a/openssh-6.6p1/mac.h
+++ b/openssh-6.6p1/mac.h
@@ -24,8 +24,9 @@
*/
int mac_valid(const char *);
char *mac_alg_list(char);
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 --git a/openssh-6.6p1/monitor.c b/openssh-6.6p1/monitor.c
--- a/openssh-6.6p1/monitor.c
+++ b/openssh-6.6p1/monitor.c
@@ -179,16 +179,17 @@ int mm_answer_gss_checkmic(int, Buffer *
#endif
#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 *);
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 *);
static Authctxt *authctxt;
static BIGNUM *ssh1_challenge = NULL; /* used for ssh1 rsa auth */
/* local state for key verify */
@@ -232,16 +233,17 @@ struct mon_table mon_dispatch_proto20[]
{MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query},
{MONITOR_REQ_PAM_RESPOND, MON_ISAUTH, mm_answer_pam_respond},
{MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx},
#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},
+ {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},
{MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH, mm_answer_bsdauthrespond},
#endif
#ifdef SKEY
{MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
{MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},
@@ -264,16 +266,17 @@ struct mon_table mon_dispatch_postauth20
{MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup},
{MONITOR_REQ_TERM, 0, mm_answer_term},
#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},
{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}
};
struct mon_table mon_dispatch_proto15[] = {
{MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
{MONITOR_REQ_SESSKEY, MON_ONCE, mm_answer_sesskey},
{MONITOR_REQ_SESSID, MON_ONCE, mm_answer_sessid},
@@ -297,30 +300,32 @@ struct mon_table mon_dispatch_proto15[]
{MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query},
{MONITOR_REQ_PAM_RESPOND, MON_ISAUTH, mm_answer_pam_respond},
{MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx},
#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},
+ {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body},
#endif
{0, 0, NULL}
};
struct mon_table mon_dispatch_postauth15[] = {
{MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty},
{MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup},
{MONITOR_REQ_TERM, 0, mm_answer_term},
#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},
{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}
};
struct mon_table *mon_dispatch;
/* Specifies if a certain message is allowed at the moment */
@@ -1949,21 +1954,23 @@ mm_get_keystate(struct monitor *pmonitor
goto skip;
} else {
/* Get the Kex for rekeying */
*pmonitor->m_pkex = mm_get_kex(&m);
}
blob = buffer_get_string(&m, &bloblen);
current_keys[MODE_OUT] = mm_newkeys_from_blob(blob, bloblen);
+ memset(blob, 0, bloblen);
free(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);
free(blob);
/* Now get sequence numbers for the packets */
seqnr = buffer_get_int(&m);
blocks = buffer_get_int64(&m);
packets = buffer_get_int(&m);
bytes = buffer_get_int64(&m);
packet_set_state(MODE_OUT, seqnr, blocks, packets, bytes);
@@ -1999,16 +2006,31 @@ mm_get_keystate(struct monitor *pmonitor
/* Roaming */
if (compat20) {
child_state.sent_bytes = buffer_get_int64(&m);
child_state.recv_bytes = buffer_get_int64(&m);
}
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)
+ ;
+
}
/* Allocation functions for zlib */
void *
mm_zalloc(struct mm_master *mm, u_int ncount, u_int size)
{
size_t len = (size_t) size * ncount;
@@ -2240,10 +2262,28 @@ mm_answer_audit_kex_body(int sock, Buffe
free(mac);
free(compress);
buffer_clear(m);
mm_request_send(sock, MONITOR_ANS_AUDIT_KEX, m);
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 --git a/openssh-6.6p1/monitor.h b/openssh-6.6p1/monitor.h
--- a/openssh-6.6p1/monitor.h
+++ b/openssh-6.6p1/monitor.h
@@ -62,16 +62,17 @@ enum monitor_reqtype {
MONITOR_REQ_PAM_INIT_CTX = 104, MONITOR_ANS_PAM_INIT_CTX = 105,
MONITOR_REQ_PAM_QUERY = 106, MONITOR_ANS_PAM_QUERY = 107,
MONITOR_REQ_PAM_RESPOND = 108, MONITOR_ANS_PAM_RESPOND = 109,
MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111,
MONITOR_REQ_AUDIT_EVENT = 112, MONITOR_REQ_AUDIT_COMMAND = 113,
MONITOR_ANS_AUDIT_COMMAND = 114, MONITOR_REQ_AUDIT_END_COMMAND = 115,
MONITOR_REQ_AUDIT_UNSUPPORTED = 116, MONITOR_ANS_AUDIT_UNSUPPORTED = 117,
MONITOR_REQ_AUDIT_KEX = 118, MONITOR_ANS_AUDIT_KEX = 119,
+ MONITOR_REQ_AUDIT_SESSION_KEY_FREE = 120, MONITOR_ANS_AUDIT_SESSION_KEY_FREE = 121,
};
struct mm_master;
struct monitor {
int m_recvfd;
int m_sendfd;
int m_log_recvfd;
diff --git a/openssh-6.6p1/monitor_wrap.c b/openssh-6.6p1/monitor_wrap.c
--- a/openssh-6.6p1/monitor_wrap.c
+++ b/openssh-6.6p1/monitor_wrap.c
@@ -649,22 +649,24 @@ mm_send_keystate(struct monitor *monitor
__func__, packet_get_newkeys(MODE_OUT),
packet_get_newkeys(MODE_IN));
/* Keys from Kex */
if (!mm_newkeys_to_blob(MODE_OUT, &blob, &bloblen))
fatal("%s: conversion of newkeys failed", __func__);
buffer_put_string(&m, blob, bloblen);
+ memset(blob, 0, bloblen);
free(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);
free(blob);
packet_get_state(MODE_OUT, &seqnr, &blocks, &packets, &bytes);
buffer_put_int(&m, seqnr);
buffer_put_int64(&m, blocks);
buffer_put_int(&m, packets);
buffer_put_int64(&m, bytes);
packet_get_state(MODE_IN, &seqnr, &blocks, &packets, &bytes);
@@ -1356,10 +1358,25 @@ mm_audit_kex_body(int ctos, char *cipher
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);
}
+
+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 --git a/openssh-6.6p1/monitor_wrap.h b/openssh-6.6p1/monitor_wrap.h
--- a/openssh-6.6p1/monitor_wrap.h
+++ b/openssh-6.6p1/monitor_wrap.h
@@ -74,16 +74,17 @@ void mm_sshpam_free_ctx(void *);
#ifdef SSH_AUDIT_EVENTS
#include "audit.h"
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);
+void mm_audit_session_key_free_body(int, pid_t, uid_t);
#endif
struct Session;
void mm_terminate(void);
int mm_pty_allocate(int *, int *, char *, size_t);
void mm_session_pty_cleanup2(struct Session *);
/* SSHv1 interfaces */
diff --git a/openssh-6.6p1/packet.c b/openssh-6.6p1/packet.c
--- a/openssh-6.6p1/packet.c
+++ b/openssh-6.6p1/packet.c
@@ -56,16 +56,17 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include "xmalloc.h"
+#include "audit.h"
#include "buffer.h"
#include "packet.h"
#include "crc32.h"
#include "compress.h"
#include "deattack.h"
#include "channels.h"
#include "compat.h"
#include "ssh1.h"
@@ -469,41 +470,51 @@ packet_get_connection_in(void)
/* Returns the descriptor used for writing. */
int
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
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);
buffer_free(&active_state->incoming_packet);
if (active_state->compression_buffer_ready) {
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. */
void
packet_set_protocol_flags(u_int protocol_flags)
{
active_state->remote_protocol_flags = protocol_flags;
@@ -729,16 +740,35 @@ packet_send1(void)
/*
* Note that the packet is now only buffered in output. It won't be
* actually sent until packet_write_wait or packet_write_poll is
* called.
*/
}
+static void
+newkeys_destroy_and_free(Newkeys *newkeys)
+{
+ if (newkeys == NULL)
+ return;
+
+ free(newkeys->enc.name);
+
+ mac_clear(&newkeys->mac);
+ /* MAC may happen to be empty - if the GCM mode of AES is used */
+ if (newkeys->mac.name)
+ free(newkeys->mac.name);
+
+ free(newkeys->comp.name);
+
+ newkeys_destroy(newkeys);
+ free(newkeys);
+}
+
void
set_newkeys(int mode)
{
Enc *enc;
Mac *mac;
Comp *comp;
CipherContext *cc;
u_int64_t *max_blocks;
@@ -754,31 +784,19 @@ set_newkeys(int mode)
} else {
cc = &active_state->receive_context;
crypt_type = CIPHER_DECRYPT;
active_state->p_read.packets = active_state->p_read.blocks = 0;
max_blocks = &active_state->max_blocks_in;
}
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);
- explicit_bzero(enc->iv, enc->iv_len);
- explicit_bzero(enc->key, enc->key_len);
- explicit_bzero(mac->key, mac->key_len);
- free(enc->name);
- free(enc->iv);
- free(enc->key);
- free(mac->name);
- free(mac->key);
- free(comp->name);
- free(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)
fatal("newkeys: no keys for mode %d", mode);
enc = &active_state->newkeys[mode]->enc;
mac = &active_state->newkeys[mode]->mac;
comp = &active_state->newkeys[mode]->comp;
if (cipher_authlen(enc->cipher) == 0 && mac_init(mac) == 0)
@@ -2004,54 +2022,93 @@ packet_get_output(void)
}
void *
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.
*/
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();
}
/*
* Swap in the old state when resuming a connecion.
*/
void
packet_restore_state(void)
{
struct session_state *tmp;
void *buf;
u_int len;
tmp = backup_state;
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);
buffer_append(&active_state->input, buf, len);
buffer_clear(&backup_state->input);
add_recv_bytes(len);
}
+ backup_state->connection_in = -1;
+ backup_state->connection_out = -1;
+ packet_destroy_state(backup_state);
+ free(backup_state);
+ backup_state = NULL;
}
+
diff --git a/openssh-6.6p1/packet.h b/openssh-6.6p1/packet.h
--- a/openssh-6.6p1/packet.h
+++ b/openssh-6.6p1/packet.h
@@ -119,9 +119,10 @@ void packet_set_rekey_limits(u_int32_t,
time_t packet_get_rekey_timeout(void);
void packet_backup_state(void);
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 --git a/openssh-6.6p1/session.c b/openssh-6.6p1/session.c
--- a/openssh-6.6p1/session.c
+++ b/openssh-6.6p1/session.c
@@ -1694,16 +1694,19 @@ do_child(Session *s, const char *command
int env_size;
char *argv[ARGV_MAX];
const char *shell, *shell0, *hostname = NULL;
struct passwd *pw = s->pw;
int r = 0;
/* 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) {
do_setusercontext(pw);
child_close_fds();
do_pwchange(s);
exit(1);
}
diff --git a/openssh-6.6p1/sshd.c b/openssh-6.6p1/sshd.c
--- a/openssh-6.6p1/sshd.c
+++ b/openssh-6.6p1/sshd.c
@@ -720,16 +720,18 @@ privsep_preauth(Authctxt *authctxt)
setproctitle("%s", "[net]");
if (box != NULL)
ssh_sandbox_child(box);
return 0;
}
}
+extern Newkeys *current_keys[];
+
static void
privsep_postauth(Authctxt *authctxt)
{
u_int32_t rnd[256];
#ifdef DISABLE_FD_PASSING
if (1) {
#else
@@ -744,16 +746,20 @@ privsep_postauth(Authctxt *authctxt)
monitor_reinit(pmonitor);
pmonitor->m_pid = fork();
if (pmonitor->m_pid == -1)
fatal("fork of unprivileged child failed");
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 */
exit(0);
}
/* child */
@@ -2118,16 +2124,17 @@ main(int ac, char **av)
do_authentication(authctxt);
}
/*
* If we use privilege separation, the unprivileged child transfers
* the current keystate and exits
*/
if (use_privsep) {
mm_send_keystate(pmonitor);
+ packet_destroy_all(1, 1);
exit(0);
}
authenticated:
/*
* Cancel the alarm we set to limit the time taken for
* authentication.
*/
@@ -2170,16 +2177,18 @@ main(int ac, char **av)
packet_set_timeout(options.client_alive_interval,
options.client_alive_count_max);
/* Start session. */
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",
(unsigned long long)obytes, (unsigned long long)ibytes);
verbose("Closing connection to %.500s port %d", remote_ip, remote_port);
#ifdef USE_PAM
@@ -2526,26 +2535,38 @@ do_ssh2_kex(void)
#endif
debug("KEX done");
}
/* server specific fatal cleanup */
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) {
debug("Killing privsep child %d", pmonitor->m_pid);
if (kill(pmonitor->m_pid, SIGKILL) != 0 &&
errno != ESRCH)
error("%s: kill(%d): %s", __func__,
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) &&
(!use_privsep || mm_is_monitor()))
audit_event(SSH_CONNECTION_ABANDON);
#endif
_exit(i);
}

View File

@ -0,0 +1,742 @@
# server key destruction and auditing
# based on:
# https://bugzilla.mindrot.org/show_bug.cgi?id=1402
# https://bugzilla.mindrot.org/attachment.cgi?id=2015
# by jchadima@redhat.com
diff --git a/openssh-6.6p1/audit-bsm.c b/openssh-6.6p1/audit-bsm.c
--- a/openssh-6.6p1/audit-bsm.c
+++ b/openssh-6.6p1/audit-bsm.c
@@ -486,9 +486,27 @@ 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 */
}
+
+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 --git a/openssh-6.6p1/audit-linux.c b/openssh-6.6p1/audit-linux.c
--- a/openssh-6.6p1/audit-linux.c
+++ b/openssh-6.6p1/audit-linux.c
@@ -351,9 +351,55 @@ audit_session_key_free_body(int ctos, pi
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");
}
+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 --git a/openssh-6.6p1/audit.c b/openssh-6.6p1/audit.c
--- a/openssh-6.6p1/audit.c
+++ b/openssh-6.6p1/audit.c
@@ -285,10 +285,29 @@ audit_kex_body(int ctos, char *enc, char
* 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);
}
+
+/*
+ * 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 --git a/openssh-6.6p1/audit.h b/openssh-6.6p1/audit.h
--- a/openssh-6.6p1/audit.h
+++ b/openssh-6.6p1/audit.h
@@ -43,26 +43,30 @@ enum ssh_audit_event_type {
SSH_INVALID_USER,
SSH_NOLOGIN, /* denied by /etc/nologin, not implemented */
SSH_CONNECTION_CLOSE, /* closed after attempting auth or session */
SSH_CONNECTION_ABANDON, /* closed without completing auth */
SSH_AUDIT_UNKNOWN
};
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);
void audit_session_open(struct logininfo *);
void audit_session_close(struct logininfo *);
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 *);
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);
+void audit_destroy_sensitive_data(const char *, pid_t, uid_t);
+void audit_generate_ephemeral_server_key(const char *);
#endif /* _SSH_AUDIT_H */
diff --git a/openssh-6.6p1/key.c b/openssh-6.6p1/key.c
--- a/openssh-6.6p1/key.c
+++ b/openssh-6.6p1/key.c
@@ -1964,16 +1964,43 @@ key_demote(const Key *k)
fatal("key_demote: bad key type %d", k->type);
break;
}
return (pk);
}
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
+ case KEY_ED25519_CERT:
+ case KEY_ED25519:
+ return k->ed25519_sk != NULL;
+ default:
+ fatal("key_is_private: bad key type %d", k->type);
+ return 1;
+ }
+}
+
+int
key_is_cert(const Key *k)
{
if (k == NULL)
return 0;
return key_type_is_cert(k->type);
}
/* Return the cert-less equivalent to a certified key type */
diff --git a/openssh-6.6p1/key.h b/openssh-6.6p1/key.h
--- a/openssh-6.6p1/key.h
+++ b/openssh-6.6p1/key.h
@@ -113,16 +113,17 @@ int key_read(Key *, char **);
u_int key_size(const Key *);
enum fp_type key_fp_type_select(void);
char *key_fp_type_str(enum fp_type);
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_is_cert(int);
int key_type_plain(int);
int key_to_certified(Key *, int);
int key_drop_cert(Key *);
int key_certify(Key *, Key *);
void key_cert_copy(const Key *, struct Key *);
int key_cert_check_authority(const Key *, int, int, const char *,
const char **);
diff --git a/openssh-6.6p1/monitor.c b/openssh-6.6p1/monitor.c
--- a/openssh-6.6p1/monitor.c
+++ b/openssh-6.6p1/monitor.c
@@ -109,16 +109,18 @@ extern u_int utmp_len;
extern Newkeys *current_keys[];
extern z_stream incoming_stream;
extern z_stream outgoing_stream;
extern u_char session_id[];
extern Buffer auth_debug;
extern int auth_debug_init;
extern Buffer loginmsg;
+extern void destroy_sensitive_data(int);
+
/* State exported from the child */
struct {
z_stream incoming;
z_stream outgoing;
u_char *keyin;
u_int keyinlen;
u_char *keyout;
@@ -180,16 +182,17 @@ 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 *);
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 *);
static Authctxt *authctxt;
static BIGNUM *ssh1_challenge = NULL; /* used for ssh1 rsa auth */
/* local state for key verify */
@@ -234,16 +237,17 @@ struct mon_table mon_dispatch_proto20[]
{MONITOR_REQ_PAM_RESPOND, MON_ISAUTH, mm_answer_pam_respond},
{MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx},
#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},
{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},
{MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH, mm_answer_bsdauthrespond},
#endif
#ifdef SKEY
{MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
{MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},
@@ -267,16 +271,17 @@ struct mon_table mon_dispatch_postauth20
{MONITOR_REQ_TERM, 0, mm_answer_term},
#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},
{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}
};
struct mon_table mon_dispatch_proto15[] = {
{MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
{MONITOR_REQ_SESSKEY, MON_ONCE, mm_answer_sesskey},
{MONITOR_REQ_SESSID, MON_ONCE, mm_answer_sessid},
@@ -301,31 +306,33 @@ struct mon_table mon_dispatch_proto15[]
{MONITOR_REQ_PAM_RESPOND, MON_ISAUTH, mm_answer_pam_respond},
{MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx},
#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},
{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}
};
struct mon_table mon_dispatch_postauth15[] = {
{MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty},
{MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup},
{MONITOR_REQ_TERM, 0, mm_answer_term},
#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},
{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}
};
struct mon_table *mon_dispatch;
/* Specifies if a certain message is allowed at the moment */
@@ -1739,16 +1746,18 @@ mm_answer_term(int sock, Buffer *req)
/* The child is terminating */
session_destroy_all(&mm_session_close);
#ifdef USE_PAM
if (options.use_pam)
sshpam_cleanup();
#endif
+ destroy_sensitive_data(0);
+
while (waitpid(pmonitor->m_pid, &status, 0) == -1)
if (errno != EINTR)
exit(1);
res = WIFEXITED(status) ? WEXITSTATUS(status) : 1;
/* Terminate process */
exit(res);
@@ -2280,10 +2289,31 @@ mm_answer_audit_session_key_free_body(in
audit_session_key_free_body(ctos, pid, uid);
buffer_clear(m);
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);
+
+ free(fp);
+ buffer_clear(m);
+
+ mm_request_send(sock, MONITOR_ANS_AUDIT_SERVER_KEY_FREE, m);
+ return 0;
+}
#endif /* SSH_AUDIT_EVENTS */
diff --git a/openssh-6.6p1/monitor.h b/openssh-6.6p1/monitor.h
--- a/openssh-6.6p1/monitor.h
+++ b/openssh-6.6p1/monitor.h
@@ -63,16 +63,17 @@ enum monitor_reqtype {
MONITOR_REQ_PAM_QUERY = 106, MONITOR_ANS_PAM_QUERY = 107,
MONITOR_REQ_PAM_RESPOND = 108, MONITOR_ANS_PAM_RESPOND = 109,
MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111,
MONITOR_REQ_AUDIT_EVENT = 112, MONITOR_REQ_AUDIT_COMMAND = 113,
MONITOR_ANS_AUDIT_COMMAND = 114, MONITOR_REQ_AUDIT_END_COMMAND = 115,
MONITOR_REQ_AUDIT_UNSUPPORTED = 116, MONITOR_ANS_AUDIT_UNSUPPORTED = 117,
MONITOR_REQ_AUDIT_KEX = 118, MONITOR_ANS_AUDIT_KEX = 119,
MONITOR_REQ_AUDIT_SESSION_KEY_FREE = 120, MONITOR_ANS_AUDIT_SESSION_KEY_FREE = 121,
+ MONITOR_REQ_AUDIT_SERVER_KEY_FREE = 122, MONITOR_ANS_AUDIT_SERVER_KEY_FREE = 123,
};
struct mm_master;
struct monitor {
int m_recvfd;
int m_sendfd;
int m_log_recvfd;
diff --git a/openssh-6.6p1/monitor_wrap.c b/openssh-6.6p1/monitor_wrap.c
--- a/openssh-6.6p1/monitor_wrap.c
+++ b/openssh-6.6p1/monitor_wrap.c
@@ -1373,10 +1373,26 @@ mm_audit_session_key_free_body(int ctos,
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);
}
+
+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 --git a/openssh-6.6p1/monitor_wrap.h b/openssh-6.6p1/monitor_wrap.h
--- a/openssh-6.6p1/monitor_wrap.h
+++ b/openssh-6.6p1/monitor_wrap.h
@@ -75,16 +75,17 @@ void mm_sshpam_free_ctx(void *);
#ifdef SSH_AUDIT_EVENTS
#include "audit.h"
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);
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;
void mm_terminate(void);
int mm_pty_allocate(int *, int *, char *, size_t);
void mm_session_pty_cleanup2(struct Session *);
/* SSHv1 interfaces */
diff --git a/openssh-6.6p1/session.c b/openssh-6.6p1/session.c
--- a/openssh-6.6p1/session.c
+++ b/openssh-6.6p1/session.c
@@ -132,17 +132,17 @@ static int session_pty_req(Session *);
/* import */
extern ServerOptions options;
extern char *__progname;
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. */
const char *original_command = NULL;
/* data */
static int sessions_first_unused = -1;
static int sessions_nalloc = 0;
@@ -1693,17 +1693,17 @@ do_child(Session *s, const char *command
char **env;
int env_size;
char *argv[ARGV_MAX];
const char *shell, *shell0, *hostname = NULL;
struct passwd *pw = s->pw;
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);
/* Force a password change */
if (s->authctxt->force_pwchange) {
do_setusercontext(pw);
child_close_fds();
diff --git a/openssh-6.6p1/sshd.c b/openssh-6.6p1/sshd.c
--- a/openssh-6.6p1/sshd.c
+++ b/openssh-6.6p1/sshd.c
@@ -259,17 +259,17 @@ Buffer cfg;
/* message to be displayed after login */
Buffer loginmsg;
/* Unprivileged user */
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);
static void do_ssh2_kex(void);
/*
* Close all listening sockets
*/
@@ -278,16 +278,25 @@ close_listen_socks(void)
{
int i;
for (i = 0; i < num_listen_socks; i++)
close(listen_socks[i]);
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)
{
int i;
if (startup_pipes)
for (i = 0; i < options.max_startups; i++)
if (startup_pipes[i] != -1)
@@ -557,60 +566,99 @@ sshd_exchange_identification(int sock_in
close(sock_out);
logit("Protocol major versions differ for %s: %.200s vs. %.200s",
get_remote_ipaddr(),
server_version_string, client_version_string);
cleanup_exit(255);
}
}
-/* 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],
+ key_fp_type_select(), 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);
+ free(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;
}
}
sensitive_data.ssh1_host_key = NULL;
explicit_bzero(sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH);
}
/* Demote private to public keys for network child */
void
demote_sensitive_data(void)
{
Key *tmp;
+ pid_t pid;
+ uid_t uid;
int i;
+ pid = getpid();
+ uid = getuid();
if (sensitive_data.server_key) {
tmp = key_demote(sensitive_data.server_key);
key_free(sensitive_data.server_key);
sensitive_data.server_key = tmp;
}
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],
+ key_fp_type_select(), 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);
+ free(fp);
+ }
}
/* Certs do not need demotion */
}
/* We do not clear ssh1_host key and cookie. XXX - Okay Niels? */
}
static void
@@ -1201,16 +1249,17 @@ server_accept_loop(int *sock_in, int *so
/* Wait in select until there is a connection. */
ret = select(maxfd+1, fdset, NULL, NULL, NULL);
if (ret < 0 && errno != EINTR)
error("select: %.100s", strerror(errno));
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);
}
if (key_used && key_do_regen) {
generate_ephemeral_server_key();
key_used = 0;
key_do_regen = 0;
@@ -2167,27 +2216,28 @@ main(int ac, char **av)
/*
* In privilege separation, we fork another child and prepare
* file descriptor passing.
*/
if (use_privsep) {
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,
options.client_alive_count_max);
/* Start session. */
do_authenticated(authctxt);
/* 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);
verbose("Transferred: sent %llu, received %llu bytes",
(unsigned long long)obytes, (unsigned long long)ibytes);
verbose("Closing connection to %.500s port %d", remote_ip, remote_port);
@@ -2412,17 +2462,17 @@ do_ssh1_kex(void)
fatal("%s: hash failed", __func__);
ssh_digest_free(md);
explicit_bzero(buf, bytes);
free(buf);
for (i = 0; i < 16; i++)
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);
/* Destroy the decrypted integer. It is no longer needed. */
BN_clear_free(session_key_int);
/* Set the session key. From this on all communications will be encrypted. */
@@ -2556,16 +2606,18 @@ cleanup_exit(int i)
debug("Killing privsep child %d", pmonitor->m_pid);
if (kill(pmonitor->m_pid, SIGKILL) != 0 &&
errno != ESRCH)
error("%s: kill(%d): %s", __func__,
pmonitor->m_pid, strerror(errno));
}
}
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' */
if ((the_authctxt == NULL || !the_authctxt->authenticated) &&
(!use_privsep || mm_is_monitor()))
audit_event(SSH_CONNECTION_ABANDON);
#endif
_exit(i);

View File

@ -0,0 +1,107 @@
# definitions for AUDIT_CRYPTO_* symbols fom libaudit 2.x
diff --git a/openssh-6.6p1/audit-linux.c b/openssh-6.6p1/audit-linux.c
--- a/openssh-6.6p1/audit-linux.c
+++ b/openssh-6.6p1/audit-linux.c
@@ -25,16 +25,17 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Red Hat author: Jan F. Chadima <jchadima@redhat.com>
*/
#include "includes.h"
#if defined(USE_LINUX_AUDIT)
#include <libaudit.h>
+#include "compat-libaudit.h"
#include <unistd.h>
#include <string.h>
#include "log.h"
#include "audit.h"
#include "key.h"
#include "hostfile.h"
#include "auth.h"
diff --git a/openssh-6.6p1/compat-libaudit.h b/openssh-6.6p1/compat-libaudit.h
new file mode 100644
--- /dev/null
+++ b/openssh-6.6p1/compat-libaudit.h
@@ -0,0 +1,79 @@
+/* AUDIT_CRYPTO symbol definitions from libaudit 2.x */
+/* libaudit.h --
+ * Copyright 2004-2011 Red Hat Inc., Durham, North Carolina.
+ * All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors:
+ * Steve Grubb <sgrubb@redhat.com>
+ * Rickard E. (Rik) Faith <faith@redhat.com>
+ */
+#ifndef _COMPAT_LIBAUDIT_H_
+#define _COMPAT_LIBAUDIT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef AUDIT_FIRST_CRYPTO_MSG
+#define AUDIT_FIRST_CRYPTO_MSG 2400
+#endif
+
+#ifndef AUDIT_CRYPTO_TEST_USER
+#define AUDIT_CRYPTO_TEST_USER 2400 /* Crypto test results */
+#endif
+
+#ifndef AUDIT_CRYPTO_PARAM_CHANGE_USER
+#define AUDIT_CRYPTO_PARAM_CHANGE_USER 2401 /* Crypto attribute change */
+#endif
+
+#ifndef AUDIT_CRYPTO_LOGIN
+#define AUDIT_CRYPTO_LOGIN 2402 /* Logged in as crypto officer */
+#endif
+
+#ifndef AUDIT_CRYPTO_LOGOUT
+#define AUDIT_CRYPTO_LOGOUT 2403 /* Logged out from crypto */
+#endif
+
+#ifndef AUDIT_CRYPTO_KEY_USER
+#define AUDIT_CRYPTO_KEY_USER 2404 /* Create,delete,negotiate */
+#endif
+
+#ifndef AUDIT_CRYPTO_FAILURE_USER
+#define AUDIT_CRYPTO_FAILURE_USER 2405 /* Fail decrypt,encrypt,randomiz */
+#endif
+
+#ifndef AUDIT_CRYPTO_REPLAY_USER
+#define AUDIT_CRYPTO_REPLAY_USER 2406 /* Crypto replay detected */
+#endif
+
+#ifndef AUDIT_CRYPTO_SESSION
+#define AUDIT_CRYPTO_SESSION 2407 /* Record parameters set during
+ TLS session establishment */
+#endif
+
+
+#ifndef AUDIT_LAST_CRYPTO_MSG
+#define AUDIT_LAST_CRYPTO_MSG 2499
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _COMPAT_LIBAUDIT_H_ */
+

View File

@ -0,0 +1,47 @@
# bnc#752354, bnc#757360
# prevent timeouts in libaudit code caused by DNS misconfiguration by
# explicitely disabling DNS lookups in libaudit when UseDNS is false.
# Note that this particular solution causes the logs to always contain
# "hostname=?, addr=?" when DNS lookups are disabled.
diff --git a/openssh-6.6p1/audit-linux.c b/openssh-6.6p1/audit-linux.c
--- a/openssh-6.6p1/audit-linux.c
+++ b/openssh-6.6p1/audit-linux.c
@@ -62,17 +62,17 @@ linux_audit_user_logxxx(int uid, const c
if (errno == EINVAL || errno == EPROTONOSUPPORT ||
errno == EAFNOSUPPORT)
return; /* No audit support in kernel */
else
goto fatal_report; /* Must prevent login */
}
rc = audit_log_acct_message(audit_fd, event,
NULL, "login", username ? username : "(unknown)",
- username == NULL ? uid : -1, hostname, ip, ttyn, success);
+ username == NULL ? uid : -1, options.use_dns ? hostname : NULL, 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;
@@ -114,17 +114,17 @@ linux_audit_user_auth(int uid, const cha
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);
+ username == NULL ? uid : -1, options.use_dns ? hostname : NULL, 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;

View File

@ -2,19 +2,33 @@
# grace_alarm_handler)
# bnc#57354
Index: b/log.c
===================================================================
--- a/log.c
+++ b/log.c
@@ -51,6 +51,7 @@
diff --git a/openssh-6.6p1/log.c b/openssh-6.6p1/log.c
--- a/openssh-6.6p1/log.c
+++ b/openssh-6.6p1/log.c
@@ -47,16 +47,17 @@
#include <unistd.h>
#include <errno.h>
#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS)
# include <vis.h>
#endif
#include "xmalloc.h"
#include "log.h"
+#include <signal.h>
static LogLevel log_level = SYSLOG_LEVEL_INFO;
static int log_on_stderr = 1;
@@ -388,6 +389,7 @@ do_log(LogLevel level, const char *fmt,
static int log_stderr_fd = STDERR_FILENO;
static int log_facility = LOG_AUTH;
static char *argv0;
static log_handler_fn *log_handler;
static void *log_handler_ctx;
@@ -384,16 +385,17 @@ do_log(LogLevel level, const char *fmt,
{
#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
struct syslog_data sdata = SYSLOG_DATA_INIT;
#endif
char msgbuf[MSGBUFSIZ];
char fmtbuf[MSGBUFSIZ];
char *txt = NULL;
int pri = LOG_INFO;
@ -22,7 +36,17 @@ Index: b/log.c
int saved_errno = errno;
log_handler_fn *tmp_handler;
@@ -446,6 +448,14 @@ do_log(LogLevel level, const char *fmt,
if (level > log_level)
return;
switch (level) {
case SYSLOG_LEVEL_FATAL:
@@ -442,20 +444,29 @@ do_log(LogLevel level, const char *fmt,
tmp_handler = log_handler;
log_handler = NULL;
tmp_handler(level, fmtbuf, log_handler_ctx);
log_handler = tmp_handler;
} else if (log_on_stderr) {
snprintf(msgbuf, sizeof msgbuf, "%s\r\n", fmtbuf);
(void)write(log_stderr_fd, msgbuf, strlen(msgbuf));
} else {
@ -37,7 +61,9 @@ Index: b/log.c
#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata);
syslog_r(pri, &sdata, "%.500s", fmtbuf);
@@ -455,6 +465,7 @@ do_log(LogLevel level, const char *fmt,
closelog_r(&sdata);
#else
openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility);
syslog(pri, "%.500s", fmtbuf);
closelog();
#endif

View File

@ -0,0 +1,205 @@
# Date: Sun, 20 Apr 2014 17:14:08 +1000 (EST)
# From: Damien Miller <djm@mindrot.org>
# To: openssh-unix-dev@mindrot.org
# Subject: bad bignum encoding for curve25519-sha256@libssh.org
# Message-ID: <alpine.BSO.2.11.1404201713390.26134@natsu.mindrot.org>
#
# Hi,
#
# So I screwed up when writing the support for the curve25519 KEX method
# that doesn't depend on OpenSSL's BIGNUM type - a bug in my code left
# leading zero bytes where they should have been skipped. The impact of
# this is that OpenSSH 6.5 and 6.6 will fail during key exchange with a
# peer that implements curve25519-sha256@libssh.org properly about 0.2%
# of the time (one in every 512ish connections).
#
# We've fixed this for OpenSSH 6.7 by avoiding the curve25519-sha256
# key exchange for previous versions, but I'd recommend distributors
# of OpenSSH apply this patch so the affected code doesn't become
# too entrenched in LTS releases.
#
# The patch fixes the bug and makes OpenSSH identify itself as 6.6.1 so as
# to distinguish itself from the incorrect versions so the compatibility
# code to disable the affected KEX isn't activated.
#
# I've committed this on the 6.6 branch too.
#
# Apologies for the hassle.
#
# -d
diff --git a/openssh-6.6p1/bufaux.c b/openssh-6.6p1/bufaux.c
--- a/openssh-6.6p1/bufaux.c
+++ b/openssh-6.6p1/bufaux.c
@@ -1,9 +1,9 @@
-/* $OpenBSD: bufaux.c,v 1.56 2014/02/02 03:44:31 djm Exp $ */
+/* $OpenBSD: bufaux.c,v 1.57 2014/04/16 23:22:45 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Auxiliary functions for storing and retrieving various data types to/from
* Buffers.
*
* As far as I am concerned, the code I have written for this software
@@ -367,16 +367,19 @@ buffer_get_bignum2_as_string(Buffer *buf
void
buffer_put_bignum2_from_string(Buffer *buffer, const u_char *s, u_int l)
{
u_char *buf, *p;
int pad = 0;
if (l > 8 * 1024)
fatal("%s: length %u too long", __func__, l);
+ /* Skip leading zero bytes */
+ for (; l > 0 && *s == 0; l--, s++)
+ ;
p = buf = xmalloc(l + 1);
/*
* If most significant bit is set then prepend a zero byte to
* avoid interpretation as a negative number.
*/
if (l > 0 && (s[0] & 0x80) != 0) {
*p++ = '\0';
pad = 1;
diff --git a/openssh-6.6p1/compat.c b/openssh-6.6p1/compat.c
--- a/openssh-6.6p1/compat.c
+++ b/openssh-6.6p1/compat.c
@@ -90,16 +90,19 @@ compat_datafellows(const char *version)
SSH_OLD_FORWARD_ADDR},
{ "OpenSSH_2.*,"
"OpenSSH_3.0*,"
"OpenSSH_3.1*", SSH_BUG_EXTEOF|SSH_OLD_FORWARD_ADDR},
{ "OpenSSH_3.*", SSH_OLD_FORWARD_ADDR },
{ "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF},
{ "OpenSSH_4*", 0 },
{ "OpenSSH_5*", SSH_NEW_OPENSSH|SSH_BUG_DYNAMIC_RPORT},
+ { "OpenSSH_6.6.1*", SSH_NEW_OPENSSH},
+ { "OpenSSH_6.5*,"
+ "OpenSSH_6.6*", SSH_NEW_OPENSSH|SSH_BUG_CURVE25519PAD},
{ "OpenSSH*", SSH_NEW_OPENSSH },
{ "*MindTerm*", 0 },
{ "2.1.0*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
SSH_OLD_SESSIONID|SSH_BUG_DEBUG|
SSH_BUG_RSASIGMD5|SSH_BUG_HBSERVICE|
SSH_BUG_FIRSTKEX },
{ "2.1 *", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
SSH_OLD_SESSIONID|SSH_BUG_DEBUG|
@@ -246,22 +249,34 @@ compat_cipher_proposal(char *cipher_prop
debug2("%s: original cipher proposal: %s", __func__, cipher_prop);
cipher_prop = filter_proposal(cipher_prop, "aes*");
debug2("%s: compat cipher proposal: %s", __func__, cipher_prop);
if (*cipher_prop == '\0')
fatal("No supported ciphers found");
return cipher_prop;
}
-
char *
compat_pkalg_proposal(char *pkalg_prop)
{
if (!(datafellows & SSH_BUG_RSASIGMD5))
return pkalg_prop;
debug2("%s: original public key proposal: %s", __func__, pkalg_prop);
pkalg_prop = filter_proposal(pkalg_prop, "ssh-rsa");
debug2("%s: compat public key proposal: %s", __func__, pkalg_prop);
if (*pkalg_prop == '\0')
fatal("No supported PK algorithms found");
return pkalg_prop;
}
+char *
+compat_kex_proposal(char *kex_prop)
+{
+ if (!(datafellows & SSH_BUG_CURVE25519PAD))
+ return kex_prop;
+ debug2("%s: original KEX proposal: %s", __func__, kex_prop);
+ kex_prop = filter_proposal(kex_prop, "curve25519-sha256@libssh.org");
+ debug2("%s: compat KEX proposal: %s", __func__, kex_prop);
+ if (*kex_prop == '\0')
+ fatal("No supported key exchange algorithms found");
+ return kex_prop;
+}
+
diff --git a/openssh-6.6p1/compat.h b/openssh-6.6p1/compat.h
--- a/openssh-6.6p1/compat.h
+++ b/openssh-6.6p1/compat.h
@@ -54,20 +54,22 @@
#define SSH_BUG_DUMMYCHAN 0x00100000
#define SSH_BUG_EXTEOF 0x00200000
#define SSH_BUG_PROBE 0x00400000
#define SSH_BUG_FIRSTKEX 0x00800000
#define SSH_OLD_FORWARD_ADDR 0x01000000
#define SSH_BUG_RFWD_ADDR 0x02000000
#define SSH_NEW_OPENSSH 0x04000000
#define SSH_BUG_DYNAMIC_RPORT 0x08000000
+#define SSH_BUG_CURVE25519PAD 0x10000000
void enable_compat13(void);
void enable_compat20(void);
void compat_datafellows(const char *);
int proto_spec(const char *);
char *compat_cipher_proposal(char *);
char *compat_pkalg_proposal(char *);
+char *compat_kex_proposal(char *);
extern int compat13;
extern int compat20;
extern int datafellows;
#endif
diff --git a/openssh-6.6p1/sshconnect2.c b/openssh-6.6p1/sshconnect2.c
--- a/openssh-6.6p1/sshconnect2.c
+++ b/openssh-6.6p1/sshconnect2.c
@@ -190,16 +190,18 @@ ssh_kex2(char *host, struct sockaddr *ho
else {
/* Prefer algorithms that we already have keys for */
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
compat_pkalg_proposal(
order_hostkeyalgs(host, hostaddr, port));
}
if (options.kex_algorithms != NULL)
myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms;
+ myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(
+ myproposal[PROPOSAL_KEX_ALGS]);
if (options.rekey_limit || options.rekey_interval)
packet_set_rekey_limits((u_int32_t)options.rekey_limit,
(time_t)options.rekey_interval);
/* start key exchange */
kex = kex_setup(myproposal);
kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
diff --git a/openssh-6.6p1/sshd.c b/openssh-6.6p1/sshd.c
--- a/openssh-6.6p1/sshd.c
+++ b/openssh-6.6p1/sshd.c
@@ -2457,16 +2457,19 @@ do_ssh2_kex(void)
myproposal[PROPOSAL_COMP_ALGS_STOC] = "none";
} else if (options.compression == COMP_DELAYED) {
myproposal[PROPOSAL_COMP_ALGS_CTOS] =
myproposal[PROPOSAL_COMP_ALGS_STOC] = "none,zlib@openssh.com";
}
if (options.kex_algorithms != NULL)
myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms;
+ myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(
+ myproposal[PROPOSAL_KEX_ALGS]);
+
if (options.rekey_limit || options.rekey_interval)
packet_set_rekey_limits((u_int32_t)options.rekey_limit,
(time_t)options.rekey_interval);
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal(
list_hostkey_types());
/* start key exchange */
diff --git a/openssh-6.6p1/version.h b/openssh-6.6p1/version.h
--- a/openssh-6.6p1/version.h
+++ b/openssh-6.6p1/version.h
@@ -1,6 +1,6 @@
/* $OpenBSD: version.h,v 1.70 2014/02/27 22:57:40 djm Exp $ */
-#define SSH_VERSION "OpenSSH_6.6"
+#define SSH_VERSION "OpenSSH_6.6.1"
#define SSH_PORTABLE "p1"
#define SSH_RELEASE SSH_VERSION SSH_PORTABLE

View File

@ -2,16 +2,22 @@
# reliable indicator of ABI changes and doesn't make much sense in a
# distribution package
Index: b/entropy.c
===================================================================
--- a/entropy.c
+++ b/entropy.c
@@ -213,10 +213,11 @@ seed_rng(void)
#ifndef OPENSSL_PRNG_ONLY
unsigned char buf[RANDOM_SEED_SIZE];
diff --git a/openssh-6.6p1/entropy.c b/openssh-6.6p1/entropy.c
--- a/openssh-6.6p1/entropy.c
+++ b/openssh-6.6p1/entropy.c
@@ -212,22 +212,23 @@ seed_rng(void)
#endif
/*
* OpenSSL version numbers: MNNFFPPS: major minor fix patch status
* We match major, minor, fix and status (not patch) for <1.0.0.
* After that, we acceptable compatible fix versions (so we
* allow 1.0.1 to work with 1.0.0). Going backwards is only allowed
* within a patch series.
*/
+#if 0
if (!ssh_compatible_openssl(OPENSSL_VERSION_NUMBER, SSLeay()))
u_long version_mask = SSLeay() >= 0x1000000f ? ~0xffff0L : ~0xff0L;
if (((SSLeay() ^ OPENSSL_VERSION_NUMBER) & version_mask) ||
(SSLeay() >> 12) < (OPENSSL_VERSION_NUMBER >> 12))
fatal("OpenSSL version mismatch. Built against %lx, you "
"have %lx", (u_long)OPENSSL_VERSION_NUMBER, SSLeay());
-
@ -19,3 +25,8 @@ Index: b/entropy.c
#ifndef OPENSSL_PRNG_ONLY
if (RAND_status() == 1) {
debug3("RNG is ready, skipping seeding");
return;
}
if (seed_from_prngd(buf, sizeof(buf)) == -1)
fatal("Could not obtain seed from PRNGd");

View File

@ -1,10 +1,14 @@
# fix paths and references in sshd man pages
Index: b/sshd.8
===================================================================
--- a/sshd.8
+++ b/sshd.8
@@ -873,7 +873,7 @@ are displayed to anyone trying to log in
diff --git a/openssh-6.6p1/sshd.8 b/openssh-6.6p1/sshd.8
--- a/openssh-6.6p1/sshd.8
+++ b/openssh-6.6p1/sshd.8
@@ -875,17 +875,17 @@ See
If this file exists,
.Nm
refuses to let anyone except root log in.
The contents of the file
are displayed to anyone trying to log in, and non-root connections are
refused.
The file should be world-readable.
.Pp
@ -13,30 +17,59 @@ Index: b/sshd.8
This file is used in exactly the same way as
.Pa hosts.equiv ,
but allows host-based authentication without permitting login with
@@ -953,7 +953,7 @@ The content of this file is not sensitiv
rlogin/rsh.
.Pp
.It Pa /etc/ssh/ssh_host_key
.It Pa /etc/ssh/ssh_host_dsa_key
.It Pa /etc/ssh/ssh_host_ecdsa_key
@@ -956,17 +956,17 @@ The content of this file is not sensitiv
.Xr sftp 1 ,
.Xr ssh 1 ,
.Xr ssh-add 1 ,
.Xr ssh-agent 1 ,
.Xr ssh-keygen 1 ,
.Xr ssh-keyscan 1 ,
.Xr chroot 2 ,
.Xr hosts_access 5 ,
-.Xr login.conf 5 ,
+.Xr login.defs 5 ,
.Xr moduli 5 ,
.Xr sshd_config 5 ,
.Xr inetd 8 ,
Index: b/sshd_config.5
===================================================================
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -374,8 +374,7 @@ This option is only available for protoc
.Xr sftp-server 8
.Sh AUTHORS
OpenSSH is a derivative of the original and free
ssh 1.2.12 release by Tatu Ylonen.
Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
diff --git a/openssh-6.6p1/sshd_config.5 b/openssh-6.6p1/sshd_config.5
--- a/openssh-6.6p1/sshd_config.5
+++ b/openssh-6.6p1/sshd_config.5
@@ -278,18 +278,17 @@ The contents of the specified file are s
authentication is allowed.
If the argument is
.Dq none
then no banner is displayed.
This option is only available for protocol version 2.
By default, no banner is displayed.
.It Cm ChallengeResponseAuthentication
Specifies whether challenge-response authentication is allowed (e.g. via
-PAM or through authentication styles supported in
-PAM or though authentication styles supported in
-.Xr login.conf 5 )
+PAM)
The default is
.Dq yes .
.It Cm ChrootDirectory
@@ -773,7 +772,7 @@ or
Specifies the pathname of a directory to
.Xr chroot 2
to after authentication.
All components of the pathname must be root-owned directories that are
not writable by any other user or group.
@@ -576,17 +575,17 @@ and
.Pa .shosts
files will not be used in
.Cm RhostsRSAAuthentication
or
.Cm HostbasedAuthentication .
.Pp
.Pa /etc/hosts.equiv
and
@ -45,3 +78,8 @@ Index: b/sshd_config.5
are still used.
The default is
.Dq yes .
.It Cm IgnoreUserKnownHosts
Specifies whether
.Xr sshd 8
should ignore the user's
.Pa ~/.ssh/known_hosts

View File

@ -0,0 +1,730 @@
# HG changeset patch
# Parent 8b2615db484b7061edd15f3bee36958f790f790e
# select fingerprint hash algorithms based on the environment variable
# SSH_FP_TYPE_ENVVAR and append it to hex and randomart fingerprints
# Petr Cerny <pcerny@suse.cz>
diff --git a/openssh-6.6p1/auth-rsa.c b/openssh-6.6p1/auth-rsa.c
--- a/openssh-6.6p1/auth-rsa.c
+++ b/openssh-6.6p1/auth-rsa.c
@@ -230,17 +230,17 @@ rsa_key_allowed_in_file(struct passwd *p
/* check the real bits */
keybits = BN_num_bits(key->rsa->n);
if (keybits < 0 || bits != keybits)
logit("Warning: %s, line %lu: keysize mismatch: "
"actual %d vs. announced %d.",
file, linenum, BN_num_bits(key->rsa->n), bits);
- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(key, key_fp_type_select(), SSH_FP_HEX);
debug("matching key found: file %s, line %lu %s %s",
file, linenum, key_type(key), fp);
free(fp);
/* Never accept a revoked key */
if (auth_key_is_revoked(key))
break;
diff --git a/openssh-6.6p1/auth.c b/openssh-6.6p1/auth.c
--- a/openssh-6.6p1/auth.c
+++ b/openssh-6.6p1/auth.c
@@ -680,17 +680,17 @@ auth_key_is_revoked(Key *key)
case -1:
/* Error opening revoked_keys_file: refuse all keys */
error("Revoked keys file is unreadable: refusing public key "
"authentication");
return 1;
case 1:
revoked:
/* Key revoked */
- key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+ key_fp = key_fingerprint(key, key_fp_type_select(), SSH_FP_HEX);
error("WARNING: authentication attempt with a revoked "
"%s key %s ", key_type(key), key_fp);
free(key_fp);
return 1;
}
fatal("key_in_file returned junk");
}
diff --git a/openssh-6.6p1/auth2-hostbased.c b/openssh-6.6p1/auth2-hostbased.c
--- a/openssh-6.6p1/auth2-hostbased.c
+++ b/openssh-6.6p1/auth2-hostbased.c
@@ -202,23 +202,23 @@ hostbased_key_allowed(struct passwd *pw,
_PATH_SSH_SYSTEM_HOSTFILE2,
options.ignore_user_known_hosts ? NULL :
_PATH_SSH_USER_HOSTFILE2);
}
if (host_status == HOST_OK) {
if (key_is_cert(key)) {
fp = key_fingerprint(key->cert->signature_key,
- SSH_FP_MD5, SSH_FP_HEX);
+ key_fp_type_select(), 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,
cuser, lookup);
} else {
- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(key, key_fp_type_select(), SSH_FP_HEX);
verbose("Accepted %s public key %s from %s@%s",
key_type(key), fp, cuser, lookup);
}
free(fp);
}
return (host_status == HOST_OK);
}
diff --git a/openssh-6.6p1/auth2-pubkey.c b/openssh-6.6p1/auth2-pubkey.c
--- a/openssh-6.6p1/auth2-pubkey.c
+++ b/openssh-6.6p1/auth2-pubkey.c
@@ -208,25 +208,25 @@ pubkey_auth_info(Authctxt *authctxt, con
i = vasprintf(&extra, fmt, ap);
va_end(ap);
if (i < 0 || extra == NULL)
fatal("%s: vasprintf failed", __func__);
}
if (key_is_cert(key)) {
fp = key_fingerprint(key->cert->signature_key,
- SSH_FP_MD5, SSH_FP_HEX);
+ key_fp_type_select(), SSH_FP_HEX);
auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s",
key_type(key), key->cert->key_id,
(unsigned long long)key->cert->serial,
key_type(key->cert->signature_key), fp,
extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
free(fp);
} else {
- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(key, key_fp_type_select(), SSH_FP_HEX);
auth_info(authctxt, "%s %s%s%s", key_type(key), fp,
extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
free(fp);
}
free(extra);
}
static int
@@ -360,17 +360,17 @@ check_authkeys_file(FILE *f, char *file,
if (key_is_cert(key)) {
if (!key_equal(found, key->cert->signature_key))
continue;
if (auth_parse_options(pw, key_options, file,
linenum) != 1)
continue;
if (!key_is_cert_authority)
continue;
- fp = key_fingerprint(found, SSH_FP_MD5,
+ fp = key_fingerprint(found, key_fp_type_select(),
SSH_FP_HEX);
debug("matching CA found: file %s, line %lu, %s %s",
file, linenum, key_type(found), fp);
/*
* If the user has specified a list of principals as
* a key option, then prefer that list to matching
* their username in the certificate principals list.
*/
@@ -401,17 +401,17 @@ check_authkeys_file(FILE *f, char *file,
break;
} else if (key_equal(found, key)) {
if (auth_parse_options(pw, key_options, file,
linenum) != 1)
continue;
if (key_is_cert_authority)
continue;
found_key = 1;
- fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(found, key_fp_type_select(), SSH_FP_HEX);
debug("matching key found: file %s, line %lu %s %s",
file, linenum, key_type(found), fp);
free(fp);
break;
}
}
if (found != NULL)
key_free(found);
@@ -427,17 +427,17 @@ user_cert_trusted_ca(struct passwd *pw,
char *ca_fp, *principals_file = NULL;
const char *reason;
int ret = 0;
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);
+ key_fp_type_select(), 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,
options.trusted_user_ca_keys);
goto out;
}
diff --git a/openssh-6.6p1/key.c b/openssh-6.6p1/key.c
--- a/openssh-6.6p1/key.c
+++ b/openssh-6.6p1/key.c
@@ -420,30 +420,39 @@ key_fingerprint_raw(const Key *k, enum f
*dgst_raw_length = ssh_digest_bytes(hash_alg);
} else {
fatal("%s: blob is null", __func__);
}
return retval;
}
static char *
-key_fingerprint_hex(u_char *dgst_raw, u_int dgst_raw_len)
+key_fingerprint_hex(u_char *dgst_raw, u_int dgst_raw_len, enum fp_type dgst_type)
{
char *retval;
u_int i;
- retval = xcalloc(1, dgst_raw_len * 3 + 1);
+ /* reserve space for both the key hash and the string for the hash type */
+ retval = xcalloc(1, dgst_raw_len * 3 + 1 + SSH_FP_TYPE_STRLEN + 2);
for (i = 0; i < dgst_raw_len; i++) {
char hex[4];
snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]);
strlcat(retval, hex, dgst_raw_len * 3 + 1);
}
/* Remove the trailing ':' character */
- retval[(dgst_raw_len * 3) - 1] = '\0';
+ retval[(dgst_raw_len * 3) - 1] = ' ';
+
+ /* Append hash type */
+ {
+ char hash[SSH_FP_TYPE_STRLEN + 2 + 1];
+ snprintf(hash, sizeof(hash), "[%s]", key_fp_type_str(dgst_type));
+ strlcat(retval, hash, dgst_raw_len * 3 + 1 + SSH_FP_TYPE_STRLEN + 2);
+ }
+
return retval;
}
static char *
key_fingerprint_bubblebabble(u_char *dgst_raw, u_int dgst_raw_len)
{
char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' };
char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',
@@ -518,17 +527,18 @@ key_fingerprint_bubblebabble(u_char *dgs
* can be in the exact middle of the picture, and FLDBASE should be >=8 .
* Else pictures would be too dense, and drawing the frame would
* fail, too, because the key type would not fit in anymore.
*/
#define FLDBASE 8
#define FLDSIZE_Y (FLDBASE + 1)
#define FLDSIZE_X (FLDBASE * 2 + 1)
static char *
-key_fingerprint_randomart(u_char *dgst_raw, u_int dgst_raw_len, const Key *k)
+key_fingerprint_randomart(u_char *dgst_raw, u_int dgst_raw_len, const Key *k,
+ enum fp_type dgst_type)
{
/*
* Chars to be used after each other every time the worm
* intersects with itself. Matter of taste.
*/
char *augmentation_string = " .o+=*BOX@%&#/^SE";
char *retval, *p;
u_char field[FLDSIZE_X][FLDSIZE_Y];
@@ -585,18 +595,19 @@ key_fingerprint_randomart(u_char *dgst_r
*p++ = '|';
for (x = 0; x < FLDSIZE_X; x++)
*p++ = augmentation_string[MIN(field[x][y], len)];
*p++ = '|';
*p++ = '\n';
}
/* output lower border */
- *p++ = '+';
- for (i = 0; i < FLDSIZE_X; i++)
+ i = snprintf(p, FLDSIZE_X, "+--[%s]", key_fp_type_str(dgst_type));
+ p += i;
+ for (i--; i < FLDSIZE_X; i++)
*p++ = '-';
*p++ = '+';
return retval;
}
char *
key_fingerprint(const Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep)
@@ -605,34 +616,91 @@ key_fingerprint(const Key *k, enum fp_ty
u_char *dgst_raw;
u_int dgst_raw_len;
dgst_raw = key_fingerprint_raw(k, dgst_type, &dgst_raw_len);
if (!dgst_raw)
fatal("key_fingerprint: null from key_fingerprint_raw()");
switch (dgst_rep) {
case SSH_FP_HEX:
- retval = key_fingerprint_hex(dgst_raw, dgst_raw_len);
+ retval = key_fingerprint_hex(dgst_raw, dgst_raw_len, dgst_type);
break;
case SSH_FP_BUBBLEBABBLE:
retval = key_fingerprint_bubblebabble(dgst_raw, dgst_raw_len);
break;
case SSH_FP_RANDOMART:
- retval = key_fingerprint_randomart(dgst_raw, dgst_raw_len, k);
+ retval = key_fingerprint_randomart(dgst_raw, dgst_raw_len, k, dgst_type);
break;
default:
fatal("key_fingerprint: bad digest representation %d",
dgst_rep);
break;
}
explicit_bzero(dgst_raw, dgst_raw_len);
free(dgst_raw);
return retval;
}
+enum fp_type
+key_fp_type_select(void)
+{
+ static enum fp_type fp;
+ static char fp_defined = 0;
+ char *env;
+
+ if (!fp_defined) {
+ env = getenv(SSH_FP_TYPE_ENVVAR);
+ if (env) {
+ if (!strcasecmp(env, "md5") ||
+ !strcasecmp(env, "md-5"))
+ fp = SSH_FP_MD5;
+ else if (!strcasecmp(env, "sha1") ||
+ !strcasecmp(env, "sha-1"))
+ fp = SSH_FP_SHA1;
+#ifdef HAVE_EVP_SHA256
+ else if (!strcasecmp(env, "sha256") ||
+ !strcasecmp(env, "sha-256"))
+ fp = SSH_FP_SHA256;
+#endif
+ else {
+ error("invalid key type in environment variable "
+ SSH_FP_TYPE_ENVVAR ": '%s' - falling back to MD5.",
+ env);
+ fp = SSH_FP_MD5;
+ }
+ } else
+ fp = SSH_FP_MD5;
+
+ fp_defined = 1;
+ }
+ return fp;
+}
+
+/*
+ * string lengths must be less or equal to SSH_FP_TYPE_STRLEN (defined in
+ * key.h) as to fit into the fingerprint string buffer
+ */
+char *
+key_fp_type_str(enum fp_type dgst_type)
+{
+ switch (dgst_type) {
+ case SSH_FP_MD5:
+ return "MD5";
+ case SSH_FP_SHA1:
+ return "SHA-1";
+#ifdef HAVE_EVP_SHA256
+ case SSH_FP_SHA256:
+ return "SHA-256";
+#endif
+ default:
+ fatal("%s: unknown key fingerprint hash algorithm requested", __func__);
+ }
+}
+
+
/*
* Reads a multiple-precision integer in decimal from the buffer, and advances
* the pointer. The integer must already be initialized. This function is
* permitted to modify the buffer. This leaves *cpp to point just beyond the
* last processed (and maybe modified) character. Note that this may modify
* the buffer containing the number.
*/
static int
diff --git a/openssh-6.6p1/key.h b/openssh-6.6p1/key.h
--- a/openssh-6.6p1/key.h
+++ b/openssh-6.6p1/key.h
@@ -53,16 +53,18 @@ enum fp_type {
SSH_FP_MD5,
SSH_FP_SHA256
};
enum fp_rep {
SSH_FP_HEX,
SSH_FP_BUBBLEBABBLE,
SSH_FP_RANDOMART
};
+#define SSH_FP_TYPE_ENVVAR "SSH_FINGERPRINT_TYPE"
+#define SSH_FP_TYPE_STRLEN 8
/* key is stored in external hardware */
#define KEY_FLAG_EXT 0x0001
#define CERT_MAX_PRINCIPALS 256
struct KeyCert {
Buffer certblob; /* Kept around for use on wire */
u_int type; /* SSH2_CERT_TYPE_USER or SSH2_CERT_TYPE_HOST */
@@ -104,16 +106,18 @@ int key_equal_public(const Key *, cons
int key_equal(const Key *, const Key *);
char *key_fingerprint(const Key *, enum fp_type, enum fp_rep);
u_char *key_fingerprint_raw(const Key *, enum fp_type, u_int *);
const char *key_type(const Key *);
const char *key_cert_type(const Key *);
int key_write(const Key *, FILE *);
int key_read(Key *, char **);
u_int key_size(const Key *);
+enum fp_type key_fp_type_select(void);
+char *key_fp_type_str(enum fp_type);
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_type_is_cert(int);
int key_type_plain(int);
int key_to_certified(Key *, int);
diff --git a/openssh-6.6p1/ssh-add.c b/openssh-6.6p1/ssh-add.c
--- a/openssh-6.6p1/ssh-add.c
+++ b/openssh-6.6p1/ssh-add.c
@@ -325,17 +325,17 @@ list_identities(AuthenticationConnection
int version;
for (version = 1; version <= 2; version++) {
for (key = ssh_get_first_identity(ac, &comment, version);
key != NULL;
key = ssh_get_next_identity(ac, &comment, version)) {
had_identities = 1;
if (do_fp) {
- fp = key_fingerprint(key, SSH_FP_MD5,
+ fp = key_fingerprint(key, key_fp_type_select(),
SSH_FP_HEX);
printf("%d %s %s (%s)\n",
key_size(key), fp, comment, key_type(key));
free(fp);
} else {
if (!key_write(key, stdout))
fprintf(stderr, "key_write failed");
fprintf(stdout, " %s\n", comment);
diff --git a/openssh-6.6p1/ssh-agent.c b/openssh-6.6p1/ssh-agent.c
--- a/openssh-6.6p1/ssh-agent.c
+++ b/openssh-6.6p1/ssh-agent.c
@@ -193,17 +193,17 @@ lookup_identity(Key *key, int version)
/* Check confirmation of keysign request */
static int
confirm_key(Identity *id)
{
char *p;
int ret = -1;
- p = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX);
+ p = key_fingerprint(id->key, key_fp_type_select(), SSH_FP_HEX);
if (ask_permission("Allow use of key %s?\nKey fingerprint %s.",
id->comment, p))
ret = 0;
free(p);
return (ret);
}
diff --git a/openssh-6.6p1/ssh-keygen.c b/openssh-6.6p1/ssh-keygen.c
--- a/openssh-6.6p1/ssh-keygen.c
+++ b/openssh-6.6p1/ssh-keygen.c
@@ -741,27 +741,27 @@ do_download(struct passwd *pw)
{
#ifdef ENABLE_PKCS11
Key **keys = NULL;
int i, nkeys;
enum fp_rep rep;
enum fp_type fptype;
char *fp, *ra;
- fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
+ fptype = print_bubblebabble ? SSH_FP_SHA1 : key_fp_type_select();
rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
pkcs11_init(0);
nkeys = pkcs11_add_provider(pkcs11provider, NULL, &keys);
if (nkeys <= 0)
fatal("cannot read public key from pkcs11");
for (i = 0; i < nkeys; i++) {
if (print_fingerprint) {
fp = key_fingerprint(keys[i], fptype, rep);
- ra = key_fingerprint(keys[i], SSH_FP_MD5,
+ ra = key_fingerprint(keys[i], key_fp_type_select(),
SSH_FP_RANDOMART);
printf("%u %s %s (PKCS11 key)\n", key_size(keys[i]),
fp, key_type(keys[i]));
if (log_level >= SYSLOG_LEVEL_VERBOSE)
printf("%s\n", ra);
free(ra);
free(fp);
} else {
@@ -784,29 +784,29 @@ do_fingerprint(struct passwd *pw)
FILE *f;
Key *public;
char *comment = NULL, *cp, *ep, line[16*1024], *fp, *ra;
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_fp_type_select();
rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
if (!have_identity)
ask_filename(pw, "Enter file in which the key is");
if (stat(identity_file, &st) < 0) {
perror(identity_file);
exit(1);
}
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);
+ ra = key_fingerprint(public, key_fp_type_select(), SSH_FP_RANDOMART);
printf("%u %s %s (%s)\n", key_size(public), fp, comment,
key_type(public));
if (log_level >= SYSLOG_LEVEL_VERBOSE)
printf("%s\n", ra);
key_free(public);
free(comment);
free(ra);
free(fp);
@@ -862,17 +862,17 @@ do_fingerprint(struct passwd *pw)
public = key_new(KEY_UNSPEC);
if (key_read(public, &cp) != 1) {
key_free(public);
continue;
}
}
comment = *cp ? cp : comment;
fp = key_fingerprint(public, fptype, rep);
- ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART);
+ ra = key_fingerprint(public, key_fp_type_select(), SSH_FP_RANDOMART);
printf("%u %s %s (%s)\n", key_size(public), fp,
comment ? comment : "no comment", key_type(public));
if (log_level >= SYSLOG_LEVEL_VERBOSE)
printf("%s\n", ra);
free(ra);
free(fp);
key_free(public);
invalid = 0;
@@ -983,20 +983,20 @@ do_gen_all_hostkeys(struct passwd *pw)
static void
printhost(FILE *f, const char *name, Key *public, int ca, int hash)
{
if (print_fingerprint) {
enum fp_rep rep;
enum fp_type fptype;
char *fp, *ra;
- fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
+ fptype = print_bubblebabble ? SSH_FP_SHA1 : key_fp_type_select();
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);
+ ra = key_fingerprint(public, key_fp_type_select(), SSH_FP_RANDOMART);
printf("%u %s %s (%s)\n", key_size(public), fp, name,
key_type(public));
if (log_level >= SYSLOG_LEVEL_VERBOSE)
printf("%s\n", ra);
free(ra);
free(fp);
} else {
if (hash && (name = host_hash(name, NULL, 0)) == NULL)
@@ -1873,19 +1873,19 @@ do_show_cert(struct passwd *pw)
if (stat(identity_file, &st) < 0)
fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
if ((key = key_load_public(identity_file, NULL)) == NULL)
fatal("%s is not a public key", identity_file);
if (!key_is_cert(key))
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);
+ key_fp = key_fingerprint(key, key_fp_type_select(), SSH_FP_HEX);
ca_fp = key_fingerprint(key->cert->signature_key,
- SSH_FP_MD5, SSH_FP_HEX);
+ key_fp_type_select(), 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(" Key ID: \"%s\"\n", key->cert->key_id);
@@ -2681,18 +2681,18 @@ passphrase_again:
exit(1);
}
if (!key_write(public, f))
fprintf(stderr, "write key failed\n");
fprintf(f, " %s\n", comment);
fclose(f);
if (!quiet) {
- char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX);
- char *ra = key_fingerprint(public, SSH_FP_MD5,
+ char *fp = key_fingerprint(public, key_fp_type_select(), SSH_FP_HEX);
+ char *ra = key_fingerprint(public, key_fp_type_select(),
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("The key's randomart image is:\n");
printf("%s\n", ra);
free(ra);
diff --git a/openssh-6.6p1/sshconnect.c b/openssh-6.6p1/sshconnect.c
--- a/openssh-6.6p1/sshconnect.c
+++ b/openssh-6.6p1/sshconnect.c
@@ -909,18 +909,18 @@ check_host_key(char *hostname, struct so
"address '%.128s' to the list of known "
"hosts (%.30s).", type, ip,
user_hostfiles[0]);
else
logit("Warning: Permanently added the %s host "
"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,
+ fp = key_fingerprint(host_key, key_fp_type_select(), SSH_FP_HEX);
+ ra = key_fingerprint(host_key, key_fp_type_select(),
SSH_FP_RANDOMART);
logit("Host key fingerprint is %s\n%s\n", fp, ra);
free(ra);
free(fp);
}
break;
case HOST_NEW:
if (options.host_key_alias == NULL && port != 0 &&
@@ -950,18 +950,18 @@ check_host_key(char *hostname, struct so
if (show_other_keys(host_hostkeys, host_key))
snprintf(msg1, sizeof(msg1),
"\nbut keys of different type are already"
" known for this host.");
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,
+ fp = key_fingerprint(host_key, key_fp_type_select(), SSH_FP_HEX);
+ ra = key_fingerprint(host_key, key_fp_type_select(),
SSH_FP_RANDOMART);
msg2[0] = '\0';
if (options.verify_host_key_dns) {
if (matching_host_key_dns)
snprintf(msg2, sizeof(msg2),
"Matching host key fingerprint"
" found in DNS.\n");
else
@@ -1215,17 +1215,17 @@ fail:
/* returns 0 if key verifies or -1 if key does NOT verify */
int
verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
{
int flags = 0;
char *fp;
- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(host_key, key_fp_type_select(), SSH_FP_HEX);
debug("Server host key: %s %s", key_type(host_key), fp);
free(fp);
/* XXX certs are not yet supported for DNS */
if (!key_is_cert(host_key) && options.verify_host_key_dns &&
verify_host_key_dns(host, hostaddr, host_key, &flags) == 0) {
if (flags & DNS_VERIFY_FOUND) {
@@ -1322,18 +1322,18 @@ show_other_keys(struct hostkeys *hostkey
char *fp, *ra;
const struct hostkey_entry *found;
for (i = 0; type[i] != -1; i++) {
if (type[i] == key->type)
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_fingerprint(found->key, key_fp_type_select(), SSH_FP_HEX);
+ ra = key_fingerprint(found->key, key_fp_type_select(), SSH_FP_RANDOMART);
logit("WARNING: %s key found for host %s\n"
"in %s:%lu\n"
"%s key fingerprint %s.",
key_type(found->key),
found->host, found->file, found->line,
key_type(found->key), fp);
if (options.visual_host_key)
logit("%s", ra);
@@ -1344,17 +1344,17 @@ show_other_keys(struct hostkeys *hostkey
return ret;
}
static void
warn_changed_key(Key *host_key)
{
char *fp;
- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(host_key, key_fp_type_select(), SSH_FP_HEX);
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @");
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
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.",
diff --git a/openssh-6.6p1/sshconnect2.c b/openssh-6.6p1/sshconnect2.c
--- a/openssh-6.6p1/sshconnect2.c
+++ b/openssh-6.6p1/sshconnect2.c
@@ -579,17 +579,17 @@ input_userauth_pk_ok(int type, u_int32_t
goto done;
}
if (key->type != pktype) {
error("input_userauth_pk_ok: type mismatch "
"for decoded key (received %d, expected %d)",
key->type, pktype);
goto done;
}
- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(key, key_fp_type_select(), SSH_FP_HEX);
debug2("input_userauth_pk_ok: fp %s", fp);
free(fp);
/*
* search keys in the reverse order, because last candidate has been
* moved to the end of the queue. this also avoids confusion by
* duplicate keys
*/
@@ -990,17 +990,17 @@ sign_and_send_pubkey(Authctxt *authctxt,
Buffer b;
u_char *blob, *signature;
u_int bloblen, slen;
u_int skip = 0;
int ret = -1;
int have_sig = 1;
char *fp;
- fp = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX);
+ fp = key_fingerprint(id->key, key_fp_type_select(), SSH_FP_HEX);
debug3("sign_and_send_pubkey: %s %s", key_type(id->key), fp);
free(fp);
if (key_to_blob(id->key, &blob, &bloblen) == 0) {
/* we cannot handle this key */
debug3("sign_and_send_pubkey: cannot handle key");
return 0;
}

View File

@ -0,0 +1,529 @@
# HG changeset patch
# Parent 717873621cf4991164c61caafd9ac07473231f10
# Simple implementation of FIPS 140-2 selfchecks. Use OpenSSL to generate and
# verify checksums of binaries. Any hash iused in OpenSSH can be used (MD5 would
# obviously be a poor choice, since OpenSSL would barf and abort immediately in
# FIPS mode). SHA-2 seems to be a reasonable choice.
#
# The logic of the checks is as follows: decide whether FIPS mode is mandated
# (either by checking /proc/sys/crypto/fips_enabled or envoroinment variable
# SSH_FORCE_FIPS. In FIPS mode, checksums are required to match (inability to
# retrieve pre-calculated hash is a fatal error). In non-FIPS mode the checks
# still must be performed, unless the hashes are not installed. Thus if the hash
# file is not found (or the hash matches), proceed in non-FIPS mode and abort
# otherwise.
diff --git a/openssh-6.6p1/fips-check.c b/openssh-6.6p1/fips-check.c
new file mode 100644
--- /dev/null
+++ b/openssh-6.6p1/fips-check.c
@@ -0,0 +1,37 @@
+#include "includes.h"
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "digest.h"
+#include "fips.h"
+
+#include <openssl/err.h>
+
+#define PROC_NAME_LEN 64
+
+static const char *argv0;
+
+void
+print_help_exit(int ev)
+{
+ fprintf(stderr, "%s <-c|-w> <file> <checksum_file>\n", argv0);
+ fprintf(stderr, " -c verify hash of 'file' against hash in 'checksum_file'\n");
+ fprintf(stderr, " -w write hash of 'file' into 'checksum_file'\n");
+ exit(ev);
+}
+
+int
+main(int argc, char **argv)
+{
+
+ fips_ssh_init();
+// printf("SSL Error: %lx: %s", ERR_get_error(), ERR_get_string(ERR_get_error(), NULL));
+
+ return 0;
+}
diff --git a/openssh-6.6p1/fips.c b/openssh-6.6p1/fips.c
--- a/openssh-6.6p1/fips.c
+++ b/openssh-6.6p1/fips.c
@@ -24,21 +24,342 @@
#include "includes.h"
#include "fips.h"
#include "digest.h"
#include "key.h"
#include "log.h"
+#include "xmalloc.h"
+#include <openbsd-compat/openssl-compat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
#include <openssl/crypto.h>
+#include <openssl/err.h>
+
+enum fips_checksum_status {
+ CHECK_OK = 0,
+ CHECK_FAIL,
+ CHECK_MISSING
+};
static int fips_state = -1;
+static char *
+hex_fingerprint(u_int raw_len, u_char *raw)
+{
+ char *retval;
+ u_int i;
+
+ /* reserve space for both the key hash and the string for the hash type */
+ retval = malloc(3 * raw_len);
+ for (i = 0; i < raw_len; i++) {
+ char hex[4];
+ snprintf(hex, sizeof(hex), "%02x:", raw[i]);
+ strlcat(retval, hex, raw_len * 3);
+ }
+
+ return retval;
+}
+
+/* calculates hash of contents of file given by filename using algorithm alg
+ * and placing the resukt into newly allacated memory - remember to free it
+ * when not needed anymore */
+static int
+hash_file(const char *filename, int alg, u_char **hash_out)
+{
+ int check = -1;
+ int hash_len;
+ int fd;
+ struct stat fs;
+ void *hmap;
+ char *hash;
+
+ hash_len = ssh_digest_bytes(alg);
+ hash = xmalloc(hash_len);
+
+ fd = open(filename, O_RDONLY);
+ if (-1 == fd)
+ goto bail_out;
+
+ if (-1 == fstat(fd, &fs))
+ goto bail_out;
+
+ hmap = mmap(NULL, fs.st_size, PROT_READ, MAP_SHARED, fd, 0);
+
+ if ((void *)(-1) != hmap) {
+ check = ssh_digest_memory(alg, hmap, fs.st_size, hash, hash_len);
+ munmap(hmap, fs.st_size);
+ }
+ close(fd);
+
+bail_out:
+ if (0 == check) {
+ check = CHECK_OK;
+ *hash_out = hash;
+ } else {
+ check = CHECK_FAIL;
+ *hash_out = NULL;
+ free(hash);
+ }
+ return check;
+}
+
+/* find pathname of binary of process with PID pid. exe is buffer expected to
+ * be capable of holding at least max_pathlen characters
+ */
+static int
+get_executable_path(pid_t pid, char *exe, int max_pathlen)
+{
+ char exe_sl[PROC_EXE_PATH_LEN];
+ int n;
+
+ n = snprintf(exe_sl, sizeof(exe_sl), "/proc/%u/exe", pid);
+ if ((n <= 10) || (n >= max_pathlen)) {
+ fatal("error compiling filename of link to executable");
+ }
+
+ n = readlink(exe_sl, exe, max_pathlen);
+ if (n < max_pathlen) {
+ exe[n] = 0;
+ } else {
+ fatal("error getting executable pathname");
+ }
+ return 0;
+}
+
+/* Read checksum file chk, storing the algorithm used for generating it into
+ * *alg; allocate enough memory to hold the hash and return it in *hash.
+ * Remember to free() it when not needed anymore.
+ */
+static int
+read_hash(const char *chk, int *alg, u_char **hash)
+{
+ int check = -1;
+ int hash_len;
+ int fdh, n;
+ char alg_c;
+ char *hash_in;
+
+ *hash = NULL;
+
+ fdh = open(chk, O_RDONLY);
+ if (-1 == fdh) {
+ switch (errno) {
+ case ENOENT:
+ check = CHECK_MISSING;
+ debug("fips: checksum file %s is missing\n", chk);
+ break;
+ default:
+ check = CHECK_FAIL;
+ debug("fips: ckecksum file %s not accessible\n", chk);
+ break;
+
+ }
+ goto bail_out;
+ }
+
+ n = read(fdh, &alg_c, 1);
+ if (1 != n) {
+ check = CHECK_FAIL;
+ goto bail_out;
+ }
+
+ *alg = (int)alg_c;
+ hash_len = ssh_digest_bytes(*alg);
+ hash_in = xmalloc(hash_len);
+
+ n = read(fdh, (void *)hash_in, hash_len);
+ if (hash_len != n) {
+ debug("fips: unable to read whole checksum from checksum file\n");
+ free (hash_in);
+ check = CHECK_FAIL;
+ } else {
+ check = CHECK_OK;
+ *hash = hash_in;
+ }
+bail_out:
+ return check;
+}
+
+static int
+fips_hash_self(void)
+{
+ int check = -1;
+ int alg;
+ u_char *hash, *hash_chk;
+ char *exe, *chk;
+
+ exe = xmalloc(PATH_MAX);
+ chk = xmalloc(PATH_MAX);
+
+ /* we will need to add the ".chk" suffix and the null terminator */
+ check = get_executable_path(getpid(), exe
+ , PATH_MAX - strlen(CHECKSUM_SUFFIX) - 1);
+
+ strncpy(chk, exe, PATH_MAX);
+ strlcat(chk, CHECKSUM_SUFFIX, PATH_MAX);
+
+ check = read_hash(chk, &alg, &hash_chk);
+ if (CHECK_OK != check)
+ goto cleanup_chk;
+
+ check = hash_file(exe, alg, &hash);
+ if (CHECK_OK != check)
+ goto cleanup;
+
+ check = memcmp(hash, hash_chk, ssh_digest_bytes(alg));
+ if (0 == check) {
+ check = CHECK_OK;
+ debug("fips: checksum matches\n");
+ } else {
+ check = CHECK_FAIL;
+ debug("fips: checksum mismatch!\n");
+ }
+
+cleanup:
+ free(hash);
+cleanup_chk:
+ free(hash_chk);
+ free(chk);
+ free(exe);
+
+ return check;
+}
+
+static int
+fips_check_required_proc(void)
+{
+ int fips_required = 0;
+ int fips_fd;
+ char fips_sys = 0;
+
+ struct stat dummy;
+ if (-1 == stat(FIPS_PROC_PATH, &dummy)) {
+ switch (errno) {
+ case ENOENT:
+ case ENOTDIR:
+ break;
+ default:
+ fatal("Check for system-wide FIPS mode is required and %s cannot"
+ " be accessed for reason other than non-existence - aborting"
+ , FIPS_PROC_PATH);
+ break;
+ }
+ } else {
+ if (-1 == (fips_fd = open(FIPS_PROC_PATH, O_RDONLY)))
+ fatal("Check for system-wide FIPS mode is required and %s cannot"
+ " be opened for reading - aborting"
+ , FIPS_PROC_PATH);
+ if (1 > read(fips_fd, &fips_sys, 1))
+ fatal("Check for system-wide FIPS mode is required and %s doesn't"
+ " return at least one character - aborting"
+ , FIPS_PROC_PATH);
+ close(fips_sys);
+ switch (fips_sys) {
+ case '0':
+ case '1':
+ fips_required = fips_sys - '0';
+ break;
+ default:
+ fatal("Bogus character %c found in %s - aborting"
+ , fips_sys, FIPS_PROC_PATH);
+ }
+ }
+ return fips_required;
+}
+
+static int
+fips_check_required_env(void)
+{
+ int fips_required = 0;
+ char *env = getenv(SSH_FORCE_FIPS_ENV);
+
+ if (env) {
+ errno = 0;
+ fips_required = strtol(env, NULL, 10);
+ if (errno) {
+ debug("bogus value in the %s environment variable, ignoring\n"
+ , SSH_FORCE_FIPS_ENV);
+ fips_required = 0;
+ } else
+ fips_required = 1;
+ }
+ return fips_required;
+}
+
+static int
+fips_required(void)
+{
+ int fips_requests = 0;
+ fips_requests += fips_check_required_proc();
+ fips_requests += fips_check_required_env();
+ return fips_requests;
+}
+
+/* check whether FIPS mode is required and perform selfchecksum/selftest */
+void
+fips_ssh_init(void)
+{
+ int checksum;
+
+ checksum = fips_hash_self();
+
+ if (fips_required()) {
+ switch (checksum) {
+ case CHECK_OK:
+ debug("fips: mandatory checksum ok");
+ break;
+ case CHECK_FAIL:
+ fatal("fips: mandatory checksum failed - aborting");
+ break;
+ case CHECK_MISSING:
+ fatal("fips: mandatory checksum data missing - aborting");
+ break;
+ default:
+ fatal("Fatal error: internal error at %s:%u"
+ , __FILE__, __LINE__);
+ break;
+ }
+ fips_state = FIPS_mode_set(1);
+ if (1 != fips_state) {
+ ERR_load_crypto_strings();
+ u_long err = ERR_get_error();
+ error("fips: OpenSSL error %lx: %s", err, ERR_error_string(err, NULL));
+ fatal("fips: unable to set OpenSSL into FIPS mode - aborting"
+ , fips_state);
+ }
+ } else {
+ switch (checksum) {
+ case CHECK_OK:
+ debug("fips: checksum ok");
+ break;
+ case CHECK_FAIL:
+ fatal("fips: checksum failed - aborting");
+ break;
+ case CHECK_MISSING:
+ debug("fips: mandatory checksum data missing, but not required - continuing non-FIPS");
+ break;
+ default:
+ fatal("Fatal error: internal error at %s:%u",
+ __FILE__, __LINE__);
+ break;
+ }
+ }
+ return;
+}
+
int
fips_mode()
{
if (-1 == fips_state) {
fips_state = FIPS_mode();
if (fips_state)
debug("FIPS mode initialized");
}
diff --git a/openssh-6.6p1/fips.h b/openssh-6.6p1/fips.h
--- a/openssh-6.6p1/fips.h
+++ b/openssh-6.6p1/fips.h
@@ -1,10 +1,10 @@
/*
- * Copyright (c) 2012 Petr Cerny. All rights reserved.
+ * Copyright (c) 2012-2014 Petr Cerny. All rights reserved.
*
* 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
@@ -19,15 +19,22 @@
* 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.
*/
#ifndef FIPS_H
#define FIPS_H
+#define SSH_FORCE_FIPS_ENV "SSH_FORCE_FIPS"
+#define FIPS_PROC_PATH "/proc/sys/crypto/fips_enabled"
+
+#define PROC_EXE_PATH_LEN 64
+#define CHECKSUM_SUFFIX ".chk"
+
+void fips_ssh_init(void);
int fips_mode(void);
int fips_correct_dgst(int);
int fips_dgst_min(void);
enum fp_type fips_correct_fp_type(enum fp_type);
#endif
diff --git a/openssh-6.6p1/sftp-server.c b/openssh-6.6p1/sftp-server.c
--- a/openssh-6.6p1/sftp-server.c
+++ b/openssh-6.6p1/sftp-server.c
@@ -47,16 +47,18 @@
#include "log.h"
#include "misc.h"
#include "match.h"
#include "uidswap.h"
#include "sftp.h"
#include "sftp-common.h"
+#include "fips.h"
+
/* helper */
#define get_int64() buffer_get_int64(&iqueue);
#define get_int() buffer_get_int(&iqueue);
#define get_string(lenp) buffer_get_string(&iqueue, lenp);
/* Our verbosity */
static LogLevel log_level = SYSLOG_LEVEL_ERROR;
@@ -1453,16 +1455,19 @@ sftp_server_main(int argc, char **argv,
ssize_t len, olen, set_size;
SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
char *cp, *homedir = NULL, buf[4*4096];
long mask;
extern char *optarg;
extern char *__progname;
+ /* initialize fips */
+ fips_ssh_init();
+
__progname = ssh_get_progname(argv[0]);
log_init(__progname, log_level, log_facility, log_stderr);
pw = pwcopy(user_pw);
while (!skipargs && (ch = getopt(argc, argv,
"d:f:l:P:p:Q:u:m:cehR")) != -1) {
switch (ch) {
diff --git a/openssh-6.6p1/ssh.c b/openssh-6.6p1/ssh.c
--- a/openssh-6.6p1/ssh.c
+++ b/openssh-6.6p1/ssh.c
@@ -420,16 +420,19 @@ main(int ac, char **av)
struct stat st;
struct passwd *pw;
int timeout_ms;
extern int optind, optreset;
extern char *optarg;
Forward fwd;
struct addrinfo *addrs = NULL;
+ /* initialize fips */
+ fips_ssh_init();
+
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
__progname = ssh_get_progname(av[0]);
#ifndef HAVE_SETPROCTITLE
/* Prepare for later setproctitle emulation */
/* Save argv so it isn't clobbered by setproctitle() emulation */
diff --git a/openssh-6.6p1/sshd.c b/openssh-6.6p1/sshd.c
--- a/openssh-6.6p1/sshd.c
+++ b/openssh-6.6p1/sshd.c
@@ -1466,16 +1466,19 @@ main(int ac, char **av)
u_int64_t ibytes, obytes;
mode_t new_umask;
Key *key;
Key *pubkey;
int keytype;
Authctxt *authctxt;
struct connection_info *connection_info = get_connection_info(0, 0);
+ /* initialize fips */
+ fips_ssh_init();
+
#ifdef HAVE_SECUREWARE
(void)set_auth_parameters(ac, av);
#endif
__progname = ssh_get_progname(av[0]);
/* Save argv. Duplicate so setproctitle emulation doesn't clobber it */
saved_argc = ac;
rexec_argc = ac;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -13,11 +13,41 @@
# recommended to use the 'gssapi-with-mic' mechanism. Existing installations
# are encouraged to upgrade as soon as possible.
Index: b/auth2-gss.c
===================================================================
--- a/auth2-gss.c
+++ b/auth2-gss.c
@@ -296,4 +296,10 @@ Authmethod method_gssapi = {
diff --git a/openssh-6.6p1/auth2-gss.c b/openssh-6.6p1/auth2-gss.c
--- a/openssh-6.6p1/auth2-gss.c
+++ b/openssh-6.6p1/auth2-gss.c
@@ -168,16 +168,25 @@ input_gssapi_token(int type, u_int32_t p
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
if (flags & GSS_C_INTEG_FLAG)
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC,
&input_gssapi_mic);
else
dispatch_set(
SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE,
&input_gssapi_exchange_complete);
+
+ /*
+ * Old style 'gssapi' didn't have the GSSAPI_MIC
+ * and went straight to sending exchange_complete
+ */
+ if (options.gss_enable_mitm)
+ dispatch_set(
+ SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE,
+ &input_gssapi_exchange_complete);
}
}
gss_release_buffer(&min_status, &send_tok);
}
static void
input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
@@ -286,9 +295,15 @@ input_gssapi_mic(int type, u_int32_t ple
}
Authmethod method_gssapi = {
"gssapi-with-mic",
userauth_gssapi,
&options.gss_authentication
};
@ -28,11 +58,15 @@ Index: b/auth2-gss.c
+};
+
#endif /* GSSAPI */
Index: b/auth2.c
===================================================================
--- a/auth2.c
+++ b/auth2.c
@@ -71,6 +71,7 @@ extern Authmethod method_kbdint;
diff --git a/openssh-6.6p1/auth2.c b/openssh-6.6p1/auth2.c
--- a/openssh-6.6p1/auth2.c
+++ b/openssh-6.6p1/auth2.c
@@ -65,23 +65,25 @@ extern Buffer loginmsg;
extern Authmethod method_none;
extern Authmethod method_pubkey;
extern Authmethod method_passwd;
extern Authmethod method_kbdint;
extern Authmethod method_hostbased;
#ifdef GSSAPI
extern Authmethod method_gssapi;
@ -40,7 +74,7 @@ Index: b/auth2.c
#endif
Authmethod *authmethods[] = {
@@ -78,6 +79,7 @@ Authmethod *authmethods[] = {
&method_none,
&method_pubkey,
#ifdef GSSAPI
&method_gssapi,
@ -48,11 +82,20 @@ Index: b/auth2.c
#endif
&method_passwd,
&method_kbdint,
Index: b/readconf.c
===================================================================
--- a/readconf.c
+++ b/readconf.c
@@ -146,7 +146,7 @@ typedef enum {
&method_hostbased,
NULL
};
/* protocol */
diff --git a/openssh-6.6p1/readconf.c b/openssh-6.6p1/readconf.c
--- a/openssh-6.6p1/readconf.c
+++ b/openssh-6.6p1/readconf.c
@@ -135,17 +135,17 @@ typedef enum {
oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
oHostKeyAlgorithms, oBindAddress, oPKCS11Provider,
oClearAllForwardings, oNoHostAuthenticationForLocalhost,
oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
@ -61,7 +104,17 @@ Index: b/readconf.c
oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
oSendEnv, oControlPath, oControlMaster, oControlPersist,
oHashKnownHosts,
@@ -193,9 +193,11 @@ static struct {
oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
oVisualHostKey, oUseRoaming,
oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass,
oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
@@ -179,19 +179,21 @@ static struct {
{ "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
{ "tisauthentication", oChallengeResponseAuthentication }, /* alias */
{ "kerberosauthentication", oUnsupported },
{ "kerberostgtpassing", oUnsupported },
{ "afstokenpassing", oUnsupported },
#if defined(GSSAPI)
{ "gssapiauthentication", oGssAuthentication },
{ "gssapidelegatecredentials", oGssDelegateCreds },
@ -73,7 +126,17 @@ Index: b/readconf.c
#endif
{ "fallbacktorsh", oDeprecated },
{ "usersh", oDeprecated },
@@ -897,6 +899,10 @@ parse_time:
{ "identityfile", oIdentityFile },
{ "identityfile2", oIdentityFile }, /* obsolete */
{ "identitiesonly", oIdentitiesOnly },
{ "hostname", oHostName },
{ "hostkeyalias", oHostKeyAlias },
@@ -839,16 +841,20 @@ parse_time:
case oGssAuthentication:
intptr = &options->gss_authentication;
goto parse_flag;
case oGssDelegateCreds:
intptr = &options->gss_deleg_creds;
goto parse_flag;
@ -84,7 +147,17 @@ Index: b/readconf.c
case oBatchMode:
intptr = &options->batch_mode;
@@ -1602,6 +1608,7 @@ initialize_options(Options * options)
goto parse_flag;
case oCheckHostIP:
intptr = &options->check_host_ip;
goto parse_flag;
@@ -1493,16 +1499,17 @@ initialize_options(Options * options)
options->xauth_location = NULL;
options->gateway_ports = -1;
options->use_privileged_port = -1;
options->rsa_authentication = -1;
options->pubkey_authentication = -1;
options->challenge_response_authentication = -1;
options->gss_authentication = -1;
options->gss_deleg_creds = -1;
@ -92,7 +165,17 @@ Index: b/readconf.c
options->password_authentication = -1;
options->kbd_interactive_authentication = -1;
options->kbd_interactive_devices = NULL;
@@ -1731,6 +1738,8 @@ fill_default_options(Options * options)
options->rhosts_rsa_authentication = -1;
options->hostbased_authentication = -1;
options->batch_mode = -1;
options->check_host_ip = -1;
options->strict_host_key_checking = -1;
@@ -1613,16 +1620,18 @@ fill_default_options(Options * options)
if (options->pubkey_authentication == -1)
options->pubkey_authentication = 1;
if (options->challenge_response_authentication == -1)
options->challenge_response_authentication = 1;
if (options->gss_authentication == -1)
options->gss_authentication = 0;
if (options->gss_deleg_creds == -1)
options->gss_deleg_creds = 0;
@ -101,11 +184,20 @@ Index: b/readconf.c
if (options->password_authentication == -1)
options->password_authentication = 1;
if (options->kbd_interactive_authentication == -1)
Index: b/readconf.h
===================================================================
--- a/readconf.h
+++ b/readconf.h
@@ -46,6 +46,7 @@ typedef struct {
options->kbd_interactive_authentication = 1;
if (options->rhosts_rsa_authentication == -1)
options->rhosts_rsa_authentication = 0;
if (options->hostbased_authentication == -1)
options->hostbased_authentication = 0;
diff --git a/openssh-6.6p1/readconf.h b/openssh-6.6p1/readconf.h
--- a/openssh-6.6p1/readconf.h
+++ b/openssh-6.6p1/readconf.h
@@ -50,16 +50,17 @@ typedef struct {
* authentication. */
int rsa_authentication; /* Try RSA authentication. */
int pubkey_authentication; /* Try ssh2 pubkey authentication. */
int hostbased_authentication; /* ssh2's rhosts_rsa */
int challenge_response_authentication;
/* Try S/Key or TIS, authentication. */
int gss_authentication; /* Try GSS authentication */
int gss_deleg_creds; /* Delegate GSS credentials */
@ -113,51 +205,99 @@ Index: b/readconf.h
int password_authentication; /* Try password
* authentication. */
int kbd_interactive_authentication; /* Try keyboard-interactive auth. */
Index: b/servconf.c
===================================================================
--- a/servconf.c
+++ b/servconf.c
@@ -119,6 +119,7 @@ initialize_server_options(ServerOptions
char *kbd_interactive_devices; /* Keyboard-interactive auth devices. */
int batch_mode; /* Batch mode: do not ask for passwords. */
int check_host_ip; /* Also keep track of keys for IP address */
int strict_host_key_checking; /* Strict host key checking. */
int compression; /* Compress packets in both directions. */
diff --git a/openssh-6.6p1/servconf.c b/openssh-6.6p1/servconf.c
--- a/openssh-6.6p1/servconf.c
+++ b/openssh-6.6p1/servconf.c
@@ -104,16 +104,17 @@ initialize_server_options(ServerOptions
options->rsa_authentication = -1;
options->pubkey_authentication = -1;
options->kerberos_authentication = -1;
options->kerberos_or_local_passwd = -1;
options->kerberos_ticket_cleanup = -1;
options->kerberos_get_afs_token = -1;
options->gss_authentication=-1;
options->gss_cleanup_creds = -1;
options->gss_strict_acceptor = -1;
+ options->gss_enable_mitm = -1;
options->password_authentication = -1;
options->kbd_interactive_authentication = -1;
options->challenge_response_authentication = -1;
@@ -279,6 +280,8 @@ fill_default_server_options(ServerOption
options->permit_empty_passwd = -1;
options->permit_user_env = -1;
options->use_login = -1;
options->compression = -1;
options->rekey_limit = -1;
@@ -241,16 +242,18 @@ fill_default_server_options(ServerOption
if (options->kerberos_ticket_cleanup == -1)
options->kerberos_ticket_cleanup = 1;
if (options->kerberos_get_afs_token == -1)
options->kerberos_get_afs_token = 0;
if (options->gss_authentication == -1)
options->gss_authentication = 0;
if (options->gss_cleanup_creds == -1)
options->gss_cleanup_creds = 1;
if (options->gss_strict_acceptor == -1)
options->gss_strict_acceptor = 0;
+ if (options->gss_enable_mitm == -1)
+ options->gss_enable_mitm = 0;
if (options->password_authentication == -1)
options->password_authentication = 1;
if (options->kbd_interactive_authentication == -1)
@@ -411,7 +414,7 @@ typedef enum {
sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedKeyTypes,
sHostKeyAlgorithms,
sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
- sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
+ sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, sGssEnableMITM,
sAcceptEnv, sPermitTunnel,
options->kbd_interactive_authentication = 0;
if (options->challenge_response_authentication == -1)
options->challenge_response_authentication = 1;
if (options->permit_empty_passwd == -1)
options->permit_empty_passwd = 0;
@@ -335,17 +338,17 @@ typedef enum {
sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
sRekeyLimit, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem,
sMaxStartups, sMaxAuthTries, sMaxSessions,
sBanner, sUseDNS, sHostbasedAuthentication,
sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
sClientAliveCountMax, sAuthorizedKeysFile,
- sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
+ sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, sGssEnableMITM,
sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
sUsePrivilegeSeparation, sAllowAgentForwarding,
@@ -486,10 +489,12 @@ static struct {
sHostCertificate,
sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
sKexAlgorithms, sIPQoS, sVersionAddendum,
sAuthorizedKeysCommand, sAuthorizedKeysCommandUser,
sAuthenticationMethods, sHostKeyAgent,
sDeprecated, sUnsupported
@@ -402,19 +405,21 @@ static struct {
{ "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
{ "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
#endif
{ "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
{ "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
#ifdef GSSAPI
{ "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
{ "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
{ "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },
+ { "gssapienablemitmattack", sGssEnableMITM },
#else
{ "gssapiauthentication", sUnsupported, SSHCFG_ALL },
{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
{ "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },
+ { "gssapienablemitmattack", sUnsupported },
#endif
{ "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
@@ -1239,6 +1244,10 @@ process_server_config_line(ServerOptions
intptr = &options->gss_strict_acceptor;
{ "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
{ "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */
{ "checkmail", sDeprecated, SSHCFG_GLOBAL },
{ "listenaddress", sListenAddress, SSHCFG_GLOBAL },
{ "addressfamily", sAddressFamily, SSHCFG_GLOBAL },
@@ -1085,16 +1090,20 @@ process_server_config_line(ServerOptions
case sGssAuthentication:
intptr = &options->gss_authentication;
goto parse_flag;
case sGssCleanupCreds:
intptr = &options->gss_cleanup_creds;
goto parse_flag;
+ case sGssEnableMITM:
@ -167,23 +307,41 @@ Index: b/servconf.c
case sPasswordAuthentication:
intptr = &options->password_authentication;
goto parse_flag;
Index: b/servconf.h
===================================================================
--- a/servconf.h
+++ b/servconf.h
@@ -119,6 +119,7 @@ typedef struct {
case sKbdInteractiveAuthentication:
intptr = &options->kbd_interactive_authentication;
goto parse_flag;
diff --git a/openssh-6.6p1/servconf.h b/openssh-6.6p1/servconf.h
--- a/openssh-6.6p1/servconf.h
+++ b/openssh-6.6p1/servconf.h
@@ -108,16 +108,17 @@ typedef struct {
* such as SecurID or
* /etc/passwd */
int kerberos_ticket_cleanup; /* If true, destroy ticket
* file on logout. */
int kerberos_get_afs_token; /* If true, try to get AFS token if
* authenticated with Kerberos. */
int gss_authentication; /* If true, permit GSSAPI authentication */
int gss_cleanup_creds; /* If true, destroy cred cache on logout */
+ int gss_enable_mitm; /* If true, enable old style GSSAPI */
int gss_strict_acceptor; /* If true, restrict the GSSAPI acceptor name */
+ int gss_enable_mitm; /* If true, enable old style GSSAPI */
int password_authentication; /* If true, permit password
* authentication. */
Index: b/ssh_config
===================================================================
--- a/ssh_config
+++ b/ssh_config
@@ -56,4 +56,11 @@ ForwardX11Trusted yes
int kbd_interactive_authentication; /* If true, permit */
int challenge_response_authentication;
int permit_empty_passwd; /* If false, do not permit empty
* passwords. */
int permit_user_env; /* If true, read ~/.ssh/environment */
int use_login; /* If true, login(1) is used */
diff --git a/openssh-6.6p1/ssh_config b/openssh-6.6p1/ssh_config
--- a/openssh-6.6p1/ssh_config
+++ b/openssh-6.6p1/ssh_config
@@ -51,9 +51,16 @@ ForwardX11Trusted yes
# Ciphers aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc
# MACs hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160
# EscapeChar ~
# Tunnel no
# TunnelDevice any:any
# PermitLocalCommand no
# VisualHostKey no
# ProxyCommand ssh -q -W %h:%p gateway.example.com
@ -195,11 +353,15 @@ Index: b/ssh_config
+# GSSAPIEnableMITMAttack no
+
# RekeyLimit 1G 1h
Index: b/sshconnect2.c
===================================================================
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -326,6 +326,11 @@ Authmethod authmethods[] = {
diff --git a/openssh-6.6p1/sshconnect2.c b/openssh-6.6p1/sshconnect2.c
--- a/openssh-6.6p1/sshconnect2.c
+++ b/openssh-6.6p1/sshconnect2.c
@@ -318,16 +318,21 @@ static char *authmethods_get(void);
Authmethod authmethods[] = {
#ifdef GSSAPI
{"gssapi-with-mic",
userauth_gssapi,
NULL,
&options.gss_authentication,
NULL},
@ -211,7 +373,17 @@ Index: b/sshconnect2.c
#endif
{"hostbased",
userauth_hostbased,
@@ -703,7 +708,9 @@ process_gssapi_token(void *ctxt, gss_buf
NULL,
&options.hostbased_authentication,
NULL},
{"publickey",
userauth_pubkey,
@@ -685,17 +690,19 @@ process_gssapi_token(void *ctxt, gss_buf
packet_put_string(send_tok.value, send_tok.length);
packet_send();
gss_release_buffer(&ms, &send_tok);
}
if (status == GSS_S_COMPLETE) {
/* send either complete or MIC, depending on mechanism */
@ -222,11 +394,20 @@ Index: b/sshconnect2.c
packet_start(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE);
packet_send();
} else {
Index: b/sshd_config
===================================================================
--- a/sshd_config
+++ b/sshd_config
@@ -85,6 +85,13 @@ PasswordAuthentication no
ssh_gssapi_buildmic(&b, authctxt->server_user,
authctxt->service, "gssapi-with-mic");
gssbuf.value = buffer_ptr(&b);
gssbuf.length = buffer_len(&b);
diff --git a/openssh-6.6p1/sshd_config b/openssh-6.6p1/sshd_config
--- a/openssh-6.6p1/sshd_config
+++ b/openssh-6.6p1/sshd_config
@@ -80,16 +80,23 @@ PasswordAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no
# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes
@ -240,3 +421,8 @@ Index: b/sshd_config
# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication. Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication

View File

@ -1,14 +1,26 @@
diff -up openssh-6.8p1/HOWTO.ldap-keys.ldap openssh-6.8p1/HOWTO.ldap-keys
--- openssh-6.8p1/HOWTO.ldap-keys.ldap 2015-03-18 11:11:29.029801467 +0100
+++ openssh-6.8p1/HOWTO.ldap-keys 2015-03-18 11:11:29.029801467 +0100
@@ -0,0 +1,122 @@
# Helper app for retrieving keys from a LDAP server
# by Jan F. Chadima <jchadima@redhat.com>
#
# patch for openbsd-compat/base64.* introduces preprocessor macro
# USE_INTERNAL_B64 intended to enforce using ssh supplied functions.
# (The additional -lldap/-llber introduced in the patch cause configure to
# discover the base64 functions in glibc (libresolv) and not to build the
# internal versions. ssh-keyconverter consequently fails to link as it lacks
# the proper flags, and libopenbsd-compat doesn't contain the b64_* functions)
diff --git a/openssh-6.6p1/HOWTO.ldap-keys b/openssh-6.6p1/HOWTO.ldap-keys
new file mode 100644
--- /dev/null
+++ b/openssh-6.6p1/HOWTO.ldap-keys
@@ -0,0 +1,108 @@
+
+HOW TO START
+
+1) configure LDAP server
+ * Use LDAP server documentation
+2) add appropriate LDAP schema
+ * For OpenLDAP or SunONE Use attached schema, otherwise you have to create it.
+ * For OpenLDAP or SunONE Use attached schema, otherwise you have to create
+ it.
+ * LDAP user entry
+ User entry:
+ - attached to the 'ldapPublicKey' objectclass
@ -16,7 +28,8 @@ diff -up openssh-6.8p1/HOWTO.ldap-keys.ldap openssh-6.8p1/HOWTO.ldap-keys
+ - with a filled 'sshPublicKey' attribute
+3) insert users into LDAP
+ * Use LDAP Tree management tool as useful
+ * Entry in the LDAP server must respect 'posixAccount' and 'ldapPublicKey' which are defined in core.schema and the additionnal lpk.schema.
+ * Entry in the LDAP server must respect 'posixAccount' and 'ldapPublicKey'
+ which are defined in core.schema and the additionnal lpk.schema.
+ * Example:
+ dn: uid=captain,ou=commanders,dc=enterprise,dc=universe
+ objectclass: top
@ -36,8 +49,8 @@ diff -up openssh-6.8p1/HOWTO.ldap-keys.ldap openssh-6.8p1/HOWTO.ldap-keys
+ sshPublicKey: command="kill -9 1" ssh-rss AAAAM5...
+4) on the ssh side set in sshd_config
+ * Set up the backend
+ AuthorizedKeysCommand /usr/libexec/openssh/ssh-ldap-wrapper
+ AuthorizedKeysCommandUser <appropriate user to run LDAP>
+ AuthorizedKeysCommand "@LIBEXECDIR@/ssh-ldap-wrapper"
+ AuthorizedKeysCommandRunAs <appropriate user to run LDAP>
+ * Do not forget to set
+ PubkeyAuthentication yes
+ * Swith off unnecessary auth methods
@ -48,10 +61,7 @@ diff -up openssh-6.8p1/HOWTO.ldap-keys.ldap openssh-6.8p1/HOWTO.ldap-keys
+ * There is a possibility to change ldap.conf location
+ * There are some debug options
+ * Example
+ /usr/libexec/openssh -s -f /etc/ldap.conf -w -d >> /tmp/ldapdebuglog.txt
+7) Configure SELinux boolean which allows ldap-helper to bind ldap server
+ Run this command
+ # setsebool -P authlogin_nsswitch_use_ldap on
+ @LIBEXECDIR@/ssh-ldap-wrapper -s -f /etc/ldap.conf -w -d >> /tmp/ldapdebuglog.txt
+
+HOW TO MIGRATE FROM LPK
+
@ -67,28 +77,20 @@ diff -up openssh-6.8p1/HOWTO.ldap-keys.ldap openssh-6.8p1/HOWTO.ldap-keys
+ * ssh-ldap-helper -d -d -d -d -s <username>
+3) use tcpdump ... other ldap client etc.
+
+HOW TO CONFIGURE SSH FOR OTHER LDAP CONFIGURATION / SERVER /SCHEMA
+
+You can adjust search format string in /etc/ldap.conf using
+ 1) SSH_Filter option to limit results for only specified users
+ (this appends search condition after original query)
+ 2) Search_Format option to define your own search string using expansion
+ characters %u for username, %c for objectclass and %f for above mentioned filter.
+
+Example:
+Search_Format (&(objectclass=posixAccount)(objectclass=ldapPublicKey)(uid=%u)%f)
+
+ADVANTAGES
+
+1) Blocking an user account can be done directly from LDAP (if sshd is using PubkeyAuthentication + AuthorizedKeysCommand with ldap only).
+1) Blocking an user account can be done directly from LDAP (if sshd is using
+ PubkeyAuthentication + AuthorizedKeysCommand with ldap only).
+
+DISADVANTAGES
+
+1) LDAP must be well configured, getting the public key of some user is not a problem, but if anonymous LDAP
+ allows write to users dn, somebody could replace some user's public key by his own and impersonate some
+ of your users in all your server farm -- be VERY CAREFUL.
+2) With incomplete PKI the MITM attack when sshd is requesting the public key, could lead to a compromise of your servers allowing login
+ as the impersonated user.
+1) LDAP must be well configured, getting the public key of some user is not
+ a problem, but if anonymous LDAP allows write to users dn, somebody could
+ replace some user's public key by his own and impersonate some of your users
+ in all your server farm -- be VERY CAREFUL.
+2) With incomplete PKI the MITM attack when sshd is requesting the public key,
+ could lead to a compromise of your servers allowing login as the
+ impersonated user.
+3) If LDAP server is down there may be no fallback on passwd auth.
+
+MISC.
@ -107,7 +109,8 @@ diff -up openssh-6.8p1/HOWTO.ldap-keys.ldap openssh-6.8p1/HOWTO.ldap-keys
+ * http://fritz.potsdam.edu/projects/openssh-lpk/
+ * http://fritz.potsdam.edu/projects/sshgate/
+ * http://dev.inversepath.com/trac/openssh-lpk
+ * http://lam.sf.net/ ( http://lam.sourceforge.net/documentation/supportedSchemas.htm )
+ * http://lam.sf.net/
+ ( http://lam.sourceforge.net/documentation/supportedSchemas.htm )
+
+4) contributors/ideas/greets
+ - Eric AUGE <eau@phear.org>
@ -118,16 +121,15 @@ diff -up openssh-6.8p1/HOWTO.ldap-keys.ldap openssh-6.8p1/HOWTO.ldap-keys
+ - frederic peters.
+ - Finlay dobbie.
+ - Stefan Fisher.
+ - Robin H. Johnson.
+ - Adrian Bridgett.
+
+5) Author
+ Jan F. Chadima <jchadima@redhat.com>
+
diff -up openssh-6.8p1/Makefile.in.ldap openssh-6.8p1/Makefile.in
--- openssh-6.8p1/Makefile.in.ldap 2015-03-17 06:49:20.000000000 +0100
+++ openssh-6.8p1/Makefile.in 2015-03-18 11:13:10.147561177 +0100
@@ -25,6 +25,8 @@ SSH_PROGRAM=@bindir@/ssh
diff --git a/openssh-6.6p1/Makefile.in b/openssh-6.6p1/Makefile.in
--- a/openssh-6.6p1/Makefile.in
+++ b/openssh-6.6p1/Makefile.in
@@ -20,16 +20,18 @@ srcdir=@srcdir@
top_srcdir=@top_srcdir@
DESTDIR=
VPATH=@srcdir@
SSH_PROGRAM=@bindir@/ssh
ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass
SFTP_SERVER=$(libexecdir)/sftp-server
SSH_KEYSIGN=$(libexecdir)/ssh-keysign
@ -136,18 +138,38 @@ diff -up openssh-6.8p1/Makefile.in.ldap openssh-6.8p1/Makefile.in
SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
PRIVSEP_PATH=@PRIVSEP_PATH@
SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@
@@ -61,8 +63,9 @@ XAUTH_PATH=@XAUTH_PATH@
STRIP_OPT=@STRIP_OPT@
PATHS= -DSSHDIR=\"$(sysconfdir)\" \
-D_PATH_SSH_PROGRAM=\"$(SSH_PROGRAM)\" \
-D_PATH_SSH_ASKPASS_DEFAULT=\"$(ASKPASS_PROGRAM)\" \
@@ -56,17 +58,19 @@ INSTALL=@INSTALL@
PERL=@PERL@
SED=@SED@
ENT=@ENT@
XAUTH_PATH=@XAUTH_PATH@
LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@
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)
+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)
LIBOPENSSH_OBJS=\
ssh_api.o \
@@ -112,8 +115,8 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passw
LIBSSH_OBJS=authfd.o authfile.o bufaux.o bufbn.o buffer.o \
canohost.o channels.o cipher.o cipher-aes.o \
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 \
atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \
@@ -96,18 +100,18 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passw
kexc25519s.o auth-krb5.o \
auth2-gss.o gss-serv.o gss-serv-krb5.o \
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-seccomp-filter.o sandbox-capsicum.o
@ -158,28 +180,55 @@ diff -up openssh-6.8p1/Makefile.in.ldap openssh-6.8p1/Makefile.in
MANTYPE = @MANTYPE@
CONFIGFILES=sshd_config.out ssh_config.out moduli.out
@@ -184,6 +187,9 @@ ssh-keysign$(EXEEXT): $(LIBCOMPAT) libss
CONFIGFILES_IN=sshd_config ssh_config moduli
PATHSUBS = \
-e 's|/etc/ssh/ssh_config|$(sysconfdir)/ssh_config|g' \
-e 's|/etc/ssh/ssh_known_hosts|$(sysconfdir)/ssh_known_hosts|g' \
@@ -171,16 +175,19 @@ ssh-keysign$(EXEEXT): $(LIBCOMPAT) libss
$(LD) -o $@ ssh-keysign.o readconf.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat $(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)
+ssh-ldap-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o sshbuf-getput-basic.o ssherr.o
+ $(LD) -o $@ ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o sshbuf-getput-basic.o ssherr.o $(LDFLAGS) -lssh -lopenbsd-compat -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 $(LIBS)
@@ -311,6 +317,10 @@ install-files:
+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 $(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)
sftp$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-client.o sftp-common.o sftp-glob.o progressmeter.o
$(LD) -o $@ progressmeter.o sftp.o sftp-client.o sftp-common.o sftp-glob.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(LIBEDIT)
# test driver for the loginrec code - not built by default
logintest: logintest.o $(LIBCOMPAT) libssh.a loginrec.o
@@ -273,30 +280,38 @@ install-files:
$(INSTALL) -m 0755 $(STRIP_OPT) ssh-agent$(EXEEXT) $(DESTDIR)$(bindir)/ssh-agent$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) ssh-keygen$(EXEEXT) $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) ssh-keyscan$(EXEEXT) $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) sshd$(EXEEXT) $(DESTDIR)$(sbindir)/sshd$(EXEEXT)
$(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)
+ if test ! -z "$(INSTALL_SSH_LDAP_HELPER)" ; then \
+ $(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) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
+ if test ! -z "$(INSTALL_SSH_LDAP_HELPER)" ; then \
+ $(INSTALL) -m 0755 $(STRIP_OPT) ssh-ldap-helper $(DESTDIR)$(SSH_LDAP_HELPER) ; \
+ $(INSTALL) -m 0755 ssh-ldap-wrapper $(DESTDIR)$(SSH_LDAP_WRAPPER) ; \
+ fi
$(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
@@ -327,6 +337,10 @@ install-files:
$(INSTALL) -m 644 scp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1
$(INSTALL) -m 644 ssh-add.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1
$(INSTALL) -m 644 ssh-agent.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-agent.1
$(INSTALL) -m 644 ssh-keygen.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1
$(INSTALL) -m 644 ssh-keyscan.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1
$(INSTALL) -m 644 moduli.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/moduli.5
$(INSTALL) -m 644 sshd_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/sshd_config.5
$(INSTALL) -m 644 ssh_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/ssh_config.5
$(INSTALL) -m 644 sshd.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8
$(INSTALL) -m 644 sftp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1
$(INSTALL) -m 644 sftp-server.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8
$(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8
$(INSTALL) -m 644 ssh-pkcs11-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8
@ -190,7 +239,17 @@ diff -up openssh-6.8p1/Makefile.in.ldap openssh-6.8p1/Makefile.in
-rm -f $(DESTDIR)$(bindir)/slogin
ln -s ./ssh$(EXEEXT) $(DESTDIR)$(bindir)/slogin
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
@@ -356,6 +370,13 @@ install-sysconf:
ln -s ./ssh.1 $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
install-sysconf:
if [ ! -d $(DESTDIR)$(sysconfdir) ]; then \
$(srcdir)/mkinstalldirs $(DESTDIR)$(sysconfdir); \
@@ -316,16 +331,23 @@ install-sysconf:
echo "moving $(DESTDIR)$(sysconfdir)/primes to $(DESTDIR)$(sysconfdir)/moduli"; \
mv "$(DESTDIR)$(sysconfdir)/primes" "$(DESTDIR)$(sysconfdir)/moduli"; \
else \
$(INSTALL) -m 644 moduli.out $(DESTDIR)$(sysconfdir)/moduli; \
fi ; \
else \
echo "$(DESTDIR)$(sysconfdir)/moduli already exists, install will not overwrite"; \
fi
@ -204,7 +263,17 @@ diff -up openssh-6.8p1/Makefile.in.ldap openssh-6.8p1/Makefile.in
host-key: ssh-keygen$(EXEEXT)
@if [ -z "$(DESTDIR)" ] ; then \
@@ -419,6 +440,8 @@ uninstall:
if [ -f "$(sysconfdir)/ssh_host_key" ] ; then \
echo "$(sysconfdir)/ssh_host_key already exists, skipping." ; \
else \
./ssh-keygen -t rsa1 -f $(sysconfdir)/ssh_host_key -N "" ; \
fi ; \
@@ -379,27 +401,30 @@ uninstall:
-rm -f $(DESTDIR)$(bindir)/ssh-agent$(EXEEXT)
-rm -f $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT)
-rm -f $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT)
-rm -f $(DESTDIR)$(bindir)/sftp$(EXEEXT)
-rm -f $(DESTDIR)$(sbindir)/sshd$(EXEEXT)
-rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
-rm -f $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT)
-rm -f $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT)
@ -213,20 +282,34 @@ diff -up openssh-6.8p1/Makefile.in.ldap openssh-6.8p1/Makefile.in
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1
@@ -430,6 +453,7 @@ uninstall:
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-agent.1
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8
+ -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-ldap-helper.8
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
regress-prep:
diff -up openssh-6.8p1/configure.ac.ldap openssh-6.8p1/configure.ac
--- openssh-6.8p1/configure.ac.ldap 2015-03-17 06:49:20.000000000 +0100
+++ openssh-6.8p1/configure.ac 2015-03-18 11:11:29.030801464 +0100
@@ -1605,6 +1605,106 @@ if test "x$use_pie" != "xno"; then
fi
fi
regress/modpipe$(EXEEXT): $(srcdir)/regress/modpipe.c
[ -d `pwd`/regress ] || mkdir -p `pwd`/regress
[ -f `pwd`/regress/Makefile ] || \
ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile
$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $? \
$(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
diff --git a/openssh-6.6p1/configure.ac b/openssh-6.6p1/configure.ac
--- a/openssh-6.6p1/configure.ac
+++ b/openssh-6.6p1/configure.ac
@@ -1599,16 +1599,116 @@ AC_ARG_WITH([audit],
AC_MSG_RESULT([no])
;;
*)
AC_MSG_ERROR([Unknown audit module $withval])
;;
esac ]
)
+# Check whether user wants LDAP support
+LDAP_MSG="no"
@ -328,12 +411,18 @@ diff -up openssh-6.8p1/configure.ac.ldap openssh-6.8p1/configure.ac
+)
+AC_SUBST(INSTALL_SSH_LDAP_HELPER)
+
dnl Checks for library functions. Please keep in alphabetical order
AC_CHECK_FUNCS([ \
Blowfish_initstate \
diff -up openssh-6.8p1/ldap-helper.c.ldap openssh-6.8p1/ldap-helper.c
--- openssh-6.8p1/ldap-helper.c.ldap 2015-03-18 11:11:29.030801464 +0100
+++ openssh-6.8p1/ldap-helper.c 2015-03-18 11:11:29.030801464 +0100
AC_ARG_WITH([pie],
[ --with-pie Build Position Independent Executables if possible], [
if test "x$withval" = "xno"; then
use_pie=no
fi
if test "x$withval" = "xyes"; then
use_pie=yes
fi
diff --git a/openssh-6.6p1/ldap-helper.c b/openssh-6.6p1/ldap-helper.c
new file mode 100644
--- /dev/null
+++ b/openssh-6.6p1/ldap-helper.c
@@ -0,0 +1,155 @@
+/* $OpenBSD: ssh-pka-ldap.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */
+/*
@ -490,9 +579,10 @@ diff -up openssh-6.8p1/ldap-helper.c.ldap openssh-6.8p1/ldap-helper.c
+void *buffer_get_string(Buffer *b, u_int *l) { return NULL; }
+void buffer_put_string(Buffer *b, const void *f, u_int l) {}
+
diff -up openssh-6.8p1/ldap-helper.h.ldap openssh-6.8p1/ldap-helper.h
--- openssh-6.8p1/ldap-helper.h.ldap 2015-03-18 11:11:29.031801462 +0100
+++ openssh-6.8p1/ldap-helper.h 2015-03-18 11:11:29.031801462 +0100
diff --git a/openssh-6.6p1/ldap-helper.h b/openssh-6.6p1/ldap-helper.h
new file mode 100644
--- /dev/null
+++ b/openssh-6.6p1/ldap-helper.h
@@ -0,0 +1,32 @@
+/* $OpenBSD: ldap-helper.h,v 1.1 2009/12/03 03:34:42 jfch Exp $ */
+/*
@ -526,10 +616,11 @@ diff -up openssh-6.8p1/ldap-helper.h.ldap openssh-6.8p1/ldap-helper.h
+extern int config_warning_config_file;
+
+#endif /* LDAP_HELPER_H */
diff -up openssh-6.8p1/ldap.conf.ldap openssh-6.8p1/ldap.conf
--- openssh-6.8p1/ldap.conf.ldap 2015-03-18 11:11:29.031801462 +0100
+++ openssh-6.8p1/ldap.conf 2015-03-18 11:11:29.031801462 +0100
@@ -0,0 +1,95 @@
diff --git a/openssh-6.6p1/ldap.conf b/openssh-6.6p1/ldap.conf
new file mode 100644
--- /dev/null
+++ b/openssh-6.6p1/ldap.conf
@@ -0,0 +1,88 @@
+# $Id: openssh-5.5p1-ldap.patch,v 1.3 2010/07/07 13:48:36 jfch2222 Exp $
+#
+# This is the example configuration file for the OpenSSH
@ -618,17 +709,11 @@ diff -up openssh-6.8p1/ldap.conf.ldap openssh-6.8p1/ldap.conf
+#tls_cert
+#tls_key
+
+# OpenLDAP search_format
+# format used to search for users in LDAP directory using substitution
+# for %u for user name and %f for SSH_Filter option (optional, empty by default)
+#search_format (&(objectclass=%c)(objectclass=ldapPublicKey)(uid=%u)%f)
+
+#AccountClass posixAccount
+
diff -up openssh-6.8p1/ldapbody.c.ldap openssh-6.8p1/ldapbody.c
--- openssh-6.8p1/ldapbody.c.ldap 2015-03-18 11:11:29.031801462 +0100
+++ openssh-6.8p1/ldapbody.c 2015-03-18 11:11:29.031801462 +0100
@@ -0,0 +1,493 @@
diff --git a/openssh-6.6p1/ldapbody.c b/openssh-6.6p1/ldapbody.c
new file mode 100644
--- /dev/null
+++ b/openssh-6.6p1/ldapbody.c
@@ -0,0 +1,494 @@
+/* $OpenBSD: ldapbody.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */
+/*
+ * Copyright (c) 2009 Jan F. Chadima. All rights reserved.
@ -662,9 +747,8 @@ diff -up openssh-6.8p1/ldapbody.c.ldap openssh-6.8p1/ldapbody.c
+#include "ldapbody.h"
+#include <stdio.h>
+#include <unistd.h>
+#include "misc.h"
+
+#define LDAPSEARCH_FORMAT "(&(objectclass=%c)(objectclass=ldapPublicKey)(uid=%u)%f)"
+#define LDAPSEARCH_FORMAT "(&(objectclass=posixAccount)(objectclass=ldapPublicKey)(uid=%s)%s)"
+#define PUBKEYATTR "sshPublicKey"
+#define LDAP_LOGFILE "%s/ldap.%d"
+
@ -798,7 +882,7 @@ diff -up openssh-6.8p1/ldapbody.c.ldap openssh-6.8p1/ldapbody.c
+ ber_set_option (NULL, LBER_OPT_DEBUG_LEVEL, &options.debug);
+#endif /* LBER_OPT_DEBUG_LEVEL */
+#ifdef LDAP_OPT_DEBUG_LEVEL
+ (void) ldap_set_option (NULL, LDAP_OPT_DEBUG_LEVEL, &options.debug);
+ ldap_set_option (NULL, LDAP_OPT_DEBUG_LEVEL, &options.debug);
+#endif /* LDAP_OPT_DEBUG_LEVEL */
+ debug3 ("Set LDAP debug to %d", options.debug);
+ }
@ -1051,8 +1135,8 @@ diff -up openssh-6.8p1/ldapbody.c.ldap openssh-6.8p1/ldapbody.c
+process_user (const char *user, FILE *output)
+{
+ LDAPMessage *res, *e;
+ char *buffer, *format;
+ int rc, i;
+ char *buffer;
+ int bufflen, rc, i;
+ struct timeval timeout;
+
+ debug ("LDAP process user");
@ -1065,10 +1149,12 @@ diff -up openssh-6.8p1/ldapbody.c.ldap openssh-6.8p1/ldapbody.c
+ }
+
+ /* build filter for LDAP request */
+ format = LDAPSEARCH_FORMAT;
+ if (options.search_format != NULL)
+ format = options.search_format;
+ buffer = percent_expand(format, "c", options.account_class, "u", user, "f", options.ssh_filter, (char *)NULL);
+ bufflen = strlen (LDAPSEARCH_FORMAT) + strlen (user);
+ if (options.ssh_filter != NULL)
+ bufflen += strlen (options.ssh_filter);
+ buffer = xmalloc (bufflen);
+ snprintf(buffer, bufflen, LDAPSEARCH_FORMAT, user, (options.ssh_filter != NULL) ? options.ssh_filter : NULL);
+ buffer[bufflen - 1] = 0;
+
+ debug3 ("LDAP search scope = %d %s", options.scope, buffer);
+
@ -1122,9 +1208,10 @@ diff -up openssh-6.8p1/ldapbody.c.ldap openssh-6.8p1/ldapbody.c
+ return;
+}
+
diff -up openssh-6.8p1/ldapbody.h.ldap openssh-6.8p1/ldapbody.h
--- openssh-6.8p1/ldapbody.h.ldap 2015-03-18 11:11:29.031801462 +0100
+++ openssh-6.8p1/ldapbody.h 2015-03-18 11:11:29.031801462 +0100
diff --git a/openssh-6.6p1/ldapbody.h b/openssh-6.6p1/ldapbody.h
new file mode 100644
--- /dev/null
+++ b/openssh-6.6p1/ldapbody.h
@@ -0,0 +1,37 @@
+/* $OpenBSD: ldapbody.h,v 1.1 2009/12/03 03:34:42 jfch Exp $ */
+/*
@ -1163,10 +1250,11 @@ diff -up openssh-6.8p1/ldapbody.h.ldap openssh-6.8p1/ldapbody.h
+
+#endif /* LDAPBODY_H */
+
diff -up openssh-6.8p1/ldapconf.c.ldap openssh-6.8p1/ldapconf.c
--- openssh-6.8p1/ldapconf.c.ldap 2015-03-18 11:11:29.032801460 +0100
+++ openssh-6.8p1/ldapconf.c 2015-03-18 11:11:29.032801460 +0100
@@ -0,0 +1,728 @@
diff --git a/openssh-6.6p1/ldapconf.c b/openssh-6.6p1/ldapconf.c
new file mode 100644
--- /dev/null
+++ b/openssh-6.6p1/ldapconf.c
@@ -0,0 +1,682 @@
+/* $OpenBSD: ldapconf.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */
+/*
+ * Copyright (c) 2009 Jan F. Chadima. All rights reserved.
@ -1210,8 +1298,8 @@ diff -up openssh-6.8p1/ldapconf.c.ldap openssh-6.8p1/ldapconf.c
+ lLdap_Version, lBind_Policy, lSSLPath, lSSL, lReferrals,
+ lRestart, lTLS_CheckPeer, lTLS_CaCertFile,
+ lTLS_CaCertDir, lTLS_Ciphers, lTLS_Cert, lTLS_Key,
+ lTLS_RandFile, lLogDir, lDebug, lSSH_Filter, lSearch_Format,
+ lAccountClass, lDeprecated, lUnsupported
+ lTLS_RandFile, lLogDir, lDebug, lSSH_Filter,
+ lDeprecated, lUnsupported
+} OpCodes;
+
+/* Textual representations of the tokens. */
@ -1263,8 +1351,6 @@ diff -up openssh-6.8p1/ldapconf.c.ldap openssh-6.8p1/ldapconf.c
+ { "LogDir", lLogDir },
+ { "Debug", lDebug },
+ { "SSH_Filter", lSSH_Filter },
+ { "search_format", lSearch_Format },
+ { "AccountClass", lAccountClass },
+ { NULL, lBadOption }
+};
+
@ -1291,35 +1377,6 @@ diff -up openssh-6.8p1/ldapconf.c.ldap openssh-6.8p1/ldapconf.c
+ return lBadOption;
+}
+
+/* Characters considered whitespace in strsep calls. */
+#define WHITESPACE " \t\r\n"
+
+/* return next token in configuration line */
+static char *
+ldap_strdelim(char **s)
+{
+ char *old;
+ int wspace = 0;
+
+ if (*s == NULL)
+ return NULL;
+
+ old = *s;
+
+ *s = strpbrk(*s, WHITESPACE);
+ if (*s == NULL)
+ return (old);
+
+ *s[0] = '\0';
+
+ /* Skip any extra whitespace after first token */
+ *s += strspn(*s + 1, WHITESPACE) + 1;
+ if (*s[0] == '=' && !wspace)
+ *s += strspn(*s + 1, WHITESPACE) + 1;
+
+ return (old);
+}
+
+/*
+ * Processes a single option line as used in the configuration files. This
+ * only sets those values that have not already been set.
@ -1343,11 +1400,11 @@ diff -up openssh-6.8p1/ldapconf.c.ldap openssh-6.8p1/ldapconf.c
+
+ s = line;
+ /* Get the keyword. (Each line is supposed to begin with a keyword). */
+ if ((keyword = ldap_strdelim(&s)) == NULL)
+ if ((keyword = strdelim(&s)) == NULL)
+ return 0;
+ /* Ignore leading whitespace. */
+ if (*keyword == '\0')
+ keyword = ldap_strdelim(&s);
+ keyword = strdelim(&s);
+ if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
+ return 0;
+
@ -1383,7 +1440,7 @@ diff -up openssh-6.8p1/ldapconf.c.ldap openssh-6.8p1/ldapconf.c
+ case lBindPW:
+ charptr = &options.bindpw;
+parse_string:
+ arg = ldap_strdelim(&s);
+ arg = strdelim(&s);
+ if (!arg || *arg == '\0')
+ fatal("%.200s line %d: Missing argument.", filename, linenum);
+ if (*charptr == NULL)
@ -1396,7 +1453,7 @@ diff -up openssh-6.8p1/ldapconf.c.ldap openssh-6.8p1/ldapconf.c
+
+ case lScope:
+ intptr = &options.scope;
+ arg = ldap_strdelim(&s);
+ arg = strdelim(&s);
+ if (!arg || *arg == '\0')
+ fatal("%.200s line %d: Missing sub/one/base argument.", filename, linenum);
+ value = 0; /* To avoid compiler warning... */
@ -1414,7 +1471,7 @@ diff -up openssh-6.8p1/ldapconf.c.ldap openssh-6.8p1/ldapconf.c
+
+ case lDeref:
+ intptr = &options.scope;
+ arg = ldap_strdelim(&s);
+ arg = strdelim(&s);
+ if (!arg || *arg == '\0')
+ fatal("%.200s line %d: Missing never/searching/finding/always argument.", filename, linenum);
+ value = 0; /* To avoid compiler warning... */
@ -1435,7 +1492,7 @@ diff -up openssh-6.8p1/ldapconf.c.ldap openssh-6.8p1/ldapconf.c
+ case lPort:
+ intptr = &options.port;
+parse_int:
+ arg = ldap_strdelim(&s);
+ arg = strdelim(&s);
+ if (!arg || *arg == '\0')
+ fatal("%.200s line %d: Missing argument.", filename, linenum);
+ if (arg[0] < '0' || arg[0] > '9')
@ -1452,7 +1509,7 @@ diff -up openssh-6.8p1/ldapconf.c.ldap openssh-6.8p1/ldapconf.c
+ case lTimeLimit:
+ intptr = &options.timelimit;
+parse_time:
+ arg = ldap_strdelim(&s);
+ arg = strdelim(&s);
+ if (!arg || *arg == '\0')
+ fatal("%s line %d: missing time value.",
+ filename, linenum);
@ -1473,7 +1530,7 @@ diff -up openssh-6.8p1/ldapconf.c.ldap openssh-6.8p1/ldapconf.c
+
+ case lBind_Policy:
+ intptr = &options.bind_policy;
+ arg = ldap_strdelim(&s);
+ arg = strdelim(&s);
+ if (!arg || *arg == '\0')
+ fatal("%.200s line %d: Missing soft/hard argument.", filename, linenum);
+ value = 0; /* To avoid compiler warning... */
@ -1484,7 +1541,6 @@ diff -up openssh-6.8p1/ldapconf.c.ldap openssh-6.8p1/ldapconf.c
+ else
+ fatal("%.200s line %d: Bad soft/hard argument.", filename, linenum);
+ if (*intptr == -1)
+ *intptr = value;
+ break;
+
+ case lSSLPath:
@ -1493,7 +1549,7 @@ diff -up openssh-6.8p1/ldapconf.c.ldap openssh-6.8p1/ldapconf.c
+
+ case lSSL:
+ intptr = &options.ssl;
+ arg = ldap_strdelim(&s);
+ arg = strdelim(&s);
+ if (!arg || *arg == '\0')
+ fatal("%.200s line %d: Missing yes/no/start_tls argument.", filename, linenum);
+ value = 0; /* To avoid compiler warning... */
@ -1512,7 +1568,7 @@ diff -up openssh-6.8p1/ldapconf.c.ldap openssh-6.8p1/ldapconf.c
+ case lReferrals:
+ intptr = &options.referrals;
+parse_flag:
+ arg = ldap_strdelim(&s);
+ arg = strdelim(&s);
+ if (!arg || *arg == '\0')
+ fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
+ value = 0; /* To avoid compiler warning... */
@ -1532,7 +1588,7 @@ diff -up openssh-6.8p1/ldapconf.c.ldap openssh-6.8p1/ldapconf.c
+
+ case lTLS_CheckPeer:
+ intptr = &options.tls_checkpeer;
+ arg = ldap_strdelim(&s);
+ arg = strdelim(&s);
+ if (!arg || *arg == '\0')
+ fatal("%.200s line %d: Missing never/hard/demand/alow/try argument.", filename, linenum);
+ value = 0; /* To avoid compiler warning... */
@ -1549,7 +1605,6 @@ diff -up openssh-6.8p1/ldapconf.c.ldap openssh-6.8p1/ldapconf.c
+ else
+ fatal("%.200s line %d: Bad never/hard/demand/alow/try argument.", filename, linenum);
+ if (*intptr == -1)
+ *intptr = value;
+ break;
+
+ case lTLS_CaCertFile:
@ -1588,14 +1643,6 @@ diff -up openssh-6.8p1/ldapconf.c.ldap openssh-6.8p1/ldapconf.c
+ xstringptr = &options.ssh_filter;
+ goto parse_xstring;
+
+ case lSearch_Format:
+ charptr = &options.search_format;
+ goto parse_string;
+
+ case lAccountClass:
+ charptr = &options.account_class;
+ goto parse_string;
+
+ case lDeprecated:
+ debug("%s line %d: Deprecated option \"%s\"",
+ filename, linenum, keyword);
@ -1611,7 +1658,7 @@ diff -up openssh-6.8p1/ldapconf.c.ldap openssh-6.8p1/ldapconf.c
+ }
+
+ /* Check that there is no garbage at end of line. */
+ if ((arg = ldap_strdelim(&s)) != NULL && *arg != '\0') {
+ if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+ fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
+ filename, linenum, arg);
+ }
@ -1629,7 +1676,7 @@ diff -up openssh-6.8p1/ldapconf.c.ldap openssh-6.8p1/ldapconf.c
+{
+ FILE *f;
+ char line[1024];
+ int linenum;
+ int active, linenum;
+ int bad_options = 0;
+ struct stat sb;
+
@ -1648,6 +1695,7 @@ diff -up openssh-6.8p1/ldapconf.c.ldap openssh-6.8p1/ldapconf.c
+ * Mark that we are now processing the options. This flag is turned
+ * on/off by Host specifications.
+ */
+ active = 1;
+ linenum = 0;
+ while (fgets(line, sizeof(line), f)) {
+ /* Update line number counter. */
@ -1698,8 +1746,6 @@ diff -up openssh-6.8p1/ldapconf.c.ldap openssh-6.8p1/ldapconf.c
+ options.logdir = NULL;
+ options.debug = -1;
+ options.ssh_filter = NULL;
+ options.search_format = NULL;
+ options.account_class = NULL;
+}
+
+/*
@ -1742,7 +1788,7 @@ diff -up openssh-6.8p1/ldapconf.c.ldap openssh-6.8p1/ldapconf.c
+ len = snprintf (options.uri, MAXURILEN, "ldap%s://%s:%d",
+ (options.ssl == 0) ? "" : "s", options.host, options.port);
+ options.uri[MAXURILEN - 1] = 0;
+ options.uri = xreallocarray(options.uri, len + 1, 1);
+ options.uri = xrealloc (options.uri, len + 1, 1);
+ }
+ if (options.binddn == NULL)
+ options.binddn = "";
@ -1770,8 +1816,6 @@ diff -up openssh-6.8p1/ldapconf.c.ldap openssh-6.8p1/ldapconf.c
+ options.debug = 0;
+ if (options.ssh_filter == NULL)
+ options.ssh_filter = "";
+ if (options.account_class == NULL)
+ options.account_class = "posixAccount";
+}
+
+static const char *
@ -1891,14 +1935,13 @@ diff -up openssh-6.8p1/ldapconf.c.ldap openssh-6.8p1/ldapconf.c
+ dump_cfg_string(lLogDir, options.logdir);
+ dump_cfg_int(lDebug, options.debug);
+ dump_cfg_string(lSSH_Filter, options.ssh_filter);
+ dump_cfg_string(lSearch_Format, options.search_format);
+ dump_cfg_string(lAccountClass, options.account_class);
+}
+
diff -up openssh-6.8p1/ldapconf.h.ldap openssh-6.8p1/ldapconf.h
--- openssh-6.8p1/ldapconf.h.ldap 2015-03-18 11:11:29.032801460 +0100
+++ openssh-6.8p1/ldapconf.h 2015-03-18 11:11:29.032801460 +0100
@@ -0,0 +1,73 @@
diff --git a/openssh-6.6p1/ldapconf.h b/openssh-6.6p1/ldapconf.h
new file mode 100644
--- /dev/null
+++ b/openssh-6.6p1/ldapconf.h
@@ -0,0 +1,71 @@
+/* $OpenBSD: ldapconf.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */
+/*
+ * Copyright (c) 2009 Jan F. Chadima. All rights reserved.
@ -1960,8 +2003,6 @@ diff -up openssh-6.8p1/ldapconf.h.ldap openssh-6.8p1/ldapconf.h
+ char *logdir;
+ int debug;
+ char *ssh_filter;
+ char *search_format;
+ char *account_class;
+} Options;
+
+extern Options options;
@ -1972,9 +2013,10 @@ diff -up openssh-6.8p1/ldapconf.h.ldap openssh-6.8p1/ldapconf.h
+void dump_config(void);
+
+#endif /* LDAPCONF_H */
diff -up openssh-6.8p1/ldapincludes.h.ldap openssh-6.8p1/ldapincludes.h
--- openssh-6.8p1/ldapincludes.h.ldap 2015-03-18 11:11:29.032801460 +0100
+++ openssh-6.8p1/ldapincludes.h 2015-03-18 11:11:29.032801460 +0100
diff --git a/openssh-6.6p1/ldapincludes.h b/openssh-6.6p1/ldapincludes.h
new file mode 100644
--- /dev/null
+++ b/openssh-6.6p1/ldapincludes.h
@@ -0,0 +1,41 @@
+/* $OpenBSD: ldapconf.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */
+/*
@ -2017,9 +2059,10 @@ diff -up openssh-6.8p1/ldapincludes.h.ldap openssh-6.8p1/ldapincludes.h
+#endif
+
+#endif /* LDAPINCLUDES_H */
diff -up openssh-6.8p1/ldapmisc.c.ldap openssh-6.8p1/ldapmisc.c
--- openssh-6.8p1/ldapmisc.c.ldap 2015-03-18 11:11:29.032801460 +0100
+++ openssh-6.8p1/ldapmisc.c 2015-03-18 11:11:29.032801460 +0100
diff --git a/openssh-6.6p1/ldapmisc.c b/openssh-6.6p1/ldapmisc.c
new file mode 100644
--- /dev/null
+++ b/openssh-6.6p1/ldapmisc.c
@@ -0,0 +1,79 @@
+
+#include "ldapincludes.h"
@ -2100,9 +2143,10 @@ diff -up openssh-6.8p1/ldapmisc.c.ldap openssh-6.8p1/ldapmisc.c
+}
+#endif
+
diff -up openssh-6.8p1/ldapmisc.h.ldap openssh-6.8p1/ldapmisc.h
--- openssh-6.8p1/ldapmisc.h.ldap 2015-03-18 11:11:29.032801460 +0100
+++ openssh-6.8p1/ldapmisc.h 2015-03-18 11:11:29.032801460 +0100
diff --git a/openssh-6.6p1/ldapmisc.h b/openssh-6.6p1/ldapmisc.h
new file mode 100644
--- /dev/null
+++ b/openssh-6.6p1/ldapmisc.h
@@ -0,0 +1,35 @@
+/* $OpenBSD: ldapbody.h,v 1.1 2009/12/03 03:34:42 jfch Exp $ */
+/*
@ -2139,9 +2183,102 @@ diff -up openssh-6.8p1/ldapmisc.h.ldap openssh-6.8p1/ldapmisc.h
+
+#endif /* LDAPMISC_H */
+
diff -up openssh-6.8p1/openssh-lpk-openldap.schema.ldap openssh-6.8p1/openssh-lpk-openldap.schema
--- openssh-6.8p1/openssh-lpk-openldap.schema.ldap 2015-03-18 11:11:29.033801457 +0100
+++ openssh-6.8p1/openssh-lpk-openldap.schema 2015-03-18 11:11:29.033801457 +0100
diff --git a/openssh-6.6p1/openbsd-compat/base64.c b/openssh-6.6p1/openbsd-compat/base64.c
--- a/openssh-6.6p1/openbsd-compat/base64.c
+++ b/openssh-6.6p1/openbsd-compat/base64.c
@@ -41,17 +41,17 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
* IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
/* OPENBSD ORIGINAL: lib/libc/net/base64.c */
#include "includes.h"
-#if (!defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP)) || (!defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON))
+#if (!defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP)) || (!defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON)) || defined(USE_INTERNAL_B64)
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
@@ -124,17 +124,17 @@ static const char Pad64 = '=';
(2) the final quantum of encoding input is exactly 8 bits;
here, the final unit of encoded output will be two
characters followed by two "=" padding characters, or
(3) the final quantum of encoding input is exactly 16 bits;
here, the final unit of encoded output will be three
characters followed by one "=" padding character.
*/
-#if !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP)
+#if !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) || defined(USE_INTERNAL_B64)
int
b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize)
{
size_t datalength = 0;
u_char input[3];
u_char output[4];
u_int i;
@@ -180,17 +180,17 @@ b64_ntop(u_char const *src, size_t srcle
}
if (datalength >= targsize)
return (-1);
target[datalength] = '\0'; /* Returned value doesn't count \0. */
return (datalength);
}
#endif /* !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) */
-#if !defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON)
+#if !defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON) || defined(USE_INTERNAL_B64)
/* skips all whitespace anywhere.
converts characters, four at a time, starting at (or after)
src from base - 64 numbers into three 8 bit bytes in the target area.
it returns the number of data bytes stored at the target, or -1 on error.
*/
int
diff --git a/openssh-6.6p1/openbsd-compat/base64.h b/openssh-6.6p1/openbsd-compat/base64.h
--- a/openssh-6.6p1/openbsd-compat/base64.h
+++ b/openssh-6.6p1/openbsd-compat/base64.h
@@ -42,24 +42,24 @@
* IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
*/
#ifndef _BSD_BASE64_H
#define _BSD_BASE64_H
#include "includes.h"
-#ifndef HAVE___B64_NTOP
-# ifndef HAVE_B64_NTOP
+#if !defined(HAVE___B64_NTOP) || defined(USE_INTERNAL_B64)
+# if !defined(HAVE_B64_NTOP) || defined(USE_INTERNAL_B64)
int b64_ntop(u_char const *src, size_t srclength, char *target,
size_t targsize);
# endif /* !HAVE_B64_NTOP */
# define __b64_ntop(a,b,c,d) b64_ntop(a,b,c,d)
#endif /* HAVE___B64_NTOP */
-#ifndef HAVE___B64_PTON
-# ifndef HAVE_B64_PTON
+#if !defined(HAVE___B64_PTON) || defined(USE_INTERNAL_B64)
+# if !defined(HAVE_B64_PTON) || defined(USE_INTERNAL_B64)
int b64_pton(char const *src, u_char *target, size_t targsize);
# endif /* !HAVE_B64_PTON */
# define __b64_pton(a,b,c) b64_pton(a,b,c)
#endif /* HAVE___B64_PTON */
#endif /* _BSD_BASE64_H */
diff --git a/openssh-6.6p1/openssh-lpk-openldap.schema b/openssh-6.6p1/openssh-lpk-openldap.schema
new file mode 100644
--- /dev/null
+++ b/openssh-6.6p1/openssh-lpk-openldap.schema
@@ -0,0 +1,21 @@
+#
+# LDAP Public Key Patch schema for use with openssh-ldappubkey
@ -2164,9 +2301,10 @@ diff -up openssh-6.8p1/openssh-lpk-openldap.schema.ldap openssh-6.8p1/openssh-lp
+ DESC 'MANDATORY: OpenSSH LPK objectclass'
+ MUST ( sshPublicKey $ uid )
+ )
diff -up openssh-6.8p1/openssh-lpk-sun.schema.ldap openssh-6.8p1/openssh-lpk-sun.schema
--- openssh-6.8p1/openssh-lpk-sun.schema.ldap 2015-03-18 11:11:29.033801457 +0100
+++ openssh-6.8p1/openssh-lpk-sun.schema 2015-03-18 11:11:29.033801457 +0100
diff --git a/openssh-6.6p1/openssh-lpk-sun.schema b/openssh-6.6p1/openssh-lpk-sun.schema
new file mode 100644
--- /dev/null
+++ b/openssh-6.6p1/openssh-lpk-sun.schema
@@ -0,0 +1,23 @@
+#
+# LDAP Public Key Patch schema for use with openssh-ldappubkey
@ -2191,9 +2329,10 @@ diff -up openssh-6.8p1/openssh-lpk-sun.schema.ldap openssh-6.8p1/openssh-lpk-sun
+ DESC 'MANDATORY: OpenSSH LPK objectclass'
+ MUST ( sshPublicKey $ uid )
+ )
diff -up openssh-6.8p1/ssh-ldap-helper.8.ldap openssh-6.8p1/ssh-ldap-helper.8
--- openssh-6.8p1/ssh-ldap-helper.8.ldap 2015-03-18 11:11:29.033801457 +0100
+++ openssh-6.8p1/ssh-ldap-helper.8 2015-03-18 11:11:29.033801457 +0100
diff --git a/openssh-6.6p1/ssh-ldap-helper.8 b/openssh-6.6p1/ssh-ldap-helper.8
new file mode 100644
--- /dev/null
+++ b/openssh-6.6p1/ssh-ldap-helper.8
@@ -0,0 +1,79 @@
+.\" $OpenBSD: ssh-ldap-helper.8,v 1.1 2010/02/10 23:20:38 markus Exp $
+.\"
@ -2234,7 +2373,7 @@ diff -up openssh-6.8p1/ssh-ldap-helper.8.ldap openssh-6.8p1/ssh-ldap-helper.8
+by setting
+.Cm AuthorizedKeysCommand
+to
+.Dq /usr/libexec/ssh-ldap-wrapper .
+.Dq @LIBEXECDIR@/ssh-ldap-wrapper .
+.Pp
+.Nm
+is not intended to be invoked by the user, but from
@ -2274,18 +2413,20 @@ diff -up openssh-6.8p1/ssh-ldap-helper.8.ldap openssh-6.8p1/ssh-ldap-helper.8
+OpenSSH 5.5 + PKA-LDAP .
+.Sh AUTHORS
+.An Jan F. Chadima Aq jchadima@redhat.com
diff -up openssh-6.8p1/ssh-ldap-wrapper.ldap openssh-6.8p1/ssh-ldap-wrapper
--- openssh-6.8p1/ssh-ldap-wrapper.ldap 2015-03-18 11:11:29.033801457 +0100
+++ openssh-6.8p1/ssh-ldap-wrapper 2015-03-18 11:11:29.033801457 +0100
diff --git a/openssh-6.6p1/ssh-ldap-wrapper b/openssh-6.6p1/ssh-ldap-wrapper
new file mode 100644
--- /dev/null
+++ b/openssh-6.6p1/ssh-ldap-wrapper
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+exec /usr/libexec/openssh/ssh-ldap-helper -s "$1"
+exec @LIBEXECDIR@/ssh-ldap-helper -s "$1"
+
diff -up openssh-6.8p1/ssh-ldap.conf.5.ldap openssh-6.8p1/ssh-ldap.conf.5
--- openssh-6.8p1/ssh-ldap.conf.5.ldap 2015-03-18 11:11:29.033801457 +0100
+++ openssh-6.8p1/ssh-ldap.conf.5 2015-03-18 11:11:29.033801457 +0100
@@ -0,0 +1,385 @@
diff --git a/openssh-6.6p1/ssh-ldap.conf.5 b/openssh-6.6p1/ssh-ldap.conf.5
new file mode 100644
--- /dev/null
+++ b/openssh-6.6p1/ssh-ldap.conf.5
@@ -0,0 +1,376 @@
+.\" $OpenBSD: ssh-ldap.conf.5,v 1.1 2010/02/10 23:20:38 markus Exp $
+.\"
+.\" Copyright (c) 2010 Jan F. Chadima. All rights reserved.
@ -2644,17 +2785,8 @@ diff -up openssh-6.8p1/ssh-ldap.conf.5.ldap openssh-6.8p1/ssh-ldap.conf.5
+Specifies the debug level used for logging by the LDAP client library.
+There is no default.
+.It Cm SSH_Filter
+Specifies the user filter applied on the LDAP search.
+Specifies the user filter applied on the LDAP serch.
+The default is no filter.
+.It Cm AccountClass
+Specifies the LDAP class used to find user accounts.
+The default is posixAccount.
+.It Cm search_format
+Specifies the user format of search string in LDAP substituting %u for user name
+and %f for additional ssh filter
+.Cm SSH_Filter
+(optional).
+The default value is (&(objectclass=%c)(objectclass=ldapPublicKey)(uid=%u)%f)
+.El
+.Sh FILES
+.Bl -tag -width Ds
@ -2671,51 +2803,3 @@ diff -up openssh-6.8p1/ssh-ldap.conf.5.ldap openssh-6.8p1/ssh-ldap.conf.5
+OpenSSH 5.5 + PKA-LDAP .
+.Sh AUTHORS
+.An Jan F. Chadima Aq jchadima@redhat.com
diff --git a/openssh-lpk-openldap.ldif b/openssh-lpk-openldap.ldif
new file mode 100644
index 0000000..9adf4b8
--- /dev/null
+++ b/openssh-lpk-openldap.ldif
@@ -0,0 +1,19 @@
+#
+# LDAP Public Key Patch schema for use with openssh-ldappubkey
+# useful with PKA-LDAP also
+#
+# Author: Eric AUGE <eau@phear.org>
+#
+# LDIF for openLDAP Directory Server.
+# Based on the original schema, modified by Jakub Jelen.
+#
+
+dn: cn=openssh-lpk,cn=schema,cn=config
+objectClass: olcSchemaConfig
+cn: openssh-lpk
+olcAttributeTypes: {0}( 1.3.6.1.4.1.24552.500.1.1.1.13
+ NAME 'sshPublicKey' DESC 'MANDATORY: OpenSSH Public key'
+ EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
+olcObjectClasses: {0}( 1.3.6.1.4.1.24552.500.1.1.2.0
+ NAME 'ldapPublicKey' DESC 'MANDATORY: OpenSSH LPK objectclass'
+ SUP top AUXILIARY MUST ( sshPublicKey $ uid ) )
diff --git a/openssh-lpk-sun.ldif b/openssh-lpk-sun.ldif
new file mode 100644
index 0000000..9adf4b8
--- /dev/null
+++ b/openssh-lpk-sun.ldif
@@ -0,0 +1,17 @@
+#
+# LDAP Public Key Patch schema for use with openssh-ldappubkey
+# useful with PKA-LDAP also
+#
+# Author: Eric AUGE <eau@phear.org>
+#
+# LDIF for Sun Directory Server.
+# Based on the original schema, modified by Jakub Jelen.
+#
+
+dn: cn=schema
+attributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13
+ NAME 'sshPublicKey' DESC 'MANDATORY: OpenSSH Public key'
+ EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
+objectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0
+ NAME 'ldapPublicKey' DESC 'MANDATORY: OpenSSH LPK objectclass'
+ SUP top AUXILIARY MUST ( sshPublicKey $ uid ) )

View File

@ -0,0 +1,24 @@
# Do not write a PID file when not daemonizing (e.g. when running from systemd)
diff --git a/openssh-6.6p1/sshd.c b/openssh-6.6p1/sshd.c
--- a/openssh-6.6p1/sshd.c
+++ b/openssh-6.6p1/sshd.c
@@ -1994,17 +1994,17 @@ main(int ac, char **av)
signal(SIGCHLD, main_sigchld_handler);
signal(SIGTERM, sigterm_handler);
signal(SIGQUIT, sigterm_handler);
/*
* Write out the pid file after the sigterm handler
* is setup and the listen sockets are bound
*/
- if (!debug_flag) {
+ if (!(debug_flag || no_daemon_flag)) {
FILE *f = fopen(options.pid_file, "w");
if (f == NULL) {
error("Couldn't create pid file \"%s\": %s",
options.pid_file, strerror(errno));
} else {
fprintf(f, "%ld\n", (long) getpid());
fclose(f);

View File

@ -2,11 +2,15 @@
# UsePAM is used
# bnc#708678, FATE#312033
Index: b/auth.c
===================================================================
--- a/auth.c
+++ b/auth.c
@@ -109,7 +109,7 @@ allowed_user(struct passwd * pw)
diff --git a/openssh-6.6p1/auth.c b/openssh-6.6p1/auth.c
--- a/openssh-6.6p1/auth.c
+++ b/openssh-6.6p1/auth.c
@@ -103,17 +103,17 @@ allowed_user(struct passwd * pw)
struct spwd *spw = NULL;
#endif
/* Shouldn't be called if pw is NULL, but better safe than sorry... */
if (!pw || !pw->pw_name)
return 0;
#ifdef USE_SHADOW
@ -15,7 +19,17 @@ Index: b/auth.c
spw = getspnam(pw->pw_name);
#ifdef HAS_SHADOW_EXPIRE
if (!options.use_pam && spw != NULL && auth_shadow_acctexpired(spw))
@@ -129,7 +129,7 @@ allowed_user(struct passwd * pw)
return 0;
#endif /* HAS_SHADOW_EXPIRE */
#endif /* USE_SHADOW */
/* grab passwd field for locked account check */
@@ -123,17 +123,17 @@ allowed_user(struct passwd * pw)
#ifdef USE_LIBIAF
passwd = get_iaf_password(pw);
#else
passwd = spw->sp_pwdp;
#endif /* USE_LIBIAF */
#endif
/* check for locked account */
@ -24,11 +38,20 @@ Index: b/auth.c
int locked = 0;
#ifdef LOCKED_PASSWD_STRING
Index: b/servconf.c
===================================================================
--- a/servconf.c
+++ b/servconf.c
@@ -74,6 +74,7 @@ initialize_server_options(ServerOptions
if (strcmp(passwd, LOCKED_PASSWD_STRING) == 0)
locked = 1;
#endif
#ifdef LOCKED_PASSWD_PREFIX
if (strncmp(passwd, LOCKED_PASSWD_PREFIX,
diff --git a/openssh-6.6p1/servconf.c b/openssh-6.6p1/servconf.c
--- a/openssh-6.6p1/servconf.c
+++ b/openssh-6.6p1/servconf.c
@@ -66,16 +66,17 @@ extern Buffer cfg;
void
initialize_server_options(ServerOptions *options)
{
memset(options, 0, sizeof(*options));
/* Portable-specific options */
options->use_pam = -1;
@ -36,7 +59,17 @@ Index: b/servconf.c
/* Standard Options */
options->num_ports = 0;
@@ -187,6 +188,8 @@ fill_default_server_options(ServerOption
options->ports_from_cmdline = 0;
options->listen_addrs = NULL;
options->address_family = -1;
options->num_host_key_files = 0;
options->num_host_cert_files = 0;
@@ -157,16 +158,18 @@ initialize_server_options(ServerOptions
}
void
fill_default_server_options(ServerOptions *options)
{
/* Portable-specific options */
if (options->use_pam == -1)
options->use_pam = 0;
@ -45,16 +78,36 @@ Index: b/servconf.c
/* Standard Options */
if (options->protocol == SSH_PROTO_UNKNOWN)
@@ -392,7 +395,7 @@ fill_default_server_options(ServerOption
options->protocol = SSH_PROTO_2;
if (options->num_host_key_files == 0) {
/* fill default hostkeys for protocols */
if (options->protocol & SSH_PROTO_1)
options->host_key_files[options->num_host_key_files++] =
@@ -317,17 +320,17 @@ fill_default_server_options(ServerOption
#endif
}
/* Keyword tokens. */
typedef enum {
sBadOption, /* == unknown option */
/* Portable-specific options */
- sUsePAM,
+ sUsePAM, sUsePAMChecklocks,
/* Standard Options */
sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime,
sKeyRegenerationTime, sPermitRootLogin, sLogFacility, sLogLevel,
@@ -442,8 +445,10 @@ static struct {
sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
sPermitRootLogin, sLogFacility, sLogLevel,
sRhostsRSAAuthentication, sRSAAuthentication,
sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
sKerberosGetAFSToken,
sKerberosTgtPassing, sChallengeResponseAuthentication,
sPasswordAuthentication, sKbdInteractiveAuthentication,
@@ -362,18 +365,20 @@ typedef enum {
static struct {
const char *name;
ServerOpCodes opcode;
u_int flags;
} keywords[] = {
/* Portable-specific options */
#ifdef USE_PAM
{ "usepam", sUsePAM, SSHCFG_GLOBAL },
@ -65,7 +118,17 @@ Index: b/servconf.c
#endif
{ "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL },
/* Standard Options */
@@ -1004,6 +1009,9 @@ process_server_config_line(ServerOptions
{ "port", sPort, SSHCFG_GLOBAL },
{ "hostkey", sHostKeyFile, SSHCFG_GLOBAL },
{ "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL }, /* alias */
{ "hostkeyagent", sHostKeyAgent, SSHCFG_GLOBAL },
{ "pidfile", sPidFile, SSHCFG_GLOBAL },
@@ -870,16 +875,19 @@ process_server_config_line(ServerOptions
}
}
switch (opcode) {
/* Portable-specific options */
case sUsePAM:
intptr = &options->use_pam;
goto parse_flag;
@ -75,11 +138,20 @@ Index: b/servconf.c
/* Standard Options */
case sBadOption:
Index: b/servconf.h
===================================================================
--- a/servconf.h
+++ b/servconf.h
@@ -173,6 +173,7 @@ typedef struct {
return -1;
case sPort:
/* ignore ports from configfile if cmdline specifies ports */
if (options->ports_from_cmdline)
return 0;
diff --git a/openssh-6.6p1/servconf.h b/openssh-6.6p1/servconf.h
--- a/openssh-6.6p1/servconf.h
+++ b/openssh-6.6p1/servconf.h
@@ -160,16 +160,17 @@ typedef struct {
*/
u_int num_authkeys_files; /* Files containing public keys */
char *authorized_keys_files[MAX_AUTHKEYS_FILES];
char *adm_forced_command;
int use_pam; /* Enable auth via PAM */
@ -87,13 +159,22 @@ Index: b/servconf.h
int permit_tun;
Index: b/sshd_config.0
===================================================================
--- a/sshd_config.0
+++ b/sshd_config.0
@@ -950,6 +950,14 @@ DESCRIPTION
int num_permitted_opens;
char *chroot_directory;
char *revoked_keys_file;
char *trusted_user_ca_keys;
diff --git a/openssh-6.6p1/sshd_config.0 b/openssh-6.6p1/sshd_config.0
--- a/openssh-6.6p1/sshd_config.0
+++ b/openssh-6.6p1/sshd_config.0
@@ -728,16 +728,24 @@ DESCRIPTION
Because PAM challenge-response authentication usually serves an
equivalent role to password authentication, you should disable
either PasswordAuthentication or ChallengeResponseAuthentication.
If UsePAM is enabled, you will not be able to run sshd(8) as a
non-root user. The default is M-bM-^@M-^\noM-bM-^@M-^].
non-root user. The default is ``no''.
+ UsePAMCheckLocks
+ When set to ``yes'', the checks whether the account has been
@ -106,11 +187,20 @@ Index: b/sshd_config.0
UsePrivilegeSeparation
Specifies whether sshd(8) separates privileges by creating an
unprivileged child process to deal with incoming network traffic.
Index: b/sshd_config.5
===================================================================
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -1574,6 +1574,18 @@ is enabled, you will not be able to run
After successful authentication, another process will be created
that has the privilege of the authenticated user. The goal of
privilege separation is to prevent privilege escalation by
containing any corruption within the unprivileged processes. The
default is ``yes''. If UsePrivilegeSeparation is set to
diff --git a/openssh-6.6p1/sshd_config.5 b/openssh-6.6p1/sshd_config.5
--- a/openssh-6.6p1/sshd_config.5
+++ b/openssh-6.6p1/sshd_config.5
@@ -1214,16 +1214,28 @@ or
.Pp
If
.Cm UsePAM
is enabled, you will not be able to run
.Xr sshd 8
as a non-root user.
The default is
.Dq no .
@ -129,3 +219,8 @@ Index: b/sshd_config.5
.It Cm UsePrivilegeSeparation
Specifies whether
.Xr sshd 8
separates privileges by creating an unprivileged child process
to deal with incoming network traffic.
After successful authentication, another process will be created that has
the privilege of the authenticated user.
The goal of privilege separation is to prevent privilege

View File

@ -3,20 +3,27 @@
add 'getuid' syscall to list of allowed ones to prevent the sanboxed thread
from being killed by the seccomp filter
Index: b/sandbox-seccomp-filter.c
===================================================================
--- a/sandbox-seccomp-filter.c
+++ b/sandbox-seccomp-filter.c
@@ -147,6 +147,12 @@ static const struct sock_filter preauth_
#ifdef __NR_getpid
diff --git a/openssh-6.6p1/sandbox-seccomp-filter.c b/openssh-6.6p1/sandbox-seccomp-filter.c
--- a/openssh-6.6p1/sandbox-seccomp-filter.c
+++ b/openssh-6.6p1/sandbox-seccomp-filter.c
@@ -85,16 +85,20 @@ static const struct sock_filter preauth_
offsetof(struct seccomp_data, arch)),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SECCOMP_AUDIT_ARCH, 1, 0),
BPF_STMT(BPF_RET+BPF_K, SECCOMP_FILTER_FAIL),
/* Load the syscall number for checking. */
BPF_STMT(BPF_LD+BPF_W+BPF_ABS,
offsetof(struct seccomp_data, nr)),
SC_DENY(open, EACCES),
SC_ALLOW(getpid),
#endif
+#ifdef __NR_getuid
+ SC_ALLOW(getuid),
+#endif
+#ifdef __NR_getuid32
+ SC_ALLOW(getuid32),
+#endif
#ifdef __NR_gettimeofday
SC_ALLOW(gettimeofday),
SC_ALLOW(clock_gettime),
#ifdef __NR_time /* not defined on EABI ARM */
SC_ALLOW(time),
#endif
SC_ALLOW(read),
SC_ALLOW(write),
SC_ALLOW(close),

View File

@ -1,11 +1,15 @@
# extended support for (re-)seeding the OpenSSL PRNG from /dev/random
# bnc#703221, FATE#312172
Index: b/audit-bsm.c
===================================================================
--- a/audit-bsm.c
+++ b/audit-bsm.c
@@ -509,4 +509,10 @@ audit_generate_ephemeral_server_key(cons
diff --git a/openssh-6.6p1/audit-bsm.c b/openssh-6.6p1/audit-bsm.c
--- a/openssh-6.6p1/audit-bsm.c
+++ b/openssh-6.6p1/audit-bsm.c
@@ -504,9 +504,15 @@ audit_destroy_sensitive_data(const char
/* not implemented */
}
void
audit_generate_ephemeral_server_key(const char *fp)
{
/* not implemented */
}
@ -16,11 +20,15 @@ Index: b/audit-bsm.c
+ /* not implemented */
+}
#endif /* BSM */
Index: b/audit-linux.c
===================================================================
--- a/audit-linux.c
+++ b/audit-linux.c
@@ -407,4 +407,26 @@ audit_generate_ephemeral_server_key(cons
diff --git a/openssh-6.6p1/audit-linux.c b/openssh-6.6p1/audit-linux.c
--- a/openssh-6.6p1/audit-linux.c
+++ b/openssh-6.6p1/audit-linux.c
@@ -398,9 +398,31 @@ audit_generate_ephemeral_server_key(cons
}
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");
}
@ -47,11 +55,15 @@ Index: b/audit-linux.c
+ error("cannot write into audit");
+}
#endif /* USE_LINUX_AUDIT */
Index: b/audit.c
===================================================================
--- a/audit.c
+++ b/audit.c
@@ -309,5 +309,11 @@ audit_generate_ephemeral_server_key(cons
diff --git a/openssh-6.6p1/audit.c b/openssh-6.6p1/audit.c
--- a/openssh-6.6p1/audit.c
+++ b/openssh-6.6p1/audit.c
@@ -304,10 +304,16 @@ audit_destroy_sensitive_data(const char
/*
* 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);
}
@ -63,22 +75,30 @@ Index: b/audit.c
+}
# endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */
#endif /* SSH_AUDIT_EVENTS */
Index: b/audit.h
===================================================================
--- a/audit.h
+++ b/audit.h
@@ -68,5 +68,6 @@ void audit_session_key_free(int ctos);
diff --git a/openssh-6.6p1/audit.h b/openssh-6.6p1/audit.h
--- a/openssh-6.6p1/audit.h
+++ b/openssh-6.6p1/audit.h
@@ -63,10 +63,11 @@ 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);
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 *);
+void audit_linux_prng_seed(long, const char *);
#endif /* _SSH_AUDIT_H */
Index: b/entropy.c
===================================================================
--- a/entropy.c
+++ b/entropy.c
@@ -54,6 +54,7 @@
diff --git a/openssh-6.6p1/entropy.c b/openssh-6.6p1/entropy.c
--- a/openssh-6.6p1/entropy.c
+++ b/openssh-6.6p1/entropy.c
@@ -45,16 +45,17 @@
#include "ssh.h"
#include "misc.h"
#include "xmalloc.h"
#include "atomicio.h"
#include "pathnames.h"
#include "log.h"
#include "buffer.h"
@ -86,7 +106,17 @@ Index: b/entropy.c
/*
* Portable OpenSSH PRNG seeding:
@@ -229,6 +230,9 @@ seed_rng(void)
* If OpenSSL has not "internally seeded" itself (e.g. pulled data from
* /dev/random), then collect RANDOM_SEED_SIZE bytes of randomness from
* PRNGd.
*/
#ifndef OPENSSL_PRNG_ONLY
@@ -229,11 +230,14 @@ seed_rng(void)
}
if (seed_from_prngd(buf, sizeof(buf)) == -1)
fatal("Could not obtain seed from PRNGd");
RAND_add(buf, sizeof(buf), sizeof(buf));
memset(buf, '\0', sizeof(buf));
#endif /* OPENSSL_PRNG_ONLY */
@ -96,23 +126,32 @@ Index: b/entropy.c
if (RAND_status() != 1)
fatal("PRNG is not seeded");
}
Index: b/openbsd-compat/Makefile.in
===================================================================
--- a/openbsd-compat/Makefile.in
+++ b/openbsd-compat/Makefile.in
@@ -20,7 +20,7 @@ OPENBSD=base64.o basename.o bcrypt_pbkdf
diff --git a/openssh-6.6p1/openbsd-compat/Makefile.in b/openssh-6.6p1/openbsd-compat/Makefile.in
--- a/openssh-6.6p1/openbsd-compat/Makefile.in
+++ b/openssh-6.6p1/openbsd-compat/Makefile.in
@@ -15,17 +15,17 @@ AR=@AR@
RANLIB=@RANLIB@
INSTALL=@INSTALL@
LDFLAGS=-L. @LDFLAGS@
COMPAT=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-setres_id.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xmmap.o xcrypt.o kludge-fd_set.o
OPENBSD=base64.o basename.o bcrypt_pbkdf.o bindresvport.o blowfish.o daemon.o dirname.o fmt_scaled.o getcwd.o getgrouplist.o getopt_long.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o pwcache.o readpassphrase.o realpath.o rresvport.o setenv.o setproctitle.o sha2.o sigact.o strlcat.o strlcpy.o strmode.o strnlen.o strptime.o strsep.o strtonum.o strtoll.o strtoul.o strtoull.o timingsafe_bcmp.o vis.o blowfish.o bcrypt_pbkdf.o explicit_bzero.o
COMPAT=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-setres_id.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-prng.o port-solaris.o port-tun.o port-uw.o
.c.o:
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
Index: b/openbsd-compat/port-linux-prng.c
===================================================================
all: libopenbsd-compat.a
$(COMPAT): ../config.h
$(OPENBSD): ../config.h
diff --git a/openssh-6.6p1/openbsd-compat/port-linux-prng.c b/openssh-6.6p1/openbsd-compat/port-linux-prng.c
new file mode 100644
--- /dev/null
+++ b/openbsd-compat/port-linux-prng.c
+++ b/openssh-6.6p1/openbsd-compat/port-linux-prng.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2011 Jan F. Chadima <jchadima@redhat.com>
@ -193,11 +232,15 @@ Index: b/openbsd-compat/port-linux-prng.c
+ fatal ("EOF reading %s", random);
+ }
+}
Index: b/openbsd-compat/port-linux.h
===================================================================
--- a/openbsd-compat/port-linux.h
+++ b/openbsd-compat/port-linux.h
@@ -19,6 +19,10 @@
diff --git a/openssh-6.6p1/openbsd-compat/port-linux.h b/openssh-6.6p1/openbsd-compat/port-linux.h
--- a/openssh-6.6p1/openbsd-compat/port-linux.h
+++ b/openssh-6.6p1/openbsd-compat/port-linux.h
@@ -14,16 +14,20 @@
* 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.
*/
#ifndef _PORT_LINUX_H
#define _PORT_LINUX_H
@ -208,11 +251,20 @@ Index: b/openbsd-compat/port-linux.h
#ifdef WITH_SELINUX
int ssh_selinux_enabled(void);
void ssh_selinux_setup_pty(char *, const char *);
Index: b/ssh-add.1
===================================================================
--- a/ssh-add.1
+++ b/ssh-add.1
@@ -171,6 +171,20 @@ to make this work.)
void ssh_selinux_setup_exec_context(char *);
void ssh_selinux_change_context(const char *);
void ssh_selinux_setfscreatecon(const char *);
#endif
diff --git a/openssh-6.6p1/ssh-add.1 b/openssh-6.6p1/ssh-add.1
--- a/openssh-6.6p1/ssh-add.1
+++ b/openssh-6.6p1/ssh-add.1
@@ -156,16 +156,30 @@ or related script.
(Note that on some machines it
may be necessary to redirect the input from
.Pa /dev/null
to make this work.)
.It Ev SSH_AUTH_SOCK
Identifies the path of a
.Ux Ns -domain
socket used to communicate with the agent.
@ -233,11 +285,20 @@ Index: b/ssh-add.1
.El
.Sh FILES
.Bl -tag -width Ds
Index: b/ssh-agent.1
===================================================================
--- a/ssh-agent.1
+++ b/ssh-agent.1
@@ -194,6 +194,23 @@ sockets used to contain the connection t
.It Pa ~/.ssh/identity
Contains the protocol version 1 RSA authentication identity of the user.
.It Pa ~/.ssh/id_dsa
Contains the protocol version 2 DSA authentication identity of the user.
.It Pa ~/.ssh/id_ecdsa
diff --git a/openssh-6.6p1/ssh-agent.1 b/openssh-6.6p1/ssh-agent.1
--- a/openssh-6.6p1/ssh-agent.1
+++ b/openssh-6.6p1/ssh-agent.1
@@ -196,16 +196,33 @@ Contains the protocol version 2 ED25519
.It Pa ~/.ssh/id_rsa
Contains the protocol version 2 RSA authentication identity of the user.
.It Pa $TMPDIR/ssh-XXXXXXXXXX/agent.\*(Ltppid\*(Gt
.Ux Ns -domain
sockets used to contain the connection to the authentication agent.
These sockets should only be readable by the owner.
The sockets should get automatically removed when the agent exits.
.El
@ -261,11 +322,20 @@ Index: b/ssh-agent.1
.Sh SEE ALSO
.Xr ssh 1 ,
.Xr ssh-add 1 ,
Index: b/ssh-keygen.1
===================================================================
--- a/ssh-keygen.1
+++ b/ssh-keygen.1
@@ -842,6 +842,23 @@ Contains Diffie-Hellman groups used for
.Xr ssh-keygen 1 ,
.Xr sshd 8
.Sh AUTHORS
OpenSSH is a derivative of the original and free
ssh 1.2.12 release by Tatu Ylonen.
diff --git a/openssh-6.6p1/ssh-keygen.1 b/openssh-6.6p1/ssh-keygen.1
--- a/openssh-6.6p1/ssh-keygen.1
+++ b/openssh-6.6p1/ssh-keygen.1
@@ -827,16 +827,33 @@ on all machines
where the user wishes to log in using public key authentication.
There is no need to keep the contents of this file secret.
.Pp
.It Pa /etc/moduli
Contains Diffie-Hellman groups used for DH-GEX.
The file format is described in
.Xr moduli 5 .
.El
@ -289,11 +359,20 @@ Index: b/ssh-keygen.1
.Sh SEE ALSO
.Xr ssh 1 ,
.Xr ssh-add 1 ,
Index: b/ssh-keysign.8
===================================================================
--- a/ssh-keysign.8
+++ b/ssh-keysign.8
@@ -80,6 +80,23 @@ must be set-uid root if host-based authe
.Xr ssh-agent 1 ,
.Xr moduli 5 ,
.Xr sshd 8
.Rs
.%R RFC 4716
diff --git a/openssh-6.6p1/ssh-keysign.8 b/openssh-6.6p1/ssh-keysign.8
--- a/openssh-6.6p1/ssh-keysign.8
+++ b/openssh-6.6p1/ssh-keysign.8
@@ -75,16 +75,33 @@ must be set-uid root if host-based authe
.Pp
.It Pa /etc/ssh/ssh_host_dsa_key-cert.pub
.It Pa /etc/ssh/ssh_host_ecdsa_key-cert.pub
.It Pa /etc/ssh/ssh_host_ed25519_key-cert.pub
.It Pa /etc/ssh/ssh_host_rsa_key-cert.pub
If these files exist they are assumed to contain public certificate
information corresponding with the private keys above.
.El
@ -317,11 +396,20 @@ Index: b/ssh-keysign.8
.Sh SEE ALSO
.Xr ssh 1 ,
.Xr ssh-keygen 1 ,
Index: b/ssh.1
===================================================================
--- a/ssh.1
+++ b/ssh.1
@@ -1415,6 +1415,20 @@ For more information, see the
.Xr ssh_config 5 ,
.Xr sshd 8
.Sh HISTORY
.Nm
first appeared in
diff --git a/openssh-6.6p1/ssh.1 b/openssh-6.6p1/ssh.1
--- a/openssh-6.6p1/ssh.1
+++ b/openssh-6.6p1/ssh.1
@@ -1304,16 +1304,30 @@ reads
and adds lines of the format
.Dq VARNAME=value
to the environment if the file exists and users are allowed to
change their environment.
For more information, see the
.Cm PermitUserEnvironment
option in
.Xr sshd_config 5 .
@ -342,11 +430,20 @@ Index: b/ssh.1
.Sh FILES
.Bl -tag -width Ds -compact
.It Pa ~/.rhosts
Index: b/sshd.8
===================================================================
--- a/sshd.8
+++ b/sshd.8
@@ -944,6 +944,23 @@ concurrently for different ports, this c
This file is used for host-based authentication (see above).
On some machines this file may need to be
world-readable if the user's home directory is on an NFS partition,
because
.Xr sshd 8
diff --git a/openssh-6.6p1/sshd.8 b/openssh-6.6p1/sshd.8
--- a/openssh-6.6p1/sshd.8
+++ b/openssh-6.6p1/sshd.8
@@ -946,16 +946,33 @@ and not group or world-writable.
.It Pa /var/run/sshd.pid
Contains the process ID of the
.Nm
listening for connections (if there are several daemons running
concurrently for different ports, this contains the process ID of the one
started last).
The content of this file is not sensitive; it can be world-readable.
.El
@ -370,11 +467,20 @@ Index: b/sshd.8
.Sh SEE ALSO
.Xr scp 1 ,
.Xr sftp 1 ,
Index: b/sshd.c
===================================================================
--- a/sshd.c
+++ b/sshd.c
@@ -55,6 +55,8 @@
.Xr ssh 1 ,
.Xr ssh-add 1 ,
.Xr ssh-agent 1 ,
.Xr ssh-keygen 1 ,
.Xr ssh-keyscan 1 ,
diff --git a/openssh-6.6p1/sshd.c b/openssh-6.6p1/sshd.c
--- a/openssh-6.6p1/sshd.c
+++ b/openssh-6.6p1/sshd.c
@@ -50,16 +50,18 @@
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#include "openbsd-compat/sys-tree.h"
#include "openbsd-compat/sys-queue.h"
@ -383,7 +489,17 @@ Index: b/sshd.c
#include <sys/wait.h>
#include <errno.h>
@@ -214,6 +216,13 @@ struct {
#include <fcntl.h>
#include <netdb.h>
#ifdef HAVE_PATHS_H
#include <paths.h>
#endif
@@ -218,16 +220,23 @@ struct {
Key **host_pubkeys; /* all public host keys */
Key **host_certificates; /* all public host certificates */
int have_ssh1_key;
int have_ssh2_key;
u_char ssh1_cookie[SSH_SESSION_KEY_LENGTH];
} sensitive_data;
/*
@ -397,7 +513,17 @@ Index: b/sshd.c
* Flag indicating whether the RSA server key needs to be regenerated.
* Is set in the SIGALRM handler and cleared when the key is regenerated.
*/
@@ -1400,6 +1409,11 @@ server_accept_loop(int *sock_in, int *so
static volatile sig_atomic_t key_do_regen = 0;
/* This is set to true when a signal is received. */
static volatile sig_atomic_t received_sighup = 0;
static volatile sig_atomic_t received_sigterm = 0;
@@ -1322,16 +1331,21 @@ server_accept_loop(int *sock_in, int *so
for (j = 0; j < options.max_startups; j++)
if (startup_pipes[j] == -1) {
startup_pipes[j] = startup_p[0];
if (maxfd < startup_p[0])
maxfd = startup_p[0];
startups++;
break;
}
@ -409,3 +535,8 @@ Index: b/sshd.c
/*
* Got connection. Fork a child to handle it, unless
* we are in debugging mode.
*/
if (debug_flag) {
/*
* In debugging mode. Close the listening

View File

@ -3,11 +3,15 @@
# http://lists.mindrot.org/pipermail/openssh-unix-dev/2010-November/029044.html
# http://marc.info/?l=openssh-unix-dev&m=128896838930893
Index: b/sftp-server.8
===================================================================
--- a/sftp-server.8
+++ b/sftp-server.8
@@ -38,6 +38,7 @@
diff --git a/openssh-6.6p1/sftp-server.8 b/openssh-6.6p1/sftp-server.8
--- a/openssh-6.6p1/sftp-server.8
+++ b/openssh-6.6p1/sftp-server.8
@@ -33,16 +33,17 @@
.Bk -words
.Op Fl ehR
.Op Fl d Ar start_directory
.Op Fl f Ar log_facility
.Op Fl l Ar log_level
.Op Fl P Ar blacklisted_requests
.Op Fl p Ar whitelisted_requests
.Op Fl u Ar umask
@ -15,7 +19,17 @@ Index: b/sftp-server.8
.Ek
.Nm
.Fl Q Ar protocol_feature
@@ -138,6 +139,10 @@ Sets an explicit
.Sh DESCRIPTION
.Nm
is a program that speaks the server side of SFTP protocol
to stdout and expects client requests from stdin.
.Nm
@@ -133,16 +134,20 @@ Places this instance of
into a read-only mode.
Attempts to open files for writing, as well as other operations that change
the state of the filesystem, will be denied.
.It Fl u Ar umask
Sets an explicit
.Xr umask 2
to be applied to newly-created files and directories, instead of the
user's default mask.
@ -25,12 +39,21 @@ Index: b/sftp-server.8
+777, 755, 750, 666, 644, 640, etc. Option -u is ineffective if -m is set.
.El
.Pp
On some systems,
Index: b/sftp-server.c
===================================================================
--- a/sftp-server.c
+++ b/sftp-server.c
@@ -78,6 +78,10 @@ static int readonly;
For logging to work,
.Nm
must be able to access
.Pa /dev/log .
Use of
.Nm
diff --git a/openssh-6.6p1/sftp-server.c b/openssh-6.6p1/sftp-server.c
--- a/openssh-6.6p1/sftp-server.c
+++ b/openssh-6.6p1/sftp-server.c
@@ -75,16 +75,20 @@ static u_int version;
static int init_done;
/* Disable writes */
static int readonly;
/* Requests that are allowed/denied */
static char *request_whitelist, *request_blacklist;
@ -41,18 +64,38 @@ Index: b/sftp-server.c
/* portable attributes, etc. */
typedef struct Stat Stat;
@@ -692,6 +696,10 @@ process_open(u_int32_t id)
struct Stat {
char *name;
char *long_name;
Attrib attrib;
};
@@ -670,16 +674,20 @@ process_open(u_int32_t id)
int handle, fd, flags, mode, status = SSH2_FX_FAILURE;
name = get_string(NULL);
pflags = get_int(); /* portable flags */
debug3("request %u: open flags %d", id, pflags);
a = get_attrib();
flags = flags_from_portable(pflags);
mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a.perm : 0666;
+ if (permforce == 1) {
+ mode = permforcemode;
+ (void)umask(0); /* so umask does not interfere */
+ }
mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666;
+ if (permforce == 1) {
+ mode = permforcemode;
+ (void)umask(0); /* so umask does not interfere */
+ }
logit("open \"%s\" flags %s mode 0%o",
name, string_from_portable(pflags), mode);
if (readonly &&
@@ -1494,7 +1502,8 @@ sftp_server_usage(void)
((flags & O_ACCMODE) == O_WRONLY ||
(flags & O_ACCMODE) == O_RDWR)) {
verbose("Refusing open request in read-only mode");
status = SSH2_FX_PERMISSION_DENIED;
} else {
@@ -1425,17 +1433,18 @@ sftp_server_cleanup_exit(int i)
static void
sftp_server_usage(void)
{
extern char *__progname;
fprintf(stderr,
"usage: %s [-ehR] [-d start_directory] [-f log_facility] "
"[-l log_level]\n\t[-P blacklisted_requests] "
@ -62,7 +105,17 @@ Index: b/sftp-server.c
" %s -Q protocol_feature\n",
__progname, __progname);
exit(1);
@@ -1519,7 +1528,7 @@ sftp_server_main(int argc, char **argv,
}
int
sftp_server_main(int argc, char **argv, struct passwd *user_pw)
{
@@ -1450,17 +1459,17 @@ 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);
pw = pwcopy(user_pw);
while (!skipargs && (ch = getopt(argc, argv,
@ -71,7 +124,17 @@ Index: b/sftp-server.c
switch (ch) {
case 'Q':
if (strcasecmp(optarg, "requests") != 0) {
@@ -1579,6 +1588,13 @@ sftp_server_main(int argc, char **argv,
fprintf(stderr, "Invalid query type\n");
exit(1);
}
for (i = 0; handlers[i].handler != NULL; i++)
printf("%s\n", handlers[i].name);
@@ -1510,16 +1519,23 @@ sftp_server_main(int argc, char **argv,
case 'u':
errno = 0;
mask = strtol(optarg, &cp, 8);
if (mask < 0 || mask > 0777 || *cp != '\0' ||
cp == optarg || (mask == 0 && errno != 0))
fatal("Invalid umask \"%s\"", optarg);
(void)umask((mode_t)mask);
break;
@ -85,3 +148,8 @@ Index: b/sftp-server.c
case 'h':
default:
sftp_server_usage();
}
}
log_init(__progname, log_level, log_facility, log_stderr);

View File

@ -1,10 +1,14 @@
# run sftp sessions inside a chroot
Index: b/session.c
===================================================================
--- a/session.c
+++ b/session.c
@@ -127,6 +127,8 @@ void do_child(Session *, const char *);
diff --git a/openssh-6.6p1/session.c b/openssh-6.6p1/session.c
--- a/openssh-6.6p1/session.c
+++ b/openssh-6.6p1/session.c
@@ -120,16 +120,18 @@ int do_exec(Session *, const char *);
void do_login(Session *, const char *);
#ifdef LOGIN_NEEDS_UTMPX
static void do_pre_login(Session *s);
#endif
void do_child(Session *, const char *);
void do_motd(void);
int check_quietlogin(Session *, const char *);
@ -13,7 +17,17 @@ Index: b/session.c
static void do_authenticated1(Authctxt *);
static void do_authenticated2(Authctxt *);
@@ -816,6 +818,11 @@ do_exec(Session *s, const char *command)
static int session_pty_req(Session *);
/* import */
extern ServerOptions options;
extern char *__progname;
@@ -827,16 +829,21 @@ do_exec(Session *s, const char *command)
"subsystem '%.900s'", s->subsys);
} else if (command == NULL) {
snprintf(session_type, sizeof(session_type), "shell");
} else {
/* NB. we don't log unforced commands to preserve privacy */
snprintf(session_type, sizeof(session_type), "command");
}
@ -25,78 +39,95 @@ Index: b/session.c
if (s->ttyfd != -1) {
tty = s->tty;
if (strncmp(tty, "/dev/", 5) == 0)
@@ -1453,6 +1460,62 @@ do_nologin(struct passwd *pw)
tty += 5;
}
verbose("Starting session: %s%s%s for %s from %.200s port %d",
session_type,
@@ -1463,67 +1470,132 @@ do_nologin(struct passwd *pw)
while (fgets(buf, sizeof(buf), f))
fputs(buf, stderr);
fclose(f);
}
exit(254);
}
/*
+ * Test if filesystem is mounted nosuid and nodev
+ */
+
+static void
+test_nosuid (char * path, dev_t fs)
+{
+ FILE *f;
+ struct stat st;
+ char buf[4096], *s, *on, *mountpoint, *opt;
+ int nodev, nosuid;
+ FILE *f;
+ struct stat st;
+ char buf[4096], *s, *on, *mountpoint, *opt;
+ int nodev, nosuid;
+
+ if (!(f = popen ("/bin/mount", "r")))
+ fatal ("%s: popen(\"/bin/mount\", \"r\"): %s",
+ __func__, strerror (errno));
+ for (;;) {
+ s = fgets (buf, sizeof (buf), f);
+ if (ferror (f))
+ fatal ("%s: read from popen: %s", __func__,
+ strerror (errno));
+ if (!s) {
+ pclose (f);
+ fatal ("cannot find filesystem with the chroot directory");
+ }
+ (void) strtok (buf, " ");
+ on = strtok (NULL, " ");
+ if (strcmp (on, "on")) {
+ pclose (f);
+ fatal ("bad format of mount output");
+ }
+ mountpoint = strtok (NULL, " ");
+ if (memcmp (path, mountpoint, strlen (mountpoint)))
+ continue;
+ if (stat(mountpoint, &st) != 0) {
+ pclose (f);
+ fatal("%s: stat(\"%s\"): %s", __func__,
+ mountpoint, strerror(errno));
+ }
+ if (fs != st.st_dev)
+ continue;
+ nodev = nosuid = 0;
+ for (opt = strtok (NULL, "("); opt; opt = strtok (NULL, " ,)")) {
+ if (!strcmp (opt, "nodev"))
+ nodev = 1;
+ else if (!strcmp (opt, "nosuid"))
+ nosuid = 1;
+ else if (!strcmp (opt, "noexec"))
+ nosuid = 1;
+ if (nodev && nosuid) {
+ pclose (f);
+ return;
+ }
+ }
+ fatal ("chroot into directory without nodev and either noexec or nosuid");
+ }
+ if (!(f = popen ("/bin/mount", "r")))
+ fatal ("%s: popen(\"/bin/mount\", \"r\"): %s",
+ __func__, strerror (errno));
+ for (;;) {
+ s = fgets (buf, sizeof (buf), f);
+ if (ferror (f))
+ fatal ("%s: read from popen: %s", __func__,
+ strerror (errno));
+ if (!s) {
+ pclose (f);
+ fatal ("cannot find filesystem with the chroot directory");
+ }
+ (void) strtok (buf, " ");
+ on = strtok (NULL, " ");
+ if (strcmp (on, "on")) {
+ pclose (f);
+ fatal ("bad format of mount output");
+ }
+ mountpoint = strtok (NULL, " ");
+ if (memcmp (path, mountpoint, strlen (mountpoint)))
+ continue;
+ if (stat(mountpoint, &st) != 0) {
+ pclose (f);
+ fatal("%s: stat(\"%s\"): %s", __func__,
+ mountpoint, strerror(errno));
+ }
+ if (fs != st.st_dev)
+ continue;
+ nodev = nosuid = 0;
+ for (opt = strtok (NULL, "("); opt; opt = strtok (NULL, " ,)")) {
+ if (!strcmp (opt, "nodev"))
+ nodev = 1;
+ else if (!strcmp (opt, "nosuid"))
+ nosuid = 1;
+ else if (!strcmp (opt, "noexec"))
+ nosuid = 1;
+ if (nodev && nosuid) {
+ pclose (f);
+ return;
+ }
+ }
+ fatal ("chroot into directory without nodev and either noexec or nosuid");
+ }
+}
+
+/*
* Chroot into a directory after checking it for safety: all path components
* must be root-owned directories with strict permissions.
*/
@@ -1462,6 +1525,7 @@ safely_chroot(const char *path, uid_t ui
static void
safely_chroot(const char *path, uid_t uid)
{
const char *cp;
char component[PATH_MAX];
char component[MAXPATHLEN];
struct stat st;
+ int last;
if (*path != '/')
fatal("chroot path does not begin at root");
@@ -1473,7 +1537,7 @@ safely_chroot(const char *path, uid_t ui
if (strlen(path) >= sizeof(component))
fatal("chroot path too long");
/*
* Descend the path, checking that each component is a
* root-owned directory with strict permissions.
*/
for (cp = path; cp != NULL;) {
@ -105,7 +136,12 @@ Index: b/session.c
strlcpy(component, path, sizeof(component));
else {
cp++;
@@ -1486,7 +1550,7 @@ safely_chroot(const char *path, uid_t ui
memcpy(component, path, cp - path);
component[cp - path] = '\0';
}
debug3("%s: checking '%s'", __func__, component);
if (stat(component, &st) != 0)
fatal("%s: stat(\"%s\"): %s", __func__,
component, strerror(errno));
@ -114,24 +150,40 @@ Index: b/session.c
fatal("bad ownership or modes for chroot "
"directory %s\"%s\"",
cp == NULL ? "" : "component ", component);
@@ -1495,6 +1559,13 @@ safely_chroot(const char *path, uid_t ui
if (!S_ISDIR(st.st_mode))
fatal("chroot path %s\"%s\" is not a directory",
cp == NULL ? "" : "component ", component);
}
-
+ }
+ setenv ("TZ", "/etc/localtime", 0);
+ tzset();
+
+ if (st.st_uid) {
+ test_nosuid(path, st.st_dev);
+ ++chroot_no_tree;
+ }
}
if (chdir(path) == -1)
fatal("Unable to chdir to chroot path \"%s\": "
Index: b/sftp-chrootenv.h
===================================================================
"%s", path, strerror(errno));
if (chroot(path) == -1)
fatal("chroot(\"%s\"): %s", path, strerror(errno));
if (chdir("/") == -1)
fatal("%s: chdir(/) after chroot: %s",
__func__, strerror(errno));
+
verbose("Changed root directory to \"%s\"", path);
}
/* Set login name, uid, gid, and groups. */
void
do_setusercontext(struct passwd *pw)
{
char *chroot_path, *tmp;
diff --git a/openssh-6.6p1/sftp-chrootenv.h b/openssh-6.6p1/sftp-chrootenv.h
new file mode 100644
--- /dev/null
+++ b/sftp-chrootenv.h
+++ b/openssh-6.6p1/sftp-chrootenv.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2009 Jan F Chadima. All rights reserved.
@ -163,11 +215,15 @@ Index: b/sftp-chrootenv.h
+
+#endif
+
Index: b/sftp-common.c
===================================================================
--- a/sftp-common.c
+++ b/sftp-common.c
@@ -48,6 +48,7 @@
diff --git a/openssh-6.6p1/sftp-common.c b/openssh-6.6p1/sftp-common.c
--- a/openssh-6.6p1/sftp-common.c
+++ b/openssh-6.6p1/sftp-common.c
@@ -42,16 +42,17 @@
#endif
#include "xmalloc.h"
#include "buffer.h"
#include "log.h"
#include "sftp.h"
#include "sftp-common.h"
@ -175,7 +231,17 @@ Index: b/sftp-common.c
/* Clear contents of attributes structure */
void
@@ -221,13 +222,13 @@ ls_file(const char *name, const struct s
attrib_clear(Attrib *a)
{
a->flags = 0;
a->size = 0;
a->uid = 0;
@@ -193,23 +194,23 @@ ls_file(const char *name, const struct s
int ulen, glen, sz = 0;
struct tm *ltime = localtime(&st->st_mtime);
char *user, *group;
char buf[1024], mode[11+1], tbuf[12+1], ubuf[11+1], gbuf[11+1];
char sbuf[FMT_SCALED_STRSIZE];
time_t now;
strmode(st->st_mode, mode);
@ -191,11 +257,20 @@ Index: b/sftp-common.c
group = group_from_gid(st->st_gid, 0);
} else {
snprintf(gbuf, sizeof gbuf, "%u", (u_int)st->st_gid);
Index: b/sftp-server-main.c
===================================================================
--- a/sftp-server-main.c
+++ b/sftp-server-main.c
@@ -22,11 +22,14 @@
group = gbuf;
}
if (ltime != NULL) {
now = time(NULL);
if (now - (365*24*60*60)/2 < st->st_mtime &&
diff --git a/openssh-6.6p1/sftp-server-main.c b/openssh-6.6p1/sftp-server-main.c
--- a/openssh-6.6p1/sftp-server-main.c
+++ b/openssh-6.6p1/sftp-server-main.c
@@ -17,21 +17,24 @@
#include "includes.h"
#include <sys/types.h>
#include <pwd.h>
#include <stdarg.h>
#include <stdio.h>
#include <unistd.h>
@ -210,11 +285,20 @@ Index: b/sftp-server-main.c
void
cleanup_exit(int i)
{
Index: b/sftp.c
===================================================================
--- a/sftp.c
+++ b/sftp.c
@@ -117,6 +117,8 @@ int remote_glob(struct sftp_conn *, cons
sftp_server_cleanup_exit(i);
}
int
main(int argc, char **argv)
diff --git a/openssh-6.6p1/sftp.c b/openssh-6.6p1/sftp.c
--- a/openssh-6.6p1/sftp.c
+++ b/openssh-6.6p1/sftp.c
@@ -109,16 +109,18 @@ struct complete_ctx {
char **remote_pathp;
};
int remote_glob(struct sftp_conn *, const char *, int,
int (*)(const char *, int), glob_t *); /* proto for sftp-glob.c */
extern char *__progname;
@ -223,13 +307,22 @@ Index: b/sftp.c
/* Separators for interactive commands */
#define WHITESPACE " \t\r\n"
Index: b/sshd_config.0
===================================================================
--- a/sshd_config.0
+++ b/sshd_config.0
@@ -258,6 +258,14 @@ DESCRIPTION
(especially those outside the jail). Misconfiguration can lead
to unsafe environments which sshd(8) cannot detect.
/* ls flags */
#define LS_LONG_VIEW 0x0001 /* Full view ala ls -l */
#define LS_SHORT_VIEW 0x0002 /* Single row view ala ls -1 */
#define LS_NUMERIC_VIEW 0x0004 /* Long view with numeric uid/gid */
#define LS_NAME_SORT 0x0008 /* Sort by name (default) */
diff --git a/openssh-6.6p1/sshd_config.0 b/openssh-6.6p1/sshd_config.0
--- a/openssh-6.6p1/sshd_config.0
+++ b/openssh-6.6p1/sshd_config.0
@@ -189,16 +189,24 @@ DESCRIPTION
session this requires at least a shell, typically sh(1), and
basic /dev nodes such as null(4), zero(4), stdin(4), stdout(4),
stderr(4), arandom(4) and tty(4) devices. For file transfer
sessions using ``sftp'', no additional configuration of the
environment is necessary if the in-process sftp server is used,
though sessions which use logging do require /dev/log inside the
chroot directory (see sftp-server(8) for details).
+ In the special case when only sftp is used, not ssh nor scp, it
+ is possible to use ChrootDirectory %h or ChrootDirectory
@ -242,11 +335,20 @@ Index: b/sshd_config.0
The default is not to chroot(2).
Ciphers
Index: b/sshd_config.5
===================================================================
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -421,6 +421,17 @@ inside the chroot directory on some oper
Specifies the ciphers allowed for protocol version 2. Multiple
ciphers must be comma-separated. The supported ciphers are:
``3des-cbc'', ``aes128-cbc'', ``aes192-cbc'', ``aes256-cbc'',
``aes128-ctr'', ``aes192-ctr'', ``aes256-ctr'',
diff --git a/openssh-6.6p1/sshd_config.5 b/openssh-6.6p1/sshd_config.5
--- a/openssh-6.6p1/sshd_config.5
+++ b/openssh-6.6p1/sshd_config.5
@@ -324,16 +324,27 @@ For file transfer sessions using
no additional configuration of the environment is necessary if the
in-process sftp server is used,
though sessions which use logging do require
.Pa /dev/log
inside the chroot directory (see
.Xr sftp-server 8
for details).
.Pp
@ -261,6 +363,11 @@ Index: b/sshd_config.5
+must fulfill the usual conditions. No aditional files are required to be present
+in the directory.
+.Pp
For safety, it is very important that the directory hierarchy be
prevented from modification by other processes on the system (especially
those outside the jail).
The default is not to
.Xr chroot 2 .
.It Cm Ciphers
Specifies the ciphers allowed for protocol version 2.
Multiple ciphers must be comma-separated.
The supported ciphers are:
.Pp
.Dq 3des-cbc ,

3
openssh-6.6p1.tar.gz Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:48c1f0664b4534875038004cc4f3555b8329c2a81c1df48db5c517800de203bb
size 1282502

14
openssh-6.6p1.tar.gz.asc Normal file
View File

@ -0,0 +1,14 @@
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.22 (OpenBSD)
iQGlAwUAUyEVxtPl9Wttkg0wAQr39wx/SkCPbWVsEG2Do7IXKg1FudhKIt8QGQZC
4bNvnwFbFZ/RNEv+BZRKH7AmgNLXn6/VTlRkifF3osrvJ6gh8EfQMkNPB5WcRz5h
c4KdAcL6u/KFxku0x/hjqUaAV980HlUFvAmGv3/YTL8n14uRBRlrVCnG5q1LmIv7
piBnb+FrAivrNV+PUMkkrC6XKrfR2ns+ZtfgwBQGQ/VuJTQZPOUMp/GLViHBxz4l
G0H52bolzAIunzBxXF9fWwFU8JFtCEharFr7jYuLQzViUPCaf3L9w3yPb2S24wnU
772CEyGbdCJVLmtD9ObaNKk0We6hdc6Dz+mx/JbHkoWSw0LYdHFbjFR75vjNENYh
evRgqLCP91micfhZDQqX6tOLnMfBjxCjHsCYvMlDACiEvxb1Ct6Fm9m1lXIGUsh3
ssScaCvQItMAvQdjQOdCXS7Zcucfzzx3Fd8Q2X/h2R81yYv6JjYQy7aBV/DaFDzP
/BhCwnq5sP6XW6rHRZGYXhMaAEjZml8ySRFEzW+esnGf9vSJgnQ+Kw==
=H2K/
-----END PGP SIGNATURE-----

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:dd75f024dcf21e06a0d6421d582690bf987a1f6323e32ad6619392f3bfde6bbd
size 1475829

View File

@ -1,14 +0,0 @@
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2
iQGsBAABCgAGBQJWlvZKAAoJENPl9Wttkg0w0kwMfRd8u1P8+RDXoF32uhtOwQAY
31cJz2gBf2jnBV/BEzxBNCvpObE9ECCMyWK0RSCjHQBxfwoW4YdkAArBZxbexXtU
fXOlUdcB1cc4OqgvvufktMt5txg17VSKv8tI23mCT0Ibs3dppz+PNAH2LzcKWTXb
Hr7PQzY4qufZ336R6ADKuXqfUFDNx7oLEiehTrSC7AhIM3Wagqv2dRBJNkW/Ci3w
qWnTQ6IOD5A//EDLVW0SqQ1/4n7mWBmkoiRw0xzFxRnnHKjhwIGqwj5oOoDFzZOa
6XtOcIwh9VXemTl5Gq+ZaiaRFA1TRHsVXVT1TgSUgB3Muy3PyOFHmHEZlLyfPrNV
/WjoV18zosVGd2egGB8jK6xzftpPeoVndiWPwSIz52E6xBtoCVXr0ksjz3wbgx+9
NOVF58Zo19eN6Nf1H4EP3K0aNDnjM5lsByphGGk5W7sQUc0u4Yvw4Rbc9VGV8I/Z
Sddw5WProNQXmsO06eO2ey8POUI4CaKTe8UWfc74MXkF93m8MD7VdmB4lYCsFi8=
=0gQS
-----END PGP SIGNATURE-----

View File

@ -1,28 +0,0 @@
--- openssh-7.1p2.orig/xmalloc.h
+++ openssh-7.1p2/xmalloc.h
@@ -16,10 +16,10 @@
* called by a name other than "ssh" or "Secure Shell".
*/
-void *xmalloc(size_t);
-void *xcalloc(size_t, size_t);
-void *xreallocarray(void *, size_t, size_t);
-char *xstrdup(const char *);
+void *xmalloc(size_t) __attribute__((__malloc__, __alloc_size__(1)));
+void *xcalloc(size_t, size_t) __attribute__((__malloc__, __alloc_size__(1,2)));
+void *xreallocarray(void *, size_t, size_t) __attribute__((__alloc_size__(2,3)));
+char *xstrdup(const char *) __attribute__((__malloc__));
int xasprintf(char **, const char *, ...)
__attribute__((__format__ (printf, 2, 3)))
__attribute__((__nonnull__ (2)));
--- openssh-7.1p2.orig/openbsd-compat/openbsd-compat.h
+++ openssh-7.1p2/openbsd-compat/openbsd-compat.h
@@ -66,7 +66,7 @@ char *getcwd(char *pt, size_t size);
#endif
#ifndef HAVE_REALLOCARRAY
-void *reallocarray(void *, size_t, size_t);
+void *reallocarray(void *, size_t, size_t) __attribute__((__alloc_size__(2,3)));
#endif
#if !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH)

View File

@ -1,12 +0,0 @@
--- openssh-7.1p2.orig/sandbox-seccomp-filter.c
+++ openssh-7.1p2/sandbox-seccomp-filter.c
@@ -153,6 +153,9 @@ static const struct sock_filter preauth_
#ifdef __NR_getuid32
SC_ALLOW(getuid32),
#endif
+#ifdef __NR_getrandom
+ SC_ALLOW(getrandom),
+#endif
#ifdef __NR_gettimeofday
SC_ALLOW(gettimeofday),
#endif

View File

@ -1,9 +1,3 @@
-------------------------------------------------------------------
Mon Jan 18 06:58:40 UTC 2016 - tchvatal@suse.com
- Cleanup with spec-cleaner
- Update of the master OpenSSH to 7.1p2
-------------------------------------------------------------------
Fri Apr 11 21:50:51 UTC 2014 - pcerny@suse.com

View File

@ -16,15 +16,7 @@
#
%define _name openssh
Name: openssh-askpass-gnome
Version: 7.1p2
Release: 0
Summary: A GNOME-Based Passphrase Dialog for OpenSSH
License: BSD-3-Clause
Group: Productivity/Networking/SSH
Url: http://www.openssh.com/
Source: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz
BuildRequires: autoconf
BuildRequires: automake
BuildRequires: gtk2-devel
@ -34,7 +26,15 @@ BuildRequires: openssl-devel
BuildRequires: pam-devel
BuildRequires: tcpd-devel
BuildRequires: update-desktop-files
Version: 6.6p1
Release: 0
Requires: openssh = %{version}
Summary: A GNOME-Based Passphrase Dialog for OpenSSH
License: BSD-3-Clause
Group: Productivity/Networking/SSH
Url: http://www.openssh.com/
%define _name openssh
Source: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-build
%description

View File

@ -1,24 +0,0 @@
--- openssh-7.1p2.orig/configure.ac
+++ openssh-7.1p2/configure.ac
@@ -2873,6 +2873,10 @@ else
AC_CHECK_FUNCS([crypt])
fi
+AC_CHECK_DECLS([b64_ntop, b64_pton], [], [], [#include <resolv.h>])
+AC_SEARCH_LIBS([__b64_ntop], [resolv])
+AC_SEARCH_LIBS([__b64_pton], [resolv])
+
AC_CHECK_FUNCS([ \
arc4random \
arc4random_buf \
--- openssh-7.1p2.orig/Makefile.in
+++ openssh-7.1p2/Makefile.in
@@ -45,7 +45,7 @@ PATHS= -DSSHDIR=\"$(sysconfdir)\" \
CC=@CC@
LD=@LD@
CFLAGS=@CFLAGS@
-CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@
+CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@ -include config.h
LIBS=@LIBS@
K5LIBS=@K5LIBS@
GSSLIBS=@GSSLIBS@

View File

@ -1,94 +1,3 @@
-------------------------------------------------------------------
Mon Feb 8 16:54:22 UTC 2016 - crrodriguez@opensuse.org
- openssh-alloc_size.patch: anotate xmalloc.h with alloc_size
attribute so the compiler knows these functions allocate memory
so overflow or misuse can be detected sooner.
- openssh-allow_getrandom.patch; allow the getrandom(2) system
call in the seccomp sandbox, upstream commit 26ad18247213
- openssh-fix-b64_xx-detection.patch: configure.ac has incorrect
tests for b64_ntop, b64_pton on linux/glibc.
-------------------------------------------------------------------
Wed Jan 20 11:18:48 UTC 2016 - tchvatal@suse.com
- Take refreshed and updated audit patch from redhat
* Remove our old patches:
+ openssh-6.6p1-audit1-remove_duplicit_audit.patch
+ openssh-6.6p1-audit2-better_audit_of_user_actions.patch
+ openssh-6.6p1-audit3-key_auth_usage-fips.patch
+ openssh-6.6p1-audit3-key_auth_usage.patch
+ openssh-6.6p1-audit4-kex_results-fips.patch
+ openssh-6.6p1-audit4-kex_results.patch
+ openssh-6.6p1-audit5-session_key_destruction.patch
+ openssh-6.6p1-audit6-server_key_destruction.patch
+ openssh-6.6p1-audit7-libaudit_compat.patch
+ openssh-6.6p1-audit8-libaudit_dns_timeouts.patch
* add openssh-6.7p1-audit.patch
- Reenable the openssh-6.6p1-ldap.patch
- Update the fips patch from RH build openssh-6.6p1-fips.patch
- Update and refresh openssh-6.6p1-gssapi_key_exchange.patch
- Remove fips-check patch as it is merged to fips patch
* openssh-6.6p1-fips-checks.patch
- Rebase and enable chroot patch:
* openssh-6.6p1-sftp_homechroot.patch
- Reenable rebased patch for linux seed:
* openssh-6.6p1-seed-prng.patch
- Reenable key converting patch:
* openssh-6.6p1-key-converter.patch
-------------------------------------------------------------------
Mon Jan 18 07:33:17 UTC 2016 - tchvatal@suse.com
- Version update to 7.1p2:
* various upstream bugfixes and cleanups
- Remove upstreamed patch:
* openssh-6.6p1-curve25519-6.6.1p1.patch
* CVE-2016-0777_CVE-2016-0778.patch
- Remove patches fixed differently in upstream:
* openssh-6.6p1-fingerprint_hash.patch
* openssh-6.6p1-no_fork-no_pid_file.patch
- Disable patch for fips, needs a lot of work:
* openssh-6.6p1-fips.patch
* openssh-6.6p1-audit3-key_auth_usage-fips.patch
- Refresh non-applying patches:
* openssh-6.6p1-blocksigalrm.patch
* openssh-6.6p1-eal3.patch
* openssh-6.6p1-gssapimitm.patch
* openssh-6.6p1-pam-check-locks.patch
* openssh-6.6p1-disable-openssl-abi-check.patch
* openssh-6.6p1-sftp_force_permissions.patch
* openssh-6.6p1-seccomp_getuid.patch
* openssh-6.6p1-ldap.patch
- Disable non-applying patches requiring review:
* openssh-6.6p1-audit2-better_audit_of_user_actions.patch
* openssh-6.6p1-audit3-key_auth_usage.patch
* openssh-6.6p1-audit4-kex_results.patch
* openssh-6.6p1-audit4-kex_results-fips.patch
* openssh-6.6p1-audit5-session_key_destruction.patch
* openssh-6.6p1-audit6-server_key_destruction.patch
* openssh-6.6p1-seed-prng.patch
* openssh-6.6p1-gssapi_key_exchange.patch
* openssh-6.6p1-sftp_homechroot.patch
* openssh-6.6p1-fips-checks.patch
* openssh-6.6p1-ldap.patch
-------------------------------------------------------------------
Mon Jan 18 07:06:52 UTC 2016 - tchvatal@suse.com
- Merge few of conditionals as we do not support many of the specified
version ranges
-------------------------------------------------------------------
Mon Jan 18 06:52:33 UTC 2016 - tchvatal@suse.com
- Rename README.SuSE to README.SUSE
-------------------------------------------------------------------
Mon Jan 18 06:50:36 UTC 2016 - tchvatal@suse.com
- Cleanup with spec-cleaner
-------------------------------------------------------------------
Thu Jan 14 15:35:55 UTC 2016 - astieger@suse.com

View File

@ -16,46 +16,95 @@
#
%define sandbox_seccomp 0
%define _fwdir %{_sysconfdir}/sysconfig/SuSEfirewall2.d
%define _fwdefdir %{_fwdir}/services
%define _appdefdir %( grep "configdirspec=" $( which xmkmf ) | sed -r 's,^[^=]+=.*-I(.*)/config.*$,\\1/app-defaults,' )
%{!?_initddir:%global _initddir %{_initrddir}}
%if 0%{?suse_version} >= 1100
%if 0%{suse_version} >= 1100
%define has_fw_dir 1
%define has_libselinux 1
%else
%define has_fw_dir 0
%endif
%if 0%{suse_version} >= 1110
%define has_libselinux 1
%else
%define has_libselinux 0
%endif
%if 0%{?suse_version} >= 1130
%define needs_all_dirs 1
%else
%define needs_all_dirs 0
%endif
%if 0%{?suse_version} >= 1140
%define needs_libedit 1
%define has_krb_mini 1
%else
%define needs_libedit 0
%endif
%if 0%{?suse_version} > 1140
%define has_krb_mini 1
%else
%define has_krb_mini 0
%endif
%if 0%{?suse_version} > 1220
%define uses_systemd 1
%else
%define uses_systemd 0
%endif
%define sandbox_seccomp 0
%ifarch %ix86 x86_64
%if 0%{?suse_version} > 1220
%define sandbox_seccomp 1
%endif
%endif
%define _fwdir %{_sysconfdir}/sysconfig/SuSEfirewall2.d
%define _fwdefdir %{_fwdir}/services
%define _appdefdir %( grep "configdirspec=" $( which xmkmf ) | sed -r 's,^[^=]+=.*-I(.*)/config.*$,\\1/app-defaults,' )
%{!?_initddir:%global _initddir %{_initrddir}}
Name: openssh
Version: 7.1p2
BuildRequires: audit-devel
BuildRequires: autoconf
BuildRequires: groff
%if %{has_krb_mini}
BuildRequires: krb5-mini-devel
%else
BuildRequires: krb5-devel
%endif
%if %{needs_libedit}
BuildRequires: libedit-devel
%endif
%if %{has_libselinux}
BuildRequires: libselinux-devel
%endif
BuildRequires: openldap2-devel
BuildRequires: openssl
BuildRequires: openssl-devel
BuildRequires: pam-devel
%if %{uses_systemd}
BuildRequires: pkgconfig(systemd)
%{?systemd_requires}
%else
PreReq: %{insserv_prereq}
%endif
PreReq: pwdutils %{fillup_prereq} coreutils
Conflicts: nonfreessh
Recommends: xauth
Recommends: %{name}-helpers
Version: 6.6p1
Release: 0
Summary: Secure Shell Client and Server (Remote Login Program)
License: BSD-3-Clause and MIT
Group: Productivity/Networking/SSH
Url: http://www.openssh.com/
Source: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz
Source42: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc
Source43: openssh.keyring
Source1: sshd.init
Source2: sshd.pamd
Source3: README.SUSE
Source3: README.SuSE
Source4: README.kerberos
Source5: ssh.reg
Source6: ssh-askpass
@ -63,8 +112,7 @@ Source7: sshd.fw
Source8: sysconfig.ssh
Source9: sshd-gen-keys-start
Source10: sshd.service
Source42: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc
Source43: openssh.keyring
Patch0: openssh-6.6p1-curve25519-6.6.1p1.patch
Patch1: openssh-6.6p1-key-converter.patch
Patch2: openssh-6.6p1-X11-forwarding.patch
Patch3: openssh-6.6p1-lastlog.patch
@ -80,55 +128,32 @@ Patch12: openssh-6.6p1-xauth.patch
Patch13: openssh-6.6p1-default-protocol.patch
Patch14: openssh-6.6p1-pts.patch
Patch15: openssh-6.6p1-pam-check-locks.patch
Patch16: openssh-6.6p1-fingerprint_hash.patch
Patch17: openssh-6.6p1-fips.patch
# PATCH-FIX-SUSE: audit patch taken from redhat
Patch18: openssh-6.7p1-audit.patch
Patch18: openssh-6.6p1-audit1-remove_duplicit_audit.patch
Patch19: openssh-6.6p1-audit2-better_audit_of_user_actions.patch
Patch20: openssh-6.6p1-audit3-key_auth_usage.patch
Patch21: openssh-6.6p1-audit3-key_auth_usage-fips.patch
Patch22: openssh-6.6p1-audit4-kex_results.patch
Patch23: openssh-6.6p1-audit4-kex_results-fips.patch
Patch24: openssh-6.6p1-audit5-session_key_destruction.patch
Patch25: openssh-6.6p1-audit6-server_key_destruction.patch
Patch26: openssh-6.6p1-audit7-libaudit_compat.patch
Patch27: openssh-6.6p1-audit8-libaudit_dns_timeouts.patch
Patch28: openssh-6.6p1-seed-prng.patch
Patch29: openssh-6.6p1-gssapi_key_exchange.patch
Patch30: openssh-6.6p1-login_options.patch
Patch31: openssh-6.6p1-disable-openssl-abi-check.patch
Patch32: openssh-6.6p1-no_fork-no_pid_file.patch
Patch33: openssh-6.6p1-host_ident.patch
Patch34: openssh-6.6p1-sftp_homechroot.patch
Patch35: openssh-6.6p1-sftp_force_permissions.patch
Patch36: openssh-6.6p1-seccomp_getuid.patch
Patch37: openssh-6.6p1-X_forward_with_disabled_ipv6.patch
Patch38: openssh-6.6p1-fips-checks.patch
Patch39: openssh-6.6p1-ldap.patch
Patch40: openssh-alloc_size.patch
Patch41: openssh-allow_getrandom.patch
Patch42: openssh-fix-b64_xx-detection.patch
BuildRequires: audit-devel
BuildRequires: autoconf
BuildRequires: fipscheck-devel
BuildRequires: groff
BuildRequires: openldap2-devel
BuildRequires: openssl
BuildRequires: openssl-devel
BuildRequires: pam-devel
Requires(post): %fillup_prereq
Requires(pre): coreutils
Requires(pre): pwdutils
Recommends: %{name}-helpers
Recommends: xauth
Conflicts: nonfreessh
Patch40: CVE-2016-0777_CVE-2016-0778.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-build
%if %{has_krb_mini}
BuildRequires: krb5-mini-devel
%else
BuildRequires: krb5-devel
%endif
%if %{needs_libedit}
BuildRequires: libedit-devel
%endif
%if %{has_libselinux}
BuildRequires: libselinux-devel
%endif
%if %{uses_systemd}
BuildRequires: pkgconfig(systemd)
%{?systemd_requires}
%else
Requires(pre): %insserv_prereq
Requires(preun): %insserv_prereq
%endif
%description
SSH (Secure Shell) is a program for logging into and executing commands
@ -139,6 +164,7 @@ hosts over an insecure network.
xorg-x11 (X Window System) connections and arbitrary TCP/IP ports can
also be forwarded over the secure channel.
%package helpers
Summary: OpenSSH AuthorizedKeysCommand helpers
Group: Productivity/Networking/SSH
@ -147,6 +173,7 @@ Requires: openssh
%description helpers
Helper applications for OpenSSH which retrieve keys from various sources.
%package fips
Summary: OpenSSH FIPS cryptomodule hashes
Group: Productivity/Networking/SSH
@ -156,51 +183,77 @@ Requires: openssh
Hashes that together with the main package form the FIPS certifiable
cryptomodule.
%prep
%setup -q
%patch1 -p2
%patch0 -p2
#patch1 -p2
%patch2 -p2
%patch3 -p2
%patch4 -p2
%patch5 -p2
%patch6 -p2
%patch7 -p1
%patch8 -p1
%patch9 -p1
%patch7 -p2
%patch8 -p2
%patch9 -p2
%patch10 -p2
%patch11 -p2
%patch12 -p2
%patch13 -p2
%patch14 -p2
%patch15 -p1
%patch18 -p1
%patch28 -p1
%patch29 -p1
%patch15 -p2
%patch16 -p2
%patch17 -p2
%patch18 -p2
%patch19 -p2
%patch20 -p2
%patch21 -p2
%patch22 -p2
%patch23 -p2
%patch24 -p2
%patch25 -p2
%patch26 -p2
%if 0%{?suse_version} > 1310
%patch27 -p2
%endif
%patch28 -p2
%patch29 -p2
%patch30 -p2
%patch31 -p1
%patch31 -p2
%patch32 -p2
%patch33 -p2
%patch34 -p1
%patch35 -p1
%patch36 -p1
%patch34 -p2
%patch35 -p2
%patch36 -p2
%patch37 -p2
%patch39 -p1
%patch40 -p1
%patch41 -p1
%patch42 -p1
%patch17 -p1
%patch38 -p2
%patch39 -p2
%patch40 -p0
cp %{SOURCE3} %{SOURCE4} .
%build
# set libexec dir in the LDAP patch
sed -i.libexec 's,@LIBEXECDIR@,%{_libexecdir}/ssh,' \
$( grep -Rl @LIBEXECDIR@ \
$( grep "^+++" %{PATCH39} | sed -r 's@^.+/([^/\t ]+).*$@\1@' )
)
autoreconf -fiv
%ifarch s390 s390x %{sparc}
%ifarch s390 s390x %sparc
PIEFLAGS="-fPIE"
%else
PIEFLAGS="-fpie"
%endif
CFLAGS="%{optflags} $PIEFLAGS -fstack-protector"
#%if 0%{?suse_version} < 1230
#CFLAGS="-lrt $CFLAGS"
#%endif
CXXFLAGS="%{optflags} $PIEFLAGS -fstack-protector"
LDFLAGS="-pie -Wl,--as-needed"
#%if 0%{?suse_version} < 1230
#LDFLAGS="-lrt $LDFLAGS"
#%endif
#CPPFLAGS="%{optflags} -DUSE_INTERNAL_B64"
export LDFLAGS CFLAGS CXXFLAGS CPPFLAGS
./configure \
--prefix=%{_prefix} \
@ -217,7 +270,7 @@ export LDFLAGS CFLAGS CXXFLAGS CPPFLAGS
--with-ssl-engine \
--with-pam \
--with-kerberos5=%{_prefix} \
--with-privsep-path=%{_localstatedir}/lib/empty \
--with-privsep-path=/var/lib/empty \
%if %{sandbox_seccomp}
--with-sandbox=seccomp_filter \
%else
@ -238,11 +291,14 @@ export LDFLAGS CFLAGS CXXFLAGS CPPFLAGS
### configure end
make %{?_smp_mflags}
#make %{?_smp_mflags} -C converter
%install
make DESTDIR=%{buildroot} install %{?_smp_mflags}
make install DESTDIR=%{buildroot}
#make install DESTDIR=%{buildroot} -C converter
install -d -m 755 %{buildroot}%{_sysconfdir}/pam.d
install -d -m 755 %{buildroot}%{_localstatedir}/lib/sshd
install -d -m 755 %{buildroot}/var/lib/sshd
install -m 644 %{SOURCE2} %{buildroot}%{_sysconfdir}/pam.d/sshd
install -d -m 755 %{buildroot}%{_sysconfdir}/slp.reg.d/
install -m 644 %{SOURCE5} %{buildroot}%{_sysconfdir}/slp.reg.d/
@ -250,20 +306,22 @@ install -d -m 755 %{buildroot}%{_initddir}
%if %{uses_systemd}
install -m 0755 %{SOURCE1} .
install -D -m 0644 %{SOURCE10} %{buildroot}%{_unitdir}/sshd.service
ln -s %{_sbindir}/service %{buildroot}%{_sbindir}/rcsshd
ln -s /usr/sbin/service %{buildroot}%{_sbindir}/rcsshd
%else
install -D -m 0755 %{SOURCE1} %{buildroot}%{_initddir}/sshd
install -m 0644 %{SOURCE10} .
ln -s ../..%{_initddir}/sshd %{buildroot}%{_sbindir}/rcsshd
%endif
install -d -m 755 %{buildroot}%{_localstatedir}/adm/fillup-templates
install -m 644 %{SOURCE8} %{buildroot}%{_localstatedir}/adm/fillup-templates
install -d -m 755 %{buildroot}/var/adm/fillup-templates
install -m 644 %{SOURCE8} %{buildroot}/var/adm/fillup-templates
# install shell script to automate the process of adding your public key to a remote machine
install -m 755 contrib/ssh-copy-id %{buildroot}%{_bindir}
install -m 644 contrib/ssh-copy-id.1 %{buildroot}%{_mandir}/man1
sed -i -e s@%{_prefix}/libexec@%{_libexecdir}@g %{buildroot}%{_sysconfdir}/ssh/sshd_config
sed -i -e s@/usr/libexec@%{_libexecdir}@g %{buildroot}%{_sysconfdir}/ssh/sshd_config
%if %{has_fw_dir}
#install firewall definitions format is described here:
#%{_datadir}/SuSEfirewall2/services/TEMPLATE
mkdir -p %{buildroot}%{_fwdefdir}
install -m 644 %{SOURCE7} %{buildroot}%{_fwdefdir}/sshd
%endif
@ -279,7 +337,7 @@ install -D -m 0755 %{SOURCE9} %{buildroot}%{_sbindir}/sshd-gen-keys-start
# re-define the __os_install_post macro: the macro strips
# the binaries and thereby invalidates any hashes created earlier.
#
# this shows up earlier because otherwise the %%expand of
# this shows up earlier because otherwise the %expand of
# the macro is too late.
%{expand:%%global __os_install_post {%__os_install_post
@ -295,7 +353,7 @@ done
%pre
getent group sshd >/dev/null || %{_sbindir}/groupadd -r sshd
getent passwd sshd >/dev/null || %{_sbindir}/useradd -r -g sshd -d %{_localstatedir}/lib/sshd -s /bin/false -c "SSH daemon" sshd
getent passwd sshd >/dev/null || %{_sbindir}/useradd -r -g sshd -d /var/lib/sshd -s /bin/false -c "SSH daemon" sshd
%if %{uses_systemd}
%service_add_pre sshd.service
%endif
@ -320,7 +378,7 @@ getent passwd sshd >/dev/null || %{_sbindir}/useradd -r -g sshd -d %{_localstate
%service_del_postun sshd.service
%else
%restart_on_update sshd
%insserv_cleanup
%{insserv_cleanup}
%endif
%files
@ -328,32 +386,36 @@ getent passwd sshd >/dev/null || %{_sbindir}/useradd -r -g sshd -d %{_localstate
%exclude %{_bindir}/*.chk
%exclude %{_sbindir}/*.chk
%exclude %{_libexecdir}/ssh/sftp-server.chk
%dir %attr(755,root,root) %{_localstatedir}/lib/sshd
%doc README.SUSE README.kerberos ChangeLog OVERVIEW README TODO LICENCE CREDITS
%dir %attr(755,root,root) /var/lib/sshd
%doc README.SuSE README.kerberos ChangeLog OVERVIEW README TODO LICENCE CREDITS
%attr(0755,root,root) %dir %{_sysconfdir}/ssh
%attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ssh/moduli
%verify(not mode) %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ssh/ssh_config
%verify(not mode) %attr(0640,root,root) %config(noreplace) %{_sysconfdir}/ssh/sshd_config
%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/pam.d/sshd
%if %{uses_systemd}
%attr(0644,root,root) %{_unitdir}/sshd.service
%doc sshd.init
%attr(0644,root,root) %config %{_unitdir}/sshd.service
%else
%attr(0755,root,root) %config %{_initddir}/sshd
%doc sshd.service
%endif
%attr(0755,root,root) %{_bindir}/*
%attr(0755,root,root) %{_sbindir}/*
%attr(0755,root,root) %dir %{_libexecdir}/ssh
%exclude %{_libexecdir}/ssh/ssh-ldap*
%attr(0755,root,root) %{_libexecdir}/ssh/*
%attr(0444,root,root) %{_mandir}/man1/*
%attr(0444,root,root) %{_mandir}/man5/*
%attr(0444,root,root) %{_mandir}/man8/*
%attr(0444,root,root) %doc %{_mandir}/man1/*
%attr(0444,root,root) %doc %{_mandir}/man5/*
%attr(0444,root,root) %doc %{_mandir}/man8/*
%dir %{_sysconfdir}/slp.reg.d
%config %{_sysconfdir}/slp.reg.d/ssh.reg
%{_localstatedir}/adm/fillup-templates/sysconfig.ssh
/var/adm/fillup-templates/sysconfig.ssh
%if %{has_fw_dir}
%if %{needs_all_dirs}
%dir %{_fwdir}
%dir %{_fwdefdir}
%endif
%config %{_fwdefdir}/sshd
%endif