From 642f5e8889ab86c9b2e48c14fbd9f6f5aea90a3c72d49ffd243ceb84601b9486 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ismail=20D=C3=B6nmez?= Date: Thu, 21 Jan 2016 07:28:30 +0000 Subject: [PATCH 1/5] Accepting request 354941 from home:scarabeus_iv:branches:network - Cleanup with spec-cleaner - Update of the master OpenSSH to 7.1p2 - 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 - Version update to 7.1p2: * various upstream bugfixes and cleanups OBS-URL: https://build.opensuse.org/request/show/354941 OBS-URL: https://build.opensuse.org/package/show/network/openssh?expand=0&rev=95 --- CVE-2016-0777_CVE-2016-0778.patch | 34 - README.SuSE => README.SUSE | 2 +- ...h-6.6p1-audit1-remove_duplicit_audit.patch | 33 - ...-audit2-better_audit_of_user_actions.patch | 867 ------ ...ssh-6.6p1-audit3-key_auth_usage-fips.patch | 61 - openssh-6.6p1-audit3-key_auth_usage.patch | 506 ---- openssh-6.6p1-audit4-kex_results-fips.patch | 82 - openssh-6.6p1-audit4-kex_results.patch | 701 ----- ...6.6p1-audit5-session_key_destruction.patch | 983 ------ ...-6.6p1-audit6-server_key_destruction.patch | 742 ----- openssh-6.6p1-audit7-libaudit_compat.patch | 107 - ...h-6.6p1-audit8-libaudit_dns_timeouts.patch | 47 - openssh-6.6p1-blocksigalrm.patch | 42 +- openssh-6.6p1-curve25519-6.6.1p1.patch | 205 -- openssh-6.6p1-disable-openssl-abi-check.patch | 27 +- openssh-6.6p1-eal3.patch | 64 +- openssh-6.6p1-fingerprint_hash.patch | 730 ----- openssh-6.6p1-fips-checks.patch | 529 ---- openssh-6.6p1-fips.patch | 1414 ++++----- openssh-6.6p1-gssapi_key_exchange.patch | 2652 +++++------------ openssh-6.6p1-gssapimitm.patch | 324 +- openssh-6.6p1-ldap.patch | 602 ++-- openssh-6.6p1-no_fork-no_pid_file.patch | 24 - openssh-6.6p1-pam-check-locks.patch | 161 +- openssh-6.6p1-seccomp_getuid.patch | 27 +- openssh-6.6p1-seed-prng.patch | 285 +- openssh-6.6p1-sftp_force_permissions.patch | 110 +- openssh-6.6p1-sftp_homechroot.patch | 299 +- openssh-6.6p1.tar.gz | 3 - openssh-6.6p1.tar.gz.asc | 14 - openssh-6.7p1-audit.patch | 2360 +++++++++++++++ openssh-7.1p2.tar.gz | 3 + openssh-7.1p2.tar.gz.asc | 14 + openssh-askpass-gnome.changes | 6 + openssh-askpass-gnome.spec | 16 +- openssh.changes | 80 + openssh.spec | 225 +- 37 files changed, 4461 insertions(+), 9920 deletions(-) delete mode 100644 CVE-2016-0777_CVE-2016-0778.patch rename README.SuSE => README.SUSE (90%) delete mode 100644 openssh-6.6p1-audit1-remove_duplicit_audit.patch delete mode 100644 openssh-6.6p1-audit2-better_audit_of_user_actions.patch delete mode 100644 openssh-6.6p1-audit3-key_auth_usage-fips.patch delete mode 100644 openssh-6.6p1-audit3-key_auth_usage.patch delete mode 100644 openssh-6.6p1-audit4-kex_results-fips.patch delete mode 100644 openssh-6.6p1-audit4-kex_results.patch delete mode 100644 openssh-6.6p1-audit5-session_key_destruction.patch delete mode 100644 openssh-6.6p1-audit6-server_key_destruction.patch delete mode 100644 openssh-6.6p1-audit7-libaudit_compat.patch delete mode 100644 openssh-6.6p1-audit8-libaudit_dns_timeouts.patch delete mode 100644 openssh-6.6p1-curve25519-6.6.1p1.patch delete mode 100644 openssh-6.6p1-fingerprint_hash.patch delete mode 100644 openssh-6.6p1-fips-checks.patch delete mode 100644 openssh-6.6p1-no_fork-no_pid_file.patch delete mode 100644 openssh-6.6p1.tar.gz delete mode 100644 openssh-6.6p1.tar.gz.asc create mode 100644 openssh-6.7p1-audit.patch create mode 100644 openssh-7.1p2.tar.gz create mode 100644 openssh-7.1p2.tar.gz.asc diff --git a/CVE-2016-0777_CVE-2016-0778.patch b/CVE-2016-0777_CVE-2016-0778.patch deleted file mode 100644 index ca2c704..0000000 --- a/CVE-2016-0777_CVE-2016-0778.patch +++ /dev/null @@ -1,34 +0,0 @@ -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); - } diff --git a/README.SuSE b/README.SUSE similarity index 90% rename from README.SuSE rename to README.SUSE index 10b49da..1552003 100644 --- a/README.SuSE +++ b/README.SUSE @@ -1,4 +1,4 @@ -This is OpenSSH version 5.6p1. +This is OpenSSH version compiled for SUSE. There are following changes in default settings of ssh client: diff --git a/openssh-6.6p1-audit1-remove_duplicit_audit.patch b/openssh-6.6p1-audit1-remove_duplicit_audit.patch deleted file mode 100644 index 96d9c54..0000000 --- a/openssh-6.6p1-audit1-remove_duplicit_audit.patch +++ /dev/null @@ -1,33 +0,0 @@ -# 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); diff --git a/openssh-6.6p1-audit2-better_audit_of_user_actions.patch b/openssh-6.6p1-audit2-better_audit_of_user_actions.patch deleted file mode 100644 index 656bbe3..0000000 --- a/openssh-6.6p1-audit2-better_audit_of_user_actions.patch +++ /dev/null @@ -1,867 +0,0 @@ -# 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 - #include - #include - - #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); - } diff --git a/openssh-6.6p1-audit3-key_auth_usage-fips.patch b/openssh-6.6p1-audit3-key_auth_usage-fips.patch deleted file mode 100644 index ac95216..0000000 --- a/openssh-6.6p1-audit3-key_auth_usage-fips.patch +++ /dev/null @@ -1,61 +0,0 @@ -# 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. - */ - diff --git a/openssh-6.6p1-audit3-key_auth_usage.patch b/openssh-6.6p1-audit3-key_auth_usage.patch deleted file mode 100644 index 1471ec8..0000000 --- a/openssh-6.6p1-audit3-key_auth_usage.patch +++ /dev/null @@ -1,506 +0,0 @@ -# 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 *); diff --git a/openssh-6.6p1-audit4-kex_results-fips.patch b/openssh-6.6p1-audit4-kex_results-fips.patch deleted file mode 100644 index 7f781d7..0000000 --- a/openssh-6.6p1-audit4-kex_results-fips.patch +++ /dev/null @@ -1,82 +0,0 @@ -# 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 - #include - int allow_severity; - int deny_severity; - #endif /* LIBWRAP */ - - #ifndef O_NOCTTY diff --git a/openssh-6.6p1-audit4-kex_results.patch b/openssh-6.6p1-audit4-kex_results.patch deleted file mode 100644 index d6bb569..0000000 --- a/openssh-6.6p1-audit4-kex_results.patch +++ /dev/null @@ -1,701 +0,0 @@ -# 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 - #include -+#include - - #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 -+ */ -+ -+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 : "", - 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(); diff --git a/openssh-6.6p1-audit5-session_key_destruction.patch b/openssh-6.6p1-audit5-session_key_destruction.patch deleted file mode 100644 index cee4029..0000000 --- a/openssh-6.6p1-audit5-session_key_destruction.patch +++ /dev/null @@ -1,983 +0,0 @@ -# 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 - */ - -+#include -+ - 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 - #include - #include - #include - #include - #include - - #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); - } diff --git a/openssh-6.6p1-audit6-server_key_destruction.patch b/openssh-6.6p1-audit6-server_key_destruction.patch deleted file mode 100644 index 73821e8..0000000 --- a/openssh-6.6p1-audit6-server_key_destruction.patch +++ /dev/null @@ -1,742 +0,0 @@ -# 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); diff --git a/openssh-6.6p1-audit7-libaudit_compat.patch b/openssh-6.6p1-audit7-libaudit_compat.patch deleted file mode 100644 index ce46452..0000000 --- a/openssh-6.6p1-audit7-libaudit_compat.patch +++ /dev/null @@ -1,107 +0,0 @@ -# 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 - */ - - #include "includes.h" - #if defined(USE_LINUX_AUDIT) - #include -+#include "compat-libaudit.h" - #include - #include - - #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 -+ * Rickard E. (Rik) Faith -+ */ -+#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_ */ -+ diff --git a/openssh-6.6p1-audit8-libaudit_dns_timeouts.patch b/openssh-6.6p1-audit8-libaudit_dns_timeouts.patch deleted file mode 100644 index c199c65..0000000 --- a/openssh-6.6p1-audit8-libaudit_dns_timeouts.patch +++ /dev/null @@ -1,47 +0,0 @@ -# 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; diff --git a/openssh-6.6p1-blocksigalrm.patch b/openssh-6.6p1-blocksigalrm.patch index 1cd7f05..2727eaf 100644 --- a/openssh-6.6p1-blocksigalrm.patch +++ b/openssh-6.6p1-blocksigalrm.patch @@ -2,33 +2,19 @@ # grace_alarm_handler) # bnc#57354 -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 - #include - #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) - # include +Index: b/log.c +=================================================================== +--- a/log.c ++++ b/log.c +@@ -51,6 +51,7 @@ #endif - #include "xmalloc.h" #include "log.h" +#include static LogLevel log_level = SYSLOG_LEVEL_INFO; static int log_on_stderr = 1; - 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]; +@@ -388,6 +389,7 @@ do_log(LogLevel level, const char *fmt, char fmtbuf[MSGBUFSIZ]; char *txt = NULL; int pri = LOG_INFO; @@ -36,17 +22,7 @@ diff --git a/openssh-6.6p1/log.c b/openssh-6.6p1/log.c int saved_errno = errno; log_handler_fn *tmp_handler; - 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) { +@@ -446,6 +448,14 @@ do_log(LogLevel level, const char *fmt, snprintf(msgbuf, sizeof msgbuf, "%s\r\n", fmtbuf); (void)write(log_stderr_fd, msgbuf, strlen(msgbuf)); } else { @@ -61,9 +37,7 @@ diff --git a/openssh-6.6p1/log.c b/openssh-6.6p1/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); - closelog_r(&sdata); - #else - openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility); +@@ -455,6 +465,7 @@ do_log(LogLevel level, const char *fmt, syslog(pri, "%.500s", fmtbuf); closelog(); #endif diff --git a/openssh-6.6p1-curve25519-6.6.1p1.patch b/openssh-6.6p1-curve25519-6.6.1p1.patch deleted file mode 100644 index 7eb8086..0000000 --- a/openssh-6.6p1-curve25519-6.6.1p1.patch +++ /dev/null @@ -1,205 +0,0 @@ -# Date: Sun, 20 Apr 2014 17:14:08 +1000 (EST) -# From: Damien Miller -# To: openssh-unix-dev@mindrot.org -# Subject: bad bignum encoding for curve25519-sha256@libssh.org -# Message-ID: -# -# 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 - * Copyright (c) 1995 Tatu Ylonen , 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 diff --git a/openssh-6.6p1-disable-openssl-abi-check.patch b/openssh-6.6p1-disable-openssl-abi-check.patch index 61ce8d5..ff94de7 100644 --- a/openssh-6.6p1-disable-openssl-abi-check.patch +++ b/openssh-6.6p1-disable-openssl-abi-check.patch @@ -2,22 +2,16 @@ # reliable indicator of ABI changes and doesn't make much sense in a # distribution package -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) +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]; #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 - u_long version_mask = SSLeay() >= 0x1000000f ? ~0xffff0L : ~0xff0L; - if (((SSLeay() ^ OPENSSL_VERSION_NUMBER) & version_mask) || - (SSLeay() >> 12) < (OPENSSL_VERSION_NUMBER >> 12)) + if (!ssh_compatible_openssl(OPENSSL_VERSION_NUMBER, SSLeay())) fatal("OpenSSL version mismatch. Built against %lx, you " "have %lx", (u_long)OPENSSL_VERSION_NUMBER, SSLeay()); - @@ -25,8 +19,3 @@ diff --git a/openssh-6.6p1/entropy.c b/openssh-6.6p1/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"); diff --git a/openssh-6.6p1-eal3.patch b/openssh-6.6p1-eal3.patch index a3058d3..871b50c 100644 --- a/openssh-6.6p1-eal3.patch +++ b/openssh-6.6p1-eal3.patch @@ -1,14 +1,10 @@ # fix paths and references in sshd man pages -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 +Index: b/sshd.8 +=================================================================== +--- a/sshd.8 ++++ b/sshd.8 +@@ -873,7 +873,7 @@ are displayed to anyone trying to log in refused. The file should be world-readable. .Pp @@ -17,59 +13,30 @@ diff --git a/openssh-6.6p1/sshd.8 b/openssh-6.6p1/sshd.8 This file is used in exactly the same way as .Pa hosts.equiv , but allows host-based authentication without permitting login with - 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 , +@@ -953,7 +953,7 @@ The content of this file is not sensitiv .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 , - .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. +Index: b/sshd_config.5 +=================================================================== +--- a/sshd_config.5 ++++ b/sshd_config.5 +@@ -374,8 +374,7 @@ This option is only available for protoc By default, no banner is displayed. .It Cm ChallengeResponseAuthentication Specifies whether challenge-response authentication is allowed (e.g. via --PAM or though authentication styles supported in +-PAM or through authentication styles supported in -.Xr login.conf 5 ) +PAM) The default is .Dq yes . .It Cm ChrootDirectory - 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 . +@@ -773,7 +772,7 @@ or .Pp .Pa /etc/hosts.equiv and @@ -78,8 +45,3 @@ diff --git a/openssh-6.6p1/sshd_config.5 b/openssh-6.6p1/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 diff --git a/openssh-6.6p1-fingerprint_hash.patch b/openssh-6.6p1-fingerprint_hash.patch deleted file mode 100644 index 7a0a76f..0000000 --- a/openssh-6.6p1-fingerprint_hash.patch +++ /dev/null @@ -1,730 +0,0 @@ -# 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 - -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; - } diff --git a/openssh-6.6p1-fips-checks.patch b/openssh-6.6p1-fips-checks.patch deleted file mode 100644 index 3c78a2a..0000000 --- a/openssh-6.6p1-fips-checks.patch +++ /dev/null @@ -1,529 +0,0 @@ -# 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "digest.h" -+#include "fips.h" -+ -+#include -+ -+#define PROC_NAME_LEN 64 -+ -+static const char *argv0; -+ -+void -+print_help_exit(int ev) -+{ -+ fprintf(stderr, "%s <-c|-w> \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 -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include - - #include -+#include -+ -+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; diff --git a/openssh-6.6p1-fips.patch b/openssh-6.6p1-fips.patch index 21e675f..a7573a7 100644 --- a/openssh-6.6p1-fips.patch +++ b/openssh-6.6p1-fips.patch @@ -1,247 +1,22 @@ -# comply with FIPS 140-2 by using only approved crypto algorithms -# when OpenSSL is detected to be running in FIPS mode -# -# HG changeset patch -# Parent 844066cb9c0ec2b10eb1ace7134f7bced7cc802d - -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 -@@ -71,17 +71,18 @@ LIBSSH_OBJS=authfd.o authfile.o bufaux.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 \ - 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 -+ sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o blocks.o \ -+ fips.o +Index: openssh-7.1p2/cipher.c +=================================================================== +--- openssh-7.1p2.orig/cipher.c ++++ openssh-7.1p2/cipher.c +@@ -39,6 +39,8 @@ - SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ - sshconnect.o sshconnect1.o sshconnect2.o mux.o \ - roaming_common.o roaming_client.o + #include - 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/auth-rsa.c b/openssh-6.6p1/auth-rsa.c ---- a/openssh-6.6p1/auth-rsa.c -+++ b/openssh-6.6p1/auth-rsa.c -@@ -44,16 +44,18 @@ - #include "ssh-gss.h" - #endif - #include "monitor_wrap.h" - #include "ssh.h" - #include "misc.h" - - #include "digest.h" - -+#include "fips.h" ++#include + - /* import */ - extern ServerOptions options; - - /* - * Session identifier that is used to bind key exchange and authentication - * responses to a particular session. - */ - extern u_char session_id[16]; -@@ -84,45 +86,52 @@ auth_rsa_generate_challenge(Key *key) - if (BN_mod(challenge, challenge, key->rsa->n, ctx) == 0) - fatal("auth_rsa_generate_challenge: BN_mod failed"); - BN_CTX_free(ctx); - - return challenge; - } - - int --auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16]) -+auth_rsa_verify_response(Key *key, BIGNUM *challenge, -+ u_char response[SSH_DIGEST_MAX_LENGTH]) - { -- u_char buf[32], mdbuf[16]; -+ 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; - - /* 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); - } - -- /* The response is MD5 of decrypted challenge plus session id. */ -+ dgst = fips_correct_dgst(SSH_DIGEST_MD5); -+ dgst_len = ssh_digest_bytes(dgst); -+ -+ /* The response is a hash of decrypted challenge plus session id. -+ * Normally this is MD5, in FIPS mode a stronger function is used. */ - len = BN_num_bytes(challenge); -- if (len <= 0 || len > 32) -+ if (len <= 0 || (unsigned int)len > (2 * dgst_len)) - fatal("%s: bad challenge length %d", __func__, len); -- memset(buf, 0, 32); -- BN_bn2bin(challenge, buf + 32 - len); -- if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL || -- ssh_digest_update(md, buf, 32) < 0 || -- ssh_digest_update(md, session_id, 16) < 0 || -+ memset(buf, 0, sizeof(buf)); -+ BN_bn2bin(challenge, buf + 2 * dgst_len - len); -+ 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, 16) != 0) { -+ if (timingsafe_bcmp(response, mdbuf, dgst_len) != 0) { - /* Wrong answer. */ - return (0); - } - /* Correct answer. */ - return (1); - } - - /* -@@ -130,17 +139,17 @@ auth_rsa_verify_response(Key *key, BIGNU - * and returns true (non-zero) if the client gave the correct answer to - * our challenge; returns zero if the client gives a wrong answer. - */ - - int - auth_rsa_challenge_dialog(Key *key) - { - BIGNUM *challenge, *encrypted_challenge; -- u_char response[16]; -+ u_char response[SSH_DIGEST_MAX_LENGTH]; - int i, success; - - if ((encrypted_challenge = BN_new()) == NULL) - fatal("auth_rsa_challenge_dialog: BN_new() failed"); - - challenge = PRIVSEP(auth_rsa_generate_challenge(key)); - - /* Encrypt the challenge with the public key. */ -@@ -150,17 +159,17 @@ auth_rsa_challenge_dialog(Key *key) - packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE); - packet_put_bignum(encrypted_challenge); - packet_send(); - BN_clear_free(encrypted_challenge); - packet_write_wait(); - - /* Wait for a response. */ - packet_read_expect(SSH_CMSG_AUTH_RSA_RESPONSE); -- for (i = 0; i < 16; i++) -+ for (i = 0; i < ssh_digest_bytes(fips_dgst_min()); i++) - response[i] = (u_char)packet_get_char(); - packet_check_eom(); - - success = PRIVSEP(auth_rsa_verify_response(key, challenge, response)); - BN_clear_free(challenge); - return (success); - } - -diff --git a/openssh-6.6p1/cipher-ctr.c b/openssh-6.6p1/cipher-ctr.c ---- a/openssh-6.6p1/cipher-ctr.c -+++ b/openssh-6.6p1/cipher-ctr.c -@@ -22,16 +22,18 @@ - #include #include - - #include - - #include "xmalloc.h" - #include "log.h" - -+#include "fips.h" -+ - /* compatibility with old or broken OpenSSL versions */ - #include "openbsd-compat/openssl-compat.h" - - #ifndef USE_BUILTIN_RIJNDAEL - #include - #endif - - struct ssh_aes_ctr_ctx -@@ -134,13 +136,15 @@ evp_aes_128_ctr(void) - aes_ctr.iv_len = AES_BLOCK_SIZE; - aes_ctr.key_len = 16; - aes_ctr.init = ssh_aes_ctr_init; - aes_ctr.cleanup = ssh_aes_ctr_cleanup; - aes_ctr.do_cipher = ssh_aes_ctr; - #ifndef SSH_OLD_EVP - aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | - EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV; -+ if (fips_mode()) -+ aes_ctr.flags |= EVP_CIPH_FLAG_FIPS; - #endif - return (&aes_ctr); - } - - #endif /* OPENSSL_HAVE_EVPCTR */ -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 -@@ -45,16 +45,18 @@ - - #include "xmalloc.h" - #include "log.h" - #include "misc.h" - #include "cipher.h" - #include "buffer.h" - #include "digest.h" - -+#include "fips.h" -+ - /* 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 { -@@ -66,17 +68,17 @@ struct Cipher { - 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[] = { -+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", - SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 1, EVP_bf_cbc }, -@@ -99,27 +101,67 @@ static const struct Cipher ciphers[] = { - { "aes256-gcm@openssh.com", - SSH_CIPHER_SSH2, 16, 32, 12, 16, 0, 0, EVP_aes_256_gcm }, - #endif - { "chacha20-poly1305@openssh.com", - SSH_CIPHER_SSH2, 8, 64, 0, 16, 0, CFLAG_CHACHAPOLY, NULL }, + #include + #include +@@ -99,6 +101,26 @@ static const struct sshcipher ciphers[] { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL } }; -+static const struct Cipher ciphers_fips140_2[] = { ++static const struct sshcipher fips_ciphers[] = { + { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null }, -+ { "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des }, -+ + { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 0, 0, 1, EVP_des_ede3_cbc }, + { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 1, EVP_aes_128_cbc }, + { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 1, EVP_aes_192_cbc }, @@ -262,449 +37,205 @@ diff --git a/openssh-6.6p1/cipher.c b/openssh-6.6p1/cipher.c + /*--*/ -+/* Returns array of ciphers available depending on selected FIPS mode */ -+static struct Cipher * -+fips_select_ciphers(void) -+{ -+ int fips = fips_mode(); -+ switch (fips) { -+ case 0: -+ return ciphers_all; -+ case 1: -+ return ciphers_fips140_2; -+ default: -+ /* should not be reached */ -+ fatal("Fatal error: incorrect FIPS mode '%i' at %s:%u", -+ fips, __FILE__, __LINE__); -+ return NULL; -+ } -+} -+ - /* Returns a list of supported ciphers separated by the specified char. */ - char * - cipher_alg_list(char sep, int auth_only) - { - char *ret = NULL; + /* Returns a comma-separated list of supported ciphers. */ +@@ -109,7 +131,7 @@ cipher_alg_list(char sep, int auth_only) size_t nlen, rlen = 0; - const Cipher *c; + const struct sshcipher *c; - for (c = ciphers; c->name != NULL; c++) { -+ for (c = fips_select_ciphers(); c->name != NULL; c++) { ++ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) { if (c->number != SSH_CIPHER_SSH2) continue; if (auth_only && c->auth_len == 0) - continue; - if (ret != NULL) - ret[rlen++] = sep; - nlen = strlen(c->name); - ret = xrealloc(ret, 1, rlen + nlen + 2); -@@ -189,27 +231,27 @@ cipher_mask_ssh1(int client) - } - return mask; - } - - const Cipher * +@@ -193,7 +215,7 @@ const struct sshcipher * cipher_by_name(const char *name) { - const Cipher *c; + const struct sshcipher *c; - for (c = ciphers; c->name != NULL; c++) -+ for (c = fips_select_ciphers(); c->name != NULL; c++) ++ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) if (strcmp(c->name, name) == 0) return c; return NULL; - } - - const Cipher * +@@ -203,7 +225,7 @@ const struct sshcipher * cipher_by_number(int id) { - const Cipher *c; + const struct sshcipher *c; - for (c = ciphers; c->name != NULL; c++) -+ for (c = fips_select_ciphers(); c->name != NULL; c++) ++ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) if (c->number == id) return c; return NULL; - } - - #define CIPHER_SEP "," - int - ciphers_valid(const char *names) -@@ -241,17 +283,17 @@ ciphers_valid(const char *names) - */ - - int - cipher_number(const char *name) - { - const Cipher *c; +@@ -244,7 +266,7 @@ cipher_number(const char *name) + const struct sshcipher *c; if (name == NULL) return -1; - for (c = ciphers; c->name != NULL; c++) -+ for (c = fips_select_ciphers(); c->name != NULL; c++) ++ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) if (strcasecmp(c->name, name) == 0) return c->number; return -1; +Index: openssh-7.1p2/cipher-ctr.c +=================================================================== +--- openssh-7.1p2.orig/cipher-ctr.c ++++ openssh-7.1p2/cipher-ctr.c +@@ -138,7 +138,8 @@ evp_aes_128_ctr(void) + aes_ctr.do_cipher = ssh_aes_ctr; + #ifndef SSH_OLD_EVP + aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | +- EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV; ++ EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV | ++ EVP_CIPH_FLAG_FIPS; + #endif + return (&aes_ctr); } +Index: openssh-7.1p2/dh.h +=================================================================== +--- openssh-7.1p2.orig/dh.h ++++ openssh-7.1p2/dh.h +@@ -46,6 +46,7 @@ u_int dh_estimate(int); - char * - cipher_name(int id) - { -@@ -429,23 +471,24 @@ cipher_cleanup(CipherContext *cc) - * Selects the cipher, and keys if by computing the MD5 checksum of the - * passphrase and using the resulting 16 bytes as the key. - */ - - void - cipher_set_key_string(CipherContext *cc, const Cipher *cipher, - const char *passphrase, int do_encrypt) - { -- u_char digest[16]; -+ u_char digest[SSH_DIGEST_MAX_LENGTH]; -+ int dgst = fips_correct_dgst(SSH_DIGEST_MD5); - -- if (ssh_digest_memory(SSH_DIGEST_MD5, passphrase, strlen(passphrase), -+ if (ssh_digest_memory(dgst, passphrase, strlen(passphrase), - digest, sizeof(digest)) < 0) - fatal("%s: md5 failed", __func__); - -- cipher_init(cc, cipher, digest, 16, NULL, 0, do_encrypt); -+ cipher_init(cc, cipher, digest, ssh_digest_bytes(dgst), NULL, 0, do_encrypt); - - explicit_bzero(digest, sizeof(digest)); - } + /* Min and max values from RFC4419. */ + #define DH_GRP_MIN 1024 ++#define DH_GRP_MIN_FIPS 2048 + #define DH_GRP_MAX 8192 /* - * Exports an IV from the CipherContext required to export the key - * state back from the unprivileged child to the privileged parent - * process. -diff --git a/openssh-6.6p1/fips.c b/openssh-6.6p1/fips.c -new file mode 100644 ---- /dev/null -+++ b/openssh-6.6p1/fips.c -@@ -0,0 +1,128 @@ -+/* -+ * Copyright (c) 2012 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 -+ * 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. -+ */ -+ -+#include "includes.h" -+ -+#include "fips.h" -+ -+#include "digest.h" -+#include "key.h" -+#include "log.h" -+ -+#include -+ -+static int fips_state = -1; -+ -+int -+fips_mode() -+{ -+ if (-1 == fips_state) { -+ fips_state = FIPS_mode(); -+ if (fips_state) -+ debug("FIPS mode initialized"); -+ } -+ return fips_state; -+} -+ -+enum fp_type -+fips_correct_fp_type(enum fp_type fp) -+{ -+ int fips; -+ enum fp_type fp_fix = fp; -+ -+ fips = fips_mode(); -+ switch (fips) { -+ case 0: -+ break; -+ case 1: -+ if (SSH_FP_MD5 == fp) { -+ fp_fix = SSH_FP_SHA1; -+ debug("MD5 not allowed in FIPS 140-2 mode, " -+ "using SHA-1 for key fingerprints instead."); -+ } -+ break; -+ default: -+ /* should not be reached */ -+ fatal("Fatal error: incorrect FIPS mode '%i' at %s:%u", -+ fips, __FILE__, __LINE__); -+ } -+ -+ return fp_fix; -+} -+ -+int -+fips_correct_dgst(int digest) -+{ -+ int fips; -+ int rv = -1; -+ -+ fips = fips_mode(); -+ switch (fips) { -+ case 0: -+ rv = digest; -+ break; -+ case 1: -+ switch (digest) { -+ case SSH_DIGEST_MD5: -+ case SSH_DIGEST_RIPEMD160: -+ debug("MD5/RIPEMD160 digests not allowed in FIPS 140-2 mode" -+ "using SHA-1 instead."); -+ rv = SSH_DIGEST_SHA1; -+ break; -+ default: -+ rv = digest; -+ break; -+ } -+ break; -+ default: -+ /* should not be reached */ -+ fatal("Fatal error: incorrect FIPS mode '%i' at %s:%u", -+ fips, __FILE__, __LINE__); -+ } -+ -+ return rv; -+} -+ -+int -+fips_dgst_min(void) -+{ -+ int fips; -+ int dgst; -+ -+ fips = fips_mode(); -+ switch (fips) { -+ case 0: -+ dgst = SSH_DIGEST_MD5; -+ break; -+ case 1: -+ dgst = SSH_DIGEST_SHA1; -+ break; -+ default: -+ /* should not be reached */ -+ fatal("Fatal error: incorrect FIPS mode '%i' at %s:%u", -+ fips, __FILE__, __LINE__); -+ } -+ return dgst; -+} -+ -diff --git a/openssh-6.6p1/fips.h b/openssh-6.6p1/fips.h -new file mode 100644 ---- /dev/null -+++ b/openssh-6.6p1/fips.h -@@ -0,0 +1,33 @@ -+/* -+ * Copyright (c) 2012 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 -+ * 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. -+ */ -+#ifndef FIPS_H -+#define FIPS_H -+ -+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/hmac.c b/openssh-6.6p1/hmac.c ---- a/openssh-6.6p1/hmac.c -+++ b/openssh-6.6p1/hmac.c -@@ -139,17 +139,17 @@ ssh_hmac_free(struct ssh_hmac_ctx *ctx) - /* cc -DTEST hmac.c digest.c buffer.c cleanup.c fatal.c log.c xmalloc.c -lcrypto */ - static void - hmac_test(void *key, size_t klen, void *m, size_t mlen, u_char *e, size_t elen) - { - struct ssh_hmac_ctx *ctx; - size_t i; - u_char digest[16]; +Index: openssh-7.1p2/entropy.c +=================================================================== +--- openssh-7.1p2.orig/entropy.c ++++ openssh-7.1p2/entropy.c +@@ -218,6 +218,8 @@ seed_rng(void) + fatal("OpenSSL version mismatch. Built against %lx, you " + "have %lx", (u_long)OPENSSL_VERSION_NUMBER, SSLeay()); + #endif ++ /* clean the PRNG status when exiting the program */ ++ atexit(RAND_cleanup); + #ifndef OPENSSL_PRNG_ONLY + if (RAND_status() == 1) { + debug3("RNG is ready, skipping seeding"); +Index: openssh-7.1p2/kex.c +=================================================================== +--- openssh-7.1p2.orig/kex.c ++++ openssh-7.1p2/kex.c +@@ -35,6 +35,7 @@ -- if ((ctx = ssh_hmac_start(SSH_DIGEST_MD5)) == NULL) -+ if ((ctx = ssh_hmac_start(fips_correct_dgst(SSH_DIGEST_MD5))) == NULL) - printf("ssh_hmac_start failed"); - if (ssh_hmac_init(ctx, key, klen) < 0 || - ssh_hmac_update(ctx, m, mlen) < 0 || - ssh_hmac_final(ctx, digest, sizeof(digest)) < 0) - printf("ssh_hmac_xxx failed"); - ssh_hmac_free(ctx); + #ifdef WITH_OPENSSL + #include ++#include + #endif - if (memcmp(e, digest, elen)) { -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 -@@ -638,19 +638,21 @@ kex_get_newkeys(int mode) - } - - void - derive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus, - u_int8_t cookie[8], u_int8_t id[16]) - { - u_int8_t nbuf[2048], obuf[SSH_DIGEST_MAX_LENGTH]; - int len; -+ int digest; - struct ssh_digest_ctx *hashctx; - -- if ((hashctx = ssh_digest_start(SSH_DIGEST_MD5)) == NULL) -+ digest = fips_correct_dgst(SSH_DIGEST_MD5); -+ if ((hashctx = ssh_digest_start(digest)) == NULL) - fatal("%s: ssh_digest_start", __func__); - - len = BN_num_bytes(host_modulus); - if (len < (512 / 8) || (u_int)len > sizeof(nbuf)) - fatal("%s: bad host modulus (len %d)", __func__, len); - BN_bn2bin(host_modulus, nbuf); - if (ssh_digest_update(hashctx, nbuf, len) != 0) - fatal("%s: ssh_digest_update failed", __func__); -@@ -659,17 +661,17 @@ derive_ssh1_session_id(BIGNUM *host_modu - if (len < (512 / 8) || (u_int)len > sizeof(nbuf)) - fatal("%s: bad server modulus (len %d)", __func__, len); - BN_bn2bin(server_modulus, nbuf); - if (ssh_digest_update(hashctx, nbuf, len) != 0 || - ssh_digest_update(hashctx, cookie, 8) != 0) - fatal("%s: ssh_digest_update failed", __func__); - if (ssh_digest_final(hashctx, obuf, sizeof(obuf)) != 0) - fatal("%s: ssh_digest_final failed", __func__); -- memcpy(id, obuf, ssh_digest_bytes(SSH_DIGEST_MD5)); -+ memcpy(id, obuf, ssh_digest_bytes(digest)); - - explicit_bzero(nbuf, sizeof(nbuf)); - explicit_bzero(obuf, sizeof(obuf)); - } - - #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) - void - dump_digest(char *msg, u_char *digest, int len) -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 -@@ -53,16 +53,18 @@ - #include "rsa.h" - #include "uuencode.h" - #include "buffer.h" - #include "log.h" - #include "misc.h" #include "ssh2.h" - #include "digest.h" +@@ -108,6 +109,25 @@ static const struct kexalg kexalgs[] = { + { NULL, -1, -1, -1}, + }; -+#include "fips.h" ++static const struct kexalg kexalgs_fips[] = { ++ { KEX_DH14, KEX_DH_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, ++ { KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, ++#ifdef HAVE_EVP_SHA256 ++ { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, SSH_DIGEST_SHA256 }, ++#endif ++#ifdef OPENSSL_HAS_ECC ++ { KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2, ++ NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, ++ { KEX_ECDH_SHA2_NISTP384, KEX_ECDH_SHA2, NID_secp384r1, ++ SSH_DIGEST_SHA384 }, ++# ifdef OPENSSL_HAS_NISTP521 ++ { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1, ++ SSH_DIGEST_SHA512 }, ++# endif ++#endif ++ { NULL, -1, -1, -1}, ++}; + - static int to_blob(const Key *, u_char **, u_int *, int); - static Key *key_from_blob2(const u_char *, u_int, int); - - static struct KeyCert * - cert_new(void) + char * + kex_alg_list(char sep) { - struct KeyCert *cert; +@@ -135,7 +155,7 @@ kex_alg_by_name(const char *name) + { + const struct kexalg *k; -@@ -664,16 +666,19 @@ key_fp_type_select(void) - 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; +- for (k = kexalgs; k->name != NULL; k++) { ++ for (k = (FIPS_mode() ? kexalgs_fips : kexalgs); k->name != NULL; k++) { + if (strcmp(k->name, name) == 0) + return k; + #ifdef GSSAPI +@@ -161,7 +181,10 @@ kex_names_valid(const char *names) + for ((p = strsep(&cp, ",")); p && *p != '\0'; + (p = strsep(&cp, ","))) { + if (kex_alg_by_name(p) == NULL) { +- error("Unsupported KEX algorithm \"%.100s\"", p); ++ if (FIPS_mode()) ++ error("\"%.100s\" is not allowed in FIPS mode", p); ++ else ++ error("Unsupported KEX algorithm \"%.100s\"", p); + free(s); + return 0; + } +Index: openssh-7.1p2/kexgexc.c +=================================================================== +--- openssh-7.1p2.orig/kexgexc.c ++++ openssh-7.1p2/kexgexc.c +@@ -28,6 +28,7 @@ -+ if (fips_mode()) -+ fp = fips_correct_fp_type(fp); + #ifdef WITH_OPENSSL + ++#include + #include + #include + +@@ -63,7 +64,7 @@ kexgex_client(struct ssh *ssh) + + nbits = dh_estimate(kex->dh_need * 8); + +- kex->min = DH_GRP_MIN; ++ kex->min = FIPS_mode() ? DH_GRP_MIN_FIPS : DH_GRP_MIN; + kex->max = DH_GRP_MAX; + kex->nbits = nbits; + if (datafellows & SSH_BUG_DHGEX_LARGE) +Index: openssh-7.1p2/kexgexs.c +=================================================================== +--- openssh-7.1p2.orig/kexgexs.c ++++ openssh-7.1p2/kexgexs.c +@@ -83,9 +83,9 @@ input_kex_dh_gex_request(int type, u_int + kex->nbits = nbits; + kex->min = min; + kex->max = max; +- min = MAX(DH_GRP_MIN, min); ++ min = MAX(FIPS_mode() ? DH_GRP_MIN_FIPS : DH_GRP_MIN, min); + max = MIN(DH_GRP_MAX, max); +- nbits = MAX(DH_GRP_MIN, nbits); ++ nbits = MAX(FIPS_mode() ? DH_GRP_MIN_FIPS : DH_GRP_MIN, nbits); + nbits = MIN(DH_GRP_MAX, nbits); + + if (kex->max < kex->min || kex->nbits < kex->min || +Index: openssh-7.1p2/mac.c +=================================================================== +--- openssh-7.1p2.orig/mac.c ++++ openssh-7.1p2/mac.c +@@ -27,6 +27,8 @@ + + #include + ++#include + - fp_defined = 1; - } - return fp; - } + #include + #include - /* - * string lengths must be less or equal to SSH_FP_TYPE_STRLEN (defined in - * key.h) as to fit into the fingerprint string buffer -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 -@@ -39,33 +39,35 @@ - #include "kex.h" - #include "mac.h" - #include "misc.h" - - #include "digest.h" - #include "hmac.h" - #include "umac.h" - -+#include "fips.h" -+ - #include "openbsd-compat/openssl-compat.h" - - #define SSH_DIGEST 1 /* SSH_DIGEST_XXX */ - #define SSH_UMAC 2 /* UMAC (not integrated with OpenSSL) */ - #define SSH_UMAC128 3 - - struct macalg { - char *name; - int type; - int alg; - int truncatebits; /* truncate digest if != 0 */ - int key_len; /* just for UMAC */ - int len; /* just for UMAC */ +@@ -54,7 +56,7 @@ struct macalg { int etm; /* Encrypt-then-MAC */ }; -static const struct macalg macs[] = { -+static const struct macalg macs_all[] = { ++static const struct macalg all_macs[] = { /* Encrypt-and-MAC (encrypt-and-authenticate) variants */ { "hmac-sha1", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 0 }, { "hmac-sha1-96", SSH_DIGEST, SSH_DIGEST_SHA1, 96, 0, 0, 0 }, - #ifdef HAVE_EVP_SHA256 - { "hmac-sha2-256", SSH_DIGEST, SSH_DIGEST_SHA256, 0, 0, 0, 0 }, - { "hmac-sha2-512", SSH_DIGEST, SSH_DIGEST_SHA512, 0, 0, 0, 0 }, - #endif - { "hmac-md5", SSH_DIGEST, SSH_DIGEST_MD5, 0, 0, 0, 0 }, -@@ -86,25 +88,59 @@ static const struct macalg macs[] = { - { "hmac-md5-96-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_MD5, 96, 0, 0, 1 }, - { "hmac-ripemd160-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_RIPEMD160, 0, 0, 0, 1 }, - { "umac-64-etm@openssh.com", SSH_UMAC, 0, 0, 128, 64, 1 }, - { "umac-128-etm@openssh.com", SSH_UMAC128, 0, 0, 128, 128, 1 }, - +@@ -85,6 +87,24 @@ static const struct macalg macs[] = { { NULL, 0, 0, 0, 0, 0, 0 } }; -+static const struct macalg macs_fips140_2[] = { ++static const struct macalg fips_macs[] = { + /* Encrypt-and-MAC (encrypt-and-authenticate) variants */ + { "hmac-sha1", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 0 }, +#ifdef HAVE_EVP_SHA256 @@ -713,347 +244,410 @@ diff --git a/openssh-6.6p1/mac.c b/openssh-6.6p1/mac.c +#endif + + /* Encrypt-then-MAC variants */ ++ { "hmac-sha1-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 1 }, +#ifdef HAVE_EVP_SHA256 + { "hmac-sha2-256-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA256, 0, 0, 0, 1 }, + { "hmac-sha2-512-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA512, 0, 0, 0, 1 }, +#endif ++ + { NULL, 0, 0, 0, 0, 0, 0 } +}; -+ -+/* Returns array of macs available depending on selected FIPS mode */ -+static struct macalg * -+fips_select_macs(void) -+{ -+ int fips = fips_mode(); -+ switch (fips) { -+ case 0: -+ return macs_all; -+ case 1: -+ return macs_fips140_2; -+ default: -+ /* should not be reached */ -+ fatal("Fatal error: incorrect FIPS mode '%i' at %s:%u", -+ fips, __FILE__, __LINE__); -+// return NULL; -+ } -+} + /* Returns a list of supported MACs separated by the specified char. */ char * mac_alg_list(char sep) - { - char *ret = NULL; +@@ -93,7 +113,7 @@ mac_alg_list(char sep) size_t nlen, rlen = 0; const struct macalg *m; - for (m = macs; m->name != NULL; m++) { -+ for (m = fips_select_macs(); m->name != NULL; m++) { ++ for (m = FIPS_mode() ? fips_macs : all_macs; m->name != NULL; m++) { if (ret != NULL) ret[rlen++] = sep; nlen = strlen(m->name); - ret = xrealloc(ret, 1, rlen + nlen + 2); - memcpy(ret + rlen, m->name, nlen + 1); - rlen += nlen; - } - return ret; -@@ -128,17 +164,17 @@ mac_setup_by_alg(Mac *mac, const struct - mac->etm = macalg->etm; - } - - int - mac_setup(Mac *mac, char *name) +@@ -132,7 +152,7 @@ mac_setup(struct sshmac *mac, char *name { const struct macalg *m; - for (m = macs; m->name != NULL; m++) { -+ for (m = fips_select_macs(); m->name != NULL; m++) { ++ for (m = FIPS_mode() ? fips_macs : all_macs; m->name != NULL; m++) { if (strcmp(name, m->name) != 0) continue; - if (mac != NULL) { - mac_setup_by_alg(mac, m); - debug2("mac_setup: setup %s", name); - } - return (0); - } -diff --git a/openssh-6.6p1/myproposal.h b/openssh-6.6p1/myproposal.h ---- a/openssh-6.6p1/myproposal.h -+++ b/openssh-6.6p1/myproposal.h -@@ -104,16 +104,20 @@ + if (mac != NULL) +Index: openssh-7.1p2/Makefile.in +=================================================================== +--- openssh-7.1p2.orig/Makefile.in ++++ openssh-7.1p2/Makefile.in +@@ -165,25 +165,25 @@ libssh.a: $(LIBSSH_OBJS) + $(RANLIB) $@ - #define KEX_DEFAULT_ENCRYPT \ - "aes128-ctr,aes192-ctr,aes256-ctr," \ - "arcfour256,arcfour128," \ - AESGCM_CIPHER_MODES \ - "chacha20-poly1305@openssh.com," \ - "aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc," \ - "aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se" -+#define KEX_FIPS_140_2_ENCRYPT \ + ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS) +- $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHLIBS) $(LIBS) $(GSSLIBS) ++ $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(SSHLIBS) $(LIBS) $(GSSLIBS) + + sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS) +- $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS) ++ $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS) + + scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o +- $(LD) -o $@ scp.o progressmeter.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ++ $(LD) -o $@ scp.o progressmeter.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) + + ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o +- $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ++ $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) + + ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o ssh-pkcs11-client.o +- $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ++ $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) + + ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o +- $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ++ $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) + + ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o roaming_dummy.o readconf.o +- $(LD) -o $@ ssh-keysign.o readconf.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ++ $(LD) -o $@ ssh-keysign.o readconf.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) + + ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-pkcs11-helper.o ssh-pkcs11.o + $(LD) -o $@ ssh-pkcs11-helper.o ssh-pkcs11.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) +@@ -192,7 +192,7 @@ ssh-ldap-helper$(EXEEXT): $(LIBCOMPAT) l + $(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) ++ $(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS) + + sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o + $(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) +Index: openssh-7.1p2/myproposal.h +=================================================================== +--- openssh-7.1p2.orig/myproposal.h ++++ openssh-7.1p2/myproposal.h +@@ -138,6 +138,28 @@ + "hmac-sha1-96," \ + "hmac-md5-96" + ++#define KEX_DEFAULT_KEX_FIPS \ ++ KEX_ECDH_METHODS \ ++ KEX_SHA256_METHODS \ ++ "diffie-hellman-group-exchange-sha1," \ ++ "diffie-hellman-group14-sha1" ++#define KEX_FIPS_ENCRYPT \ + "aes128-ctr,aes192-ctr,aes256-ctr," \ + "aes128-cbc,3des-cbc," \ + "aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se" - - #define KEX_DEFAULT_MAC \ - "hmac-md5-etm@openssh.com," \ - "hmac-sha1-etm@openssh.com," \ - "umac-64-etm@openssh.com," \ - "umac-128-etm@openssh.com," \ - "hmac-sha2-256-etm@openssh.com," \ - "hmac-sha2-512-etm@openssh.com," \ -@@ -124,16 +128,19 @@ - "hmac-sha1," \ - "umac-64@openssh.com," \ - "umac-128@openssh.com," \ - SHA2_HMAC_MODES \ - "hmac-ripemd160," \ - "hmac-ripemd160@openssh.com," \ - "hmac-sha1-96," \ - "hmac-md5-96" -+#define KEX_FIPS_140_2_MAC \ ++#ifdef HAVE_EVP_SHA256 ++#define KEX_FIPS_MAC \ + "hmac-sha1," \ -+ SHA2_HMAC_MODES \ - - #define KEX_DEFAULT_COMP "none,zlib@openssh.com,zlib" - #define KEX_DEFAULT_LANG "" - - - static char *myproposal[PROPOSAL_MAX] = { - KEX_DEFAULT_KEX, - KEX_DEFAULT_PK_ALG, -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 -@@ -100,16 +100,18 @@ - #include "mac.h" - #include "sshpty.h" - #include "match.h" - #include "msg.h" - #include "uidswap.h" - #include "roaming.h" - #include "version.h" - -+#include "fips.h" ++ "hmac-sha2-256," \ ++ "hmac-sha2-512," \ ++ "hmac-sha1-etm@openssh.com," \ ++ "hmac-sha2-256-etm@openssh.com," \ ++ "hmac-sha2-512-etm@openssh.com" ++#else ++#define KEX_FIPS_MAC \ ++ "hmac-sha1" ++#endif + - #ifdef ENABLE_PKCS11 - #include "ssh-pkcs11.h" + #else + + #define KEX_SERVER_KEX \ +Index: openssh-7.1p2/readconf.c +=================================================================== +--- openssh-7.1p2.orig/readconf.c ++++ openssh-7.1p2/readconf.c +@@ -1905,9 +1905,12 @@ fill_default_options(Options * options) + options->fingerprint_hash = SSH_FP_HASH_DEFAULT; + if (options->update_hostkeys == -1) + options->update_hostkeys = 0; +- if (kex_assemble_names(KEX_CLIENT_ENCRYPT, &options->ciphers) != 0 || +- kex_assemble_names(KEX_CLIENT_MAC, &options->macs) != 0 || +- kex_assemble_names(KEX_CLIENT_KEX, &options->kex_algorithms) != 0 || ++ if (kex_assemble_names((FIPS_mode() ? KEX_FIPS_ENCRYPT ++ : KEX_CLIENT_ENCRYPT), &options->ciphers) != 0 || ++ kex_assemble_names((FIPS_mode() ? KEX_FIPS_MAC ++ : KEX_CLIENT_MAC), &options->macs) != 0 || ++ kex_assemble_names((FIPS_mode() ? KEX_DEFAULT_KEX_FIPS ++ : KEX_CLIENT_KEX), &options->kex_algorithms) != 0 || + kex_assemble_names(KEX_DEFAULT_PK_ALG, + &options->hostbased_key_types) != 0 || + kex_assemble_names(KEX_DEFAULT_PK_ALG, +Index: openssh-7.1p2/servconf.c +=================================================================== +--- openssh-7.1p2.orig/servconf.c ++++ openssh-7.1p2/servconf.c +@@ -354,9 +354,12 @@ fill_default_server_options(ServerOption + if (options->fingerprint_hash == -1) + options->fingerprint_hash = SSH_FP_HASH_DEFAULT; + +- if (kex_assemble_names(KEX_SERVER_ENCRYPT, &options->ciphers) != 0 || +- kex_assemble_names(KEX_SERVER_MAC, &options->macs) != 0 || +- kex_assemble_names(KEX_SERVER_KEX, &options->kex_algorithms) != 0 || ++ if (kex_assemble_names((FIPS_mode() ? KEX_FIPS_ENCRYPT ++ : KEX_SERVER_ENCRYPT), &options->ciphers) != 0 || ++ kex_assemble_names((FIPS_mode() ? KEX_FIPS_MAC ++ : KEX_SERVER_MAC), &options->macs) != 0 || ++ kex_assemble_names((FIPS_mode() ? KEX_DEFAULT_KEX_FIPS ++ : KEX_SERVER_KEX), &options->kex_algorithms) != 0 || + kex_assemble_names(KEX_DEFAULT_PK_ALG, + &options->hostbased_key_types) != 0 || + kex_assemble_names(KEX_DEFAULT_PK_ALG, +@@ -2316,8 +2319,10 @@ dump_config(ServerOptions *o) + /* string arguments */ + dump_cfg_string(sPidFile, o->pid_file); + dump_cfg_string(sXAuthLocation, o->xauth_location); +- dump_cfg_string(sCiphers, o->ciphers ? o->ciphers : KEX_SERVER_ENCRYPT); +- dump_cfg_string(sMacs, o->macs ? o->macs : KEX_SERVER_MAC); ++ dump_cfg_string(sCiphers, o->ciphers ? o->ciphers : FIPS_mode() ++ ? KEX_FIPS_ENCRYPT : KEX_SERVER_ENCRYPT); ++ dump_cfg_string(sMacs, o->macs ? o->macs : FIPS_mode() ++ ? KEX_FIPS_MAC : KEX_SERVER_MAC); + dump_cfg_string(sBanner, o->banner); + dump_cfg_string(sForceCommand, o->adm_forced_command); + dump_cfg_string(sChrootDirectory, o->chroot_directory); +@@ -2332,8 +2337,8 @@ dump_config(ServerOptions *o) + dump_cfg_string(sAuthorizedPrincipalsCommand, o->authorized_principals_command); + dump_cfg_string(sAuthorizedPrincipalsCommandUser, o->authorized_principals_command_user); + dump_cfg_string(sHostKeyAgent, o->host_key_agent); +- dump_cfg_string(sKexAlgorithms, +- o->kex_algorithms ? o->kex_algorithms : KEX_SERVER_KEX); ++ dump_cfg_string(sKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : ++ FIPS_mode() ? KEX_DEFAULT_KEX_FIPS : KEX_SERVER_KEX); + dump_cfg_string(sHostbasedAcceptedKeyTypes, o->hostbased_key_types ? + o->hostbased_key_types : KEX_DEFAULT_PK_ALG); + dump_cfg_string(sHostKeyAlgorithms, o->hostkeyalgorithms ? +Index: openssh-7.1p2/ssh.c +=================================================================== +--- openssh-7.1p2.orig/ssh.c ++++ openssh-7.1p2/ssh.c +@@ -75,6 +75,8 @@ + #include + #include #endif ++#include ++#include + #include "openbsd-compat/openssl-compat.h" + #include "openbsd-compat/sys-queue.h" - extern char *__progname; +@@ -522,6 +524,14 @@ main(int ac, char **av) + sanitise_stdfd(); + + __progname = ssh_get_progname(av[0]); ++ SSLeay_add_all_algorithms(); ++ if (access("/etc/system-fips", F_OK) == 0) ++ if (! FIPSCHECK_verify(NULL, NULL)){ ++ if (FIPS_mode()) ++ fatal("FIPS integrity verification test failed."); ++ else ++ logit("FIPS integrity verification test failed."); ++ } - /* Saves a copy of argv for setproctitle emulation */ #ifndef HAVE_SETPROCTITLE -@@ -499,16 +501,18 @@ main(int ac, char **av) - logfile = NULL; - argv0 = av[0]; - - again: - while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx" - "ACD:E:F:I:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) { + /* Prepare for later setproctitle emulation */ +@@ -599,6 +609,9 @@ main(int ac, char **av) + "ACD:E:F:GI:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) { switch (opt) { case '1': -+ if (fips_mode()) ++ if (FIPS_mode()) { + fatal("Protocol 1 not allowed in the FIPS mode."); ++ } options.protocol = SSH_PROTO_1; break; case '2': - options.protocol = SSH_PROTO_2; - break; - case '4': - options.address_family = AF_INET; - break; -@@ -826,16 +830,22 @@ main(int ac, char **av) - if (!host) - usage(); - +@@ -940,7 +953,6 @@ main(int ac, char **av) host_arg = xstrdup(host); - OpenSSL_add_all_algorithms(); + #ifdef WITH_OPENSSL +- OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); + #endif + +@@ -1114,6 +1126,10 @@ main(int ac, char **av) + + seed_rng(); + ++ if (FIPS_mode()) { ++ logit("FIPS mode initialized"); ++ } ++ + if (options.user == NULL) + options.user = xstrdup(pw->pw_name); + +@@ -1191,6 +1207,12 @@ main(int ac, char **av) + + timeout_ms = options.connection_timeout * 1000; + if (FIPS_mode()) { + options.protocol &= SSH_PROTO_2; + if (options.protocol == 0) -+ fatal("Protocol 2 disabled by configuration but required in the FIPS mode"); ++ fatal("Protocol 2 disabled by configuration but required in the FIPS mode."); + } + - /* Initialize the command to execute on remote host. */ - buffer_init(&command); - - /* - * Save the command to execute on the remote host in a buffer. There - * is no limit on the length of the command, except by the maximum - * packet size. Also sets the tty flag if there is no command. - */ -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 -@@ -66,16 +66,18 @@ - #include "match.h" - #include "dispatch.h" - #include "canohost.h" - #include "msg.h" - #include "pathnames.h" - #include "uidswap.h" - #include "hostfile.h" - -+#include "fips.h" -+ - #ifdef GSSAPI - #include "ssh-gss.h" + /* Open a connection to the remote host. */ + if (ssh_connect(host, addrs, &hostaddr, options.port, + options.address_family, options.connection_attempts, +Index: openssh-7.1p2/sshconnect2.c +=================================================================== +--- openssh-7.1p2.orig/sshconnect2.c ++++ openssh-7.1p2/sshconnect2.c +@@ -44,6 +44,8 @@ + #include #endif - /* import */ - extern char *client_version_string; - extern char *server_version_string; - extern Options options; -@@ -163,31 +165,41 @@ ssh_kex2(char *host, struct sockaddr *ho - - if (options.ciphers == (char *)-1) { - logit("No valid ciphers for protocol version 2 given, using defaults."); - options.ciphers = NULL; - } - if (options.ciphers != NULL) { - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; -+ } else if (fips_mode()) { -+ /* TODO: use intersection of FIPS ciphers and those requested in -+ * configuration */ -+ myproposal[PROPOSAL_ENC_ALGS_CTOS] = -+ myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_FIPS_140_2_ENCRYPT; - } - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); - myproposal[PROPOSAL_ENC_ALGS_STOC] = - compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_STOC]); - if (options.compression) { - myproposal[PROPOSAL_COMP_ALGS_CTOS] = - myproposal[PROPOSAL_COMP_ALGS_STOC] = "zlib@openssh.com,zlib,none"; - } else { - myproposal[PROPOSAL_COMP_ALGS_CTOS] = - myproposal[PROPOSAL_COMP_ALGS_STOC] = "none,zlib@openssh.com,zlib"; - } - if (options.macs != NULL) { - myproposal[PROPOSAL_MAC_ALGS_CTOS] = - myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; -+ } else if (fips_mode()) { -+ /* TODO: use intersection of FIPS macs and those requested in -+ * configuration */ -+ myproposal[PROPOSAL_MAC_ALGS_CTOS] = -+ myproposal[PROPOSAL_MAC_ALGS_STOC] = KEX_FIPS_140_2_MAC; - } - if (options.hostkeyalgorithms != NULL) - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = - compat_pkalg_proposal(options.hostkeyalgorithms); - else { - /* Prefer algorithms that we already have keys for */ - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = - compat_pkalg_proposal( -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 -@@ -117,16 +117,18 @@ - #ifdef GSSAPI - #include "ssh-gss.h" - #endif - #include "monitor_wrap.h" - #include "roaming.h" - #include "ssh-sandbox.h" - #include "version.h" - -+#include "fips.h" ++#include + - #ifdef LIBWRAP - #include - #include - int allow_severity; - int deny_severity; - #endif /* LIBWRAP */ + #include "openbsd-compat/sys-queue.h" - #ifndef O_NOCTTY -@@ -1723,16 +1725,20 @@ main(int ac, char **av) - case KEY_ECDSA: - case KEY_ED25519: - sensitive_data.have_ssh2_key = 1; - break; + #include "xmalloc.h" +@@ -170,20 +172,25 @@ ssh_kex2(char *host, struct sockaddr *ho + + #ifdef GSSAPI + if (options.gss_keyex) { +- /* Add the GSSAPI mechanisms currently supported on this +- * client to the key exchange algorithm proposal */ +- orig = options.kex_algorithms; +- +- if (options.gss_trust_dns) +- gss_host = (char *)get_canonical_hostname(1); +- else +- gss_host = host; +- +- gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity); +- if (gss) { +- debug("Offering GSSAPI proposal: %s", gss); +- xasprintf(&options.kex_algorithms, +- "%s,%s", gss, orig); ++ if (FIPS_mode()) { ++ logit("Disabling GSSAPIKeyExchange. Not usable in FIPS mode"); ++ options.gss_keyex = 0; ++ } else { ++ /* Add the GSSAPI mechanisms currently supported on this ++ * client to the key exchange algorithm proposal */ ++ orig = options.kex_algorithms; ++ ++ if (options.gss_trust_dns) ++ gss_host = (char *)get_canonical_hostname(1); ++ else ++ gss_host = host; ++ ++ gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity); ++ if (gss) { ++ debug("Offering GSSAPI proposal: %s", gss); ++ xasprintf(&options.kex_algorithms, ++ "%s,%s", gss, orig); ++ } } - debug("private host key: #%d type %d %s", i, keytype, - key_type(key ? key : pubkey)); } -+ if ((options.protocol & SSH_PROTO_1) && fips_mode()) { + #endif +Index: openssh-7.1p2/sshd.c +=================================================================== +--- openssh-7.1p2.orig/sshd.c ++++ openssh-7.1p2/sshd.c +@@ -66,6 +66,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -77,6 +78,8 @@ + #include + #include + #include ++#include ++#include + #include "openbsd-compat/openssl-compat.h" + #endif + +@@ -1536,6 +1539,18 @@ main(int ac, char **av) + #endif + __progname = ssh_get_progname(av[0]); + ++ SSLeay_add_all_algorithms(); ++ if (access("/etc/system-fips", F_OK) == 0) ++ if (! FIPSCHECK_verify(NULL, NULL)) { ++ openlog(__progname, LOG_PID, LOG_AUTHPRIV); ++ if (FIPS_mode()) { ++ syslog(LOG_CRIT, "FIPS integrity verification test failed."); ++ cleanup_exit(255); ++ } ++ else ++ syslog(LOG_INFO, "FIPS integrity verification test failed."); ++ closelog(); ++ } + /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */ + saved_argc = ac; + rexec_argc = ac; +@@ -1692,7 +1707,7 @@ main(int ac, char **av) + else + closefrom(REEXEC_DEVCRYPTO_RESERVED_FD); + +-#ifdef WITH_OPENSSL ++#if 0 /* FIPS */ + OpenSSL_add_all_algorithms(); + #endif + +@@ -1888,6 +1903,10 @@ main(int ac, char **av) + sshkey_type(pubkey) : sshkey_ssh_name(pubkey), fp); + free(fp); + } ++ if ((options.protocol & SSH_PROTO_1) && FIPS_mode()) { + logit("Disabling protocol version 1. Not allowed in the FIPS mode."); + options.protocol &= ~SSH_PROTO_1; + } if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) { logit("Disabling protocol version 1. Could not load host key"); options.protocol &= ~SSH_PROTO_1; - } - if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) { - logit("Disabling protocol version 2. Could not load host key"); - options.protocol &= ~SSH_PROTO_2; - } -@@ -2370,30 +2376,30 @@ do_ssh1_kex(void) - } - if (rsafail) { - int bytes = BN_num_bytes(session_key_int); - u_char *buf = xmalloc(bytes); - struct ssh_digest_ctx *md; +@@ -2056,6 +2075,10 @@ main(int ac, char **av) + /* Reinitialize the log (because of the fork above). */ + log_init(__progname, options.log_level, options.log_facility, log_stderr); - logit("do_connection: generating a fake encryption key"); - BN_bn2bin(session_key_int, buf); -- if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL || -+ if ((md = ssh_digest_start(fips_correct_dgst(SSH_DIGEST_MD5))) == NULL || - ssh_digest_update(md, buf, bytes) < 0 || - ssh_digest_update(md, sensitive_data.ssh1_cookie, - SSH_SESSION_KEY_LENGTH) < 0 || - ssh_digest_final(md, session_key, sizeof(session_key)) < 0) -- fatal("%s: md5 failed", __func__); -+ fatal("%s: hash failed", __func__); - ssh_digest_free(md); -- if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL || -+ if ((md = ssh_digest_start(fips_correct_dgst(SSH_DIGEST_MD5))) == NULL || - ssh_digest_update(md, session_key, 16) < 0 || - ssh_digest_update(md, sensitive_data.ssh1_cookie, - SSH_SESSION_KEY_LENGTH) < 0 || - ssh_digest_final(md, session_key + 16, - sizeof(session_key) - 16) < 0) -- fatal("%s: md5 failed", __func__); -+ 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(); -@@ -2441,25 +2447,31 @@ sshd_hostkey_sign(Key *privkey, Key *pub - static void - do_ssh2_kex(void) - { - Kex *kex; ++ if (FIPS_mode()) { ++ logit("FIPS mode initialized"); ++ } ++ + /* Chdir to the root directory so that the current disk can be + unmounted if desired. */ + if (chdir("/") == -1) +@@ -2654,10 +2677,14 @@ do_ssh2_kex(void) + if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0) + orig = NULL; - if (options.ciphers != NULL) { - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; -+ } else if (fips_mode()) { -+ myproposal[PROPOSAL_ENC_ALGS_CTOS] = -+ myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_FIPS_140_2_ENCRYPT; - } - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); - myproposal[PROPOSAL_ENC_ALGS_STOC] = - compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_STOC]); +- if (options.gss_keyex) +- gss = ssh_gssapi_server_mechanisms(); +- else +- gss = NULL; ++ if (options.gss_keyex) { ++ if (FIPS_mode()) { ++ logit("Disabling GSSAPIKeyExchange. Not usable in FIPS mode"); ++ options.gss_keyex = 0; ++ } else { ++ gss = ssh_gssapi_server_mechanisms(); ++ } ++ } - if (options.macs != NULL) { - myproposal[PROPOSAL_MAC_ALGS_CTOS] = - myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; -+ } else if (fips_mode()) { -+ myproposal[PROPOSAL_MAC_ALGS_CTOS] = -+ myproposal[PROPOSAL_MAC_ALGS_STOC] = KEX_FIPS_140_2_MAC; + if (gss && orig) + xasprintf(&newstr, "%s,%s", gss, orig); +Index: openssh-7.1p2/sshkey.c +=================================================================== +--- openssh-7.1p2.orig/sshkey.c ++++ openssh-7.1p2/sshkey.c +@@ -35,6 +35,7 @@ + #include + #include + #include ++#include + #endif + + #include "crypto_api.h" +@@ -1555,6 +1556,8 @@ rsa_generate_private_key(u_int bits, RSA } - if (options.compression == COMP_NONE) { - myproposal[PROPOSAL_COMP_ALGS_CTOS] = - 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 (!BN_set_word(f4, RSA_F4) || + !RSA_generate_key_ex(private, bits, f4, NULL)) { ++ if (FIPS_mode()) ++ logit("%s: the key length might be unsupported by FIPS mode approved key generation method", __func__); + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; } diff --git a/openssh-6.6p1-gssapi_key_exchange.patch b/openssh-6.6p1-gssapi_key_exchange.patch index dc2fb22..418917a 100644 --- a/openssh-6.6p1-gssapi_key_exchange.patch +++ b/openssh-6.6p1-gssapi_key_exchange.patch @@ -1,260 +1,38 @@ -# HG changeset patch -# Parent 0b2761bdc8c2071a11ca24387c3f58be2fdbaa5e - -diff --git a/openssh-6.6p1/ChangeLog.gssapi b/openssh-6.6p1/ChangeLog.gssapi -new file mode 100644 ---- /dev/null -+++ b/openssh-6.6p1/ChangeLog.gssapi -@@ -0,0 +1,113 @@ -+20110101 -+ - Finally update for OpenSSH 5.6p1 -+ - Add GSSAPIServerIdentity option from Jim Basney -+ -+20100308 -+ - [ Makefile.in, key.c, key.h ] -+ Updates for OpenSSH 5.4p1 -+ - [ servconf.c ] -+ Include GSSAPI options in the sshd -T configuration dump, and flag -+ some older configuration options as being unsupported. Thanks to Colin -+ Watson. -+ - -+ -+20100124 -+ - [ sshconnect2.c ] -+ Adapt to deal with additional element in Authmethod structure. Thanks to -+ Colin Watson -+ -+20090615 -+ - [ gss-genr.c gss-serv.c kexgssc.c kexgsss.c monitor.c sshconnect2.c -+ sshd.c ] -+ Fix issues identified by Greg Hudson following a code review -+ Check return value of gss_indicate_mechs -+ Protect GSSAPI calls in monitor, so they can only be used if enabled -+ Check return values of bignum functions in key exchange -+ Use BN_clear_free to clear other side's DH value -+ Make ssh_gssapi_id_kex more robust -+ Only configure kex table pointers if GSSAPI is enabled -+ Don't leak mechanism list, or gss mechanism list -+ Cast data.length before printing -+ If serverkey isn't provided, use an empty string, rather than NULL -+ -+20090201 -+ - [ gss-genr.c gss-serv.c kex.h kexgssc.c readconf.c readconf.h ssh-gss.h -+ ssh_config.5 sshconnet2.c ] -+ Add support for the GSSAPIClientIdentity option, which allows the user -+ to specify which GSSAPI identity to use to contact a given server -+ -+20080404 -+ - [ gss-serv.c ] -+ Add code to actually implement GSSAPIStrictAcceptCheck, which had somehow -+ been omitted from a previous version of this patch. Reported by Borislav -+ Stoichkov -+ -+20070317 -+ - [ gss-serv-krb5.c ] -+ Remove C99ism, where new_ccname was being declared in the middle of a -+ function -+ -+20061220 -+ - [ servconf.c ] -+ Make default for GSSAPIStrictAcceptorCheck be Yes, to match previous, and -+ documented, behaviour. Reported by Dan Watson. -+ -+20060910 -+ - [ gss-genr.c kexgssc.c kexgsss.c kex.h monitor.c sshconnect2.c sshd.c -+ ssh-gss.h ] -+ add support for gss-group14-sha1 key exchange mechanisms -+ - [ gss-serv.c servconf.c servconf.h sshd_config sshd_config.5 ] -+ Add GSSAPIStrictAcceptorCheck option to allow the disabling of -+ acceptor principal checking on multi-homed machines. -+ -+ - [ sshd_config ssh_config ] -+ Add settings for GSSAPIKeyExchange and GSSAPITrustDNS to the sample -+ configuration files -+ - [ kexgss.c kegsss.c sshconnect2.c sshd.c ] -+ Code cleanup. Replace strlen/xmalloc/snprintf sequences with xasprintf() -+ Limit length of error messages displayed by client -+ -+20060909 -+ - [ gss-genr.c gss-serv.c ] -+ move ssh_gssapi_acquire_cred() and ssh_gssapi_server_ctx to be server -+ only, where they belong -+ -+ -+20060829 -+ - [ gss-serv-krb5.c ] -+ Fix CCAPI credentials cache name when creating KRB5CCNAME environment -+ variable -+ -+20060828 -+ - [ gss-genr.c ] -+ Avoid Heimdal context freeing problem -+ -+ -+20060818 -+ - [ gss-genr.c ssh-gss.h sshconnect2.c ] -+ Make sure that SPENGO is disabled -+ -+ -+20060421 -+ - [ gssgenr.c, sshconnect2.c ] -+ a few type changes (signed versus unsigned, int versus size_t) to -+ fix compiler errors/warnings -+ (from jbasney AT ncsa.uiuc.edu) -+ - [ kexgssc.c, sshconnect2.c ] -+ fix uninitialized variable warnings -+ (from jbasney AT ncsa.uiuc.edu) -+ - [ gssgenr.c ] -+ pass oid to gss_display_status (helpful when using GSSAPI mechglue) -+ (from jbasney AT ncsa.uiuc.edu) -+ -+ - [ gss-serv-krb5.c ] -+ #ifdef HAVE_GSSAPI_KRB5 should be #ifdef HAVE_GSSAPI_KRB5_H -+ (from jbasney AT ncsa.uiuc.edu) -+ -+ - [ readconf.c, readconf.h, ssh_config.5, sshconnect2.c -+ add client-side GssapiKeyExchange option -+ (from jbasney AT ncsa.uiuc.edu) -+ - [ sshconnect2.c ] -+ add support for GssapiTrustDns option for gssapi-with-mic -+ (from jbasney AT ncsa.uiuc.edu) -+ -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 -@@ -67,16 +67,17 @@ LIBSSH_OBJS=authfd.o authfile.o bufaux.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 \ - 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 \ -+ kexgssc.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 \ - auditstub.o - -@@ -86,17 +87,17 @@ SSHOBJS= ssh.o readconf.o clientloop.o s - - 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 \ - auth.o auth1.o auth2.o auth-options.o session.o \ - auth-chall.o auth2-chall.o groupaccess.o \ - auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \ - auth2-none.o auth2-passwd.o auth2-pubkey.o \ -- monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o kexecdhs.o \ -+ monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o kexecdhs.o kexgsss.o \ - 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 - -diff --git a/openssh-6.6p1/auth-krb5.c b/openssh-6.6p1/auth-krb5.c ---- a/openssh-6.6p1/auth-krb5.c -+++ b/openssh-6.6p1/auth-krb5.c -@@ -177,18 +177,23 @@ auth_krb5_password(Authctxt *authctxt, c - if (problem) - goto out; +Index: openssh-7.1p2/auth2.c +=================================================================== +--- openssh-7.1p2.orig/auth2.c ++++ openssh-7.1p2/auth2.c +@@ -70,6 +70,7 @@ extern Authmethod method_passwd; + extern Authmethod method_kbdint; + extern Authmethod method_hostbased; + #ifdef GSSAPI ++extern Authmethod method_gsskeyex; + extern Authmethod method_gssapi; + extern Authmethod method_gssapi_old; #endif - - authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); - - len = strlen(authctxt->krb5_ticket_file) + 6; - authctxt->krb5_ccname = xmalloc(len); -+#ifdef USE_CCAPI -+ snprintf(authctxt->krb5_ccname, len, "API:%s", -+ authctxt->krb5_ticket_file); -+#else - snprintf(authctxt->krb5_ccname, len, "FILE:%s", - authctxt->krb5_ticket_file); -+#endif - - #ifdef USE_PAM - if (options.use_pam) - do_pam_putenv("KRB5CCNAME", authctxt->krb5_ccname); +@@ -78,6 +79,7 @@ Authmethod *authmethods[] = { + &method_none, + &method_pubkey, + #ifdef GSSAPI ++ &method_gsskeyex, + &method_gssapi, + &method_gssapi_old, #endif +Index: openssh-7.1p2/auth2-gss.c +=================================================================== +--- openssh-7.1p2.orig/auth2-gss.c ++++ openssh-7.1p2/auth2-gss.c +@@ -31,6 +31,7 @@ + #include - out: - restore_uid(); -@@ -238,35 +243,42 @@ krb5_cleanup_proc(Authctxt *authctxt) - } + #include ++#include - #ifndef HEIMDAL - krb5_error_code - ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) { - int tmpfd, ret, oerrno; - char ccname[40]; - mode_t old_umask; -+#ifdef USE_CCAPI -+ char cctemplate[] = "API:krb5cc_%d"; -+#else -+ char cctemplate[] = "FILE:/tmp/krb5cc_%d_XXXXXXXXXX"; -+#endif - - ret = snprintf(ccname, sizeof(ccname), -- "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid()); -+ cctemplate, geteuid()); - if (ret < 0 || (size_t)ret >= sizeof(ccname)) - return ENOMEM; - -+#ifndef USE_CCAPI - old_umask = umask(0177); - tmpfd = mkstemp(ccname + strlen("FILE:")); - oerrno = errno; - umask(old_umask); - if (tmpfd == -1) { - logit("mkstemp(): %.100s", strerror(oerrno)); - return oerrno; - } - - if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) { - oerrno = errno; - logit("fchmod(): %.100s", strerror(oerrno)); - close(tmpfd); - return oerrno; - } - close(tmpfd); -+#endif - - return (krb5_cc_resolve(ctx, ccname, ccache)); - } - #endif /* !HEIMDAL */ - #endif /* KRB5 */ -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 -@@ -1,12 +1,12 @@ - /* $OpenBSD: auth2-gss.c,v 1.21 2014/02/26 20:28:44 djm Exp $ */ - - /* -- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. -+ * Copyright (c) 2001-2007 Simon Wilkinson. 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 -@@ -47,16 +47,50 @@ - - extern ServerOptions options; - - static void input_gssapi_token(int type, u_int32_t plen, void *ctxt); - static void input_gssapi_mic(int type, u_int32_t plen, void *ctxt); - static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt); - static void input_gssapi_errtok(int, u_int32_t, void *); + #include "xmalloc.h" + #include "key.h" +@@ -53,6 +54,40 @@ static int input_gssapi_mic(int type, u_ + static int input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt); + static int input_gssapi_errtok(int, u_int32_t, void *); +/* + * The 'gssapi_keyex' userauth mechanism. @@ -293,17 +71,7 @@ diff --git a/openssh-6.6p1/auth2-gss.c b/openssh-6.6p1/auth2-gss.c /* * We only support those mechanisms that we know about (ie ones that we know * how to check local user kuserok and the like) - */ - static int - userauth_gssapi(Authctxt *authctxt) - { - gss_OID_desc goid = {0, NULL}; -@@ -239,17 +273,18 @@ input_gssapi_exchange_complete(int type, - - /* - * We don't need to check the status, because we're only enabled in - * the dispatcher once the exchange is complete - */ +@@ -238,7 +273,8 @@ input_gssapi_exchange_complete(int type, packet_check_eom(); @@ -313,17 +81,7 @@ diff --git a/openssh-6.6p1/auth2-gss.c b/openssh-6.6p1/auth2-gss.c authctxt->postponed = 0; dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); - userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL); - } -@@ -274,31 +309,38 @@ input_gssapi_mic(int type, u_int32_t ple - - ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service, - "gssapi-with-mic"); - - gssbuf.value = buffer_ptr(&b); +@@ -274,7 +310,8 @@ input_gssapi_mic(int type, u_int32_t ple gssbuf.length = buffer_len(&b); if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic)))) @@ -333,15 +91,8 @@ diff --git a/openssh-6.6p1/auth2-gss.c b/openssh-6.6p1/auth2-gss.c else logit("GSSAPI MIC check failed"); - buffer_free(&b); - free(mic.value); - - authctxt->postponed = 0; - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); - userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL); +@@ -290,6 +327,12 @@ input_gssapi_mic(int type, u_int32_t ple + return 0; } +Authmethod method_gsskeyex = { @@ -353,52 +104,13 @@ diff --git a/openssh-6.6p1/auth2-gss.c b/openssh-6.6p1/auth2-gss.c Authmethod method_gssapi = { "gssapi-with-mic", userauth_gssapi, - &options.gss_authentication - }; - - Authmethod method_gssapi_old = { - "gssapi", -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 -@@ -64,24 +64,26 @@ extern Buffer loginmsg; - /* methods */ - - 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_gsskeyex; - extern Authmethod method_gssapi; - extern Authmethod method_gssapi_old; - #endif - - Authmethod *authmethods[] = { - &method_none, - &method_pubkey, - #ifdef GSSAPI -+ &method_gsskeyex, - &method_gssapi, - &method_gssapi_old, - #endif - &method_passwd, - &method_kbdint, - &method_hostbased, - NULL - }; -diff --git a/openssh-6.6p1/clientloop.c b/openssh-6.6p1/clientloop.c ---- a/openssh-6.6p1/clientloop.c -+++ b/openssh-6.6p1/clientloop.c -@@ -106,16 +106,20 @@ - #include "authfd.h" - #include "atomicio.h" - #include "sshpty.h" - #include "misc.h" - #include "match.h" - #include "msg.h" - #include "roaming.h" +Index: openssh-7.1p2/clientloop.c +=================================================================== +--- openssh-7.1p2.orig/clientloop.c ++++ openssh-7.1p2/clientloop.c +@@ -115,6 +115,10 @@ + #include "ssherr.h" + #include "hostfile.h" +#ifdef GSSAPI +#include "ssh-gss.h" @@ -407,17 +119,7 @@ diff --git a/openssh-6.6p1/clientloop.c b/openssh-6.6p1/clientloop.c /* import options */ extern Options options; - /* Flag indicating that stdin should be redirected from /dev/null. */ - extern int stdin_null_flag; - - /* Flag indicating that no shell has been requested */ - extern int no_shell_flag; -@@ -1603,16 +1607,25 @@ client_loop(int have_pty, int escape_cha - &max_fd2, &nalloc, rekeying); - - if (quit_pending) - break; - +@@ -1610,6 +1614,15 @@ client_loop(int have_pty, int escape_cha /* Do channel operations unless rekeying in progress. */ if (!rekeying) { channel_after_select(readset, writeset); @@ -432,21 +134,12 @@ diff --git a/openssh-6.6p1/clientloop.c b/openssh-6.6p1/clientloop.c + if (need_rekeying || packet_need_rekeying()) { debug("need rekeying"); - xxx_kex->done = 0; - kex_send_kexinit(xxx_kex); - need_rekeying = 0; - } - } - -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 -@@ -579,16 +579,40 @@ main() { if (NSVersionOfRunTimeLibrary(" - AC_DEFINE([BROKEN_GLOB], [1], [OS X glob does not do what we expect]) - AC_DEFINE_UNQUOTED([BIND_8_COMPAT], [1], - [Define if your resolver libs need this for getrrsetbyname]) - AC_DEFINE([SSH_TUN_FREEBSD], [1], [Open tunnel devices the FreeBSD way]) - AC_DEFINE([SSH_TUN_COMPAT_AF], [1], + active_state->kex->done = 0; +Index: openssh-7.1p2/configure.ac +=================================================================== +--- openssh-7.1p2.orig/configure.ac ++++ openssh-7.1p2/configure.ac +@@ -625,6 +625,30 @@ main() { if (NSVersionOfRunTimeLibrary(" [Use tunnel device compatibility to OpenBSD]) AC_DEFINE([SSH_TUN_PREPEND_AF], [1], [Prepend the address family to IP tunnel traffic]) @@ -477,34 +170,11 @@ diff --git a/openssh-6.6p1/configure.ac b/openssh-6.6p1/configure.ac m4_pattern_allow([AU_IPv]) AC_CHECK_DECL([AU_IPv4], [], AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records]) - [#include ] - AC_DEFINE([LASTLOG_WRITE_PUTUTXLINE], [1], - [Define if pututxline updates lastlog too]) - ) - AC_DEFINE([SPT_TYPE], [SPT_REUSEARGV], -diff --git a/openssh-6.6p1/gss-genr.c b/openssh-6.6p1/gss-genr.c ---- a/openssh-6.6p1/gss-genr.c -+++ b/openssh-6.6p1/gss-genr.c -@@ -1,12 +1,12 @@ - /* $OpenBSD: gss-genr.c,v 1.22 2013/11/08 00:39:15 djm Exp $ */ - - /* -- * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. -+ * Copyright (c) 2001-2009 Simon Wilkinson. 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 -@@ -34,22 +34,177 @@ - #include - #include - #include - - #include "xmalloc.h" +Index: openssh-7.1p2/gss-genr.c +=================================================================== +--- openssh-7.1p2.orig/gss-genr.c ++++ openssh-7.1p2/gss-genr.c +@@ -41,12 +41,167 @@ #include "buffer.h" #include "log.h" #include "ssh2.h" @@ -672,17 +342,7 @@ diff --git a/openssh-6.6p1/gss-genr.c b/openssh-6.6p1/gss-genr.c /* Check that the OID in a data stream matches that in the context */ int ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len) - { - return (ctx != NULL && ctx->oid != GSS_C_NO_OID && - ctx->oid->length == len && - memcmp(ctx->oid->elements, data, len) == 0); - } -@@ -192,17 +347,17 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int de - int deleg_flag = 0; - - if (deleg_creds) { - deleg_flag = GSS_C_DELEG_FLAG; - debug("Delegating credentials"); +@@ -199,7 +354,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int de } ctx->major = gss_init_sec_context(&ctx->minor, @@ -691,17 +351,7 @@ diff --git a/openssh-6.6p1/gss-genr.c b/openssh-6.6p1/gss-genr.c GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag, 0, NULL, recv_tok, NULL, send_tok, flags, NULL); - if (GSS_ERROR(ctx->major)) - ssh_gssapi_error(ctx); - - return (ctx->major); - } -@@ -222,60 +377,173 @@ ssh_gssapi_import_name(Gssctxt *ctx, con - &gssbuf, GSS_C_NT_HOSTBASED_SERVICE, &ctx->name))) - ssh_gssapi_error(ctx); - - free(gssbuf.value); - return (ctx->major); +@@ -229,8 +384,42 @@ ssh_gssapi_import_name(Gssctxt *ctx, con } OM_uint32 @@ -744,7 +394,7 @@ diff --git a/openssh-6.6p1/gss-genr.c b/openssh-6.6p1/gss-genr.c if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context, GSS_C_QOP_DEFAULT, buffer, hash))) ssh_gssapi_error(ctx); - +@@ -238,6 +427,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer return (ctx->major); } @@ -764,13 +414,7 @@ diff --git a/openssh-6.6p1/gss-genr.c b/openssh-6.6p1/gss-genr.c void ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service, const char *context) - { - buffer_init(b); - buffer_put_string(b, session_id2, session_id2_len); - buffer_put_char(b, SSH2_MSG_USERAUTH_REQUEST); - buffer_put_cstring(b, user); - buffer_put_cstring(b, service); - buffer_put_cstring(b, context); +@@ -251,11 +453,16 @@ ssh_gssapi_buildmic(Buffer *b, const cha } int @@ -788,9 +432,7 @@ diff --git a/openssh-6.6p1/gss-genr.c b/openssh-6.6p1/gss-genr.c /* RFC 4462 says we MUST NOT do SPNEGO */ if (oid->length == spnego_oid.length && - (memcmp(oid->elements, spnego_oid.elements, oid->length) == 0)) - return 0; /* false */ - +@@ -265,6 +472,10 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx ssh_gssapi_build_ctx(ctx); ssh_gssapi_set_oid(*ctx, oid); major = ssh_gssapi_import_name(*ctx, host); @@ -801,9 +443,7 @@ diff --git a/openssh-6.6p1/gss-genr.c b/openssh-6.6p1/gss-genr.c if (!GSS_ERROR(major)) { major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, NULL); - gss_release_buffer(&minor, &token); - if ((*ctx)->context != GSS_C_NO_CONTEXT) - gss_delete_sec_context(&minor, &(*ctx)->context, +@@ -274,10 +485,66 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx GSS_C_NO_BUFFER); } @@ -823,7 +463,6 @@ diff --git a/openssh-6.6p1/gss-genr.c b/openssh-6.6p1/gss-genr.c + static OM_uint32 last_call = 0; + OM_uint32 lifetime, now, major, minor; + int equal; -+ gss_cred_usage_t usage = GSS_C_INITIATE; + + now = time(NULL); + @@ -872,193 +511,25 @@ diff --git a/openssh-6.6p1/gss-genr.c b/openssh-6.6p1/gss-genr.c +} + #endif /* GSSAPI */ -diff --git a/openssh-6.6p1/gss-serv-krb5.c b/openssh-6.6p1/gss-serv-krb5.c ---- a/openssh-6.6p1/gss-serv-krb5.c -+++ b/openssh-6.6p1/gss-serv-krb5.c -@@ -1,12 +1,12 @@ - /* $OpenBSD: gss-serv-krb5.c,v 1.8 2013/07/20 01:55:13 djm Exp $ */ - - /* -- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. -+ * Copyright (c) 2001-2007 Simon Wilkinson. 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 -@@ -117,16 +117,17 @@ static void - ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) - { - krb5_ccache ccache; - krb5_error_code problem; - krb5_principal princ; - OM_uint32 maj_status, min_status; - int len; - const char *errmsg; -+ const char *new_ccname; - - if (client->creds == NULL) { - debug("No credentials stored"); - return; - } - - if (ssh_gssapi_krb5_init() == 0) - return; -@@ -175,37 +176,108 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl - - if ((maj_status = gss_krb5_copy_ccache(&min_status, - client->creds, ccache))) { - logit("gss_krb5_copy_ccache() failed"); - krb5_cc_destroy(krb_context, ccache); - return; - } - -- client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache)); -+ new_ccname = krb5_cc_get_name(krb_context, ccache); -+ - client->store.envvar = "KRB5CCNAME"; -- len = strlen(client->store.filename) + 6; -- client->store.envval = xmalloc(len); -- snprintf(client->store.envval, len, "FILE:%s", client->store.filename); -+#ifdef USE_CCAPI -+ xasprintf(&client->store.envval, "API:%s", new_ccname); -+ client->store.filename = NULL; -+#else -+ xasprintf(&client->store.envval, "FILE:%s", new_ccname); -+ client->store.filename = xstrdup(new_ccname); -+#endif - - #ifdef USE_PAM - if (options.use_pam) - do_pam_putenv(client->store.envvar, client->store.envval); - #endif - - krb5_cc_close(krb_context, ccache); - - return; - } - -+int -+ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store, -+ ssh_gssapi_client *client) -+{ -+ krb5_ccache ccache = NULL; -+ krb5_principal principal = NULL; -+ char *name = NULL; -+ krb5_error_code problem; -+ OM_uint32 maj_status, min_status; -+ -+ if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) { -+ logit("krb5_cc_resolve(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ return 0; -+ } -+ -+ /* Find out who the principal in this cache is */ -+ if ((problem = krb5_cc_get_principal(krb_context, ccache, -+ &principal))) { -+ logit("krb5_cc_get_principal(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ if ((problem = krb5_unparse_name(krb_context, principal, &name))) { -+ logit("krb5_unparse_name(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ krb5_free_principal(krb_context, principal); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ -+ if (strcmp(name,client->exportedname.value)!=0) { -+ debug("Name in local credentials cache differs. Not storing"); -+ krb5_free_principal(krb_context, principal); -+ krb5_cc_close(krb_context, ccache); -+ krb5_free_unparsed_name(krb_context, name); -+ return 0; -+ } -+ krb5_free_unparsed_name(krb_context, name); -+ -+ /* Name matches, so lets get on with it! */ -+ -+ if ((problem = krb5_cc_initialize(krb_context, ccache, principal))) { -+ logit("krb5_cc_initialize(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ krb5_free_principal(krb_context, principal); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ krb5_free_principal(krb_context, principal); -+ -+ if ((maj_status = gss_krb5_copy_ccache(&min_status, client->creds, -+ ccache))) { -+ logit("gss_krb5_copy_ccache() failed. Sorry!"); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ return 1; -+} -+ - ssh_gssapi_mech gssapi_kerberos_mech = { - "toWM5Slw5Ew8Mqkay+al2g==", - "Kerberos", - {9, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02"}, - NULL, - &ssh_gssapi_krb5_userok, - NULL, -- &ssh_gssapi_krb5_storecreds -+ &ssh_gssapi_krb5_storecreds, -+ &ssh_gssapi_krb5_updatecreds - }; - - #endif /* KRB5 */ - - #endif /* GSSAPI */ -diff --git a/openssh-6.6p1/gss-serv.c b/openssh-6.6p1/gss-serv.c ---- a/openssh-6.6p1/gss-serv.c -+++ b/openssh-6.6p1/gss-serv.c -@@ -1,12 +1,12 @@ - /* $OpenBSD: gss-serv.c,v 1.26 2014/02/26 20:28:44 djm Exp $ */ - - /* -- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. -+ * Copyright (c) 2001-2009 Simon Wilkinson. 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 -@@ -40,25 +40,30 @@ - #include "buffer.h" - #include "key.h" - #include "hostfile.h" - #include "auth.h" - #include "log.h" - #include "channels.h" +Index: openssh-7.1p2/gss-serv.c +=================================================================== +--- openssh-7.1p2.orig/gss-serv.c ++++ openssh-7.1p2/gss-serv.c +@@ -45,17 +45,19 @@ #include "session.h" #include "misc.h" -+#include "servconf.h" + #include "servconf.h" +#include "uidswap.h" #include "ssh-gss.h" +#include "monitor_wrap.h" -+ -+extern ServerOptions options; + + extern ServerOptions options; static ssh_gssapi_client gssapi_client = { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, - GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL, NULL}}; -+ GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME, NULL, {NULL, NULL, NULL, NULL, NULL}, 0, 0}; ++ GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME, {NULL, NULL, NULL}, 0, 0}; ssh_gssapi_mech gssapi_null_mech = - { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL}; @@ -1066,71 +537,7 @@ diff --git a/openssh-6.6p1/gss-serv.c b/openssh-6.6p1/gss-serv.c #ifdef KRB5 extern ssh_gssapi_mech gssapi_kerberos_mech; - #endif - - ssh_gssapi_mech* supported_mechs[]= { - #ifdef KRB5 - &gssapi_kerberos_mech, -@@ -95,59 +100,91 @@ ssh_gssapi_test_oid_supported(OM_uint32 - /* Privileged (called from ssh_gssapi_server_ctx) */ - static OM_uint32 - ssh_gssapi_acquire_cred(Gssctxt *ctx) - { - OM_uint32 status; - char lname[MAXHOSTNAMELEN]; - gss_OID_set oidset; - -- gss_create_empty_oid_set(&status, &oidset); -- gss_add_oid_set_member(&status, ctx->oid, &oidset); -+ if (options.gss_strict_acceptor) { -+ gss_create_empty_oid_set(&status, &oidset); -+ gss_add_oid_set_member(&status, ctx->oid, &oidset); - -- if (gethostname(lname, MAXHOSTNAMELEN)) { -- gss_release_oid_set(&status, &oidset); -- return (-1); -- } -+ if (gethostname(lname, MAXHOSTNAMELEN)) { -+ gss_release_oid_set(&status, &oidset); -+ return (-1); -+ } - -- if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) { -+ if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) { -+ gss_release_oid_set(&status, &oidset); -+ return (ctx->major); -+ } -+ -+ if ((ctx->major = gss_acquire_cred(&ctx->minor, -+ ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, -+ NULL, NULL))) -+ ssh_gssapi_error(ctx); -+ - gss_release_oid_set(&status, &oidset); - return (ctx->major); -+ } else { -+ ctx->name = GSS_C_NO_NAME; -+ ctx->creds = GSS_C_NO_CREDENTIAL; - } -- -- if ((ctx->major = gss_acquire_cred(&ctx->minor, -- ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, NULL, NULL))) -- ssh_gssapi_error(ctx); -- -- gss_release_oid_set(&status, &oidset); -- return (ctx->major); -+ return GSS_S_COMPLETE; - } - - /* Privileged */ - OM_uint32 - ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid) - { - if (*ctx) - ssh_gssapi_delete_ctx(ctx); - ssh_gssapi_build_ctx(ctx); - ssh_gssapi_set_oid(*ctx, oid); - return (ssh_gssapi_acquire_cred(*ctx)); +@@ -142,6 +144,29 @@ ssh_gssapi_server_ctx(Gssctxt **ctx, gss } /* Unprivileged */ @@ -1160,9 +567,7 @@ diff --git a/openssh-6.6p1/gss-serv.c b/openssh-6.6p1/gss-serv.c void ssh_gssapi_supported_oids(gss_OID_set *oidset) { - int i = 0; - OM_uint32 min_status; - int present; +@@ -151,7 +176,9 @@ ssh_gssapi_supported_oids(gss_OID_set *o gss_OID_set supported; gss_create_empty_oid_set(&min_status, oidset); @@ -1173,25 +578,14 @@ diff --git a/openssh-6.6p1/gss-serv.c b/openssh-6.6p1/gss-serv.c while (supported_mechs[i]->name != NULL) { if (GSS_ERROR(gss_test_oid_set_member(&min_status, - &supported_mechs[i]->oid, supported, &present))) - present = 0; - if (present) - gss_add_oid_set_member(&min_status, - &supported_mechs[i]->oid, oidset); -@@ -263,32 +300,79 @@ ssh_gssapi_parse_ename(Gssctxt *ctx, gss - /* Extract the client details from a given context. This can only reliably - * be called once for a context */ - - /* Privileged (called from accept_secure_ctx) */ - OM_uint32 +@@ -277,8 +304,48 @@ OM_uint32 ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) { int i = 0; + int equal = 0; + gss_name_t new_name = GSS_C_NO_NAME; + gss_buffer_desc ename = GSS_C_EMPTY_BUFFER; - -- gss_buffer_desc ename; ++ + if (options.gss_store_rekey && client->used && ctx->client_creds) { + if (client->mech->oid.length != ctx->oid->length || + (memcmp(client->mech->oid.elements, @@ -1206,7 +600,8 @@ diff --git a/openssh-6.6p1/gss-serv.c b/openssh-6.6p1/gss-serv.c + ssh_gssapi_error(ctx); + return (ctx->major); + } -+ + +- gss_buffer_desc ename; + ctx->major = gss_compare_name(&ctx->minor, client->name, + new_name, &equal); + @@ -1233,14 +628,7 @@ diff --git a/openssh-6.6p1/gss-serv.c b/openssh-6.6p1/gss-serv.c client->mech = NULL; - while (supported_mechs[i]->name != NULL) { - if (supported_mechs[i]->oid.length == ctx->oid->length && - (memcmp(supported_mechs[i]->oid.elements, - ctx->oid->elements, ctx->oid->length) == 0)) - client->mech = supported_mechs[i]; - i++; - } - +@@ -293,6 +360,13 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g if (client->mech == NULL) return GSS_S_FAILURE; @@ -1254,17 +642,7 @@ diff --git a/openssh-6.6p1/gss-serv.c b/openssh-6.6p1/gss-serv.c if ((ctx->major = gss_display_name(&ctx->minor, ctx->client, &client->displayname, NULL))) { ssh_gssapi_error(ctx); - return (ctx->major); - } - - if ((ctx->major = gss_export_name(&ctx->minor, ctx->client, - &ename))) { -@@ -296,16 +380,18 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g - return (ctx->major); - } - - if ((ctx->major = ssh_gssapi_parse_ename(ctx,&ename, - &client->exportedname))) { +@@ -310,6 +384,8 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g return (ctx->major); } @@ -1273,18 +651,34 @@ diff --git a/openssh-6.6p1/gss-serv.c b/openssh-6.6p1/gss-serv.c /* We can't copy this structure, so we just move the pointer to it */ client->creds = ctx->client_creds; ctx->client_creds = GSS_C_NO_CREDENTIAL; - return (ctx->major); - } - - /* As user - called on fatal/exit */ +@@ -320,11 +396,20 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g void -@@ -343,45 +429,124 @@ ssh_gssapi_do_child(char ***envp, u_int - gssapi_client.store.envval); - child_set_env(envp, envsizep, gssapi_client.store.envvar, - gssapi_client.store.envval); + ssh_gssapi_cleanup_creds(void) + { +- if (gssapi_client.store.filename != NULL) { +- /* Unlink probably isn't sufficient */ +- debug("removing gssapi cred file\"%s\"", +- gssapi_client.store.filename); +- unlink(gssapi_client.store.filename); ++ krb5_ccache ccache = NULL; ++ krb5_error_code problem; ++ ++ if (gssapi_client.store.data != NULL) { ++ if ((problem = krb5_cc_resolve(gssapi_client.store.data, gssapi_client.store.envval, &ccache))) { ++ debug("%s: krb5_cc_resolve(): %.100s", __func__, ++ krb5_get_err_text(gssapi_client.store.data, problem)); ++ } else if ((problem = krb5_cc_destroy(gssapi_client.store.data, ccache))) { ++ debug("%s: krb5_cc_resolve(): %.100s", __func__, ++ krb5_get_err_text(gssapi_client.store.data, problem)); ++ } else { ++ krb5_free_context(gssapi_client.store.data); ++ gssapi_client.store.data = NULL; ++ } } } +@@ -357,7 +442,7 @@ ssh_gssapi_do_child(char ***envp, u_int + /* Privileged */ int -ssh_gssapi_userok(char *user) @@ -1292,9 +686,7 @@ diff --git a/openssh-6.6p1/gss-serv.c b/openssh-6.6p1/gss-serv.c { OM_uint32 lmin; - if (gssapi_client.exportedname.length == 0 || - gssapi_client.exportedname.value == NULL) { - debug("No suitable client data"); +@@ -367,9 +452,11 @@ ssh_gssapi_userok(char *user) return 0; } if (gssapi_client.mech && gssapi_client.mech->userok) @@ -1304,21 +696,15 @@ diff --git a/openssh-6.6p1/gss-serv.c b/openssh-6.6p1/gss-serv.c + gssapi_client.store.owner = pw; return 1; - else { -+ } else { ++ } else { /* Destroy delegated credentials if userok fails */ gss_release_buffer(&lmin, &gssapi_client.displayname); gss_release_buffer(&lmin, &gssapi_client.exportedname); - gss_release_cred(&lmin, &gssapi_client.creds); - explicit_bzero(&gssapi_client, - sizeof(ssh_gssapi_client)); - return 0; - } - else - debug("ssh_gssapi_userok: Unknown GSSAPI mechanism"); +@@ -383,14 +470,90 @@ ssh_gssapi_userok(char *user) return (0); } - /* Privileged */ +-/* Privileged */ -OM_uint32 -ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) +/* These bits are only used for rekeying. The unpriviledged child is running @@ -1411,15 +797,142 @@ diff --git a/openssh-6.6p1/gss-serv.c b/openssh-6.6p1/gss-serv.c } #endif -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 -@@ -47,16 +47,20 @@ - #include "mac.h" - #include "match.h" - #include "dispatch.h" - #include "monitor.h" - #include "roaming.h" +Index: openssh-7.1p2/gss-serv-krb5.c +=================================================================== +--- openssh-7.1p2.orig/gss-serv-krb5.c ++++ openssh-7.1p2/gss-serv-krb5.c +@@ -121,7 +121,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl + krb5_error_code problem; + krb5_principal princ; + OM_uint32 maj_status, min_status; +- int len; ++ const char *new_ccname, *new_cctype; + const char *errmsg; + + if (client->creds == NULL) { +@@ -181,11 +181,26 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl + return; + } + +- client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache)); ++ new_cctype = krb5_cc_get_type(krb_context, ccache); ++ new_ccname = krb5_cc_get_name(krb_context, ccache); ++ + client->store.envvar = "KRB5CCNAME"; +- len = strlen(client->store.filename) + 6; +- client->store.envval = xmalloc(len); +- snprintf(client->store.envval, len, "FILE:%s", client->store.filename); ++#ifdef USE_CCAPI ++ xasprintf(&client->store.envval, "API:%s", new_ccname); ++ client->store.filename = NULL; ++#else ++ if (new_ccname[0] == ':') ++ new_ccname++; ++ xasprintf(&client->store.envval, "%s:%s", new_cctype, new_ccname); ++ if (strcmp(new_cctype, "DIR") == 0) { ++ char *p; ++ p = strrchr(client->store.envval, '/'); ++ if (p) ++ *p = '\0'; ++ } ++ if ((strcmp(new_cctype, "FILE") == 0) || (strcmp(new_cctype, "DIR") == 0)) ++ client->store.filename = xstrdup(new_ccname); ++#endif + + #ifdef USE_PAM + if (options.use_pam) +@@ -194,9 +209,76 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl + + krb5_cc_close(krb_context, ccache); + ++ client->store.data = krb_context; ++ + return; + } + ++int ++ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store, ++ ssh_gssapi_client *client) ++{ ++ krb5_ccache ccache = NULL; ++ krb5_principal principal = NULL; ++ char *name = NULL; ++ krb5_error_code problem; ++ OM_uint32 maj_status, min_status; ++ ++ if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) { ++ logit("krb5_cc_resolve(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ return 0; ++ } ++ ++ /* Find out who the principal in this cache is */ ++ if ((problem = krb5_cc_get_principal(krb_context, ccache, ++ &principal))) { ++ logit("krb5_cc_get_principal(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ if ((problem = krb5_unparse_name(krb_context, principal, &name))) { ++ logit("krb5_unparse_name(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ krb5_free_principal(krb_context, principal); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ ++ if (strcmp(name,client->exportedname.value)!=0) { ++ debug("Name in local credentials cache differs. Not storing"); ++ krb5_free_principal(krb_context, principal); ++ krb5_cc_close(krb_context, ccache); ++ krb5_free_unparsed_name(krb_context, name); ++ return 0; ++ } ++ krb5_free_unparsed_name(krb_context, name); ++ ++ /* Name matches, so lets get on with it! */ ++ ++ if ((problem = krb5_cc_initialize(krb_context, ccache, principal))) { ++ logit("krb5_cc_initialize(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ krb5_free_principal(krb_context, principal); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ krb5_free_principal(krb_context, principal); ++ ++ if ((maj_status = gss_krb5_copy_ccache(&min_status, client->creds, ++ ccache))) { ++ logit("gss_krb5_copy_ccache() failed. Sorry!"); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ return 1; ++} ++ + ssh_gssapi_mech gssapi_kerberos_mech = { + "toWM5Slw5Ew8Mqkay+al2g==", + "Kerberos", +@@ -204,7 +286,8 @@ ssh_gssapi_mech gssapi_kerberos_mech = { + NULL, + &ssh_gssapi_krb5_userok, + NULL, +- &ssh_gssapi_krb5_storecreds ++ &ssh_gssapi_krb5_storecreds, ++ &ssh_gssapi_krb5_updatecreds + }; + + #endif /* KRB5 */ +Index: openssh-7.1p2/kex.c +=================================================================== +--- openssh-7.1p2.orig/kex.c ++++ openssh-7.1p2/kex.c +@@ -56,6 +56,10 @@ #include "digest.h" #include "audit.h" @@ -1430,106 +943,36 @@ diff --git a/openssh-6.6p1/kex.c b/openssh-6.6p1/kex.c #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 - -@@ -86,16 +90,21 @@ static const struct kexalg kexalgs[] = { - { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1, - SSH_DIGEST_SHA512 }, - # endif - #endif - { KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, - #ifdef HAVE_EVP_SHA256 +@@ -96,6 +100,11 @@ static const struct kexalg kexalgs[] = { + #if defined(HAVE_EVP_SHA256) || !defined(WITH_OPENSSL) { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, - #endif + #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ +#ifdef GSSAPI -+ { KEX_GSS_GEX_SHA1_ID, KEX_GSS_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, -+ { KEX_GSS_GRP1_SHA1_ID, KEX_GSS_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, -+ { KEX_GSS_GRP14_SHA1_ID, KEX_GSS_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, ++ { KEX_GSS_GEX_SHA1_ID, KEX_GSS_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, ++ { KEX_GSS_GRP1_SHA1_ID, KEX_GSS_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, ++ { KEX_GSS_GRP14_SHA1_ID, KEX_GSS_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, +#endif { NULL, -1, -1, -1}, }; - char * - kex_alg_list(char sep) - { - char *ret = NULL; - size_t nlen, rlen = 0; -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 -@@ -71,16 +71,19 @@ enum kex_modes { - - enum kex_exchange { - KEX_DH_GRP1_SHA1, - KEX_DH_GRP14_SHA1, - KEX_DH_GEX_SHA1, - KEX_DH_GEX_SHA256, - KEX_ECDH_SHA2, - KEX_C25519_SHA256, -+ KEX_GSS_GRP1_SHA1, -+ KEX_GSS_GRP14_SHA1, -+ KEX_GSS_GEX_SHA1, - KEX_MAX - }; - - #define KEX_INIT_SENT 0x0001 - - typedef struct Kex Kex; - typedef struct Mac Mac; - typedef struct Comp Comp; -@@ -130,16 +133,22 @@ struct Kex { - int kex_type; - int roaming; - Buffer my; - Buffer peer; - sig_atomic_t done; - int flags; - int hash_alg; - int ec_nid; +@@ -129,6 +138,12 @@ kex_alg_by_name(const char *name) + for (k = kexalgs; k->name != NULL; k++) { + if (strcmp(k->name, name) == 0) + return k; +#ifdef GSSAPI -+ int gss_deleg_creds; -+ int gss_trust_dns; -+ char *gss_host; -+ char *gss_client; ++ if (strncmp(name, "gss-", 4) == 0) { ++ if (strncmp(k->name, name, strlen(k->name)) == 0) ++ return k; ++ } +#endif - char *client_version_string; - char *server_version_string; - int (*verify_host_key)(Key *); - Key *(*load_host_public_key)(int); - Key *(*load_host_private_key)(int); - int (*host_key_index)(Key *); - void (*sign)(Key *, Key *, u_char **, u_int *, u_char *, u_int); - void (*kex[KEX_MAX])(Kex *); -@@ -163,16 +172,21 @@ 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); -+ -+#ifdef GSSAPI -+void kexgss_client(Kex *); -+void kexgss_server(Kex *); -+#endif - - 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 *); -diff --git a/openssh-6.6p1/kexgssc.c b/openssh-6.6p1/kexgssc.c -new file mode 100644 + } + return NULL; + } +Index: openssh-7.1p2/kexgssc.c +=================================================================== --- /dev/null -+++ b/openssh-6.6p1/kexgssc.c -@@ -0,0 +1,334 @@ ++++ openssh-7.1p2/kexgssc.c +@@ -0,0 +1,338 @@ +/* + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. + * @@ -1574,22 +1017,23 @@ new file mode 100644 +#include "log.h" +#include "packet.h" +#include "dh.h" ++#include "digest.h" + +#include "ssh-gss.h" + -+void -+kexgss_client(Kex *kex) { ++int ++kexgss_client(struct ssh *ssh) { + gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; + gss_buffer_desc recv_tok, gssbuf, msg_tok, *token_ptr; + Gssctxt *ctxt; + OM_uint32 maj_status, min_status, ret_flags; -+ u_int klen, kout, slen = 0, hashlen, strlen; ++ u_int klen, kout, slen = 0, strlen; + DH *dh; + BIGNUM *dh_server_pub = NULL; + BIGNUM *shared_secret = NULL; + BIGNUM *p = NULL; + BIGNUM *g = NULL; -+ u_char *kbuf, *hash; ++ u_char *kbuf; + u_char *serverhostkey = NULL; + u_char *empty = ""; + char *msg; @@ -1597,21 +1041,23 @@ new file mode 100644 + int type = 0; + int first = 1; + int nbits = 0, min = DH_GRP_MIN, max = DH_GRP_MAX; ++ u_char hash[SSH_DIGEST_MAX_LENGTH]; ++ size_t hashlen; + + /* Initialise our GSSAPI world */ + ssh_gssapi_build_ctx(&ctxt); -+ if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type) ++ if (ssh_gssapi_id_kex(ctxt, ssh->kex->name, ssh->kex->kex_type) + == GSS_C_NO_OID) + fatal("Couldn't identify host exchange"); + -+ if (ssh_gssapi_import_name(ctxt, kex->gss_host)) ++ if (ssh_gssapi_import_name(ctxt, ssh->kex->gss_host)) + fatal("Couldn't import hostname"); + -+ if (kex->gss_client && -+ ssh_gssapi_client_identity(ctxt, kex->gss_client)) ++ if (ssh->kex->gss_client && ++ ssh_gssapi_client_identity(ctxt, ssh->kex->gss_client)) + fatal("Couldn't acquire client credentials"); + -+ switch (kex->kex_type) { ++ switch (ssh->kex->kex_type) { + case KEX_GSS_GRP1_SHA1: + dh = dh_new_group1(); + break; @@ -1620,7 +1066,7 @@ new file mode 100644 + break; + case KEX_GSS_GEX_SHA1: + debug("Doing group exchange\n"); -+ nbits = dh_estimate(kex->we_need * 8); ++ nbits = dh_estimate(ssh->kex->we_need * 8); + packet_start(SSH2_MSG_KEXGSS_GROUPREQ); + packet_put_int(min); + packet_put_int(nbits); @@ -1645,11 +1091,11 @@ new file mode 100644 + dh = dh_new_group(g, p); + break; + default: -+ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); ++ fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type); + } + + /* Step 1 - e is dh->pub_key */ -+ dh_gen_key(dh, kex->we_need * 8); ++ dh_gen_key(dh, ssh->kex->we_need * 8); + + /* This is f, we initialise it now to make life easier */ + dh_server_pub = BN_new(); @@ -1662,7 +1108,7 @@ new file mode 100644 + debug("Calling gss_init_sec_context"); + + maj_status = ssh_gssapi_init_ctx(ctxt, -+ kex->gss_deleg_creds, token_ptr, &send_tok, ++ ssh->kex->gss_deleg_creds, token_ptr, &send_tok, + &ret_flags); + + if (GSS_ERROR(maj_status)) { @@ -1782,7 +1228,7 @@ new file mode 100644 + klen = DH_size(dh); + kbuf = xmalloc(klen); + kout = DH_compute_key(kbuf, dh_server_pub, dh); -+ if (kout < 0) ++ if ((int)kout < 0) + fatal("DH_compute_key: failed"); + + shared_secret = BN_new(); @@ -1795,38 +1241,39 @@ new file mode 100644 + memset(kbuf, 0, klen); + free(kbuf); + -+ switch (kex->kex_type) { ++ hashlen = sizeof(hash); ++ switch (ssh->kex->kex_type) { + case KEX_GSS_GRP1_SHA1: + case KEX_GSS_GRP14_SHA1: -+ kex_dh_hash( kex->client_version_string, -+ kex->server_version_string, -+ buffer_ptr(&kex->my), buffer_len(&kex->my), -+ buffer_ptr(&kex->peer), buffer_len(&kex->peer), ++ kex_dh_hash( ssh->kex->client_version_string, ++ ssh->kex->server_version_string, ++ buffer_ptr(ssh->kex->my), buffer_len(ssh->kex->my), ++ buffer_ptr(ssh->kex->peer), buffer_len(ssh->kex->peer), + (serverhostkey ? serverhostkey : empty), slen, + dh->pub_key, /* e */ + dh_server_pub, /* f */ + shared_secret, /* K */ -+ &hash, &hashlen ++ hash, &hashlen + ); + break; + case KEX_GSS_GEX_SHA1: + kexgex_hash( -+ kex->hash_alg, -+ kex->client_version_string, -+ kex->server_version_string, -+ buffer_ptr(&kex->my), buffer_len(&kex->my), -+ buffer_ptr(&kex->peer), buffer_len(&kex->peer), ++ ssh->kex->hash_alg, ++ ssh->kex->client_version_string, ++ ssh->kex->server_version_string, ++ buffer_ptr(ssh->kex->my), buffer_len(ssh->kex->my), ++ buffer_ptr(ssh->kex->peer), buffer_len(ssh->kex->peer), + (serverhostkey ? serverhostkey : empty), slen, + min, nbits, max, + dh->p, dh->g, + dh->pub_key, + dh_server_pub, + shared_secret, -+ &hash, &hashlen ++ hash, &hashlen + ); + break; + default: -+ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); ++ fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type); + } + + gssbuf.value = hash; @@ -1844,13 +1291,13 @@ new file mode 100644 + BN_clear_free(dh_server_pub); + + /* save session id */ -+ if (kex->session_id == NULL) { -+ kex->session_id_len = hashlen; -+ kex->session_id = xmalloc(kex->session_id_len); -+ memcpy(kex->session_id, hash, kex->session_id_len); ++ if (ssh->kex->session_id == NULL) { ++ ssh->kex->session_id_len = hashlen; ++ ssh->kex->session_id = xmalloc(ssh->kex->session_id_len); ++ memcpy(ssh->kex->session_id, hash, ssh->kex->session_id_len); + } + -+ if (kex->gss_deleg_creds) ++ if (ssh->kex->gss_deleg_creds) + ssh_gssapi_credentials_updated(ctxt); + + if (gss_kex_context == NULL) @@ -1858,17 +1305,17 @@ new file mode 100644 + else + ssh_gssapi_delete_ctx(&ctxt); + -+ kex_derive_keys_bn(kex, hash, hashlen, shared_secret); ++ kex_derive_keys_bn(ssh, hash, hashlen, shared_secret); + BN_clear_free(shared_secret); -+ kex_finish(kex); ++ return kex_send_newkeys(ssh); +} + +#endif /* GSSAPI */ -diff --git a/openssh-6.6p1/kexgsss.c b/openssh-6.6p1/kexgsss.c -new file mode 100644 +Index: openssh-7.1p2/kexgsss.c +=================================================================== --- /dev/null -+++ b/openssh-6.6p1/kexgsss.c -@@ -0,0 +1,288 @@ ++++ openssh-7.1p2/kexgsss.c +@@ -0,0 +1,295 @@ +/* + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. + * @@ -1913,12 +1360,15 @@ new file mode 100644 +#include "dh.h" +#include "ssh-gss.h" +#include "monitor_wrap.h" ++#include "misc.h" /* servconf.h needs misc.h for struct ForwardOptions */ +#include "servconf.h" ++#include "ssh-gss.h" ++#include "digest.h" + +extern ServerOptions options; + -+void -+kexgss_server(Kex *kex) ++int ++kexgss_server(struct ssh *ssh) +{ + OM_uint32 maj_status, min_status; + @@ -1933,8 +1383,8 @@ new file mode 100644 + gss_buffer_desc gssbuf, recv_tok, msg_tok; + gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; + Gssctxt *ctxt = NULL; -+ u_int slen, klen, kout, hashlen; -+ u_char *kbuf, *hash; ++ u_int slen, klen, kout; ++ u_char *kbuf; + DH *dh; + int min = -1, max = -1, nbits = -1; + BIGNUM *shared_secret = NULL; @@ -1942,6 +1392,8 @@ new file mode 100644 + int type = 0; + gss_OID oid; + char *mechs; ++ u_char hash[SSH_DIGEST_MAX_LENGTH]; ++ size_t hashlen; + + /* Initialise GSSAPI */ + @@ -1953,8 +1405,8 @@ new file mode 100644 + if ((mechs = ssh_gssapi_server_mechanisms())) + free(mechs); + -+ debug2("%s: Identifying %s", __func__, kex->name); -+ oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type); ++ debug2("%s: Identifying %s", __func__, ssh->kex->name); ++ oid = ssh_gssapi_id_kex(NULL, ssh->kex->name, ssh->kex->kex_type); + if (oid == GSS_C_NO_OID) + fatal("Unknown gssapi mechanism"); + @@ -1963,7 +1415,7 @@ new file mode 100644 + if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) + fatal("Unable to acquire credentials for the server"); + -+ switch (kex->kex_type) { ++ switch (ssh->kex->kex_type) { + case KEX_GSS_GRP1_SHA1: + dh = dh_new_group1(); + break; @@ -1994,10 +1446,10 @@ new file mode 100644 + packet_write_wait(); + break; + default: -+ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); ++ fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type); + } + -+ dh_gen_key(dh, kex->we_need * 8); ++ dh_gen_key(dh, ssh->kex->we_need * 8); + + do { + debug("Wait SSH2_MSG_GSSAPI_INIT"); @@ -2067,7 +1519,7 @@ new file mode 100644 + klen = DH_size(dh); + kbuf = xmalloc(klen); + kout = DH_compute_key(kbuf, dh_client_pub, dh); -+ if (kout < 0) ++ if ((int)kout < 0) + fatal("DH_compute_key: failed"); + + shared_secret = BN_new(); @@ -2080,43 +1532,44 @@ new file mode 100644 + memset(kbuf, 0, klen); + free(kbuf); + -+ switch (kex->kex_type) { ++ hashlen = sizeof(hash); ++ switch (ssh->kex->kex_type) { + case KEX_GSS_GRP1_SHA1: + case KEX_GSS_GRP14_SHA1: + kex_dh_hash( -+ kex->client_version_string, kex->server_version_string, -+ buffer_ptr(&kex->peer), buffer_len(&kex->peer), -+ buffer_ptr(&kex->my), buffer_len(&kex->my), ++ ssh->kex->client_version_string, ssh->kex->server_version_string, ++ buffer_ptr(ssh->kex->peer), buffer_len(ssh->kex->peer), ++ buffer_ptr(ssh->kex->my), buffer_len(ssh->kex->my), + NULL, 0, /* Change this if we start sending host keys */ + dh_client_pub, dh->pub_key, shared_secret, -+ &hash, &hashlen ++ hash, &hashlen + ); + break; + case KEX_GSS_GEX_SHA1: + kexgex_hash( -+ kex->hash_alg, -+ kex->client_version_string, kex->server_version_string, -+ buffer_ptr(&kex->peer), buffer_len(&kex->peer), -+ buffer_ptr(&kex->my), buffer_len(&kex->my), ++ ssh->kex->hash_alg, ++ ssh->kex->client_version_string, ssh->kex->server_version_string, ++ buffer_ptr(ssh->kex->peer), buffer_len(ssh->kex->peer), ++ buffer_ptr(ssh->kex->my), buffer_len(ssh->kex->my), + NULL, 0, + min, nbits, max, + dh->p, dh->g, + dh_client_pub, + dh->pub_key, + shared_secret, -+ &hash, &hashlen ++ hash, &hashlen + ); + break; + default: -+ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); ++ fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type); + } + + BN_clear_free(dh_client_pub); + -+ if (kex->session_id == NULL) { -+ kex->session_id_len = hashlen; -+ kex->session_id = xmalloc(kex->session_id_len); -+ memcpy(kex->session_id, hash, kex->session_id_len); ++ if (ssh->kex->session_id == NULL) { ++ ssh->kex->session_id_len = hashlen; ++ ssh->kex->session_id = xmalloc(ssh->kex->session_id_len); ++ memcpy(ssh->kex->session_id, hash, ssh->kex->session_id_len); + } + + gssbuf.value = hash; @@ -2147,68 +1600,83 @@ new file mode 100644 + + DH_free(dh); + -+ kex_derive_keys_bn(kex, hash, hashlen, shared_secret); ++ kex_derive_keys_bn(ssh, hash, hashlen, shared_secret); + BN_clear_free(shared_secret); -+ kex_finish(kex); ++ kex_send_newkeys(ssh); + + /* If this was a rekey, then save out any delegated credentials we + * just exchanged. */ + if (options.gss_store_rekey) + ssh_gssapi_rekey_creds(); ++ return 0; +} +#endif /* GSSAPI */ -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 -@@ -1053,16 +1053,18 @@ static const struct keytype keytypes[] = - # endif - #endif /* OPENSSL_HAS_ECC */ - { "ssh-rsa-cert-v00@openssh.com", "RSA-CERT-V00", - KEY_RSA_CERT_V00, 0, 1 }, - { "ssh-dss-cert-v00@openssh.com", "DSA-CERT-V00", - KEY_DSA_CERT_V00, 0, 1 }, - { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", - KEY_ED25519_CERT, 0, 1 }, -+ { "null", "null", -+ KEY_NULL, 0, 0 }, - { NULL, NULL, -1, -1, 0 } +Index: openssh-7.1p2/kex.h +=================================================================== +--- openssh-7.1p2.orig/kex.h ++++ openssh-7.1p2/kex.h +@@ -93,6 +93,11 @@ enum kex_exchange { + KEX_DH_GEX_SHA256, + KEX_ECDH_SHA2, + KEX_C25519_SHA256, ++#ifdef GSSAPI ++ KEX_GSS_GRP1_SHA1, ++ KEX_GSS_GRP14_SHA1, ++ KEX_GSS_GEX_SHA1, ++#endif + KEX_MAX }; - const char * - key_type(const Key *k) - { - const struct keytype *kt; +@@ -139,6 +144,12 @@ struct kex { + u_int flags; + int hash_alg; + int ec_nid; ++#ifdef GSSAPI ++ int gss_deleg_creds; ++ int gss_trust_dns; ++ char *gss_host; ++ char *gss_client; ++#endif + char *client_version_string; + char *server_version_string; + char *failed_choice; +@@ -186,6 +197,10 @@ int kexecdh_client(struct ssh *); + int kexecdh_server(struct ssh *); + int kexc25519_client(struct ssh *); + int kexc25519_server(struct ssh *); ++#ifdef GSSAPI ++int kexgss_client(struct ssh *); ++int kexgss_server(struct ssh *); ++#endif -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 -@@ -41,16 +41,17 @@ enum types { - KEY_ECDSA, - KEY_ED25519, - KEY_RSA_CERT, - KEY_DSA_CERT, - KEY_ECDSA_CERT, - KEY_ED25519_CERT, - KEY_RSA_CERT_V00, - KEY_DSA_CERT_V00, -+ KEY_NULL, - KEY_UNSPEC - }; - enum fp_type { - SSH_FP_SHA1, - SSH_FP_MD5, - SSH_FP_SHA256 - }; - enum fp_rep { -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 -@@ -173,16 +173,18 @@ int mm_answer_pam_respond(int, Buffer *) - int mm_answer_pam_free_ctx(int, Buffer *); - #endif + void newkeys_destroy(struct newkeys *newkeys); - #ifdef GSSAPI - int mm_answer_gss_setup_ctx(int, Buffer *); +Index: openssh-7.1p2/Makefile.in +=================================================================== +--- openssh-7.1p2.orig/Makefile.in ++++ openssh-7.1p2/Makefile.in +@@ -84,6 +84,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ + readpass.o rsa.o ttymodes.o xmalloc.o addrmatch.o \ + atomicio.o key.o dispatch.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 \ ++ kexgssc.o \ + msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ + ssh-pkcs11.o smult_curve25519_ref.o \ + poly1305.o chacha.o cipher-chachapoly.o \ +@@ -105,7 +106,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passw + auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \ + auth2-none.o auth2-passwd.o auth2-pubkey.o \ + monitor_mm.o monitor.o monitor_wrap.o auth-krb5.o \ +- auth2-gss.o gss-serv.o gss-serv-krb5.o \ ++ auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.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 \ +Index: openssh-7.1p2/monitor.c +=================================================================== +--- openssh-7.1p2.orig/monitor.c ++++ openssh-7.1p2/monitor.c +@@ -160,6 +160,8 @@ 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 *); @@ -2217,17 +1685,7 @@ diff --git a/openssh-6.6p1/monitor.c b/openssh-6.6p1/monitor.c #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 *); -@@ -254,21 +256,28 @@ struct mon_table mon_dispatch_proto20[] - #endif - {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed}, - {MONITOR_REQ_KEYVERIFY, MON_AUTH, mm_answer_keyverify}, - #ifdef GSSAPI - {MONITOR_REQ_GSSSETUP, MON_ISAUTH, mm_answer_gss_setup_ctx}, +@@ -246,11 +248,18 @@ struct mon_table mon_dispatch_proto20[] {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx}, {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok}, {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic}, @@ -2243,20 +1701,10 @@ diff --git a/openssh-6.6p1/monitor.c b/openssh-6.6p1/monitor.c + {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign}, + {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds}, +#endif + #ifdef WITH_OPENSSL {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}, -@@ -381,16 +390,20 @@ monitor_child_preauth(Authctxt *_authctx - authctxt->loginmsg = &loginmsg; - - if (compat20) { - mon_dispatch = mon_dispatch_proto20; - + #endif +@@ -379,6 +388,10 @@ monitor_child_preauth(Authctxt *_authctx /* Permit requests for moduli and signatures */ monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); @@ -2267,17 +1715,7 @@ diff --git a/openssh-6.6p1/monitor.c b/openssh-6.6p1/monitor.c } else { mon_dispatch = mon_dispatch_proto15; - monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1); - } - - /* The first few requests do not require asynchronous access */ - while (!authenticated) { -@@ -486,16 +499,20 @@ monitor_child_postauth(struct monitor *p - - if (compat20) { - mon_dispatch = mon_dispatch_postauth20; - - /* Permit requests for moduli and signatures */ +@@ -487,6 +500,10 @@ monitor_child_postauth(struct monitor *p monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); @@ -2288,20 +1726,10 @@ diff --git a/openssh-6.6p1/monitor.c b/openssh-6.6p1/monitor.c } else { mon_dispatch = mon_dispatch_postauth15; monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); - } - if (!no_pty_flag) { - monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); - monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1); - } -@@ -1909,16 +1926,23 @@ mm_get_kex(Buffer *m) - fatal("mm_get_get: internal error: bad session id"); - kex->we_need = buffer_get_int(m); - kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; - kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; - kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; - kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; - kex->kex[KEX_ECDH_SHA2] = kexecdh_server; - kex->kex[KEX_C25519_SHA256] = kexc25519_server; +@@ -1944,6 +1961,13 @@ monitor_apply_keystate(struct monitor *p + # endif + #endif /* WITH_OPENSSL */ + kex->kex[KEX_C25519_SHA256] = kexc25519_server; +#ifdef GSSAPI + if (options.gss_keyex) { + kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; @@ -2309,20 +1737,10 @@ diff --git a/openssh-6.6p1/monitor.c b/openssh-6.6p1/monitor.c + kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; + } +#endif - kex->server = 1; - kex->hostkey_type = buffer_get_int(m); - kex->kex_type = buffer_get_int(m); - blob = buffer_get_string(m, &bloblen); - buffer_init(&kex->my); - buffer_append(&kex->my, blob, bloblen); - free(blob); - blob = buffer_get_string(m, &bloblen); -@@ -2133,16 +2157,19 @@ monitor_reinit(struct monitor *mon) - #ifdef GSSAPI - int - mm_answer_gss_setup_ctx(int sock, Buffer *m) - { - gss_OID_desc goid; + kex->load_host_public_key=&get_hostkey_public_by_type; + kex->load_host_private_key=&get_hostkey_private_by_type; + kex->host_key_index=&get_hostkey_index; +@@ -2059,6 +2083,9 @@ mm_answer_gss_setup_ctx(int sock, Buffer OM_uint32 major; u_int len; @@ -2332,17 +1750,7 @@ diff --git a/openssh-6.6p1/monitor.c b/openssh-6.6p1/monitor.c goid.elements = buffer_get_string(m, &len); goid.length = len; - major = ssh_gssapi_server_ctx(&gsscontext, &goid); - - free(goid.elements); - - buffer_clear(m); -@@ -2160,16 +2187,19 @@ int - mm_answer_gss_accept_ctx(int sock, Buffer *m) - { - gss_buffer_desc in; - gss_buffer_desc out = GSS_C_EMPTY_BUFFER; - OM_uint32 major, minor; +@@ -2086,6 +2113,9 @@ mm_answer_gss_accept_ctx(int sock, Buffe OM_uint32 flags = 0; /* GSI needs this */ u_int len; @@ -2352,17 +1760,7 @@ diff --git a/openssh-6.6p1/monitor.c b/openssh-6.6p1/monitor.c in.value = buffer_get_string(m, &len); in.length = len; major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags); - free(in.value); - - buffer_clear(m); - buffer_put_int(m, major); - buffer_put_string(m, out.value, out.length); -@@ -2177,27 +2207,31 @@ mm_answer_gss_accept_ctx(int sock, Buffe - mm_request_send(sock, MONITOR_ANS_GSSSTEP, m); - - gss_release_buffer(&minor, &out); - - if (major == GSS_S_COMPLETE) { +@@ -2103,6 +2133,7 @@ mm_answer_gss_accept_ctx(int sock, Buffe monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0); monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); @@ -2370,11 +1768,7 @@ diff --git a/openssh-6.6p1/monitor.c b/openssh-6.6p1/monitor.c } return (0); } - - int - mm_answer_gss_checkmic(int sock, Buffer *m) - { - gss_buffer_desc gssbuf, mic; +@@ -2114,6 +2145,9 @@ mm_answer_gss_checkmic(int sock, Buffer OM_uint32 ret; u_int len; @@ -2384,17 +1778,7 @@ diff --git a/openssh-6.6p1/monitor.c b/openssh-6.6p1/monitor.c gssbuf.value = buffer_get_string(m, &len); gssbuf.length = len; mic.value = buffer_get_string(m, &len); - mic.length = len; - - ret = ssh_gssapi_checkmic(gsscontext, &gssbuf, &mic); - - free(gssbuf.value); -@@ -2214,29 +2248,101 @@ mm_answer_gss_checkmic(int sock, Buffer - return (0); - } - - int - mm_answer_gss_userok(int sock, Buffer *m) +@@ -2140,7 +2174,11 @@ mm_answer_gss_userok(int sock, Buffer *m { int authenticated; @@ -2407,12 +1791,7 @@ diff --git a/openssh-6.6p1/monitor.c b/openssh-6.6p1/monitor.c buffer_clear(m); buffer_put_int(m, authenticated); - - debug3("%s: sending result %d", __func__, authenticated); - mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m); - - auth_method = "gssapi-with-mic"; - +@@ -2153,6 +2191,74 @@ mm_answer_gss_userok(int sock, Buffer *m /* Monitor loop will terminate if authenticated */ return (authenticated); } @@ -2487,43 +1866,24 @@ diff --git a/openssh-6.6p1/monitor.c b/openssh-6.6p1/monitor.c #endif /* GSSAPI */ #ifdef SSH_AUDIT_EVENTS - int - mm_answer_audit_unsupported_body(int sock, Buffer *m) - { - int what; +Index: openssh-7.1p2/monitor.h +=================================================================== +--- openssh-7.1p2.orig/monitor.h ++++ openssh-7.1p2/monitor.h +@@ -56,6 +56,8 @@ enum monitor_reqtype { + MONITOR_REQ_GSSUSEROK = 46, MONITOR_ANS_GSSUSEROK = 47, + MONITOR_REQ_GSSCHECKMIC = 48, MONITOR_ANS_GSSCHECKMIC = 49, + MONITOR_REQ_TERM = 50, ++ MONITOR_REQ_GSSSIGN = 82, MONITOR_ANS_GSSSIGN = 83, ++ MONITOR_REQ_GSSUPCREDS = 84, MONITOR_ANS_GSSUPCREDS = 85, -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 -@@ -65,16 +65,19 @@ enum monitor_reqtype { - 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, - -+ MONITOR_REQ_GSSSIGN = 201, MONITOR_ANS_GSSSIGN = 202, -+ MONITOR_REQ_GSSUPCREDS = 203, MONITOR_ANS_GSSUPCREDS = 204, -+ - }; - - struct mm_master; - struct monitor { - int m_recvfd; - int m_sendfd; - int m_log_recvfd; - int m_log_sendfd; -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 -@@ -1303,33 +1303,78 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss - &m); - - major = buffer_get_int(&m); - buffer_free(&m); - return(major); + MONITOR_REQ_PAM_START = 100, + MONITOR_REQ_PAM_ACCOUNT = 102, MONITOR_ANS_PAM_ACCOUNT = 103, +Index: openssh-7.1p2/monitor_wrap.c +=================================================================== +--- openssh-7.1p2.orig/monitor_wrap.c ++++ openssh-7.1p2/monitor_wrap.c +@@ -1102,7 +1102,7 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss } int @@ -2532,16 +1892,7 @@ diff --git a/openssh-6.6p1/monitor_wrap.c b/openssh-6.6p1/monitor_wrap.c { Buffer m; int authenticated = 0; - - buffer_init(&m); - - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, &m); - mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUSEROK, - &m); - - authenticated = buffer_get_int(&m); - - buffer_free(&m); +@@ -1119,6 +1119,51 @@ mm_ssh_gssapi_userok(char *user) debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not "); return (authenticated); } @@ -2579,34 +1930,25 @@ diff --git a/openssh-6.6p1/monitor_wrap.c b/openssh-6.6p1/monitor_wrap.c + buffer_put_cstring(&m, store->filename ? store->filename : ""); + buffer_put_cstring(&m, store->envvar ? store->envvar : ""); + buffer_put_cstring(&m, store->envval ? store->envval : ""); -+ ++ + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUPCREDS, &m); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUPCREDS, &m); + + ok = buffer_get_int(&m); + + buffer_free(&m); -+ ++ + return (ok); +} + #endif /* GSSAPI */ #ifdef SSH_AUDIT_EVENTS - void - mm_audit_unsupported_body(int what) - { - Buffer m; - -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 -@@ -54,18 +54,20 @@ int mm_user_key_verify(Key *, u_char *, - 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 +Index: openssh-7.1p2/monitor_wrap.h +=================================================================== +--- openssh-7.1p2.orig/monitor_wrap.h ++++ openssh-7.1p2/monitor_wrap.h +@@ -59,8 +59,10 @@ BIGNUM *mm_auth_rsa_generate_challenge(K 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 *); @@ -2618,71 +1960,41 @@ diff --git a/openssh-6.6p1/monitor_wrap.h b/openssh-6.6p1/monitor_wrap.h #endif #ifdef USE_PAM - void mm_start_pam(struct Authctxt *); - u_int mm_do_pam_account(void); - 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 **); -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 -@@ -136,16 +136,18 @@ typedef enum { - oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs, - oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication, - oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, - oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, - oHostKeyAlgorithms, oBindAddress, oPKCS11Provider, +Index: openssh-7.1p2/readconf.c +=================================================================== +--- openssh-7.1p2.orig/readconf.c ++++ openssh-7.1p2/readconf.c +@@ -147,6 +147,8 @@ typedef enum { oClearAllForwardings, oNoHostAuthenticationForLocalhost, oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, oAddressFamily, oGssAuthentication, oGssDelegateCreds, oGssEnableMITM, + oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey, -+ oGssServerIdentity, ++ oGssServerIdentity, oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, oSendEnv, oControlPath, oControlMaster, oControlPersist, oHashKnownHosts, - oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, - oVisualHostKey, oUseRoaming, - oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass, - oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, - oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, -@@ -178,22 +180,31 @@ static struct { - { "challengeresponseauthentication", oChallengeResponseAuthentication }, - { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */ - { "tisauthentication", oChallengeResponseAuthentication }, /* alias */ - { "kerberosauthentication", oUnsupported }, - { "kerberostgtpassing", oUnsupported }, +@@ -192,11 +194,20 @@ static struct { { "afstokenpassing", oUnsupported }, #if defined(GSSAPI) { "gssapiauthentication", oGssAuthentication }, + { "gssapikeyexchange", oGssKeyEx }, { "gssapidelegatecredentials", oGssDelegateCreds }, - { "gssapienablemitmattack", oGssEnableMITM }, + { "gssapitrustdns", oGssTrustDns }, + { "gssapiclientidentity", oGssClientIdentity }, + { "gssapiserveridentity", oGssServerIdentity }, + { "gssapirenewalforcesrekey", oGssRenewalRekey }, + { "gssapienablemitmattack", oGssEnableMITM }, #else { "gssapiauthentication", oUnsupported }, + { "gssapikeyexchange", oUnsupported }, { "gssapidelegatecredentials", oUnsupported }, - { "gssapienablemitmattack", oUnsupported }, + { "gssapitrustdns", oUnsupported }, + { "gssapiclientidentity", oUnsupported }, + { "gssapirenewalforcesrekey", oUnsupported }, + { "gssapienablemitmattack", oUnsupported }, #endif { "fallbacktorsh", oDeprecated }, - { "usersh", oDeprecated }, - { "identityfile", oIdentityFile }, - { "identityfile2", oIdentityFile }, /* obsolete */ - { "identitiesonly", oIdentitiesOnly }, - { "hostname", oHostName }, - { "hostkeyalias", oHostKeyAlias }, -@@ -838,24 +849,44 @@ parse_time: - case oChallengeResponseAuthentication: - intptr = &options->challenge_response_authentication; - goto parse_flag; - - case oGssAuthentication: +@@ -896,9 +907,29 @@ parse_time: intptr = &options->gss_authentication; goto parse_flag; @@ -2693,65 +2005,39 @@ diff --git a/openssh-6.6p1/readconf.c b/openssh-6.6p1/readconf.c case oGssDelegateCreds: intptr = &options->gss_deleg_creds; goto parse_flag; ++ ++ case oGssTrustDns: ++ intptr = &options->gss_trust_dns; ++ goto parse_flag; ++ ++ case oGssClientIdentity: ++ charptr = &options->gss_client_identity; ++ goto parse_string; ++ ++ case oGssServerIdentity: ++ charptr = &options->gss_server_identity; ++ goto parse_string; ++ ++ case oGssRenewalRekey: ++ intptr = &options->gss_renewal_rekey; ++ goto parse_flag; case oGssEnableMITM: intptr = &options->gss_enable_mitm; - goto parse_flag; - -+ case oGssTrustDns: -+ intptr = &options->gss_trust_dns; -+ goto parse_flag; -+ -+ case oGssClientIdentity: -+ charptr = &options->gss_client_identity; -+ goto parse_string; -+ -+ case oGssServerIdentity: -+ charptr = &options->gss_server_identity; -+ goto parse_string; -+ -+ case oGssRenewalRekey: -+ intptr = &options->gss_renewal_rekey; -+ goto parse_flag; -+ - case oBatchMode: - intptr = &options->batch_mode; - goto parse_flag; - - case oCheckHostIP: - intptr = &options->check_host_ip; - goto parse_flag; - -@@ -1498,18 +1529,23 @@ initialize_options(Options * options) - options->exit_on_forward_failure = -1; - options->xauth_location = NULL; - options->gateway_ports = -1; - options->use_privileged_port = -1; - options->rsa_authentication = -1; +@@ -1607,7 +1638,12 @@ initialize_options(Options * options) options->pubkey_authentication = -1; options->challenge_response_authentication = -1; options->gss_authentication = -1; + options->gss_keyex = -1; options->gss_deleg_creds = -1; - options->gss_enable_mitm = -1; + options->gss_trust_dns = -1; -+ options->gss_renewal_rekey = -1; -+ options->gss_client_identity = NULL; -+ options->gss_server_identity = NULL; ++ options->gss_renewal_rekey = -1; ++ options->gss_client_identity = NULL; ++ options->gss_server_identity = NULL; + options->gss_enable_mitm = -1; options->password_authentication = -1; options->kbd_interactive_authentication = -1; - options->kbd_interactive_devices = NULL; - options->rhosts_rsa_authentication = -1; - options->hostbased_authentication = -1; - options->batch_mode = -1; - options->check_host_ip = -1; - options->strict_host_key_checking = -1; -@@ -1618,20 +1654,26 @@ fill_default_options(Options * options) - if (options->rsa_authentication == -1) - options->rsa_authentication = 1; - if (options->pubkey_authentication == -1) - options->pubkey_authentication = 1; - if (options->challenge_response_authentication == -1) +@@ -1736,8 +1772,14 @@ fill_default_options(Options * options) options->challenge_response_authentication = 1; if (options->gss_authentication == -1) options->gss_authentication = 0; @@ -2759,78 +2045,111 @@ diff --git a/openssh-6.6p1/readconf.c b/openssh-6.6p1/readconf.c + options->gss_keyex = 0; if (options->gss_deleg_creds == -1) options->gss_deleg_creds = 0; - if (options->gss_enable_mitm == -1) - options->gss_enable_mitm = 0; + if (options->gss_trust_dns == -1) + options->gss_trust_dns = 0; + if (options->gss_renewal_rekey == -1) + options->gss_renewal_rekey = 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) - 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 -@@ -49,18 +49,23 @@ typedef struct { - int rhosts_rsa_authentication; /* Try rhosts with RSA - * authentication. */ - int rsa_authentication; /* Try RSA authentication. */ - int pubkey_authentication; /* Try ssh2 pubkey authentication. */ - int hostbased_authentication; /* ssh2's rhosts_rsa */ +Index: openssh-7.1p2/readconf.h +=================================================================== +--- openssh-7.1p2.orig/readconf.h ++++ openssh-7.1p2/readconf.h +@@ -45,7 +45,12 @@ typedef struct { int challenge_response_authentication; /* Try S/Key or TIS, authentication. */ int gss_authentication; /* Try GSS authentication */ -+ int gss_keyex; /* Try GSS key exchange */ ++ int gss_keyex; /* Try GSS key exchange */ int gss_deleg_creds; /* Delegate GSS credentials */ - int gss_enable_mitm; /* Enable old style gssapi auth */ -+ int gss_trust_dns; /* Trust DNS for GSS canonicalization */ -+ int gss_renewal_rekey; /* Credential renewal forces rekey */ ++ int gss_trust_dns; /* Trust DNS for GSS canonicalization */ ++ int gss_renewal_rekey; /* Credential renewal forces rekey */ + char *gss_client_identity; /* Principal to initiate GSSAPI with */ + char *gss_server_identity; /* GSSAPI target principal */ + int gss_enable_mitm; /* Enable old style gssapi auth */ int password_authentication; /* Try password * authentication. */ - int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ - 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,18 +104,21 @@ initialize_server_options(ServerOptions - options->hostbased_uses_name_from_packet_only = -1; - options->rsa_authentication = -1; - options->pubkey_authentication = -1; - options->kerberos_authentication = -1; - options->kerberos_or_local_passwd = -1; +Index: openssh-7.1p2/regress/cert-hostkey.sh +=================================================================== +--- openssh-7.1p2.orig/regress/cert-hostkey.sh ++++ openssh-7.1p2/regress/cert-hostkey.sh +@@ -46,7 +46,7 @@ touch $OBJ/host_revoked_plain + touch $OBJ/host_revoked_cert + cp $OBJ/host_ca_key.pub $OBJ/host_revoked_ca + +-PLAIN_TYPES=`$SSH -Q key-plain | sed 's/^ssh-dss/ssh-dsa/g;s/^ssh-//'` ++PLAIN_TYPES=`$SSH -Q key-plain | grep -v null | sed 's/^ssh-dss/ssh-dsa/g;s/^ssh-//'` + + # Prepare certificate, plain key and CA KRLs + ${SSHKEYGEN} -kf $OBJ/host_krl_empty || fatal "KRL init failed" +Index: openssh-7.1p2/regress/cert-userkey.sh +=================================================================== +--- openssh-7.1p2.orig/regress/cert-userkey.sh ++++ openssh-7.1p2/regress/cert-userkey.sh +@@ -7,7 +7,7 @@ rm -f $OBJ/authorized_keys_$USER $OBJ/us + cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak + cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak + +-PLAIN_TYPES=`$SSH -Q key-plain | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'` ++PLAIN_TYPES=`$SSH -Q key-plain | grep -v null | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'` + + kname() { + n=`echo "$1" | sed 's/^dsa/ssh-dss/;s/^rsa/ssh-rsa/;s/^ed/ssh-ed/'` +Index: openssh-7.1p2/regress/kextype.sh +=================================================================== +--- openssh-7.1p2.orig/regress/kextype.sh ++++ openssh-7.1p2/regress/kextype.sh +@@ -14,6 +14,9 @@ echo "KexAlgorithms=$KEXOPT" >> $OBJ/ssh + + tries="1 2 3 4" + for k in `${SSH} -Q kex`; do ++ if [ $k = "gss-gex-sha1-" -o $k = "gss-group1-sha1-" -o $k = "gss-group14-sha1-" ]; then ++ continue ++ fi + verbose "kex $k" + for i in $tries; do + ${SSH} -F $OBJ/ssh_proxy -o KexAlgorithms=$k x true +Index: openssh-7.1p2/regress/rekey.sh +=================================================================== +--- openssh-7.1p2.orig/regress/rekey.sh ++++ openssh-7.1p2/regress/rekey.sh +@@ -38,6 +38,9 @@ increase_datafile_size 300 + + opts="" + for i in `${SSH} -Q kex`; do ++ if [ $i = "gss-gex-sha1-" -o $i = "gss-group1-sha1-" -o $i = "gss-group14-sha1-" ]; then ++ continue ++ fi + opts="$opts KexAlgorithms=$i" + done + for i in `${SSH} -Q cipher`; do +@@ -56,6 +59,9 @@ done + if ${SSH} -Q cipher-auth | grep '^.*$' >/dev/null 2>&1 ; then + for c in `${SSH} -Q cipher-auth`; do + for kex in `${SSH} -Q kex`; do ++ if [ $kex = "gss-gex-sha1-" -o $kex = "gss-group1-sha1-" -o $kex = "gss-group14-sha1-" ]; then ++ continue ++ fi + verbose "client rekey $c $kex" + ssh_data_rekeying "KexAlgorithms=$kex" -oRekeyLimit=256k -oCiphers=$c + done +Index: openssh-7.1p2/servconf.c +=================================================================== +--- openssh-7.1p2.orig/servconf.c ++++ openssh-7.1p2/servconf.c +@@ -118,9 +118,11 @@ initialize_server_options(ServerOptions options->kerberos_ticket_cleanup = -1; options->kerberos_get_afs_token = -1; options->gss_authentication=-1; + options->gss_keyex = -1; options->gss_cleanup_creds = -1; + options->gss_strict_acceptor = -1; options->gss_enable_mitm = -1; -+ options->gss_strict_acceptor = -1; + options->gss_store_rekey = -1; options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->challenge_response_authentication = -1; - options->permit_empty_passwd = -1; - options->permit_user_env = -1; - options->use_login = -1; - options->compression = -1; - options->rekey_limit = -1; -@@ -243,20 +246,26 @@ fill_default_server_options(ServerOption - if (options->kerberos_or_local_passwd == -1) - options->kerberos_or_local_passwd = 1; - if (options->kerberos_ticket_cleanup == -1) - options->kerberos_ticket_cleanup = 1; - if (options->kerberos_get_afs_token == -1) +@@ -279,10 +281,14 @@ fill_default_server_options(ServerOption options->kerberos_get_afs_token = 0; if (options->gss_authentication == -1) options->gss_authentication = 0; @@ -2838,57 +2157,33 @@ diff --git a/openssh-6.6p1/servconf.c b/openssh-6.6p1/servconf.c + options->gss_keyex = 0; if (options->gss_cleanup_creds == -1) options->gss_cleanup_creds = 1; - if (options->gss_enable_mitm == -1) - options->gss_enable_mitm = 0; -+ if (options->gss_strict_acceptor == -1) -+ options->gss_strict_acceptor = 1; + if (options->gss_strict_acceptor == -1) + options->gss_strict_acceptor = 0; + if (options->gss_store_rekey == -1) + options->gss_store_rekey = 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) - 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; -@@ -342,16 +351,17 @@ typedef enum { - 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, sGssEnableMITM, -+ sGssStrictAcceptor, sGssKeyEx, sGssStoreRekey, +@@ -418,7 +424,7 @@ typedef enum { + sHostKeyAlgorithms, + sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, + sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, sGssEnableMITM, +- sAcceptEnv, sPermitTunnel, ++ sGssKeyEx, sGssStoreRekey, sAcceptEnv, sPermitTunnel, sMatch, sPermitOpen, sForceCommand, sChrootDirectory, sUsePrivilegeSeparation, sAllowAgentForwarding, sHostCertificate, - sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, - sKexAlgorithms, sIPQoS, sVersionAddendum, - sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, - sAuthenticationMethods, sHostKeyAgent, - sDeprecated, sUnsupported -@@ -411,21 +421,31 @@ static struct { - { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, - #endif - { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL }, - { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL }, - #ifdef GSSAPI - { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, +@@ -495,12 +501,18 @@ static struct { { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, + { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL }, { "gssapienablemitmattack", sGssEnableMITM }, -+ { "gssapicleanupcreds", sGssCleanupCreds, SSHCFG_GLOBAL }, -+ { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL }, + { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL }, + { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL }, #else { "gssapiauthentication", sUnsupported, SSHCFG_ALL }, { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, + { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL }, { "gssapienablemitmattack", sUnsupported }, -+ { "gssapicleanupcreds", sUnsupported, SSHCFG_GLOBAL }, -+ { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL }, + { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL }, + { "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL }, #endif @@ -2897,17 +2192,7 @@ diff --git a/openssh-6.6p1/servconf.c b/openssh-6.6p1/servconf.c { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, - { "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */ - { "checkmail", sDeprecated, SSHCFG_GLOBAL }, - { "listenaddress", sListenAddress, SSHCFG_GLOBAL }, - { "addressfamily", sAddressFamily, SSHCFG_GLOBAL }, - { "printmotd", sPrintMotd, SSHCFG_GLOBAL }, -@@ -1094,24 +1114,36 @@ process_server_config_line(ServerOptions - case sKerberosGetAFSToken: - intptr = &options->kerberos_get_afs_token; - goto parse_flag; - - case sGssAuthentication: +@@ -1244,6 +1256,10 @@ process_server_config_line(ServerOptions intptr = &options->gss_authentication; goto parse_flag; @@ -2918,15 +2203,10 @@ diff --git a/openssh-6.6p1/servconf.c b/openssh-6.6p1/servconf.c case sGssCleanupCreds: intptr = &options->gss_cleanup_creds; goto parse_flag; - - case sGssEnableMITM: +@@ -1256,6 +1272,10 @@ process_server_config_line(ServerOptions intptr = &options->gss_enable_mitm; goto parse_flag; -+ case sGssStrictAcceptor: -+ intptr = &options->gss_strict_acceptor; -+ goto parse_flag; -+ + case sGssStoreRekey: + intptr = &options->gss_store_rekey; + goto parse_flag; @@ -2934,214 +2214,37 @@ diff --git a/openssh-6.6p1/servconf.c b/openssh-6.6p1/servconf.c case sPasswordAuthentication: intptr = &options->password_authentication; goto parse_flag; - - case sKbdInteractiveAuthentication: - intptr = &options->kbd_interactive_authentication; - goto parse_flag; - -@@ -2007,17 +2039,20 @@ dump_config(ServerOptions *o) - dump_cfg_fmtint(sKerberosOrLocalPasswd, o->kerberos_or_local_passwd); - dump_cfg_fmtint(sKerberosTicketCleanup, o->kerberos_ticket_cleanup); - # ifdef USE_AFS - dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token); - # endif - #endif +@@ -2264,6 +2284,9 @@ dump_config(ServerOptions *o) #ifdef GSSAPI dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); -+ dump_cfg_fmtint(sGssKeyEx, o->gss_keyex); dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); ++ dump_cfg_fmtint(sGssKeyEx, o->gss_keyex); + dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor); + dump_cfg_fmtint(sGssStoreRekey, o->gss_store_rekey); #endif dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication); dump_cfg_fmtint(sKbdInteractiveAuthentication, - o->kbd_interactive_authentication); - dump_cfg_fmtint(sChallengeResponseAuthentication, - o->challenge_response_authentication); - dump_cfg_fmtint(sPrintMotd, o->print_motd); - dump_cfg_fmtint(sPrintLastLog, o->print_lastlog); -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 -@@ -107,18 +107,21 @@ typedef struct { - * authentication mechanism, - * such as SecurID or - * /etc/passwd */ - int kerberos_ticket_cleanup; /* If true, destroy ticket - * file on logout. */ +Index: openssh-7.1p2/servconf.h +=================================================================== +--- openssh-7.1p2.orig/servconf.h ++++ openssh-7.1p2/servconf.h +@@ -118,9 +118,11 @@ typedef struct { 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_keyex; /* If true, permit GSSAPI key exchange */ ++ int gss_keyex; /* If true, permit GSSAPI key exchange */ 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_store_rekey; + int gss_enable_mitm; /* If true, enable old style GSSAPI */ + int gss_strict_acceptor; /* If true, restrict the GSSAPI acceptor name */ ++ int gss_store_rekey; int password_authentication; /* If true, permit password * authentication. */ 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-gss.h b/openssh-6.6p1/ssh-gss.h ---- a/openssh-6.6p1/ssh-gss.h -+++ b/openssh-6.6p1/ssh-gss.h -@@ -1,11 +1,11 @@ - /* $OpenBSD: ssh-gss.h,v 1.11 2014/02/26 20:28:44 djm Exp $ */ - /* -- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. -+ * Copyright (c) 2001-2009 Simon Wilkinson. 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 -@@ -56,53 +56,70 @@ - #define SSH2_MSG_USERAUTH_GSSAPI_TOKEN 61 - #define SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE 63 - #define SSH2_MSG_USERAUTH_GSSAPI_ERROR 64 - #define SSH2_MSG_USERAUTH_GSSAPI_ERRTOK 65 - #define SSH2_MSG_USERAUTH_GSSAPI_MIC 66 - - #define SSH_GSS_OIDTYPE 0x06 - -+#define SSH2_MSG_KEXGSS_INIT 30 -+#define SSH2_MSG_KEXGSS_CONTINUE 31 -+#define SSH2_MSG_KEXGSS_COMPLETE 32 -+#define SSH2_MSG_KEXGSS_HOSTKEY 33 -+#define SSH2_MSG_KEXGSS_ERROR 34 -+#define SSH2_MSG_KEXGSS_GROUPREQ 40 -+#define SSH2_MSG_KEXGSS_GROUP 41 -+#define KEX_GSS_GRP1_SHA1_ID "gss-group1-sha1-" -+#define KEX_GSS_GRP14_SHA1_ID "gss-group14-sha1-" -+#define KEX_GSS_GEX_SHA1_ID "gss-gex-sha1-" -+ - typedef struct { - char *filename; - char *envvar; - char *envval; -+ struct passwd *owner; - void *data; - } ssh_gssapi_ccache; - - typedef struct { - gss_buffer_desc displayname; - gss_buffer_desc exportedname; - gss_cred_id_t creds; -+ gss_name_t name; - struct ssh_gssapi_mech_struct *mech; - ssh_gssapi_ccache store; -+ int used; -+ int updated; - } ssh_gssapi_client; - - typedef struct ssh_gssapi_mech_struct { - char *enc_name; - char *name; - gss_OID_desc oid; - int (*dochild) (ssh_gssapi_client *); - int (*userok) (ssh_gssapi_client *, char *); - int (*localname) (ssh_gssapi_client *, char **); - void (*storecreds) (ssh_gssapi_client *); -+ int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *); - } ssh_gssapi_mech; - - typedef struct { - OM_uint32 major; /* both */ - OM_uint32 minor; /* both */ - gss_ctx_id_t context; /* both */ - gss_name_t name; /* both */ - gss_OID oid; /* client */ - gss_cred_id_t creds; /* server */ - gss_name_t client; /* server */ -- gss_cred_id_t client_creds; /* server */ -+ gss_cred_id_t client_creds; /* both */ - } Gssctxt; - - extern ssh_gssapi_mech *supported_mechs[]; -+extern Gssctxt *gss_kex_context; - - int ssh_gssapi_check_oid(Gssctxt *, void *, size_t); - void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t); - void ssh_gssapi_set_oid(Gssctxt *, gss_OID); - void ssh_gssapi_supported_oids(gss_OID_set *); - ssh_gssapi_mech *ssh_gssapi_get_ctype(Gssctxt *); - void ssh_gssapi_prepare_supported_oids(void); - OM_uint32 ssh_gssapi_test_oid_supported(OM_uint32 *, gss_OID, int *); -@@ -114,21 +131,35 @@ OM_uint32 ssh_gssapi_accept_ctx(Gssctxt - gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *); - OM_uint32 ssh_gssapi_getclient(Gssctxt *, ssh_gssapi_client *); - void ssh_gssapi_error(Gssctxt *); - char *ssh_gssapi_last_error(Gssctxt *, OM_uint32 *, OM_uint32 *); - void ssh_gssapi_build_ctx(Gssctxt **); - void ssh_gssapi_delete_ctx(Gssctxt **); - OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); - void ssh_gssapi_buildmic(Buffer *, const char *, const char *, const char *); --int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *); -+int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *, const char *); -+OM_uint32 ssh_gssapi_client_identity(Gssctxt *, const char *); -+int ssh_gssapi_credentials_updated(Gssctxt *); - - /* In the server */ -+typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *, -+ const char *); -+char *ssh_gssapi_client_mechanisms(const char *, const char *); -+char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *, -+ const char *); -+gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int); -+int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *, -+ const char *); - OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID); --int ssh_gssapi_userok(char *name); -+int ssh_gssapi_userok(char *name, struct passwd *); - OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); - void ssh_gssapi_do_child(char ***, u_int *); - void ssh_gssapi_cleanup_creds(void); - void ssh_gssapi_storecreds(void); - -+char *ssh_gssapi_server_mechanisms(void); -+int ssh_gssapi_oid_table_ok(); -+ -+int ssh_gssapi_update_creds(ssh_gssapi_ccache *store); - #endif /* GSSAPI */ - - #endif /* _SSH_GSS_H */ -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 -@@ -32,16 +32,18 @@ Host * - ForwardX11Trusted yes - - # RhostsRSAAuthentication no - # RSAAuthentication yes - # PasswordAuthentication yes - # HostbasedAuthentication no - # GSSAPIAuthentication no - # GSSAPIDelegateCredentials no -+# GSSAPIKeyExchange no -+# GSSAPITrustDNS no - # BatchMode no - # CheckHostIP yes - # AddressFamily any - # ConnectTimeout 0 - # StrictHostKeyChecking ask - # IdentityFile ~/.ssh/identity - # IdentityFile ~/.ssh/id_rsa - # IdentityFile ~/.ssh/id_dsa -diff --git a/openssh-6.6p1/ssh_config.5 b/openssh-6.6p1/ssh_config.5 ---- a/openssh-6.6p1/ssh_config.5 -+++ b/openssh-6.6p1/ssh_config.5 -@@ -677,21 +677,53 @@ host key database, separated by whitespa - The default is - .Pa /etc/ssh/ssh_known_hosts , - .Pa /etc/ssh/ssh_known_hosts2 . - .It Cm GSSAPIAuthentication - Specifies whether user authentication based on GSSAPI is allowed. +Index: openssh-7.1p2/ssh_config.5 +=================================================================== +--- openssh-7.1p2.orig/ssh_config.5 ++++ openssh-7.1p2/ssh_config.5 +@@ -749,11 +749,43 @@ Specifies whether user authentication ba The default is .Dq no . Note that this option applies to protocol version 2 only. @@ -3186,22 +2289,26 @@ diff --git a/openssh-6.6p1/ssh_config.5 b/openssh-6.6p1/ssh_config.5 .It Cm HashKnownHosts Indicates that .Xr ssh 1 - should hash host names and addresses when they are added to - .Pa ~/.ssh/known_hosts . - These hashed names may be used normally by - .Xr ssh 1 - and -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 -@@ -155,19 +155,44 @@ order_hostkeyalgs(char *host, struct soc - return ret; - } - - void - ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) - { - Kex *kex; +Index: openssh-7.1p2/ssh_config +=================================================================== +--- openssh-7.1p2.orig/ssh_config ++++ openssh-7.1p2/ssh_config +@@ -37,6 +37,8 @@ ForwardX11Trusted yes + # HostbasedAuthentication no + # GSSAPIAuthentication no + # GSSAPIDelegateCredentials no ++# GSSAPIKeyExchange no ++# GSSAPITrustDNS no + # BatchMode no + # CheckHostIP yes + # AddressFamily any +Index: openssh-7.1p2/sshconnect2.c +=================================================================== +--- openssh-7.1p2.orig/sshconnect2.c ++++ openssh-7.1p2/sshconnect2.c +@@ -160,9 +160,34 @@ ssh_kex2(char *host, struct sockaddr *ho + struct kex *kex; + int r; +#ifdef GSSAPI + char *orig = NULL, *gss = NULL; @@ -3215,7 +2322,7 @@ diff --git a/openssh-6.6p1/sshconnect2.c b/openssh-6.6p1/sshconnect2.c + if (options.gss_keyex) { + /* Add the GSSAPI mechanisms currently supported on this + * client to the key exchange algorithm proposal */ -+ orig = myproposal[PROPOSAL_KEX_ALGS]; ++ orig = options.kex_algorithms; + + if (options.gss_trust_dns) + gss_host = (char *)get_canonical_hostname(1); @@ -3225,28 +2332,18 @@ diff --git a/openssh-6.6p1/sshconnect2.c b/openssh-6.6p1/sshconnect2.c + gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity); + if (gss) { + debug("Offering GSSAPI proposal: %s", gss); -+ xasprintf(&myproposal[PROPOSAL_KEX_ALGS], ++ xasprintf(&options.kex_algorithms, + "%s,%s", gss, orig); + } + } +#endif + - if (options.ciphers == (char *)-1) { - logit("No valid ciphers for protocol version 2 given, using defaults."); - options.ciphers = NULL; - } - if (options.ciphers != NULL) { - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; - } else if (fips_mode()) { -@@ -205,32 +230,63 @@ ssh_kex2(char *host, struct sockaddr *ho - compat_pkalg_proposal( + myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal( + options.kex_algorithms); + myproposal[PROPOSAL_ENC_ALGS_CTOS] = +@@ -193,6 +218,17 @@ ssh_kex2(char *host, struct sockaddr *ho 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]); +#ifdef GSSAPI + /* If we've got GSSAPI algorithms, then we also support the @@ -3262,15 +2359,10 @@ diff --git a/openssh-6.6p1/sshconnect2.c b/openssh-6.6p1/sshconnect2.c 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; - kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; - kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; - kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; +@@ -210,11 +246,31 @@ ssh_kex2(char *host, struct sockaddr *ho kex->kex[KEX_ECDH_SHA2] = kexecdh_client; - kex->kex[KEX_C25519_SHA256] = kexc25519_client; + # endif + #endif +#ifdef GSSAPI + if (options.gss_keyex) { + kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client; @@ -3278,6 +2370,7 @@ diff --git a/openssh-6.6p1/sshconnect2.c b/openssh-6.6p1/sshconnect2.c + kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client; + } +#endif + kex->kex[KEX_C25519_SHA256] = kexc25519_client; kex->client_version_string=client_version_string; kex->server_version_string=server_version_string; kex->verify_host_key=&verify_host_key_callback; @@ -3291,40 +2384,22 @@ diff --git a/openssh-6.6p1/sshconnect2.c b/openssh-6.6p1/sshconnect2.c + kex->gss_host = options.gss_server_identity; + } else { + kex->gss_host = gss_host; -+ } ++ } + } +#endif + - xxx_kex = kex; - - dispatch_run(DISPATCH_BLOCK, &kex->done, kex); + dispatch_run(DISPATCH_BLOCK, &kex->done, active_state); if (options.use_roaming && !kex->roaming) { - debug("Roaming not allowed by server"); - options.use_roaming = 0; - } -@@ -310,31 +366,37 @@ int userauth_hostbased(Authctxt *); - - #ifdef GSSAPI - int userauth_gssapi(Authctxt *authctxt); - void input_gssapi_response(int type, u_int32_t, void *); - void input_gssapi_token(int type, u_int32_t, void *); - void input_gssapi_hash(int type, u_int32_t, void *); - void input_gssapi_error(int, u_int32_t, void *); - void input_gssapi_errtok(int, u_int32_t, void *); +@@ -306,6 +362,7 @@ int input_gssapi_token(int type, u_int32 + int input_gssapi_hash(int type, u_int32_t, void *); + int input_gssapi_error(int, u_int32_t, void *); + int input_gssapi_errtok(int, u_int32_t, void *); +int userauth_gsskeyex(Authctxt *authctxt); #endif void userauth(Authctxt *, char *); - - static int sign_and_send_pubkey(Authctxt *, Identity *); - static void pubkey_prepare(Authctxt *); - static void pubkey_cleanup(Authctxt *); - static Key *load_identity_file(char *, int); - - static Authmethod *authmethod_get(char *authlist); - static Authmethod *authmethod_lookup(const char *name); - static char *authmethods_get(void); +@@ -321,6 +378,11 @@ static char *authmethods_get(void); Authmethod authmethods[] = { #ifdef GSSAPI @@ -3336,17 +2411,7 @@ diff --git a/openssh-6.6p1/sshconnect2.c b/openssh-6.6p1/sshconnect2.c {"gssapi-with-mic", userauth_gssapi, NULL, - &options.gss_authentication, - NULL}, - {"gssapi", - userauth_gssapi, - NULL, -@@ -626,29 +688,41 @@ done: - int - userauth_gssapi(Authctxt *authctxt) - { - Gssctxt *gssctxt = NULL; - static gss_OID_set gss_supported = NULL; +@@ -632,19 +694,31 @@ userauth_gssapi(Authctxt *authctxt) static u_int mech = 0; OM_uint32 min; int ok = 0; @@ -3380,17 +2445,7 @@ diff --git a/openssh-6.6p1/sshconnect2.c b/openssh-6.6p1/sshconnect2.c ok = 1; /* Mechanism works */ } else { mech++; - } - } - - if (!ok) - return 0; -@@ -737,18 +811,18 @@ process_gssapi_token(void *ctxt, gss_buf - } - - /* ARGSUSED */ - void - input_gssapi_response(int type, u_int32_t plen, void *ctxt) +@@ -743,8 +817,8 @@ input_gssapi_response(int type, u_int32_ { Authctxt *authctxt = ctxt; Gssctxt *gssctxt; @@ -3401,19 +2456,9 @@ diff --git a/openssh-6.6p1/sshconnect2.c b/openssh-6.6p1/sshconnect2.c if (authctxt == NULL) fatal("input_gssapi_response: no authentication context"); - gssctxt = authctxt->methoddata; - - /* Setup our OID */ - oidv = packet_get_string(&oidlen); - -@@ -847,16 +921,58 @@ input_gssapi_error(int type, u_int32_t p - lang=packet_get_string(NULL); - - packet_check_eom(); - - debug("Server GSSAPI Error:\n%s", msg); - free(msg); +@@ -857,6 +931,48 @@ input_gssapi_error(int type, u_int32_t p free(lang); + return 0; } + +int @@ -3460,41 +2505,23 @@ diff --git a/openssh-6.6p1/sshconnect2.c b/openssh-6.6p1/sshconnect2.c #endif /* GSSAPI */ int - userauth_none(Authctxt *authctxt) - { - /* initial userauth request */ - packet_start(SSH2_MSG_USERAUTH_REQUEST); - packet_put_cstring(authctxt->server_user); -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 -@@ -123,16 +123,20 @@ - #include "roaming.h" - #include "ssh-sandbox.h" - #include "version.h" - - #include "fips.h" - - #include "audit.h" - -+#ifdef USE_SECURITY_SESSION_API -+#include -+#endif -+ - #ifdef LIBWRAP - #include - #include - int allow_severity; - int deny_severity; - #endif /* LIBWRAP */ - - #ifndef O_NOCTTY -@@ -1804,20 +1808,23 @@ main(int ac, char **av) - if ((options.protocol & SSH_PROTO_1) && fips_mode()) { - logit("Disabling protocol version 1. Not allowed in the FIPS mode."); - options.protocol &= ~SSH_PROTO_1; +Index: openssh-7.1p2/sshd.c +=================================================================== +--- openssh-7.1p2.orig/sshd.c ++++ openssh-7.1p2/sshd.c +@@ -1019,8 +1019,9 @@ notify_hostkeys(struct ssh *ssh) } - if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) { + debug3("%s: sent %d hostkeys", __func__, nkeys); + if (nkeys == 0) +- fatal("%s: no hostkeys", __func__); +- packet_send(); ++ debug3("%s: no hostkeys", __func__); ++ else ++ packet_send(); + sshbuf_free(buf); + } + +@@ -1891,10 +1892,13 @@ main(int ac, char **av) logit("Disabling protocol version 1. Could not load host key"); options.protocol &= ~SSH_PROTO_1; } @@ -3508,159 +2535,7 @@ diff --git a/openssh-6.6p1/sshd.c b/openssh-6.6p1/sshd.c if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) { logit("sshd: no hostkeys available -- exiting."); exit(1); - } - - /* - * Load certificates. They are stored in an array at identical - * indices to the public keys that they relate to. -@@ -2007,16 +2014,70 @@ main(int ac, char **av) - /* Accept a connection and return in a forked child */ - server_accept_loop(&sock_in, &sock_out, - &newsock, config_s); - } - - /* This is the child processing a new connection. */ - setproctitle("%s", "[accepted]"); - -+#ifdef USE_SECURITY_SESSION_API -+ /* -+ * Create a new security session for use by the new user login if -+ * the current session is the root session or we are not launched -+ * by inetd (eg: debugging mode or server mode). We do not -+ * necessarily need to create a session if we are launched from -+ * inetd because Panther xinetd will create a session for us. -+ * -+ * The only case where this logic will fail is if there is an -+ * inetd running in a non-root session which is not creating -+ * new sessions for us. Then all the users will end up in the -+ * same session (bad). -+ * -+ * When the client exits, the session will be destroyed for us -+ * automatically. -+ * -+ * We must create the session before any credentials are stored -+ * (including AFS pags, which happens a few lines below). -+ */ -+ { -+ OSStatus err = 0; -+ SecuritySessionId sid = 0; -+ SessionAttributeBits sattrs = 0; -+ -+ err = SessionGetInfo(callerSecuritySession, &sid, &sattrs); -+ if (err) -+ error("SessionGetInfo() failed with error %.8X", -+ (unsigned) err); -+ else -+ debug("Current Session ID is %.8X / Session Attributes are %.8X", -+ (unsigned) sid, (unsigned) sattrs); -+ -+ if (inetd_flag && !(sattrs & sessionIsRoot)) -+ debug("Running in inetd mode in a non-root session... " -+ "assuming inetd created the session for us."); -+ else { -+ debug("Creating new security session..."); -+ err = SessionCreate(0, sessionHasTTY | sessionIsRemote); -+ if (err) -+ error("SessionCreate() failed with error %.8X", -+ (unsigned) err); -+ -+ err = SessionGetInfo(callerSecuritySession, &sid, -+ &sattrs); -+ if (err) -+ error("SessionGetInfo() failed with error %.8X", -+ (unsigned) err); -+ else -+ debug("New Session ID is %.8X / Session Attributes are %.8X", -+ (unsigned) sid, (unsigned) sattrs); -+ } -+ } -+#endif -+ - /* - * Create a new session and process group since the 4.4BSD - * setlogin() affects the entire process group. We don't - * want the child to be able to affect the parent. - */ - #if !defined(SSHD_ACQUIRES_CTTY) - /* - * If setsid is called, on some platforms sshd will later acquire a -@@ -2134,16 +2195,70 @@ main(int ac, char **av) - } - #endif /* LIBWRAP */ - - /* Log the connection. */ - verbose("Connection from %s port %d on %s port %d", - remote_ip, remote_port, - get_local_ipaddr(sock_in), get_local_port()); - -+#ifdef USE_SECURITY_SESSION_API -+ /* -+ * Create a new security session for use by the new user login if -+ * the current session is the root session or we are not launched -+ * by inetd (eg: debugging mode or server mode). We do not -+ * necessarily need to create a session if we are launched from -+ * inetd because Panther xinetd will create a session for us. -+ * -+ * The only case where this logic will fail is if there is an -+ * inetd running in a non-root session which is not creating -+ * new sessions for us. Then all the users will end up in the -+ * same session (bad). -+ * -+ * When the client exits, the session will be destroyed for us -+ * automatically. -+ * -+ * We must create the session before any credentials are stored -+ * (including AFS pags, which happens a few lines below). -+ */ -+ { -+ OSStatus err = 0; -+ SecuritySessionId sid = 0; -+ SessionAttributeBits sattrs = 0; -+ -+ err = SessionGetInfo(callerSecuritySession, &sid, &sattrs); -+ if (err) -+ error("SessionGetInfo() failed with error %.8X", -+ (unsigned) err); -+ else -+ debug("Current Session ID is %.8X / Session Attributes are %.8X", -+ (unsigned) sid, (unsigned) sattrs); -+ -+ if (inetd_flag && !(sattrs & sessionIsRoot)) -+ debug("Running in inetd mode in a non-root session... " -+ "assuming inetd created the session for us."); -+ else { -+ debug("Creating new security session..."); -+ err = SessionCreate(0, sessionHasTTY | sessionIsRemote); -+ if (err) -+ error("SessionCreate() failed with error %.8X", -+ (unsigned) err); -+ -+ err = SessionGetInfo(callerSecuritySession, &sid, -+ &sattrs); -+ if (err) -+ error("SessionGetInfo() failed with error %.8X", -+ (unsigned) err); -+ else -+ debug("New Session ID is %.8X / Session Attributes are %.8X", -+ (unsigned) sid, (unsigned) sattrs); -+ } -+ } -+#endif -+ - /* - * We don't want to listen forever unless the other side - * successfully authenticates itself. So we set up an alarm which is - * cleared after successful authentication. A limit of zero - * indicates no limit. Note that we don't set the alarm in debugging - * mode; it is just annoying to have the server exit just when you - * are about to discover the bug. - */ -@@ -2562,24 +2677,73 @@ do_ssh2_kex(void) - - if (options.rekey_limit || options.rekey_interval) - packet_set_rekey_limits((u_int32_t)options.rekey_limit, - (time_t)options.rekey_interval); - +@@ -2635,6 +2639,48 @@ do_ssh2_kex(void) myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal( list_hostkey_types()); @@ -3707,12 +2582,11 @@ diff --git a/openssh-6.6p1/sshd.c b/openssh-6.6p1/sshd.c +#endif + /* start key exchange */ - kex = kex_setup(myproposal); - kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; - kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; - kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; - kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; - kex->kex[KEX_ECDH_SHA2] = kexecdh_server; + if ((r = kex_setup(active_state, myproposal)) != 0) + fatal("kex_setup: %s", ssh_err(r)); +@@ -2649,6 +2695,13 @@ do_ssh2_kex(void) + # endif + #endif kex->kex[KEX_C25519_SHA256] = kexc25519_server; +#ifdef GSSAPI + if (options.gss_keyex) { @@ -3724,42 +2598,11 @@ diff --git a/openssh-6.6p1/sshd.c b/openssh-6.6p1/sshd.c kex->server = 1; kex->client_version_string=client_version_string; kex->server_version_string=server_version_string; - kex->load_host_public_key=&get_hostkey_public_by_type; - kex->load_host_private_key=&get_hostkey_private_by_type; - kex->host_key_index=&get_hostkey_index; - kex->sign = sshd_hostkey_sign; - -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 -@@ -79,16 +79,18 @@ PasswordAuthentication no - #KerberosAuthentication no - #KerberosOrLocalPasswd yes - #KerberosTicketCleanup yes - #KerberosGetAFSToken no - - # GSSAPI options - #GSSAPIAuthentication no - #GSSAPICleanupCredentials yes -+#GSSAPIStrictAcceptorCheck yes -+#GSSAPIKeyExchange no - - # Set this to 'yes' to enable support for the deprecated 'gssapi' authentication - # mechanism to OpenSSH 3.8p1. The newer 'gssapi-with-mic' mechanism is included - # in this release. The use of 'gssapi' is deprecated due to the presence of - # potential man-in-the-middle attacks, which 'gssapi-with-mic' is not susceptible to. - #GSSAPIEnableMITMAttack no - - -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 -@@ -487,22 +487,50 @@ to force remote port forwardings to bind - to allow the client to select the address to which the forwarding is bound. - The default is - .Dq no . - .It Cm GSSAPIAuthentication - Specifies whether user authentication based on GSSAPI is allowed. +Index: openssh-7.1p2/sshd_config.5 +=================================================================== +--- openssh-7.1p2.orig/sshd_config.5 ++++ openssh-7.1p2/sshd_config.5 +@@ -620,6 +620,12 @@ Specifies whether user authentication ba The default is .Dq no . Note that this option applies to protocol version 2 only. @@ -3772,36 +2615,167 @@ diff --git a/openssh-6.6p1/sshd_config.5 b/openssh-6.6p1/sshd_config.5 .It Cm GSSAPICleanupCredentials Specifies whether to automatically destroy the user's credentials cache on logout. +@@ -641,6 +647,11 @@ machine's default store. + This facility is provided to assist with operation on multi homed machines. The default is .Dq yes . - Note that this option applies to protocol version 2 only. -+.It Cm GSSAPIStrictAcceptorCheck -+Determines whether to be strict about the identity of the GSSAPI acceptor -+a client authenticates against. If -+.Dq yes -+then the client must authenticate against the -+.Pa host -+service on the current hostname. If -+.Dq no -+then the client may authenticate against any service key stored in the -+machine's default store. This facility is provided to assist with operation -+on multi homed machines. -+The default is -+.Dq yes . -+Note that this option applies only to protocol version 2 GSSAPI connections, -+and setting it to -+.Dq no -+may only work with recent Kerberos GSSAPI libraries. +.It Cm GSSAPIStoreCredentialsOnRekey +Controls whether the user's GSSAPI credentials should be updated following a +successful connection rekeying. This option can be used to accepted renewed +or updated credentials from a compatible client. The default is +.Dq no . - .It Cm HostbasedAuthentication - Specifies whether rhosts or /etc/hosts.equiv authentication together - with successful public key client host authentication is allowed - (host-based authentication). - This option is similar to - .Cm RhostsRSAAuthentication - and applies to protocol version 2 only. - The default is + .It Cm HostbasedAcceptedKeyTypes + Specifies the key types that will be accepted for hostbased authentication + as a comma-separated pattern list. +Index: openssh-7.1p2/sshd_config +=================================================================== +--- openssh-7.1p2.orig/sshd_config ++++ openssh-7.1p2/sshd_config +@@ -84,6 +84,8 @@ PasswordAuthentication no + # GSSAPI options + #GSSAPIAuthentication no + #GSSAPICleanupCredentials yes ++#GSSAPIStrictAcceptorCheck yes ++#GSSAPIKeyExchange no + + # Set this to 'yes' to enable support for the deprecated 'gssapi' authentication + # mechanism to OpenSSH 3.8p1. The newer 'gssapi-with-mic' mechanism is included +Index: openssh-7.1p2/ssh-gss.h +=================================================================== +--- openssh-7.1p2.orig/ssh-gss.h ++++ openssh-7.1p2/ssh-gss.h +@@ -1,6 +1,6 @@ + /* $OpenBSD: ssh-gss.h,v 1.11 2014/02/26 20:28:44 djm Exp $ */ + /* +- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. ++ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -61,10 +61,22 @@ + + #define SSH_GSS_OIDTYPE 0x06 + ++#define SSH2_MSG_KEXGSS_INIT 30 ++#define SSH2_MSG_KEXGSS_CONTINUE 31 ++#define SSH2_MSG_KEXGSS_COMPLETE 32 ++#define SSH2_MSG_KEXGSS_HOSTKEY 33 ++#define SSH2_MSG_KEXGSS_ERROR 34 ++#define SSH2_MSG_KEXGSS_GROUPREQ 40 ++#define SSH2_MSG_KEXGSS_GROUP 41 ++#define KEX_GSS_GRP1_SHA1_ID "gss-group1-sha1-" ++#define KEX_GSS_GRP14_SHA1_ID "gss-group14-sha1-" ++#define KEX_GSS_GEX_SHA1_ID "gss-gex-sha1-" ++ + typedef struct { + char *filename; + char *envvar; + char *envval; ++ struct passwd *owner; + void *data; + } ssh_gssapi_ccache; + +@@ -72,8 +84,11 @@ typedef struct { + gss_buffer_desc displayname; + gss_buffer_desc exportedname; + gss_cred_id_t creds; ++ gss_name_t name; + struct ssh_gssapi_mech_struct *mech; + ssh_gssapi_ccache store; ++ int used; ++ int updated; + } ssh_gssapi_client; + + typedef struct ssh_gssapi_mech_struct { +@@ -84,6 +99,7 @@ typedef struct ssh_gssapi_mech_struct { + int (*userok) (ssh_gssapi_client *, char *); + int (*localname) (ssh_gssapi_client *, char **); + void (*storecreds) (ssh_gssapi_client *); ++ int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *); + } ssh_gssapi_mech; + + typedef struct { +@@ -94,10 +110,11 @@ typedef struct { + gss_OID oid; /* client */ + gss_cred_id_t creds; /* server */ + gss_name_t client; /* server */ +- gss_cred_id_t client_creds; /* server */ ++ gss_cred_id_t client_creds; /* both */ + } Gssctxt; + + extern ssh_gssapi_mech *supported_mechs[]; ++extern Gssctxt *gss_kex_context; + + int ssh_gssapi_check_oid(Gssctxt *, void *, size_t); + void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t); +@@ -119,16 +136,32 @@ void ssh_gssapi_build_ctx(Gssctxt **); + void ssh_gssapi_delete_ctx(Gssctxt **); + OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); + void ssh_gssapi_buildmic(Buffer *, const char *, const char *, const char *); +-int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *); ++int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *, const char *); ++OM_uint32 ssh_gssapi_client_identity(Gssctxt *, const char *); ++int ssh_gssapi_credentials_updated(Gssctxt *); + + /* In the server */ ++typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *, ++ const char *); ++char *ssh_gssapi_client_mechanisms(const char *, const char *); ++char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *, ++ const char *); ++gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int); ++int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *, ++ const char *); + OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID); +-int ssh_gssapi_userok(char *name); ++int ssh_gssapi_userok(char *name, struct passwd *); + OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); + void ssh_gssapi_do_child(char ***, u_int *); + void ssh_gssapi_cleanup_creds(void); + void ssh_gssapi_storecreds(void); + ++char *ssh_gssapi_server_mechanisms(void); ++int ssh_gssapi_oid_table_ok(); ++ ++int ssh_gssapi_update_creds(ssh_gssapi_ccache *store); ++ ++void ssh_gssapi_rekey_creds(void); + #endif /* GSSAPI */ + + #endif /* _SSH_GSS_H */ +Index: openssh-7.1p2/sshkey.c +=================================================================== +--- openssh-7.1p2.orig/sshkey.c ++++ openssh-7.1p2/sshkey.c +@@ -112,6 +112,7 @@ static const struct keytype keytypes[] = + # endif /* OPENSSL_HAS_NISTP521 */ + # endif /* OPENSSL_HAS_ECC */ + #endif /* WITH_OPENSSL */ ++ { "null", "null", KEY_NULL, 0, 0 }, + { NULL, NULL, -1, -1, 0 } + }; + +Index: openssh-7.1p2/sshkey.h +=================================================================== +--- openssh-7.1p2.orig/sshkey.h ++++ openssh-7.1p2/sshkey.h +@@ -62,6 +62,7 @@ enum sshkey_types { + KEY_DSA_CERT, + KEY_ECDSA_CERT, + KEY_ED25519_CERT, ++ KEY_NULL, + KEY_UNSPEC + }; + +Index: openssh-7.1p2/auth.c +=================================================================== +--- openssh-7.1p2.orig/auth.c ++++ openssh-7.1p2/auth.c +@@ -354,6 +354,7 @@ auth_root_allowed(const char *method) + case PERMIT_NO_PASSWD: + if (strcmp(method, "publickey") == 0 || + strcmp(method, "hostbased") == 0 || ++ strcmp(method, "gssapi-keyex") == 0 || + strcmp(method, "gssapi-with-mic") == 0) + return 1; + break; diff --git a/openssh-6.6p1-gssapimitm.patch b/openssh-6.6p1-gssapimitm.patch index 8684527..2a9278d 100644 --- a/openssh-6.6p1-gssapimitm.patch +++ b/openssh-6.6p1-gssapimitm.patch @@ -13,41 +13,11 @@ # recommended to use the 'gssapi-with-mic' mechanism. Existing installations # are encouraged to upgrade as soon as possible. -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, +Index: b/auth2-gss.c +=================================================================== +--- a/auth2-gss.c ++++ b/auth2-gss.c +@@ -296,4 +296,10 @@ Authmethod method_gssapi = { &options.gss_authentication }; @@ -58,15 +28,11 @@ diff --git a/openssh-6.6p1/auth2-gss.c b/openssh-6.6p1/auth2-gss.c +}; + #endif /* GSSAPI */ -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; +Index: b/auth2.c +=================================================================== +--- a/auth2.c ++++ b/auth2.c +@@ -71,6 +71,7 @@ extern Authmethod method_kbdint; extern Authmethod method_hostbased; #ifdef GSSAPI extern Authmethod method_gssapi; @@ -74,7 +40,7 @@ diff --git a/openssh-6.6p1/auth2.c b/openssh-6.6p1/auth2.c #endif Authmethod *authmethods[] = { - &method_none, +@@ -78,6 +79,7 @@ Authmethod *authmethods[] = { &method_pubkey, #ifdef GSSAPI &method_gssapi, @@ -82,20 +48,11 @@ diff --git a/openssh-6.6p1/auth2.c b/openssh-6.6p1/auth2.c #endif &method_passwd, &method_kbdint, - &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, +Index: b/readconf.c +=================================================================== +--- a/readconf.c ++++ b/readconf.c +@@ -146,7 +146,7 @@ typedef enum { oHostKeyAlgorithms, oBindAddress, oPKCS11Provider, oClearAllForwardings, oNoHostAuthenticationForLocalhost, oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, @@ -104,17 +61,7 @@ diff --git a/openssh-6.6p1/readconf.c b/openssh-6.6p1/readconf.c oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, oSendEnv, oControlPath, oControlMaster, oControlPersist, oHashKnownHosts, - 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 }, +@@ -193,9 +193,11 @@ static struct { #if defined(GSSAPI) { "gssapiauthentication", oGssAuthentication }, { "gssapidelegatecredentials", oGssDelegateCreds }, @@ -126,17 +73,7 @@ diff --git a/openssh-6.6p1/readconf.c b/openssh-6.6p1/readconf.c #endif { "fallbacktorsh", oDeprecated }, { "usersh", oDeprecated }, - { "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; - +@@ -897,6 +899,10 @@ parse_time: case oGssDelegateCreds: intptr = &options->gss_deleg_creds; goto parse_flag; @@ -147,17 +84,7 @@ diff --git a/openssh-6.6p1/readconf.c b/openssh-6.6p1/readconf.c case oBatchMode: intptr = &options->batch_mode; - 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; +@@ -1602,6 +1608,7 @@ initialize_options(Options * options) options->challenge_response_authentication = -1; options->gss_authentication = -1; options->gss_deleg_creds = -1; @@ -165,17 +92,7 @@ diff --git a/openssh-6.6p1/readconf.c b/openssh-6.6p1/readconf.c options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->kbd_interactive_devices = NULL; - 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) +@@ -1731,6 +1738,8 @@ fill_default_options(Options * options) options->gss_authentication = 0; if (options->gss_deleg_creds == -1) options->gss_deleg_creds = 0; @@ -184,20 +101,11 @@ diff --git a/openssh-6.6p1/readconf.c b/openssh-6.6p1/readconf.c if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) - 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; +Index: b/readconf.h +=================================================================== +--- a/readconf.h ++++ b/readconf.h +@@ -46,6 +46,7 @@ typedef struct { /* Try S/Key or TIS, authentication. */ int gss_authentication; /* Try GSS authentication */ int gss_deleg_creds; /* Delegate GSS credentials */ @@ -205,99 +113,51 @@ diff --git a/openssh-6.6p1/readconf.h b/openssh-6.6p1/readconf.h int password_authentication; /* Try password * authentication. */ int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ - 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; +Index: b/servconf.c +=================================================================== +--- a/servconf.c ++++ b/servconf.c +@@ -119,6 +119,7 @@ initialize_server_options(ServerOptions 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; - 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) +@@ -279,6 +280,8 @@ fill_default_server_options(ServerOption 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) - 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, +@@ -411,7 +414,7 @@ typedef enum { + sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedKeyTypes, + sHostKeyAlgorithms, + sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, +- sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, ++ sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, sGssEnableMITM, + sAcceptEnv, sPermitTunnel, sMatch, sPermitOpen, sForceCommand, sChrootDirectory, sUsePrivilegeSeparation, sAllowAgentForwarding, - 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 +@@ -486,10 +489,12 @@ static struct { { "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 }, - { "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; +@@ -1239,6 +1244,10 @@ process_server_config_line(ServerOptions + intptr = &options->gss_strict_acceptor; goto parse_flag; + case sGssEnableMITM: @@ -307,41 +167,23 @@ diff --git a/openssh-6.6p1/servconf.c b/openssh-6.6p1/servconf.c case sPasswordAuthentication: intptr = &options->password_authentication; goto parse_flag; - - 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 +Index: b/servconf.h +=================================================================== +--- a/servconf.h ++++ b/servconf.h +@@ -119,6 +119,7 @@ typedef struct { * 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_enable_mitm; /* If true, enable old style GSSAPI */ + int gss_strict_acceptor; /* If true, restrict the GSSAPI acceptor name */ int password_authentication; /* If true, permit password * authentication. */ - 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 +Index: b/ssh_config +=================================================================== +--- a/ssh_config ++++ b/ssh_config +@@ -56,4 +56,11 @@ ForwardX11Trusted yes # PermitLocalCommand no # VisualHostKey no # ProxyCommand ssh -q -W %h:%p gateway.example.com @@ -353,15 +195,11 @@ diff --git a/openssh-6.6p1/ssh_config b/openssh-6.6p1/ssh_config +# GSSAPIEnableMITMAttack no + # RekeyLimit 1G 1h -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, +Index: b/sshconnect2.c +=================================================================== +--- a/sshconnect2.c ++++ b/sshconnect2.c +@@ -326,6 +326,11 @@ Authmethod authmethods[] = { NULL, &options.gss_authentication, NULL}, @@ -373,17 +211,7 @@ diff --git a/openssh-6.6p1/sshconnect2.c b/openssh-6.6p1/sshconnect2.c #endif {"hostbased", userauth_hostbased, - 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); - } +@@ -703,7 +708,9 @@ process_gssapi_token(void *ctxt, gss_buf if (status == GSS_S_COMPLETE) { /* send either complete or MIC, depending on mechanism */ @@ -394,20 +222,11 @@ diff --git a/openssh-6.6p1/sshconnect2.c b/openssh-6.6p1/sshconnect2.c packet_start(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE); packet_send(); } else { - 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 +Index: b/sshd_config +=================================================================== +--- a/sshd_config ++++ b/sshd_config +@@ -85,6 +85,13 @@ PasswordAuthentication no #GSSAPIAuthentication no #GSSAPICleanupCredentials yes @@ -421,8 +240,3 @@ diff --git a/openssh-6.6p1/sshd_config b/openssh-6.6p1/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 diff --git a/openssh-6.6p1-ldap.patch b/openssh-6.6p1-ldap.patch index a91ff94..5e3f7a1 100644 --- a/openssh-6.6p1-ldap.patch +++ b/openssh-6.6p1-ldap.patch @@ -1,26 +1,14 @@ -# Helper app for retrieving keys from a LDAP server -# by Jan F. Chadima -# -# 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 @@ +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 @@ + +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 @@ -28,8 +16,7 @@ new file mode 100644 + - 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 @@ -49,8 +36,8 @@ new file mode 100644 + sshPublicKey: command="kill -9 1" ssh-rss AAAAM5... +4) on the ssh side set in sshd_config + * Set up the backend -+ AuthorizedKeysCommand "@LIBEXECDIR@/ssh-ldap-wrapper" -+ AuthorizedKeysCommandRunAs ++ AuthorizedKeysCommand /usr/libexec/openssh/ssh-ldap-wrapper ++ AuthorizedKeysCommandUser + * Do not forget to set + PubkeyAuthentication yes + * Swith off unnecessary auth methods @@ -61,7 +48,10 @@ new file mode 100644 + * There is a possibility to change ldap.conf location + * There are some debug options + * Example -+ @LIBEXECDIR@/ssh-ldap-wrapper -s -f /etc/ldap.conf -w -d >> /tmp/ldapdebuglog.txt ++ /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 + +HOW TO MIGRATE FROM LPK + @@ -77,20 +67,28 @@ new file mode 100644 + * ssh-ldap-helper -d -d -d -d -s +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. @@ -109,8 +107,7 @@ new file mode 100644 + * 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 @@ -121,15 +118,16 @@ new file mode 100644 + - frederic peters. + - Finlay dobbie. + - Stefan Fisher. -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 ++ - Robin H. Johnson. ++ - Adrian Bridgett. ++ ++5) Author ++ Jan F. Chadima ++ +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 ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass SFTP_SERVER=$(libexecdir)/sftp-server SSH_KEYSIGN=$(libexecdir)/ssh-keysign @@ -138,38 +136,18 @@ diff --git a/openssh-6.6p1/Makefile.in b/openssh-6.6p1/Makefile.in SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper PRIVSEP_PATH=@PRIVSEP_PATH@ SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ - 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@ +@@ -61,8 +63,9 @@ 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) - 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 \ + LIBOPENSSH_OBJS=\ + ssh_api.o \ +@@ -112,8 +115,8 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passw sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \ sandbox-seccomp-filter.o sandbox-capsicum.o @@ -180,55 +158,28 @@ diff --git a/openssh-6.6p1/Makefile.in b/openssh-6.6p1/Makefile.in MANTYPE = @MANTYPE@ CONFIGFILES=sshd_config.out ssh_config.out moduli.out - 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) - +@@ -184,6 +187,9 @@ ssh-keysign$(EXEEXT): $(LIBCOMPAT) libss 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) -+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) +@@ -311,6 +317,10 @@ install-files: $(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 - $(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 +@@ -327,6 +337,10 @@ install-files: $(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 @@ -239,17 +190,7 @@ diff --git a/openssh-6.6p1/Makefile.in b/openssh-6.6p1/Makefile.in -rm -f $(DESTDIR)$(bindir)/slogin ln -s ./ssh$(EXEEXT) $(DESTDIR)$(bindir)/slogin -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1 - 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 ; \ +@@ -356,6 +370,13 @@ install-sysconf: else \ echo "$(DESTDIR)$(sysconfdir)/moduli already exists, install will not overwrite"; \ fi @@ -263,17 +204,7 @@ diff --git a/openssh-6.6p1/Makefile.in b/openssh-6.6p1/Makefile.in host-key: ssh-keygen$(EXEEXT) @if [ -z "$(DESTDIR)" ] ; then \ - 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) +@@ -419,6 +440,8 @@ uninstall: -rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) -rm -f $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT) -rm -f $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT) @@ -282,34 +213,20 @@ diff --git a/openssh-6.6p1/Makefile.in b/openssh-6.6p1/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 - -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 +@@ -430,6 +453,7 @@ uninstall: -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/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 ] - ) + 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 +# Check whether user wants LDAP support +LDAP_MSG="no" @@ -411,18 +328,12 @@ diff --git a/openssh-6.6p1/configure.ac b/openssh-6.6p1/configure.ac +) +AC_SUBST(INSTALL_SSH_LDAP_HELPER) + - 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 + 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 @@ -0,0 +1,155 @@ +/* $OpenBSD: ssh-pka-ldap.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ +/* @@ -579,10 +490,9 @@ new file mode 100644 +void *buffer_get_string(Buffer *b, u_int *l) { return NULL; } +void buffer_put_string(Buffer *b, const void *f, u_int l) {} + -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 +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 @@ -0,0 +1,32 @@ +/* $OpenBSD: ldap-helper.h,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ +/* @@ -616,11 +526,10 @@ new file mode 100644 +extern int config_warning_config_file; + +#endif /* LDAP_HELPER_H */ -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 @@ +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 @@ +# $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 @@ -709,11 +618,17 @@ new file mode 100644 +#tls_cert +#tls_key + -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 @@ ++# 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 @@ +/* $OpenBSD: ldapbody.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ +/* + * Copyright (c) 2009 Jan F. Chadima. All rights reserved. @@ -747,8 +662,9 @@ new file mode 100644 +#include "ldapbody.h" +#include +#include ++#include "misc.h" + -+#define LDAPSEARCH_FORMAT "(&(objectclass=posixAccount)(objectclass=ldapPublicKey)(uid=%s)%s)" ++#define LDAPSEARCH_FORMAT "(&(objectclass=%c)(objectclass=ldapPublicKey)(uid=%u)%f)" +#define PUBKEYATTR "sshPublicKey" +#define LDAP_LOGFILE "%s/ldap.%d" + @@ -882,7 +798,7 @@ new file mode 100644 + ber_set_option (NULL, LBER_OPT_DEBUG_LEVEL, &options.debug); +#endif /* LBER_OPT_DEBUG_LEVEL */ +#ifdef LDAP_OPT_DEBUG_LEVEL -+ ldap_set_option (NULL, LDAP_OPT_DEBUG_LEVEL, &options.debug); ++ (void) ldap_set_option (NULL, LDAP_OPT_DEBUG_LEVEL, &options.debug); +#endif /* LDAP_OPT_DEBUG_LEVEL */ + debug3 ("Set LDAP debug to %d", options.debug); + } @@ -1135,8 +1051,8 @@ new file mode 100644 +process_user (const char *user, FILE *output) +{ + LDAPMessage *res, *e; -+ char *buffer; -+ int bufflen, rc, i; ++ char *buffer, *format; ++ int rc, i; + struct timeval timeout; + + debug ("LDAP process user"); @@ -1149,12 +1065,10 @@ new file mode 100644 + } + + /* build filter for LDAP request */ -+ 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; ++ 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); + + debug3 ("LDAP search scope = %d %s", options.scope, buffer); + @@ -1208,10 +1122,9 @@ new file mode 100644 + return; +} + -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 +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 @@ -0,0 +1,37 @@ +/* $OpenBSD: ldapbody.h,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ +/* @@ -1250,11 +1163,10 @@ new file mode 100644 + +#endif /* LDAPBODY_H */ + -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 @@ +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 @@ +/* $OpenBSD: ldapconf.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ +/* + * Copyright (c) 2009 Jan F. Chadima. All rights reserved. @@ -1298,8 +1210,8 @@ new file mode 100644 + 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, -+ lDeprecated, lUnsupported ++ lTLS_RandFile, lLogDir, lDebug, lSSH_Filter, lSearch_Format, ++ lAccountClass, lDeprecated, lUnsupported +} OpCodes; + +/* Textual representations of the tokens. */ @@ -1351,6 +1263,8 @@ new file mode 100644 + { "LogDir", lLogDir }, + { "Debug", lDebug }, + { "SSH_Filter", lSSH_Filter }, ++ { "search_format", lSearch_Format }, ++ { "AccountClass", lAccountClass }, + { NULL, lBadOption } +}; + @@ -1377,6 +1291,35 @@ new file mode 100644 + 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. @@ -1400,11 +1343,11 @@ new file mode 100644 + + s = line; + /* Get the keyword. (Each line is supposed to begin with a keyword). */ -+ if ((keyword = strdelim(&s)) == NULL) ++ if ((keyword = ldap_strdelim(&s)) == NULL) + return 0; + /* Ignore leading whitespace. */ + if (*keyword == '\0') -+ keyword = strdelim(&s); ++ keyword = ldap_strdelim(&s); + if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#') + return 0; + @@ -1440,7 +1383,7 @@ new file mode 100644 + case lBindPW: + charptr = &options.bindpw; +parse_string: -+ arg = strdelim(&s); ++ arg = ldap_strdelim(&s); + if (!arg || *arg == '\0') + fatal("%.200s line %d: Missing argument.", filename, linenum); + if (*charptr == NULL) @@ -1453,7 +1396,7 @@ new file mode 100644 + + case lScope: + intptr = &options.scope; -+ arg = strdelim(&s); ++ arg = ldap_strdelim(&s); + if (!arg || *arg == '\0') + fatal("%.200s line %d: Missing sub/one/base argument.", filename, linenum); + value = 0; /* To avoid compiler warning... */ @@ -1471,7 +1414,7 @@ new file mode 100644 + + case lDeref: + intptr = &options.scope; -+ arg = strdelim(&s); ++ arg = ldap_strdelim(&s); + if (!arg || *arg == '\0') + fatal("%.200s line %d: Missing never/searching/finding/always argument.", filename, linenum); + value = 0; /* To avoid compiler warning... */ @@ -1492,7 +1435,7 @@ new file mode 100644 + case lPort: + intptr = &options.port; +parse_int: -+ arg = strdelim(&s); ++ arg = ldap_strdelim(&s); + if (!arg || *arg == '\0') + fatal("%.200s line %d: Missing argument.", filename, linenum); + if (arg[0] < '0' || arg[0] > '9') @@ -1509,7 +1452,7 @@ new file mode 100644 + case lTimeLimit: + intptr = &options.timelimit; +parse_time: -+ arg = strdelim(&s); ++ arg = ldap_strdelim(&s); + if (!arg || *arg == '\0') + fatal("%s line %d: missing time value.", + filename, linenum); @@ -1530,7 +1473,7 @@ new file mode 100644 + + case lBind_Policy: + intptr = &options.bind_policy; -+ arg = strdelim(&s); ++ arg = ldap_strdelim(&s); + if (!arg || *arg == '\0') + fatal("%.200s line %d: Missing soft/hard argument.", filename, linenum); + value = 0; /* To avoid compiler warning... */ @@ -1541,6 +1484,7 @@ new file mode 100644 + else + fatal("%.200s line %d: Bad soft/hard argument.", filename, linenum); + if (*intptr == -1) ++ *intptr = value; + break; + + case lSSLPath: @@ -1549,7 +1493,7 @@ new file mode 100644 + + case lSSL: + intptr = &options.ssl; -+ arg = strdelim(&s); ++ arg = ldap_strdelim(&s); + if (!arg || *arg == '\0') + fatal("%.200s line %d: Missing yes/no/start_tls argument.", filename, linenum); + value = 0; /* To avoid compiler warning... */ @@ -1568,7 +1512,7 @@ new file mode 100644 + case lReferrals: + intptr = &options.referrals; +parse_flag: -+ arg = strdelim(&s); ++ arg = ldap_strdelim(&s); + if (!arg || *arg == '\0') + fatal("%.200s line %d: Missing yes/no argument.", filename, linenum); + value = 0; /* To avoid compiler warning... */ @@ -1588,7 +1532,7 @@ new file mode 100644 + + case lTLS_CheckPeer: + intptr = &options.tls_checkpeer; -+ arg = strdelim(&s); ++ arg = ldap_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... */ @@ -1605,6 +1549,7 @@ new file mode 100644 + else + fatal("%.200s line %d: Bad never/hard/demand/alow/try argument.", filename, linenum); + if (*intptr == -1) ++ *intptr = value; + break; + + case lTLS_CaCertFile: @@ -1643,6 +1588,14 @@ new file mode 100644 + 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); @@ -1658,7 +1611,7 @@ new file mode 100644 + } + + /* Check that there is no garbage at end of line. */ -+ if ((arg = strdelim(&s)) != NULL && *arg != '\0') { ++ if ((arg = ldap_strdelim(&s)) != NULL && *arg != '\0') { + fatal("%.200s line %d: garbage at end of line; \"%.200s\".", + filename, linenum, arg); + } @@ -1676,7 +1629,7 @@ new file mode 100644 +{ + FILE *f; + char line[1024]; -+ int active, linenum; ++ int linenum; + int bad_options = 0; + struct stat sb; + @@ -1695,7 +1648,6 @@ new file mode 100644 + * 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. */ @@ -1746,6 +1698,8 @@ new file mode 100644 + options.logdir = NULL; + options.debug = -1; + options.ssh_filter = NULL; ++ options.search_format = NULL; ++ options.account_class = NULL; +} + +/* @@ -1788,7 +1742,7 @@ new file mode 100644 + len = snprintf (options.uri, MAXURILEN, "ldap%s://%s:%d", + (options.ssl == 0) ? "" : "s", options.host, options.port); + options.uri[MAXURILEN - 1] = 0; -+ options.uri = xrealloc (options.uri, len + 1, 1); ++ options.uri = xreallocarray(options.uri, len + 1, 1); + } + if (options.binddn == NULL) + options.binddn = ""; @@ -1816,6 +1770,8 @@ new file mode 100644 + options.debug = 0; + if (options.ssh_filter == NULL) + options.ssh_filter = ""; ++ if (options.account_class == NULL) ++ options.account_class = "posixAccount"; +} + +static const char * @@ -1935,13 +1891,14 @@ new file mode 100644 + 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 --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 @@ +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 @@ +/* $OpenBSD: ldapconf.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ +/* + * Copyright (c) 2009 Jan F. Chadima. All rights reserved. @@ -2003,6 +1960,8 @@ new file mode 100644 + char *logdir; + int debug; + char *ssh_filter; ++ char *search_format; ++ char *account_class; +} Options; + +extern Options options; @@ -2013,10 +1972,9 @@ new file mode 100644 +void dump_config(void); + +#endif /* LDAPCONF_H */ -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 +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 @@ -0,0 +1,41 @@ +/* $OpenBSD: ldapconf.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ +/* @@ -2059,10 +2017,9 @@ new file mode 100644 +#endif + +#endif /* LDAPINCLUDES_H */ -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 +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 @@ -0,0 +1,79 @@ + +#include "ldapincludes.h" @@ -2143,10 +2100,9 @@ new file mode 100644 +} +#endif + -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 +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 @@ -0,0 +1,35 @@ +/* $OpenBSD: ldapbody.h,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ +/* @@ -2183,102 +2139,9 @@ new file mode 100644 + +#endif /* LDAPMISC_H */ + -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 - #include - #include - #include - #include - - #include -@@ -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 +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 @@ -0,0 +1,21 @@ +# +# LDAP Public Key Patch schema for use with openssh-ldappubkey @@ -2301,10 +2164,9 @@ new file mode 100644 + DESC 'MANDATORY: OpenSSH LPK objectclass' + MUST ( sshPublicKey $ uid ) + ) -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 +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 @@ -0,0 +1,23 @@ +# +# LDAP Public Key Patch schema for use with openssh-ldappubkey @@ -2329,10 +2191,9 @@ new file mode 100644 + DESC 'MANDATORY: OpenSSH LPK objectclass' + MUST ( sshPublicKey $ uid ) + ) -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 +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 @@ -0,0 +1,79 @@ +.\" $OpenBSD: ssh-ldap-helper.8,v 1.1 2010/02/10 23:20:38 markus Exp $ +.\" @@ -2373,7 +2234,7 @@ new file mode 100644 +by setting +.Cm AuthorizedKeysCommand +to -+.Dq @LIBEXECDIR@/ssh-ldap-wrapper . ++.Dq /usr/libexec/ssh-ldap-wrapper . +.Pp +.Nm +is not intended to be invoked by the user, but from @@ -2413,20 +2274,18 @@ new file mode 100644 +OpenSSH 5.5 + PKA-LDAP . +.Sh AUTHORS +.An Jan F. Chadima Aq jchadima@redhat.com -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 +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 @@ -0,0 +1,4 @@ +#!/bin/sh + -+exec @LIBEXECDIR@/ssh-ldap-helper -s "$1" ++exec /usr/libexec/openssh/ssh-ldap-helper -s "$1" + -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 @@ +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 @@ +.\" $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. @@ -2785,8 +2644,17 @@ new file mode 100644 +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 serch. ++Specifies the user filter applied on the LDAP search. +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 @@ -2803,3 +2671,51 @@ new file mode 100644 +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 ++# ++# 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 ++# ++# 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 ) ) diff --git a/openssh-6.6p1-no_fork-no_pid_file.patch b/openssh-6.6p1-no_fork-no_pid_file.patch deleted file mode 100644 index 9ad6c49..0000000 --- a/openssh-6.6p1-no_fork-no_pid_file.patch +++ /dev/null @@ -1,24 +0,0 @@ -# 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); diff --git a/openssh-6.6p1-pam-check-locks.patch b/openssh-6.6p1-pam-check-locks.patch index 1ac4580..dacd3a5 100644 --- a/openssh-6.6p1-pam-check-locks.patch +++ b/openssh-6.6p1-pam-check-locks.patch @@ -2,15 +2,11 @@ # UsePAM is used # bnc#708678, FATE#312033 -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) +Index: b/auth.c +=================================================================== +--- a/auth.c ++++ b/auth.c +@@ -109,7 +109,7 @@ allowed_user(struct passwd * pw) return 0; #ifdef USE_SHADOW @@ -19,17 +15,7 @@ diff --git a/openssh-6.6p1/auth.c b/openssh-6.6p1/auth.c spw = getspnam(pw->pw_name); #ifdef HAS_SHADOW_EXPIRE if (!options.use_pam && spw != NULL && auth_shadow_acctexpired(spw)) - 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 */ +@@ -129,7 +129,7 @@ allowed_user(struct passwd * pw) #endif /* check for locked account */ @@ -38,20 +24,11 @@ diff --git a/openssh-6.6p1/auth.c b/openssh-6.6p1/auth.c int locked = 0; #ifdef LOCKED_PASSWD_STRING - 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)); +Index: b/servconf.c +=================================================================== +--- a/servconf.c ++++ b/servconf.c +@@ -74,6 +74,7 @@ initialize_server_options(ServerOptions /* Portable-specific options */ options->use_pam = -1; @@ -59,17 +36,7 @@ diff --git a/openssh-6.6p1/servconf.c b/openssh-6.6p1/servconf.c /* Standard Options */ options->num_ports = 0; - 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) - { +@@ -187,6 +188,8 @@ fill_default_server_options(ServerOption /* Portable-specific options */ if (options->use_pam == -1) options->use_pam = 0; @@ -78,36 +45,16 @@ diff --git a/openssh-6.6p1/servconf.c b/openssh-6.6p1/servconf.c /* Standard Options */ if (options->protocol == SSH_PROTO_UNKNOWN) - 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. */ +@@ -392,7 +395,7 @@ fill_default_server_options(ServerOption typedef enum { sBadOption, /* == unknown option */ /* Portable-specific options */ - sUsePAM, + sUsePAM, sUsePAMChecklocks, /* Standard Options */ - 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[] = { + sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, + sKeyRegenerationTime, sPermitRootLogin, sLogFacility, sLogLevel, +@@ -442,8 +445,10 @@ static struct { /* Portable-specific options */ #ifdef USE_PAM { "usepam", sUsePAM, SSHCFG_GLOBAL }, @@ -118,17 +65,7 @@ diff --git a/openssh-6.6p1/servconf.c b/openssh-6.6p1/servconf.c #endif { "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL }, /* Standard Options */ - { "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 */ +@@ -1004,6 +1009,9 @@ process_server_config_line(ServerOptions case sUsePAM: intptr = &options->use_pam; goto parse_flag; @@ -138,20 +75,11 @@ diff --git a/openssh-6.6p1/servconf.c b/openssh-6.6p1/servconf.c /* Standard Options */ case sBadOption: - 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]; - +Index: b/servconf.h +=================================================================== +--- a/servconf.h ++++ b/servconf.h +@@ -173,6 +173,7 @@ typedef struct { char *adm_forced_command; int use_pam; /* Enable auth via PAM */ @@ -159,22 +87,13 @@ diff --git a/openssh-6.6p1/servconf.h b/openssh-6.6p1/servconf.h int permit_tun; - 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. - +Index: b/sshd_config.0 +=================================================================== +--- a/sshd_config.0 ++++ b/sshd_config.0 +@@ -950,6 +950,14 @@ DESCRIPTION If UsePAM is enabled, you will not be able to run sshd(8) as a - non-root user. The default is ``no''. + non-root user. The default is M-bM-^@M-^\noM-bM-^@M-^]. + UsePAMCheckLocks + When set to ``yes'', the checks whether the account has been @@ -187,20 +106,11 @@ diff --git a/openssh-6.6p1/sshd_config.0 b/openssh-6.6p1/sshd_config.0 UsePrivilegeSeparation Specifies whether 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 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 +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 as a non-root user. The default is .Dq no . @@ -219,8 +129,3 @@ diff --git a/openssh-6.6p1/sshd_config.5 b/openssh-6.6p1/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 diff --git a/openssh-6.6p1-seccomp_getuid.patch b/openssh-6.6p1-seccomp_getuid.patch index 28efbcd..328f37b 100644 --- a/openssh-6.6p1-seccomp_getuid.patch +++ b/openssh-6.6p1-seccomp_getuid.patch @@ -3,27 +3,20 @@ add 'getuid' syscall to list of allowed ones to prevent the sanboxed thread from being killed by the seccomp filter -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), +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 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), diff --git a/openssh-6.6p1-seed-prng.patch b/openssh-6.6p1-seed-prng.patch index 9a99148..257f497 100644 --- a/openssh-6.6p1-seed-prng.patch +++ b/openssh-6.6p1-seed-prng.patch @@ -1,15 +1,11 @@ # extended support for (re-)seeding the OpenSSL PRNG from /dev/random # bnc#703221, FATE#312172 -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) +Index: b/audit-bsm.c +=================================================================== +--- a/audit-bsm.c ++++ b/audit-bsm.c +@@ -509,4 +509,10 @@ audit_generate_ephemeral_server_key(cons { /* not implemented */ } @@ -20,15 +16,11 @@ diff --git a/openssh-6.6p1/audit-bsm.c b/openssh-6.6p1/audit-bsm.c + /* 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 -@@ -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 */ +Index: b/audit-linux.c +=================================================================== +--- a/audit-linux.c ++++ b/audit-linux.c +@@ -407,4 +407,26 @@ audit_generate_ephemeral_server_key(cons if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0))) error("cannot write into audit"); } @@ -55,15 +47,11 @@ diff --git a/openssh-6.6p1/audit-linux.c b/openssh-6.6p1/audit-linux.c + 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 -@@ -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 *) +Index: b/audit.c +=================================================================== +--- a/audit.c ++++ b/audit.c +@@ -309,5 +309,11 @@ audit_generate_ephemeral_server_key(cons { debug("audit create ephemeral server key euid %d fingerprint %s", geteuid(), fp); } @@ -75,30 +63,22 @@ diff --git a/openssh-6.6p1/audit.c b/openssh-6.6p1/audit.c +} # 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 -@@ -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); +Index: b/audit.h +=================================================================== +--- a/audit.h ++++ b/audit.h +@@ -68,5 +68,6 @@ 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 */ -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" +Index: b/entropy.c +=================================================================== +--- a/entropy.c ++++ b/entropy.c +@@ -54,6 +54,7 @@ #include "pathnames.h" #include "log.h" #include "buffer.h" @@ -106,17 +86,7 @@ diff --git a/openssh-6.6p1/entropy.c b/openssh-6.6p1/entropy.c /* * Portable OpenSSH PRNG seeding: - * 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)); +@@ -229,6 +230,9 @@ seed_rng(void) memset(buf, '\0', sizeof(buf)); #endif /* OPENSSL_PRNG_ONLY */ @@ -126,32 +96,23 @@ diff --git a/openssh-6.6p1/entropy.c b/openssh-6.6p1/entropy.c if (RAND_status() != 1) fatal("PRNG is not seeded"); } -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@ +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 - 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 + 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 -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 $< - - 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 +Index: b/openbsd-compat/port-linux-prng.c +=================================================================== --- /dev/null -+++ b/openssh-6.6p1/openbsd-compat/port-linux-prng.c ++++ b/openbsd-compat/port-linux-prng.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2011 Jan F. Chadima @@ -232,15 +193,11 @@ new file mode 100644 + fatal ("EOF reading %s", random); + } +} -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. - */ - +Index: b/openbsd-compat/port-linux.h +=================================================================== +--- a/openbsd-compat/port-linux.h ++++ b/openbsd-compat/port-linux.h +@@ -19,6 +19,10 @@ #ifndef _PORT_LINUX_H #define _PORT_LINUX_H @@ -251,20 +208,11 @@ diff --git a/openssh-6.6p1/openbsd-compat/port-linux.h b/openssh-6.6p1/openbsd-c #ifdef WITH_SELINUX int ssh_selinux_enabled(void); void ssh_selinux_setup_pty(char *, const char *); - void ssh_selinux_setup_exec_context(char *); - void ssh_selinux_change_context(const char *); - void ssh_selinux_setfscreatecon(const char *); - #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 +Index: b/ssh-add.1 +=================================================================== +--- a/ssh-add.1 ++++ b/ssh-add.1 +@@ -171,6 +171,20 @@ to make this work.) Identifies the path of a .Ux Ns -domain socket used to communicate with the agent. @@ -285,20 +233,11 @@ diff --git a/openssh-6.6p1/ssh-add.1 b/openssh-6.6p1/ssh-add.1 .El .Sh FILES .Bl -tag -width Ds - .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. +Index: b/ssh-agent.1 +=================================================================== +--- a/ssh-agent.1 ++++ b/ssh-agent.1 +@@ -194,6 +194,23 @@ sockets used to contain the connection t These sockets should only be readable by the owner. The sockets should get automatically removed when the agent exits. .El @@ -322,20 +261,11 @@ diff --git a/openssh-6.6p1/ssh-agent.1 b/openssh-6.6p1/ssh-agent.1 .Sh SEE ALSO .Xr ssh 1 , .Xr ssh-add 1 , - .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. +Index: b/ssh-keygen.1 +=================================================================== +--- a/ssh-keygen.1 ++++ b/ssh-keygen.1 +@@ -842,6 +842,23 @@ Contains Diffie-Hellman groups used for The file format is described in .Xr moduli 5 . .El @@ -359,20 +289,11 @@ diff --git a/openssh-6.6p1/ssh-keygen.1 b/openssh-6.6p1/ssh-keygen.1 .Sh SEE ALSO .Xr ssh 1 , .Xr ssh-add 1 , - .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 +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 If these files exist they are assumed to contain public certificate information corresponding with the private keys above. .El @@ -396,20 +317,11 @@ diff --git a/openssh-6.6p1/ssh-keysign.8 b/openssh-6.6p1/ssh-keysign.8 .Sh SEE ALSO .Xr ssh 1 , .Xr ssh-keygen 1 , - .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 +Index: b/ssh.1 +=================================================================== +--- a/ssh.1 ++++ b/ssh.1 +@@ -1415,6 +1415,20 @@ For more information, see the .Cm PermitUserEnvironment option in .Xr sshd_config 5 . @@ -430,20 +342,11 @@ diff --git a/openssh-6.6p1/ssh.1 b/openssh-6.6p1/ssh.1 .Sh FILES .Bl -tag -width Ds -compact .It Pa ~/.rhosts - 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 +Index: b/sshd.8 +=================================================================== +--- a/sshd.8 ++++ b/sshd.8 +@@ -944,6 +944,23 @@ concurrently for different ports, this c started last). The content of this file is not sensitive; it can be world-readable. .El @@ -467,20 +370,11 @@ diff --git a/openssh-6.6p1/sshd.8 b/openssh-6.6p1/sshd.8 .Sh SEE ALSO .Xr scp 1 , .Xr sftp 1 , - .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 - #endif - #ifdef HAVE_SYS_TIME_H - # include +Index: b/sshd.c +=================================================================== +--- a/sshd.c ++++ b/sshd.c +@@ -55,6 +55,8 @@ #endif #include "openbsd-compat/sys-tree.h" #include "openbsd-compat/sys-queue.h" @@ -489,17 +383,7 @@ diff --git a/openssh-6.6p1/sshd.c b/openssh-6.6p1/sshd.c #include #include - #include - #include - #ifdef HAVE_PATHS_H - #include - #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]; +@@ -214,6 +216,13 @@ struct { } sensitive_data; /* @@ -513,17 +397,7 @@ diff --git a/openssh-6.6p1/sshd.c b/openssh-6.6p1/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. */ - 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]; +@@ -1400,6 +1409,11 @@ server_accept_loop(int *sock_in, int *so startups++; break; } @@ -535,8 +409,3 @@ diff --git a/openssh-6.6p1/sshd.c b/openssh-6.6p1/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 diff --git a/openssh-6.6p1-sftp_force_permissions.patch b/openssh-6.6p1-sftp_force_permissions.patch index 697662c..e1a6c5c 100644 --- a/openssh-6.6p1-sftp_force_permissions.patch +++ b/openssh-6.6p1-sftp_force_permissions.patch @@ -3,15 +3,11 @@ # http://lists.mindrot.org/pipermail/openssh-unix-dev/2010-November/029044.html # http://marc.info/?l=openssh-unix-dev&m=128896838930893 -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 +Index: b/sftp-server.8 +=================================================================== +--- a/sftp-server.8 ++++ b/sftp-server.8 +@@ -38,6 +38,7 @@ .Op Fl P Ar blacklisted_requests .Op Fl p Ar whitelisted_requests .Op Fl u Ar umask @@ -19,17 +15,7 @@ diff --git a/openssh-6.6p1/sftp-server.8 b/openssh-6.6p1/sftp-server.8 .Ek .Nm .Fl Q Ar protocol_feature - .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 +@@ -138,6 +139,10 @@ Sets an explicit .Xr umask 2 to be applied to newly-created files and directories, instead of the user's default mask. @@ -39,21 +25,12 @@ diff --git a/openssh-6.6p1/sftp-server.8 b/openssh-6.6p1/sftp-server.8 +777, 755, 750, 666, 644, 640, etc. Option -u is ineffective if -m is set. .El .Pp - 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; - + On some systems, +Index: b/sftp-server.c +=================================================================== +--- a/sftp-server.c ++++ b/sftp-server.c +@@ -78,6 +78,10 @@ static int readonly; /* Requests that are allowed/denied */ static char *request_whitelist, *request_blacklist; @@ -64,38 +41,18 @@ diff --git a/openssh-6.6p1/sftp-server.c b/openssh-6.6p1/sftp-server.c /* portable attributes, etc. */ typedef struct Stat Stat; - 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 */ +@@ -692,6 +696,10 @@ process_open(u_int32_t id) 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 && - ((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; - +@@ -1494,7 +1502,8 @@ sftp_server_usage(void) fprintf(stderr, "usage: %s [-ehR] [-d start_directory] [-f log_facility] " "[-l log_level]\n\t[-P blacklisted_requests] " @@ -105,17 +62,7 @@ diff --git a/openssh-6.6p1/sftp-server.c b/openssh-6.6p1/sftp-server.c " %s -Q protocol_feature\n", __progname, __progname); exit(1); - } - - 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); - +@@ -1519,7 +1528,7 @@ sftp_server_main(int argc, char **argv, pw = pwcopy(user_pw); while (!skipargs && (ch = getopt(argc, argv, @@ -124,17 +71,7 @@ diff --git a/openssh-6.6p1/sftp-server.c b/openssh-6.6p1/sftp-server.c switch (ch) { case 'Q': if (strcasecmp(optarg, "requests") != 0) { - 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)) +@@ -1579,6 +1588,13 @@ sftp_server_main(int argc, char **argv, fatal("Invalid umask \"%s\"", optarg); (void)umask((mode_t)mask); break; @@ -148,8 +85,3 @@ diff --git a/openssh-6.6p1/sftp-server.c b/openssh-6.6p1/sftp-server.c case 'h': default: sftp_server_usage(); - } - } - - log_init(__progname, log_level, log_facility, log_stderr); - diff --git a/openssh-6.6p1-sftp_homechroot.patch b/openssh-6.6p1-sftp_homechroot.patch index 71f9c83..e9af539 100644 --- a/openssh-6.6p1-sftp_homechroot.patch +++ b/openssh-6.6p1-sftp_homechroot.patch @@ -1,14 +1,10 @@ # run sftp sessions inside a chroot -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 *); +Index: b/session.c +=================================================================== +--- a/session.c ++++ b/session.c +@@ -127,6 +127,8 @@ void do_child(Session *, const char *); void do_motd(void); int check_quietlogin(Session *, const char *); @@ -17,17 +13,7 @@ diff --git a/openssh-6.6p1/session.c b/openssh-6.6p1/session.c static void do_authenticated1(Authctxt *); static void do_authenticated2(Authctxt *); - 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 */ +@@ -816,6 +818,11 @@ do_exec(Session *s, const char *command) snprintf(session_type, sizeof(session_type), "command"); } @@ -39,95 +25,78 @@ diff --git a/openssh-6.6p1/session.c b/openssh-6.6p1/session.c if (s->ttyfd != -1) { tty = s->tty; if (strncmp(tty, "/dev/", 5) == 0) - 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); +@@ -1453,6 +1460,62 @@ do_nologin(struct passwd *pw) } /* + * 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. */ - static void - safely_chroot(const char *path, uid_t uid) - { +@@ -1462,6 +1525,7 @@ safely_chroot(const char *path, uid_t ui const char *cp; - char component[MAXPATHLEN]; + char component[PATH_MAX]; struct stat st; + int last; if (*path != '/') fatal("chroot path does not begin at root"); - if (strlen(path) >= sizeof(component)) - fatal("chroot path too long"); - - /* - * Descend the path, checking that each component is a +@@ -1473,7 +1537,7 @@ safely_chroot(const char *path, uid_t ui * root-owned directory with strict permissions. */ for (cp = path; cp != NULL;) { @@ -136,12 +105,7 @@ diff --git a/openssh-6.6p1/session.c b/openssh-6.6p1/session.c strlcpy(component, path, sizeof(component)); else { cp++; - memcpy(component, path, cp - path); - component[cp - path] = '\0'; - } - - debug3("%s: checking '%s'", __func__, component); - +@@ -1486,7 +1550,7 @@ safely_chroot(const char *path, uid_t ui if (stat(component, &st) != 0) fatal("%s: stat(\"%s\"): %s", __func__, component, strerror(errno)); @@ -150,40 +114,24 @@ diff --git a/openssh-6.6p1/session.c b/openssh-6.6p1/session.c fatal("bad ownership or modes for chroot " "directory %s\"%s\"", cp == NULL ? "" : "component ", component); - if (!S_ISDIR(st.st_mode)) - fatal("chroot path %s\"%s\" is not a directory", +@@ -1495,6 +1559,13 @@ safely_chroot(const char *path, uid_t ui 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\": " - "%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 +Index: b/sftp-chrootenv.h +=================================================================== --- /dev/null -+++ b/openssh-6.6p1/sftp-chrootenv.h ++++ b/sftp-chrootenv.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2009 Jan F Chadima. All rights reserved. @@ -215,15 +163,11 @@ new file mode 100644 + +#endif + -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" +Index: b/sftp-common.c +=================================================================== +--- a/sftp-common.c ++++ b/sftp-common.c +@@ -48,6 +48,7 @@ #include "sftp.h" #include "sftp-common.h" @@ -231,17 +175,7 @@ diff --git a/openssh-6.6p1/sftp-common.c b/openssh-6.6p1/sftp-common.c /* Clear contents of attributes structure */ void - 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]; +@@ -221,13 +222,13 @@ ls_file(const char *name, const struct s time_t now; strmode(st->st_mode, mode); @@ -257,20 +191,11 @@ diff --git a/openssh-6.6p1/sftp-common.c b/openssh-6.6p1/sftp-common.c group = group_from_gid(st->st_gid, 0); } else { snprintf(gbuf, sizeof gbuf, "%u", (u_int)st->st_gid); - 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 - #include +Index: b/sftp-server-main.c +=================================================================== +--- a/sftp-server-main.c ++++ b/sftp-server-main.c +@@ -22,11 +22,14 @@ #include #include #include @@ -285,20 +210,11 @@ diff --git a/openssh-6.6p1/sftp-server-main.c b/openssh-6.6p1/sftp-server-main.c void cleanup_exit(int i) { - 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 */ +Index: b/sftp.c +=================================================================== +--- a/sftp.c ++++ b/sftp.c +@@ -117,6 +117,8 @@ int remote_glob(struct sftp_conn *, cons extern char *__progname; @@ -307,22 +223,13 @@ diff --git a/openssh-6.6p1/sftp.c b/openssh-6.6p1/sftp.c /* Separators for interactive commands */ #define WHITESPACE " \t\r\n" - /* 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). +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. + In the special case when only sftp is used, not ssh nor scp, it + is possible to use ChrootDirectory %h or ChrootDirectory @@ -335,20 +242,11 @@ diff --git a/openssh-6.6p1/sshd_config.0 b/openssh-6.6p1/sshd_config.0 The default is not to chroot(2). Ciphers - 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 +Index: b/sshd_config.5 +=================================================================== +--- a/sshd_config.5 ++++ b/sshd_config.5 +@@ -421,6 +421,17 @@ inside the chroot directory on some oper .Xr sftp-server 8 for details). .Pp @@ -363,11 +261,6 @@ diff --git a/openssh-6.6p1/sshd_config.5 b/openssh-6.6p1/sshd_config.5 +must fulfill the usual conditions. No aditional files are required to be present +in the directory. +.Pp - 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 , + 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). diff --git a/openssh-6.6p1.tar.gz b/openssh-6.6p1.tar.gz deleted file mode 100644 index f9e5859..0000000 --- a/openssh-6.6p1.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:48c1f0664b4534875038004cc4f3555b8329c2a81c1df48db5c517800de203bb -size 1282502 diff --git a/openssh-6.6p1.tar.gz.asc b/openssh-6.6p1.tar.gz.asc deleted file mode 100644 index defd54e..0000000 --- a/openssh-6.6p1.tar.gz.asc +++ /dev/null @@ -1,14 +0,0 @@ ------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----- diff --git a/openssh-6.7p1-audit.patch b/openssh-6.7p1-audit.patch new file mode 100644 index 0000000..3d0e959 --- /dev/null +++ b/openssh-6.7p1-audit.patch @@ -0,0 +1,2360 @@ +Index: openssh-7.1p2/audit-bsm.c +=================================================================== +--- openssh-7.1p2.orig/audit-bsm.c ++++ openssh-7.1p2/audit-bsm.c +@@ -375,10 +375,23 @@ audit_connection_from(const char *host, + #endif + } + +-void ++int + audit_run_command(const char *command) + { + /* not implemented */ ++ return 0; ++} ++ ++void ++audit_end_command(int handle, const char *command) ++{ ++ /* not implemented */ ++} ++ ++void ++audit_count_session_open(void) ++{ ++ /* not necessary */ + } + + void +@@ -393,6 +406,12 @@ audit_session_close(struct logininfo *li + /* not implemented */ + } + ++int ++audit_keyusage(int host_user, const char *type, unsigned bits, char *fp, int rv) ++{ ++ /* not implemented */ ++} ++ + void + audit_event(ssh_audit_event_t event) + { +@@ -454,4 +473,40 @@ audit_event(ssh_audit_event_t event) + debug("%s: unhandled event %d", __func__, event); + } + } ++ ++void ++audit_unsupported_body(int what) ++{ ++ /* not implemented */ ++} ++ ++void ++audit_kex_body(int ctos, char *enc, char *mac, char *compress, char *pfs, pid_t pid, uid_t uid) ++{ ++ /* 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 */ +Index: openssh-7.1p2/audit.c +=================================================================== +--- openssh-7.1p2.orig/audit.c ++++ openssh-7.1p2/audit.c +@@ -28,6 +28,7 @@ + + #include + #include ++#include + + #ifdef SSH_AUDIT_EVENTS + +@@ -36,6 +37,11 @@ + #include "key.h" + #include "hostfile.h" + #include "auth.h" ++#include "ssh-gss.h" ++#include "monitor_wrap.h" ++#include "xmalloc.h" ++#include "misc.h" ++#include "servconf.h" + + /* + * Care must be taken when using this since it WILL NOT be initialized when +@@ -43,6 +49,7 @@ + * audit_event(CONNECTION_ABANDON) is called. Test for NULL before using. + */ + extern Authctxt *the_authctxt; ++extern ServerOptions options; + + /* Maybe add the audit class to struct Authmethod? */ + ssh_audit_event_t +@@ -71,13 +78,10 @@ audit_classify_auth(const char *method) + const char * + audit_username(void) + { +- static const char unknownuser[] = "(unknown user)"; +- static const char invaliduser[] = "(invalid user)"; ++ static const char unknownuser[] = "(unknown)"; + +- if (the_authctxt == NULL || the_authctxt->user == NULL) ++ if (the_authctxt == NULL || the_authctxt->user == NULL || !the_authctxt->valid) + return (unknownuser); +- if (!the_authctxt->valid) +- return (invaliduser); + return (the_authctxt->user); + } + +@@ -111,6 +115,40 @@ audit_event_lookup(ssh_audit_event_t ev) + return(event_lookup[i].name); + } + ++void ++audit_key(int host_user, int *rv, const Key *key) ++{ ++ char *fp; ++ const char *crypto_name; ++ ++ fp = sshkey_fingerprint(key, options.fingerprint_hash, 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); ++} ++ ++void ++audit_unsupported(int what) ++{ ++ PRIVSEP(audit_unsupported_body(what)); ++} ++ ++void ++audit_kex(int ctos, char *enc, char *mac, char *comp, char *pfs) ++{ ++ PRIVSEP(audit_kex_body(ctos, enc, mac, comp, pfs, 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. +@@ -140,6 +178,17 @@ audit_event(ssh_audit_event_t event) + } + + /* ++ * Called when a child process has called, or will soon call, ++ * audit_session_open. ++ */ ++void ++audit_count_session_open(void) ++{ ++ debug("audit count session open euid %d user %s", geteuid(), ++ audit_username()); ++} ++ ++/* + * Called when a user session is started. Argument is the tty allocated to + * the session, or NULL if no tty was allocated. + * +@@ -174,13 +223,91 @@ audit_session_close(struct logininfo *li + /* + * This will be called when a user runs a non-interactive command. Note that + * it may be called multiple times for a single connection since SSH2 allows +- * multiple sessions within a single connection. ++ * multiple sessions within a single connection. Returns a "handle" for ++ * audit_end_command. + */ +-void ++int + audit_run_command(const char *command) + { + debug("audit run command euid %d user %s command '%.200s'", geteuid(), + audit_username(), command); ++ return 0; ++} ++ ++/* ++ * This will be called when the non-interactive command finishes. Note that ++ * it may be called multiple times for a single connection since SSH2 allows ++ * multiple sessions within a single connection. "handle" should come from ++ * the corresponding audit_run_command. ++ */ ++void ++audit_end_command(int handle, const char *command) ++{ ++ debug("audit end nopty exec euid %d user %s command '%.200s'", geteuid(), ++ audit_username(), command); ++} ++ ++/* ++ * This will be called when user is successfully autherized by the RSA1/RSA/DSA key. ++ * ++ * Type is the key type, len is the key length(byte) and fp is the fingerprint of the key. ++ */ ++int ++audit_keyusage(int host_user, const char *type, unsigned bits, char *fp, int rv) ++{ ++ debug("audit %s key usage euid %d user %s key type %s key length %d fingerprint %s%s, result %d", ++ host_user ? "pubkey" : "hostbased", geteuid(), audit_username(), type, bits, ++ sshkey_fingerprint_prefix(), fp, rv); ++} ++ ++/* ++ * This will be called when the protocol negotiation fails. ++ */ ++void ++audit_unsupported_body(int what) ++{ ++ debug("audit unsupported protocol euid %d type %d", geteuid(), what); ++} ++ ++/* ++ * This will be called on succesfull protocol negotiation. ++ */ ++void ++audit_kex_body(int ctos, char *enc, char *mac, char *compress, char *pfs, pid_t pid, ++ uid_t uid) ++{ ++ debug("audit protocol negotiation euid %d direction %d cipher %s mac %s compresion %s pfs %s from pid %ld uid %u", ++ (unsigned)geteuid(), ctos, enc, mac, compress, pfs, (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); ++} ++ ++/* ++ * 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 */ +Index: openssh-7.1p2/audit.h +=================================================================== +--- openssh-7.1p2.orig/audit.h ++++ openssh-7.1p2/audit.h +@@ -28,6 +28,7 @@ + # define _SSH_AUDIT_H + + #include "loginrec.h" ++#include "key.h" + + enum ssh_audit_event_type { + SSH_LOGIN_EXCEED_MAXTRIES, +@@ -47,11 +48,25 @@ enum ssh_audit_event_type { + }; + typedef enum ssh_audit_event_type ssh_audit_event_t; + ++int listening_for_clients(void); ++ + void audit_connection_from(const char *, int); + void audit_event(ssh_audit_event_t); ++void audit_count_session_open(void); + 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 *); ++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 *, char *); ++void audit_unsupported_body(int); ++void audit_kex_body(int, char *, 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 */ +Index: openssh-7.1p2/audit-linux.c +=================================================================== +--- openssh-7.1p2.orig/audit-linux.c ++++ openssh-7.1p2/audit-linux.c +@@ -35,13 +35,25 @@ + + #include "log.h" + #include "audit.h" ++#include "key.h" ++#include "hostfile.h" ++#include "auth.h" ++#include "misc.h" /* servconf.h needs misc.h for struct ForwardOptions */ ++#include "servconf.h" + #include "canohost.h" ++#include "packet.h" ++#include "cipher.h" + ++#define AUDIT_LOG_SIZE 256 ++ ++extern ServerOptions options; ++extern Authctxt *the_authctxt; ++extern u_int utmp_len; + const char* audit_username(void); + +-int +-linux_audit_record_event(int uid, const char *username, +- const char *hostname, const char *ip, const char *ttyn, int success) ++static void ++linux_audit_user_logxxx(int uid, const char *username, ++ const char *hostname, const char *ip, const char *ttyn, int success, int event) + { + int audit_fd, rc, saved_errno; + +@@ -49,11 +61,11 @@ linux_audit_record_event(int uid, const + if (audit_fd < 0) { + if (errno == EINVAL || errno == EPROTONOSUPPORT || + errno == EAFNOSUPPORT) +- return 1; /* No audit support in kernel */ ++ return; /* No audit support in kernel */ + else +- return 0; /* Must prevent login */ ++ goto fatal_report; /* Must prevent login */ + } +- rc = audit_log_acct_message(audit_fd, AUDIT_USER_LOGIN, ++ rc = audit_log_acct_message(audit_fd, event, + NULL, "login", username ? username : "(unknown)", + username == NULL ? uid : -1, hostname, ip, ttyn, success); + saved_errno = errno; +@@ -65,35 +77,154 @@ linux_audit_record_event(int uid, const + if ((rc == -EPERM) && (geteuid() != 0)) + rc = 0; + errno = saved_errno; +- return (rc >= 0); ++ if (rc < 0) { ++fatal_report: ++ fatal("linux_audit_write_entry failed: %s", strerror(errno)); ++ } + } + ++static void ++linux_audit_user_auth(int uid, const char *username, ++ const char *hostname, const char *ip, const char *ttyn, int success, int event) ++{ ++ int audit_fd, rc, saved_errno; ++ static const char *event_name[] = { ++ "maxtries exceeded", ++ "root denied", ++ "success", ++ "none", ++ "password", ++ "challenge-response", ++ "pubkey", ++ "hostbased", ++ "gssapi", ++ "invalid user", ++ "nologin", ++ "connection closed", ++ "connection abandoned", ++ "unknown" ++ }; ++ ++ audit_fd = audit_open(); ++ if (audit_fd < 0) { ++ if (errno == EINVAL || errno == EPROTONOSUPPORT || ++ errno == EAFNOSUPPORT) ++ return; /* No audit support in kernel */ ++ else ++ goto fatal_report; /* Must prevent login */ ++ } ++ ++ if ((event < 0) || (event > SSH_AUDIT_UNKNOWN)) ++ event = SSH_AUDIT_UNKNOWN; ++ ++ rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH, ++ NULL, event_name[event], username ? username : "(unknown)", ++ username == NULL ? uid : -1, hostname, ip, ttyn, success); ++ saved_errno = errno; ++ close(audit_fd); ++ /* ++ * Do not report error if the error is EPERM and sshd is run as non ++ * root user. ++ */ ++ if ((rc == -EPERM) && (geteuid() != 0)) ++ rc = 0; ++ errno = saved_errno; ++ if (rc < 0) { ++fatal_report: ++ fatal("linux_audit_write_entry failed: %s", strerror(errno)); ++ } ++} ++ ++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; ++ /* is the fingerprint_prefix() still needed? ++ snprintf(buf, sizeof(buf), "key algo=%s size=%d fp=%s%s rport=%d", ++ type, bits, sshkey_fingerprint_prefix(), fp, get_remote_port()); ++ */ ++ 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 */ ++} + +-void ++int + audit_run_command(const char *command) + { +- /* not implemented */ ++ if (!user_login_count++) ++ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns), ++ NULL, "ssh", 1, AUDIT_USER_LOGIN); ++ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns), ++ NULL, "ssh", 1, AUDIT_USER_START); ++ return 0; ++} ++ ++void ++audit_end_command(int handle, const char *command) ++{ ++ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns), ++ NULL, "ssh", 1, AUDIT_USER_END); ++ if (user_login_count && !--user_login_count) ++ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns), ++ NULL, "ssh", 1, AUDIT_USER_LOGOUT); ++} ++ ++void ++audit_count_session_open(void) ++{ ++ user_login_count++; + } + + void + audit_session_open(struct logininfo *li) + { +- if (linux_audit_record_event(li->uid, NULL, li->hostname, +- NULL, li->line, 1) == 0) +- fatal("linux_audit_write_entry failed: %s", strerror(errno)); ++ if (!user_login_count++) ++ linux_audit_user_logxxx(li->uid, NULL, li->hostname, ++ NULL, li->line, 1, AUDIT_USER_LOGIN); ++ linux_audit_user_logxxx(li->uid, NULL, li->hostname, ++ NULL, li->line, 1, AUDIT_USER_START); + } + + void + audit_session_close(struct logininfo *li) + { +- /* not implemented */ ++ linux_audit_user_logxxx(li->uid, NULL, li->hostname, ++ NULL, li->line, 1, AUDIT_USER_END); ++ if (user_login_count && !--user_login_count) ++ linux_audit_user_logxxx(li->uid, NULL, li->hostname, ++ NULL, li->line, 1, AUDIT_USER_LOGOUT); + } + + void +@@ -101,21 +232,43 @@ audit_event(ssh_audit_event_t event) + { + switch(event) { + case SSH_AUTH_SUCCESS: +- case SSH_CONNECTION_CLOSE: ++ linux_audit_user_auth(-1, audit_username(), NULL, ++ get_remote_ipaddr(), "ssh", 1, event); ++ break; ++ + case SSH_NOLOGIN: +- case SSH_LOGIN_EXCEED_MAXTRIES: + case SSH_LOGIN_ROOT_DENIED: ++ linux_audit_user_auth(-1, audit_username(), NULL, ++ get_remote_ipaddr(), "ssh", 0, event); ++ linux_audit_user_logxxx(-1, audit_username(), NULL, ++ get_remote_ipaddr(), "ssh", 0, AUDIT_USER_LOGIN); + break; + ++ case SSH_LOGIN_EXCEED_MAXTRIES: + case SSH_AUTH_FAIL_NONE: + case SSH_AUTH_FAIL_PASSWD: + case SSH_AUTH_FAIL_KBDINT: + case SSH_AUTH_FAIL_PUBKEY: + case SSH_AUTH_FAIL_HOSTBASED: + case SSH_AUTH_FAIL_GSSAPI: ++ linux_audit_user_auth(-1, audit_username(), NULL, ++ get_remote_ipaddr(), "ssh", 0, event); ++ break; ++ ++ case SSH_CONNECTION_CLOSE: ++ if (user_login_count) { ++ while (user_login_count--) ++ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns), ++ NULL, "ssh", 1, AUDIT_USER_END); ++ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns), ++ NULL, "ssh", 1, AUDIT_USER_LOGOUT); ++ } ++ break; ++ ++ case SSH_CONNECTION_ABANDON: + case SSH_INVALID_USER: +- linux_audit_record_event(-1, audit_username(), NULL, +- get_remote_ipaddr(), "sshd", 0); ++ linux_audit_user_logxxx(-1, audit_username(), NULL, ++ get_remote_ipaddr(), "ssh", 0, AUDIT_USER_LOGIN); + break; + + default: +@@ -123,4 +276,135 @@ audit_event(ssh_audit_event_t event) + } + } + ++void ++audit_unsupported_body(int what) ++{ ++#ifdef AUDIT_CRYPTO_SESSION ++ char buf[AUDIT_LOG_SIZE]; ++ const static char *name[] = { "cipher", "mac", "comp" }; ++ char *s; ++ int audit_fd; ++ ++ snprintf(buf, sizeof(buf), "op=unsupported-%s direction=? cipher=? ksize=? rport=%d laddr=%s lport=%d ", ++ name[what], get_remote_port(), (s = get_local_ipaddr(packet_get_connection_in())), ++ get_local_port()); ++ 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 ++} ++ ++const static char *direction[] = { "from-server", "from-client", "both" }; ++ ++void ++audit_kex_body(int ctos, char *enc, char *mac, char *compress, char *pfs, pid_t pid, ++ uid_t uid) ++{ ++#ifdef AUDIT_CRYPTO_SESSION ++ char buf[AUDIT_LOG_SIZE]; ++ int audit_fd, audit_ok; ++ const struct sshcipher *cipher = cipher_by_name(enc); ++ char *s; ++ ++ snprintf(buf, sizeof(buf), "op=start direction=%s cipher=%s ksize=%d mac=%s pfs=%s spid=%jd suid=%jd rport=%d laddr=%s lport=%d ", ++ direction[ctos], enc, cipher ? 8 * cipher->key_len : 0, mac, pfs, ++ (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 ++} ++ ++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"); ++} ++ ++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 */ +Index: openssh-7.1p2/auditstub.c +=================================================================== +--- /dev/null ++++ openssh-7.1p2/auditstub.c +@@ -0,0 +1,50 @@ ++/* $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 ++ */ ++ ++#include ++ ++void ++audit_unsupported(int n) ++{ ++} ++ ++void ++audit_kex(int ctos, char *enc, char *mac, char *comp, char *pfs) ++{ ++} ++ ++void ++audit_session_key_free(int ctos) ++{ ++} ++ ++void ++audit_session_key_free_body(int ctos, pid_t pid, uid_t uid) ++{ ++} +Index: openssh-7.1p2/auth2.c +=================================================================== +--- openssh-7.1p2.orig/auth2.c ++++ openssh-7.1p2/auth2.c +@@ -241,9 +241,6 @@ input_userauth_request(int type, u_int32 + } 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) +Index: openssh-7.1p2/auth2-hostbased.c +=================================================================== +--- openssh-7.1p2.orig/auth2-hostbased.c ++++ openssh-7.1p2/auth2-hostbased.c +@@ -138,7 +138,7 @@ userauth_hostbased(Authctxt *authctxt) + /* test for allowed key and correct signature */ + authenticated = 0; + if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) && +- PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), ++ PRIVSEP(hostbased_key_verify(key, sig, slen, buffer_ptr(&b), + buffer_len(&b))) == 1) + authenticated = 1; + +@@ -155,6 +155,18 @@ done: + return authenticated; + } + ++int ++hostbased_key_verify(const Key *key, const u_char *sig, u_int slen, const u_char *data, u_int datalen) ++{ ++ int rv; ++ ++ rv = key_verify(key, sig, slen, data, datalen); ++#ifdef SSH_AUDIT_EVENTS ++ audit_key(0, &rv, key); ++#endif ++ return rv; ++} ++ + /* return 1 if given hostkey is allowed */ + int + hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, +Index: openssh-7.1p2/auth2-pubkey.c +=================================================================== +--- openssh-7.1p2.orig/auth2-pubkey.c ++++ openssh-7.1p2/auth2-pubkey.c +@@ -173,7 +173,7 @@ userauth_pubkey(Authctxt *authctxt) + /* test for correct signature */ + authenticated = 0; + if (PRIVSEP(user_key_allowed(authctxt->pw, key, 1)) && +- 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; + /* Record the successful key to prevent reuse */ +@@ -251,6 +251,18 @@ pubkey_auth_info(Authctxt *authctxt, con + free(extra); + } + ++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; ++} ++ + /* + * Splits 's' into an argument vector. Handles quoted string and basic + * escape characters (\\, \", \'). Caller must free the argument vector +Index: openssh-7.1p2/auth.c +=================================================================== +--- openssh-7.1p2.orig/auth.c ++++ openssh-7.1p2/auth.c +@@ -645,9 +645,6 @@ getpwnamallow(const char *user) + record_failed_login(user, + get_canonical_hostname(options.use_dns), "ssh"); + #endif +-#ifdef SSH_AUDIT_EVENTS +- audit_event(SSH_INVALID_USER); +-#endif /* SSH_AUDIT_EVENTS */ + return (NULL); + } + if (!allowed_user(pw)) +Index: openssh-7.1p2/auth.h +=================================================================== +--- openssh-7.1p2.orig/auth.h ++++ openssh-7.1p2/auth.h +@@ -192,6 +192,7 @@ void abandon_challenge_response(Authctxt + + char *expand_authorized_keys(const char *, struct passwd *pw); + char *authorized_principals_file(struct passwd *); ++int user_key_verify(const Key *, const u_char *, u_int, const u_char *, u_int); + + FILE *auth_openkeyfile(const char *, struct passwd *, int); + FILE *auth_openprincipals(const char *, struct passwd *, int); +@@ -210,6 +211,7 @@ int get_hostkey_index(Key *, int, struc + int ssh1_session_key(BIGNUM *); + int sshd_hostkey_sign(Key *, Key *, u_char **, size_t *, + const u_char *, size_t, 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))); +Index: openssh-7.1p2/auth-rsa.c +=================================================================== +--- openssh-7.1p2.orig/auth-rsa.c ++++ openssh-7.1p2/auth-rsa.c +@@ -95,7 +95,10 @@ auth_rsa_verify_response(Key *key, BIGNU + { + u_char buf[32], mdbuf[16]; + struct ssh_digest_ctx *md; +- int len; ++ int len, rv; ++#ifdef SSH_AUDIT_EVENTS ++ char *fp; ++#endif + + /* don't allow short keys */ + if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { +@@ -119,12 +122,18 @@ auth_rsa_verify_response(Key *key, BIGNU + ssh_digest_free(md); + + /* Verify that the response is the original challenge. */ +- if (timingsafe_bcmp(response, mdbuf, 16) != 0) { +- /* Wrong answer. */ +- return (0); ++ rv = timingsafe_bcmp(response, mdbuf, 16) == 0; ++ ++#ifdef SSH_AUDIT_EVENTS ++ fp = sshkey_fingerprint(key, options.fingerprint_hash, 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; + } + + /* +Index: openssh-7.1p2/cipher.c +=================================================================== +--- openssh-7.1p2.orig/cipher.c ++++ openssh-7.1p2/cipher.c +@@ -57,26 +57,6 @@ extern const EVP_CIPHER *evp_ssh1_3des(v + extern int ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int); + #endif + +-struct sshcipher { +- 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) +-#define CFLAG_AESCTR (1<<2) +-#define CFLAG_NONE (1<<3) +-#ifdef WITH_OPENSSL +- const EVP_CIPHER *(*evptype)(void); +-#else +- void *ignored; +-#endif +-}; +- + static const struct sshcipher ciphers[] = { + #ifdef WITH_SSH1 + { "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc }, +Index: openssh-7.1p2/cipher.h +=================================================================== +--- openssh-7.1p2.orig/cipher.h ++++ openssh-7.1p2/cipher.h +@@ -62,7 +62,26 @@ + #define CIPHER_ENCRYPT 1 + #define CIPHER_DECRYPT 0 + +-struct sshcipher; ++struct sshcipher { ++ 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) ++#define CFLAG_AESCTR (1<<2) ++#define CFLAG_NONE (1<<3) ++#ifdef WITH_OPENSSL ++ const EVP_CIPHER *(*evptype)(void); ++#else ++ void *ignored; ++#endif ++}; ++ + struct sshcipher_ctx { + int plaintext; + int encrypt; +Index: openssh-7.1p2/kex.c +=================================================================== +--- openssh-7.1p2.orig/kex.c ++++ openssh-7.1p2/kex.c +@@ -54,6 +54,7 @@ + #include "ssherr.h" + #include "sshbuf.h" + #include "digest.h" ++#include "audit.h" + + #if OPENSSL_VERSION_NUMBER >= 0x00907000L + # if defined(HAVE_EVP_SHA256) +@@ -534,8 +535,12 @@ choose_enc(struct sshenc *enc, char *cli + { + char *name = match_list(client, server, NULL); + +- if (name == NULL) ++ if (name == NULL) { ++#ifdef SSH_AUDIT_EVENTS ++ audit_unsupported(0); ++#endif + return SSH_ERR_NO_CIPHER_ALG_MATCH; ++ } + if ((enc->cipher = cipher_by_name(name)) == NULL) + return SSH_ERR_INTERNAL_ERROR; + enc->name = name; +@@ -553,8 +558,12 @@ choose_mac(struct ssh *ssh, struct sshma + { + char *name = match_list(client, server, NULL); + +- if (name == NULL) ++ if (name == NULL) { ++#ifdef SSH_AUDIT_EVENTS ++ audit_unsupported(1); ++#endif + return SSH_ERR_NO_MAC_ALG_MATCH; ++ } + if (mac_setup(mac, name) < 0) + return SSH_ERR_INTERNAL_ERROR; + /* truncate the key */ +@@ -571,8 +580,12 @@ choose_comp(struct sshcomp *comp, char * + { + char *name = match_list(client, server, NULL); + +- if (name == NULL) ++ if (name == NULL) { ++#ifdef SSH_AUDIT_EVENTS ++ audit_unsupported(2); ++#endif + return SSH_ERR_NO_COMPRESS_ALG_MATCH; ++ } + if (strcmp(name, "zlib@openssh.com") == 0) { + comp->type = COMP_DELAYED; + } else if (strcmp(name, "zlib") == 0) { +@@ -738,6 +751,10 @@ kex_choose_conf(struct ssh *ssh) + dh_need = MAX(dh_need, newkeys->enc.block_size); + dh_need = MAX(dh_need, newkeys->enc.iv_len); + dh_need = MAX(dh_need, newkeys->mac.key_len); ++ debug("kex: %s need=%d dh_need=%d", kex->name, need, dh_need); ++#ifdef SSH_AUDIT_EVENTS ++ audit_kex(mode, newkeys->enc.name, newkeys->mac.name, newkeys->comp.name, kex->name); ++#endif + } + /* XXX need runden? */ + kex->we_need = need; +@@ -913,3 +930,34 @@ dump_digest(char *msg, u_char *digest, i + sshbuf_dump_data(digest, len, stderr); + } + #endif ++ ++static void ++enc_destroy(struct sshenc *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(struct newkeys *newkeys) ++{ ++ if (newkeys == NULL) ++ return; ++ ++ enc_destroy(&newkeys->enc); ++ mac_destroy(&newkeys->mac); ++ memset(&newkeys->comp, 0, sizeof(newkeys->comp)); ++} ++ +Index: openssh-7.1p2/kex.h +=================================================================== +--- openssh-7.1p2.orig/kex.h ++++ openssh-7.1p2/kex.h +@@ -187,6 +187,8 @@ int kexecdh_server(struct ssh *); + int kexc25519_client(struct ssh *); + int kexc25519_server(struct ssh *); + ++void newkeys_destroy(struct newkeys *newkeys); ++ + int kex_dh_hash(const char *, const char *, + const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, + const BIGNUM *, const BIGNUM *, const BIGNUM *, u_char *, size_t *); +Index: openssh-7.1p2/key.h +=================================================================== +--- openssh-7.1p2.orig/key.h ++++ openssh-7.1p2/key.h +@@ -50,6 +50,7 @@ typedef struct sshkey Key; + #define key_ecdsa_bits_to_nid sshkey_ecdsa_bits_to_nid + #define key_ecdsa_key_to_nid sshkey_ecdsa_key_to_nid + #define key_is_cert sshkey_is_cert ++#define key_is_private sshkey_is_private + #define key_type_plain sshkey_type_plain + #define key_curve_name_to_nid sshkey_curve_name_to_nid + #define key_curve_nid_to_bits sshkey_curve_nid_to_bits +Index: openssh-7.1p2/mac.c +=================================================================== +--- openssh-7.1p2.orig/mac.c ++++ openssh-7.1p2/mac.c +@@ -226,6 +226,20 @@ mac_clear(struct sshmac *mac) + mac->umac_ctx = NULL; + } + ++void ++mac_destroy(struct sshmac *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 +Index: openssh-7.1p2/mac.h +=================================================================== +--- openssh-7.1p2.orig/mac.h ++++ openssh-7.1p2/mac.h +@@ -47,5 +47,6 @@ int mac_init(struct sshmac *); + int mac_compute(struct sshmac *, u_int32_t, const u_char *, int, + u_char *, size_t); + void mac_clear(struct sshmac *); ++void mac_destroy(struct sshmac *); + + #endif /* SSHMAC_H */ +Index: openssh-7.1p2/Makefile.in +=================================================================== +--- openssh-7.1p2.orig/Makefile.in ++++ openssh-7.1p2/Makefile.in +@@ -91,7 +91,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ + sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o blocks.o \ + kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ + kexdhc.o kexgexc.o kexecdhc.o kexc25519c.o \ +- kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o ++ kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o auditstub.o + + SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ + sshconnect.o sshconnect1.o sshconnect2.o mux.o \ +Index: openssh-7.1p2/monitor.c +=================================================================== +--- openssh-7.1p2.orig/monitor.c ++++ openssh-7.1p2/monitor.c +@@ -102,6 +102,7 @@ + #include "ssh2.h" + #include "roaming.h" + #include "authfd.h" ++#include "audit.h" + #include "match.h" + #include "ssherr.h" + +@@ -117,6 +118,8 @@ extern Buffer auth_debug; + extern int auth_debug_init; + extern Buffer loginmsg; + ++extern void destroy_sensitive_data(int); ++ + /* State exported from the child */ + static struct sshbuf *child_state; + +@@ -162,6 +165,11 @@ 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 *); +@@ -218,6 +226,10 @@ struct mon_table mon_dispatch_proto20[] + #endif + #ifdef SSH_AUDIT_EVENTS + {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, ++ {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, ++ {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, ++ {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}, +@@ -249,6 +261,11 @@ struct mon_table mon_dispatch_postauth20 + #ifdef SSH_AUDIT_EVENTS + {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, + {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command}, ++ {MONITOR_REQ_AUDIT_END_COMMAND, MON_PERMIT, mm_answer_audit_end_command}, ++ {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} + }; +@@ -281,6 +298,10 @@ struct mon_table mon_dispatch_proto15[] + #endif + #ifdef SSH_AUDIT_EVENTS + {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, ++ {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, ++ {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, ++ {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 + #endif /* WITH_SSH1 */ + {0, 0, NULL} +@@ -294,6 +315,11 @@ struct mon_table mon_dispatch_postauth15 + #ifdef SSH_AUDIT_EVENTS + {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, + {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT|MON_ONCE, mm_answer_audit_command}, ++ {MONITOR_REQ_AUDIT_END_COMMAND, MON_PERMIT, mm_answer_audit_end_command}, ++ {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 + #endif /* WITH_SSH1 */ + {0, 0, NULL} +@@ -1414,9 +1440,11 @@ mm_answer_keyverify(int sock, Buffer *m) + Key *key; + u_char *signature, *data, *blob; + u_int signaturelen, datalen, bloblen; ++ int type = 0; + int verified = 0; + int valid_data = 0; + ++ type = buffer_get_int(m); + blob = buffer_get_string(m, &bloblen); + signature = buffer_get_string(m, &signaturelen); + data = buffer_get_string(m, &datalen); +@@ -1424,6 +1452,8 @@ mm_answer_keyverify(int sock, Buffer *m) + if (hostbased_cuser == NULL || hostbased_chost == NULL || + !monitor_allowed_key(blob, bloblen)) + fatal("%s: bad key, not previously allowed", __func__); ++ if (type != key_blobtype) ++ fatal("%s: bad key type", __func__); + + key = key_from_blob(blob, bloblen); + if (key == NULL) +@@ -1444,7 +1474,17 @@ mm_answer_keyverify(int sock, Buffer *m) + if (!valid_data) + fatal("%s: bad signature data blob", __func__); + +- verified = key_verify(key, signature, signaturelen, data, datalen); ++ switch (key_blobtype) { ++ case MM_USERKEY: ++ verified = user_key_verify(key, signature, signaturelen, data, datalen); ++ break; ++ case MM_HOSTKEY: ++ verified = hostbased_key_verify(key, signature, signaturelen, data, datalen); ++ break; ++ default: ++ verified = 0; ++ break; ++ } + debug3("%s: key %p signature %s", + __func__, key, (verified == 1) ? "verified" : "unverified"); + +@@ -1505,6 +1545,12 @@ mm_session_close(Session *s) + debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd); + session_pty_cleanup2(s); + } ++#ifdef SSH_AUDIT_EVENTS ++ if (s->command != NULL) { ++ debug3("%s: command %d", __func__, s->command_handle); ++ session_end_command2(s); ++ } ++#endif + session_unused(s->self); + } + +@@ -1787,6 +1833,8 @@ mm_answer_term(int sock, Buffer *req) + sshpam_cleanup(); + #endif + ++ destroy_sensitive_data(0); ++ + while (waitpid(pmonitor->m_pid, &status, 0) == -1) + if (errno != EINTR) + exit(1); +@@ -1829,11 +1877,43 @@ mm_answer_audit_command(int socket, Buff + { + u_int len; + char *cmd; ++ Session *s; + + debug3("%s entering", __func__); + cmd = buffer_get_string(m, &len); ++ + /* sanity check command, if so how? */ +- audit_run_command(cmd); ++ s = session_new(); ++ if (s == NULL) ++ fatal("%s: error allocating a session", __func__); ++ s->command = cmd; ++ s->command_handle = audit_run_command(cmd); ++ ++ buffer_clear(m); ++ buffer_put_int(m, s->self); ++ ++ mm_request_send(socket, MONITOR_ANS_AUDIT_COMMAND, m); ++ ++ return (0); ++} ++ ++int ++mm_answer_audit_end_command(int socket, Buffer *m) ++{ ++ int handle; ++ u_int len; ++ char *cmd; ++ Session *s; ++ ++ debug3("%s entering", __func__); ++ handle = buffer_get_int(m); ++ cmd = buffer_get_string(m, &len); ++ ++ s = session_by_id(handle); ++ if (s == NULL || s->ttyfd != -1 || s->command == NULL || ++ strcmp(s->command, cmd) != 0) ++ fatal("%s: invalid handle", __func__); ++ mm_session_close(s); + free(cmd); + return (0); + } +@@ -1883,6 +1963,7 @@ monitor_apply_keystate(struct monitor *p + void + mm_get_keystate(struct monitor *pmonitor) + { ++ Buffer m; + debug3("%s: Waiting for new keys", __func__); + + if ((child_state = sshbuf_new()) == NULL) +@@ -1890,6 +1971,21 @@ mm_get_keystate(struct monitor *pmonitor + mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, + child_state); + debug3("%s: GOT new keys", __func__); ++ ++#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) ++ ; ++ + } + + +@@ -2059,3 +2155,86 @@ mm_answer_gss_userok(int sock, Buffer *m + } + #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, *pfs; ++ 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); ++ pfs = buffer_get_string(m, &len); ++ pid = buffer_get_int64(m); ++ uid = buffer_get_int64(m); ++ ++ audit_kex_body(ctos, cipher, mac, compress, pfs, pid, uid); ++ ++ free(cipher); ++ free(mac); ++ free(compress); ++ free(pfs); ++ 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; ++} ++ ++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); ++ ++ return 0; ++} ++#endif /* SSH_AUDIT_EVENTS */ +Index: openssh-7.1p2/monitor.h +=================================================================== +--- openssh-7.1p2.orig/monitor.h ++++ openssh-7.1p2/monitor.h +@@ -63,7 +63,13 @@ 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_REQ_AUDIT_EVENT = 112, ++ MONITOR_REQ_AUDIT_COMMAND = 114, MONITOR_ANS_AUDIT_COMMAND = 115, ++ MONITOR_REQ_AUDIT_END_COMMAND = 116, ++ MONITOR_REQ_AUDIT_UNSUPPORTED = 118, MONITOR_ANS_AUDIT_UNSUPPORTED = 119, ++ MONITOR_REQ_AUDIT_KEX = 120, MONITOR_ANS_AUDIT_KEX = 121, ++ MONITOR_REQ_AUDIT_SESSION_KEY_FREE = 122, MONITOR_ANS_AUDIT_SESSION_KEY_FREE = 123, ++ MONITOR_REQ_AUDIT_SERVER_KEY_FREE = 124 + + }; + +Index: openssh-7.1p2/monitor_wrap.c +=================================================================== +--- openssh-7.1p2.orig/monitor_wrap.c ++++ openssh-7.1p2/monitor_wrap.c +@@ -443,7 +443,7 @@ mm_key_allowed(enum mm_keytype type, cha + */ + + int +-mm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen) ++mm_key_verify(enum mm_keytype type, Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen) + { + Buffer m; + u_char *blob; +@@ -457,6 +457,7 @@ mm_key_verify(Key *key, u_char *sig, u_i + return (0); + + buffer_init(&m); ++ buffer_put_int(&m, type); + buffer_put_string(&m, blob, len); + buffer_put_string(&m, sig, siglen); + buffer_put_string(&m, data, datalen); +@@ -474,6 +475,18 @@ mm_key_verify(Key *key, u_char *sig, u_i + return (verified); + } + ++int ++mm_hostbased_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen) ++{ ++ return mm_key_verify(MM_HOSTKEY, key, sig, siglen, data, datalen); ++} ++ ++int ++mm_user_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen) ++{ ++ return mm_key_verify(MM_USERKEY, key, sig, siglen, data, datalen); ++} ++ + void + mm_send_keystate(struct monitor *monitor) + { +@@ -986,10 +999,11 @@ mm_audit_event(ssh_audit_event_t event) + buffer_free(&m); + } + +-void ++int + mm_audit_run_command(const char *command) + { + Buffer m; ++ int handle; + + debug3("%s entering command %s", __func__, command); + +@@ -997,6 +1011,26 @@ mm_audit_run_command(const char *command + buffer_put_cstring(&m, command); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, &m); ++ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_COMMAND, &m); ++ ++ handle = buffer_get_int(&m); ++ buffer_free(&m); ++ ++ return (handle); ++} ++ ++void ++mm_audit_end_command(int handle, const char *command) ++{ ++ Buffer m; ++ ++ debug3("%s entering command %s", __func__, command); ++ ++ buffer_init(&m); ++ buffer_put_int(&m, handle); ++ buffer_put_cstring(&m, command); ++ ++ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_END_COMMAND, &m); + buffer_free(&m); + } + #endif /* SSH_AUDIT_EVENTS */ +@@ -1087,3 +1121,70 @@ mm_ssh_gssapi_userok(char *user) + } + #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, char *fps, pid_t pid, ++ uid_t uid) ++{ ++ Buffer m; ++ ++ buffer_init(&m); ++ buffer_put_int(&m, ctos); ++ buffer_put_cstring(&m, cipher); ++ buffer_put_cstring(&m, (mac ? mac : "")); ++ buffer_put_cstring(&m, compress); ++ buffer_put_cstring(&m, fps); ++ 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); ++} ++ ++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); ++} ++ ++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); ++ buffer_free(&m); ++} ++#endif /* SSH_AUDIT_EVENTS */ +Index: openssh-7.1p2/monitor_wrap.h +=================================================================== +--- openssh-7.1p2.orig/monitor_wrap.h ++++ openssh-7.1p2/monitor_wrap.h +@@ -49,7 +49,8 @@ int mm_key_allowed(enum mm_keytype, char + int mm_user_key_allowed(struct passwd *, Key *, int); + 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 *); +@@ -74,7 +75,12 @@ void mm_sshpam_free_ctx(void *); + #ifdef SSH_AUDIT_EVENTS + #include "audit.h" + void mm_audit_event(ssh_audit_event_t); +-void mm_audit_run_command(const char *); ++int mm_audit_run_command(const char *); ++void mm_audit_end_command(int, const char *); ++void mm_audit_unsupported_body(int); ++void mm_audit_kex_body(int, char *, char *, char *, char *, pid_t, uid_t); ++void mm_audit_session_key_free_body(int, pid_t, uid_t); ++void mm_audit_destroy_sensitive_data(const char *, pid_t, uid_t); + #endif + + struct Session; +Index: openssh-7.1p2/packet.c +=================================================================== +--- openssh-7.1p2.orig/packet.c ++++ openssh-7.1p2/packet.c +@@ -67,6 +67,7 @@ + #include "key.h" /* typedefs XXX */ + + #include "xmalloc.h" ++#include "audit.h" + #include "crc32.h" + #include "deattack.h" + #include "compat.h" +@@ -447,6 +448,13 @@ ssh_packet_get_connection_out(struct ssh + return ssh->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); ++} ++ + /* + * Returns the IP-address of the remote host as a string. The returned + * string must not be freed. +@@ -477,13 +485,6 @@ ssh_packet_close(struct ssh *ssh) + if (!state->initialized) + return; + state->initialized = 0; +- if (state->connection_in == state->connection_out) { +- shutdown(state->connection_out, SHUT_RDWR); +- close(state->connection_out); +- } else { +- close(state->connection_in); +- close(state->connection_out); +- } + sshbuf_free(state->input); + sshbuf_free(state->output); + sshbuf_free(state->outgoing_packet); +@@ -515,14 +516,24 @@ ssh_packet_close(struct ssh *ssh) + inflateEnd(stream); + } + } +- if ((r = cipher_cleanup(&state->send_context)) != 0) +- error("%s: cipher_cleanup failed: %s", __func__, ssh_err(r)); +- if ((r = cipher_cleanup(&state->receive_context)) != 0) +- error("%s: cipher_cleanup failed: %s", __func__, ssh_err(r)); ++ if (packet_state_has_keys(state)) { ++ if ((r = cipher_cleanup(&state->send_context)) != 0) ++ error("%s: cipher_cleanup failed: %s", __func__, ssh_err(r)); ++ if ((r = cipher_cleanup(&state->receive_context)) != 0) ++ error("%s: cipher_cleanup failed: %s", __func__, ssh_err(r)); ++ audit_session_key_free(2); ++ } + if (ssh->remote_ipaddr) { + free(ssh->remote_ipaddr); + ssh->remote_ipaddr = NULL; + } ++ if (state->connection_in == state->connection_out) { ++ shutdown(state->connection_out, SHUT_RDWR); ++ close(state->connection_out); ++ } else { ++ close(state->connection_in); ++ close(state->connection_out); ++ } + free(ssh->state); + ssh->state = NULL; + } +@@ -942,6 +953,7 @@ ssh_set_newkeys(struct ssh *ssh, int mod + } + if (state->newkeys[mode] != NULL) { + debug("set_newkeys: rekeying"); ++ audit_session_key_free(mode); + if ((r = cipher_cleanup(cc)) != 0) + return r; + enc = &state->newkeys[mode]->enc; +@@ -2291,6 +2303,75 @@ ssh_packet_get_output(struct ssh *ssh) + return (void *)ssh->state->output; + } + ++static void ++newkeys_destroy_and_free(struct newkeys *newkeys) ++{ ++ if (newkeys == NULL) ++ return; ++ ++ free(newkeys->enc.name); ++ ++ if (newkeys->mac.enabled) { ++ mac_clear(&newkeys->mac); ++ free(newkeys->mac.name); ++ } ++ ++ free(newkeys->comp.name); ++ ++ newkeys_destroy(newkeys); ++ free(newkeys); ++} ++ ++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); ++ state->input = NULL; ++ buffer_free(state->output); ++ state->output = NULL; ++ buffer_free(state->outgoing_packet); ++ state->outgoing_packet = NULL; ++ buffer_free(state->incoming_packet); ++ state->incoming_packet = NULL; ++ if( state->compression_buffer ) { ++ buffer_free(state->compression_buffer); ++ state->compression_buffer = NULL; ++ } ++ 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 = (active_state != NULL && packet_state_has_keys(active_state->state)) ++ || (backup_state != NULL && packet_state_has_keys(backup_state->state)); ++ if (active_state != NULL) ++ packet_destroy_state(active_state->state); ++ if (backup_state != NULL) ++ packet_destroy_state(backup_state->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 ++ } ++} ++ + /* XXX TODO update roaming to new API (does not work anyway) */ + /* + * Save the state for the real connection, and use a separate state when +@@ -2300,18 +2381,12 @@ void + ssh_packet_backup_state(struct ssh *ssh, + struct ssh *backup_state) + { +- struct ssh *tmp; +- + close(ssh->state->connection_in); + ssh->state->connection_in = -1; + close(ssh->state->connection_out); + ssh->state->connection_out = -1; +- if (backup_state) +- tmp = backup_state; +- else +- tmp = ssh_alloc_session_state(); + backup_state = ssh; +- ssh = tmp; ++ ssh = ssh_alloc_session_state(); + } + + /* XXX FIXME FIXME FIXME */ +@@ -2330,9 +2405,7 @@ ssh_packet_restore_state(struct ssh *ssh + backup_state = ssh; + ssh = tmp; + ssh->state->connection_in = backup_state->state->connection_in; +- backup_state->state->connection_in = -1; + ssh->state->connection_out = backup_state->state->connection_out; +- backup_state->state->connection_out = -1; + len = sshbuf_len(backup_state->state->input); + if (len > 0) { + if ((r = sshbuf_putb(ssh->state->input, +@@ -2341,6 +2414,11 @@ ssh_packet_restore_state(struct ssh *ssh + sshbuf_reset(backup_state->state->input); + add_recv_bytes(len); + } ++ backup_state->state->connection_in = -1; ++ backup_state->state->connection_out = -1; ++ packet_destroy_state(backup_state->state); ++ free(backup_state); ++ backup_state = NULL; + } + + /* Reset after_authentication and reset compression in post-auth privsep */ +Index: openssh-7.1p2/packet.h +=================================================================== +--- openssh-7.1p2.orig/packet.h ++++ openssh-7.1p2/packet.h +@@ -189,7 +189,7 @@ int sshpkt_get_end(struct ssh *ssh); + const u_char *sshpkt_ptr(struct ssh *, size_t *lenp); + + /* OLD API */ +-extern struct ssh *active_state; ++extern struct ssh *active_state, *backup_state; + #include "opacket.h" + + #if !defined(WITH_OPENSSL) +@@ -203,4 +203,5 @@ extern struct ssh *active_state; + # undef EC_POINT + #endif + ++void packet_destroy_all(int, int); + #endif /* PACKET_H */ +Index: openssh-7.1p2/sandbox-seccomp-filter.c +=================================================================== +--- openssh-7.1p2.orig/sandbox-seccomp-filter.c ++++ openssh-7.1p2/sandbox-seccomp-filter.c +@@ -150,6 +150,12 @@ static const struct sock_filter preauth_ + #ifdef __NR_gettimeofday + SC_ALLOW(gettimeofday), + #endif ++#ifdef SSH_AUDIT_EVENTS ++ SC_ALLOW(getuid), ++#ifdef __NR_getuid32 /* not defined on x86_64 */ ++ SC_ALLOW(getuid32), ++#endif ++#endif + #ifdef __NR_madvise + SC_ALLOW(madvise), + #endif +Index: openssh-7.1p2/session.c +=================================================================== +--- openssh-7.1p2.orig/session.c ++++ openssh-7.1p2/session.c +@@ -139,7 +139,7 @@ extern int log_stderr; + extern int debug_flag; + extern u_int utmp_len; + extern int startup_pipe; +-extern void destroy_sensitive_data(void); ++extern void destroy_sensitive_data(int); + extern Buffer loginmsg; + + /* original command from peer. */ +@@ -729,6 +729,14 @@ do_exec_pty(Session *s, const char *comm + /* Parent. Close the slave side of the pseudo tty. */ + close(ttyfd); + ++#ifndef HAVE_OSF_SIA ++ /* do_login in the child did not affect state in this process, ++ compensate. From an architectural standpoint, this is extremely ++ ugly. */ ++ if (!(options.use_login && command == NULL)) ++ audit_count_session_open(); ++#endif ++ + /* Enter interactive session. */ + s->ptymaster = ptymaster; + packet_set_interactive(1, +@@ -823,15 +831,19 @@ do_exec(Session *s, const char *command) + 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->ptyfd == -1) ++ s->command_handle = PRIVSEP(audit_run_command(s->command)); + #endif + if (s->ttyfd != -1) + ret = do_exec_pty(s, command); +@@ -1684,7 +1696,10 @@ do_child(Session *s, const char *command + int r = 0; + + /* remove hostkey from the child's memory */ +- destroy_sensitive_data(); ++ destroy_sensitive_data(1); ++ /* Don't audit this - both us and the parent would be talking to the ++ monitor over a single socket, with no synchronization. */ ++ packet_destroy_all(0, 1); + + /* Force a password change */ + if (s->authctxt->force_pwchange) { +@@ -1911,6 +1926,7 @@ session_unused(int id) + sessions[id].ttyfd = -1; + sessions[id].ptymaster = -1; + sessions[id].x11_chanids = NULL; ++ sessions[id].command_handle = -1; + sessions[id].next_unused = sessions_first_unused; + sessions_first_unused = id; + } +@@ -1993,6 +2009,19 @@ session_open(Authctxt *authctxt, int cha + } + + Session * ++session_by_id(int id) ++{ ++ if (id >= 0 && id < sessions_nalloc) { ++ Session *s = &sessions[id]; ++ if (s->used) ++ return s; ++ } ++ debug("session_by_id: unknown id %d", id); ++ session_dump(); ++ return NULL; ++} ++ ++Session * + session_by_tty(char *tty) + { + int i; +@@ -2509,6 +2538,32 @@ session_exit_message(Session *s, int sta + chan_write_failed(c); + } + ++#ifdef SSH_AUDIT_EVENTS ++void ++session_end_command2(Session *s) ++{ ++ if (s->command != NULL) { ++ if (s->command_handle != -1) ++ 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) { ++ if (s->command_handle != -1) ++ 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) + { +@@ -2549,6 +2604,10 @@ session_close(Session *s) + + 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); +@@ -2763,6 +2822,15 @@ do_authenticated2(Authctxt *authctxt) + server_loop2(authctxt); + } + ++static void ++do_cleanup_one_session(Session *s) ++{ ++ session_pty_cleanup2(s); ++#ifdef SSH_AUDIT_EVENTS ++ session_end_command2(s); ++#endif ++} ++ + void + do_cleanup(Authctxt *authctxt) + { +@@ -2811,5 +2879,5 @@ do_cleanup(Authctxt *authctxt) + * or if running in monitor. + */ + if (!use_privsep || mm_is_monitor()) +- session_destroy_all(session_pty_cleanup2); ++ session_destroy_all(do_cleanup_one_session); + } +Index: openssh-7.1p2/session.h +=================================================================== +--- openssh-7.1p2.orig/session.h ++++ openssh-7.1p2/session.h +@@ -61,6 +61,12 @@ struct Session { + char *name; + char *val; + } *env; ++ ++ /* exec */ ++#ifdef SSH_AUDIT_EVENTS ++ int command_handle; ++ char *command; ++#endif + }; + + void do_authenticated(Authctxt *); +@@ -73,8 +79,10 @@ void session_close_by_pid(pid_t, int); + void session_close_by_channel(int, void *); + void session_destroy_all(void (*)(Session *)); + void session_pty_cleanup2(Session *); ++void session_end_command2(Session *); + + Session *session_new(void); ++Session *session_by_id(int); + Session *session_by_tty(char *); + void session_close(Session *); + void do_setusercontext(struct passwd *); +Index: openssh-7.1p2/sshd.c +=================================================================== +--- openssh-7.1p2.orig/sshd.c ++++ openssh-7.1p2/sshd.c +@@ -122,6 +122,7 @@ + #endif + #include "monitor_wrap.h" + #include "roaming.h" ++#include "audit.h" + #include "ssh-sandbox.h" + #include "version.h" + #include "ssherr.h" +@@ -254,7 +255,7 @@ Buffer loginmsg; + struct passwd *privsep_pw = NULL; + + /* Prototypes for various functions defined later in this file. */ +-void destroy_sensitive_data(void); ++void destroy_sensitive_data(int); + void demote_sensitive_data(void); + + #ifdef WITH_SSH1 +@@ -275,6 +276,15 @@ close_listen_socks(void) + num_listen_socks = -1; + } + ++/* ++ * Is this process listening for clients (i.e. not specific to any specific ++ * client connection?) ++ */ ++int listening_for_clients(void) ++{ ++ return num_listen_socks > 0; ++} ++ + static void + close_startup_pipes(void) + { +@@ -554,22 +564,45 @@ sshd_exchange_identification(int sock_in + } + } + +-/* Destroy the host and server keys. They will no longer be needed. */ ++/* ++ * Destroy the host and server keys. They will no longer be needed. Careful, ++ * this can be called from cleanup_exit() - i.e. from just about anywhere. ++ */ + void +-destroy_sensitive_data(void) ++destroy_sensitive_data(int privsep) + { + int i; ++ pid_t pid; ++ uid_t uid; + + if (sensitive_data.server_key) { + key_free(sensitive_data.server_key); + sensitive_data.server_key = NULL; + } ++ pid = getpid(); ++ uid = getuid(); + for (i = 0; i < options.num_host_key_files; i++) { + if (sensitive_data.host_keys[i]) { ++ char *fp; ++ ++ if (key_is_private(sensitive_data.host_keys[i])) ++ fp = sshkey_fingerprint(sensitive_data.host_keys[i], options.fingerprint_hash, 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; + } +@@ -583,6 +616,8 @@ void + demote_sensitive_data(void) + { + Key *tmp; ++ pid_t pid; ++ uid_t uid; + int i; + + if (sensitive_data.server_key) { +@@ -591,13 +626,25 @@ demote_sensitive_data(void) + sensitive_data.server_key = tmp; + } + ++ pid = getpid(); ++ uid = getuid(); + for (i = 0; i < options.num_host_key_files; i++) { + if (sensitive_data.host_keys[i]) { ++ char *fp; ++ ++ if (key_is_private(sensitive_data.host_keys[i])) ++ fp = sshkey_fingerprint(sensitive_data.host_keys[i], options.fingerprint_hash, 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 */ + } +@@ -667,7 +714,7 @@ privsep_preauth(Authctxt *authctxt) + + if (use_privsep == PRIVSEP_ON) + box = ssh_sandbox_init(pmonitor); +- pid = fork(); ++ pmonitor->m_pid = pid = fork(); + if (pid == -1) { + fatal("fork of unprivileged child failed"); + } else if (pid != 0) { +@@ -751,6 +798,12 @@ privsep_postauth(Authctxt *authctxt) + else if (pmonitor->m_pid != 0) { + verbose("User child is on pid %ld", (long)pmonitor->m_pid); + buffer_clear(&loginmsg); ++ if (*pmonitor->m_pkex != NULL ){ ++ newkeys_destroy((*pmonitor->m_pkex)->newkeys[MODE_OUT]); ++ newkeys_destroy((*pmonitor->m_pkex)->newkeys[MODE_IN]); ++ audit_session_key_free_body(2, getpid(), getuid()); ++ packet_destroy_all(0, 0); ++ } + monitor_child_postauth(pmonitor); + + /* NEVERREACHED */ +@@ -1273,6 +1326,7 @@ server_accept_loop(int *sock_in, int *so + if (received_sigterm) { + logit("Received signal %d; terminating.", + (int) received_sigterm); ++ destroy_sensitive_data(0); + close_listen_socks(); + if (options.pid_file != NULL) + unlink(options.pid_file); +@@ -2216,6 +2270,7 @@ main(int ac, char **av) + */ + if (use_privsep) { + mm_send_keystate(pmonitor); ++ packet_destroy_all(1, 1); + exit(0); + } + +@@ -2258,7 +2313,7 @@ main(int ac, char **av) + privsep_postauth(authctxt); + /* the monitor process [priv] will not return */ + if (!compat20) +- destroy_sensitive_data(); ++ destroy_sensitive_data(0); + } + + packet_set_timeout(options.client_alive_interval, +@@ -2272,6 +2327,9 @@ main(int ac, char **av) + do_authenticated(authctxt); + + /* The connection has been terminated. */ ++ packet_destroy_all(1, 1); ++ destroy_sensitive_data(1); ++ + packet_get_bytes(&ibytes, &obytes); + verbose("Transferred: sent %llu, received %llu bytes", + (unsigned long long)obytes, (unsigned long long)ibytes); +@@ -2432,6 +2490,10 @@ do_ssh1_kex(void) + if (cookie[i] != packet_get_char()) + packet_disconnect("IP Spoofing check bytes do not match."); + ++#ifdef SSH_AUDIT_EVENTS ++ audit_kex(2, cipher_name(cipher_type), "crc", "none", "none"); ++#endif ++ + debug("Encryption type: %.200s", cipher_name(cipher_type)); + + /* Get the encrypted integer. */ +@@ -2491,7 +2553,7 @@ do_ssh1_kex(void) + } + + /* Destroy the private and public keys. No longer. */ +- destroy_sensitive_data(); ++ destroy_sensitive_data(1); + + if (use_privsep) + mm_ssh1_session_id(session_id); +@@ -2614,6 +2676,16 @@ do_ssh2_kex(void) + void + cleanup_exit(int i) + { ++ static int in_cleanup = 0; ++ int is_privsep_child; ++ ++ /* cleanup_exit can be called at the very least from the privsep ++ wrappers used for auditing. Make sure we don't recurse ++ indefinitely. */ ++ if (in_cleanup) ++ _exit(i); ++ in_cleanup = 1; ++ + if (the_authctxt) { + do_cleanup(the_authctxt); + if (use_privsep && privsep_is_preauth && +@@ -2625,9 +2697,14 @@ cleanup_exit(int i) + pmonitor->m_pid, strerror(errno)); + } + } ++ is_privsep_child = use_privsep && pmonitor != NULL && pmonitor->m_pid == 0; ++ 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 (!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); +Index: openssh-7.1p2/sshkey.c +=================================================================== +--- openssh-7.1p2.orig/sshkey.c ++++ openssh-7.1p2/sshkey.c +@@ -299,6 +299,33 @@ sshkey_type_is_valid_ca(int type) + } + + int ++sshkey_is_private(const struct sshkey *k) ++{ ++ switch (k->type) { ++#ifdef WITH_OPENSSL ++ case KEY_RSA_CERT: ++ case KEY_RSA1: ++ case KEY_RSA: ++ return k->rsa->d != NULL; ++ 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 /* OPENSSL_HAS_ECC */ ++#endif /* WITH_OPENSSL */ ++ case KEY_ED25519_CERT: ++ case KEY_ED25519: ++ return (k->ed25519_pk != NULL); ++ default: ++ /* fatal("key_is_private: bad key type %d", k->type); */ ++ return 0; ++ } ++} ++ ++int + sshkey_is_cert(const struct sshkey *k) + { + if (k == NULL) +Index: openssh-7.1p2/sshkey.h +=================================================================== +--- openssh-7.1p2.orig/sshkey.h ++++ openssh-7.1p2/sshkey.h +@@ -132,6 +132,7 @@ u_int sshkey_size(const struct sshkey + int sshkey_generate(int type, u_int bits, struct sshkey **keyp); + int sshkey_from_private(const struct sshkey *, struct sshkey **); + int sshkey_type_from_name(const char *); ++int sshkey_is_private(const struct sshkey *); + int sshkey_is_cert(const struct sshkey *); + int sshkey_type_is_cert(int); + int sshkey_type_plain(int); diff --git a/openssh-7.1p2.tar.gz b/openssh-7.1p2.tar.gz new file mode 100644 index 0000000..fccea51 --- /dev/null +++ b/openssh-7.1p2.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dd75f024dcf21e06a0d6421d582690bf987a1f6323e32ad6619392f3bfde6bbd +size 1475829 diff --git a/openssh-7.1p2.tar.gz.asc b/openssh-7.1p2.tar.gz.asc new file mode 100644 index 0000000..95644fa --- /dev/null +++ b/openssh-7.1p2.tar.gz.asc @@ -0,0 +1,14 @@ +-----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----- diff --git a/openssh-askpass-gnome.changes b/openssh-askpass-gnome.changes index 3a8dbfa..34c72ba 100644 --- a/openssh-askpass-gnome.changes +++ b/openssh-askpass-gnome.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +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 diff --git a/openssh-askpass-gnome.spec b/openssh-askpass-gnome.spec index 6410b72..fcf802e 100644 --- a/openssh-askpass-gnome.spec +++ b/openssh-askpass-gnome.spec @@ -16,7 +16,15 @@ # +%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 @@ -26,15 +34,7 @@ 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 diff --git a/openssh.changes b/openssh.changes index 74240a0..11b0e0e 100644 --- a/openssh.changes +++ b/openssh.changes @@ -1,3 +1,83 @@ +------------------------------------------------------------------- +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 diff --git a/openssh.spec b/openssh.spec index d44cb90..2ebdb33 100644 --- a/openssh.spec +++ b/openssh.spec @@ -16,95 +16,46 @@ # -%if 0%{suse_version} >= 1100 +%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 %define has_fw_dir 1 -%else -%define has_fw_dir 0 -%endif - -%if 0%{suse_version} >= 1110 %define has_libselinux 1 %else +%define has_fw_dir 0 %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 -%else -%define needs_libedit 0 -%endif - -%if 0%{?suse_version} > 1140 %define has_krb_mini 1 %else +%define needs_libedit 0 %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 -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 +Version: 7.1p2 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 @@ -112,7 +63,8 @@ Source7: sshd.fw Source8: sysconfig.ssh Source9: sshd-gen-keys-start Source10: sshd.service -Patch0: openssh-6.6p1-curve25519-6.6.1p1.patch +Source42: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc +Source43: openssh.keyring Patch1: openssh-6.6p1-key-converter.patch Patch2: openssh-6.6p1-X11-forwarding.patch Patch3: openssh-6.6p1-lastlog.patch @@ -128,32 +80,52 @@ 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 -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 +# PATCH-FIX-SUSE: audit patch taken from redhat +Patch18: openssh-6.7p1-audit.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: CVE-2016-0777_CVE-2016-0778.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 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 @@ -164,7 +136,6 @@ 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 @@ -173,7 +144,6 @@ 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 @@ -183,77 +153,47 @@ Requires: openssh Hashes that together with the main package form the FIPS certifiable cryptomodule. - %prep %setup -q -%patch0 -p2 -#patch1 -p2 +%patch1 -p2 %patch2 -p2 %patch3 -p2 %patch4 -p2 %patch5 -p2 %patch6 -p2 -%patch7 -p2 -%patch8 -p2 -%patch9 -p2 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 %patch10 -p2 %patch11 -p2 %patch12 -p2 %patch13 -p2 %patch14 -p2 -%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 +%patch15 -p1 +%patch18 -p1 +%patch28 -p1 +%patch29 -p1 %patch30 -p2 -%patch31 -p2 -%patch32 -p2 +%patch31 -p1 %patch33 -p2 -%patch34 -p2 -%patch35 -p2 -%patch36 -p2 +%patch34 -p1 +%patch35 -p1 +%patch36 -p1 %patch37 -p2 -%patch38 -p2 -%patch39 -p2 -%patch40 -p0 +%patch39 -p1 +%patch17 -p1 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} \ @@ -270,7 +210,7 @@ export LDFLAGS CFLAGS CXXFLAGS CPPFLAGS --with-ssl-engine \ --with-pam \ --with-kerberos5=%{_prefix} \ - --with-privsep-path=/var/lib/empty \ + --with-privsep-path=%{_localstatedir}/lib/empty \ %if %{sandbox_seccomp} --with-sandbox=seccomp_filter \ %else @@ -291,14 +231,11 @@ export LDFLAGS CFLAGS CXXFLAGS CPPFLAGS ### configure end make %{?_smp_mflags} -#make %{?_smp_mflags} -C converter - %install -make install DESTDIR=%{buildroot} -#make install DESTDIR=%{buildroot} -C converter +make DESTDIR=%{buildroot} install %{?_smp_mflags} install -d -m 755 %{buildroot}%{_sysconfdir}/pam.d -install -d -m 755 %{buildroot}/var/lib/sshd +install -d -m 755 %{buildroot}%{_localstatedir}/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/ @@ -306,22 +243,20 @@ install -d -m 755 %{buildroot}%{_initddir} %if %{uses_systemd} install -m 0755 %{SOURCE1} . install -D -m 0644 %{SOURCE10} %{buildroot}%{_unitdir}/sshd.service -ln -s /usr/sbin/service %{buildroot}%{_sbindir}/rcsshd +ln -s %{_sbindir}/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}/var/adm/fillup-templates -install -m 644 %{SOURCE8} %{buildroot}/var/adm/fillup-templates +install -d -m 755 %{buildroot}%{_localstatedir}/adm/fillup-templates +install -m 644 %{SOURCE8} %{buildroot}%{_localstatedir}/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@/usr/libexec@%{_libexecdir}@g %{buildroot}%{_sysconfdir}/ssh/sshd_config +sed -i -e s@%{_prefix}/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 @@ -337,7 +272,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 @@ -353,7 +288,7 @@ done %pre getent group sshd >/dev/null || %{_sbindir}/groupadd -r sshd -getent passwd sshd >/dev/null || %{_sbindir}/useradd -r -g sshd -d /var/lib/sshd -s /bin/false -c "SSH daemon" sshd +getent passwd sshd >/dev/null || %{_sbindir}/useradd -r -g sshd -d %{_localstatedir}/lib/sshd -s /bin/false -c "SSH daemon" sshd %if %{uses_systemd} %service_add_pre sshd.service %endif @@ -378,7 +313,7 @@ getent passwd sshd >/dev/null || %{_sbindir}/useradd -r -g sshd -d /var/lib/sshd %service_del_postun sshd.service %else %restart_on_update sshd -%{insserv_cleanup} +%insserv_cleanup %endif %files @@ -386,36 +321,32 @@ getent passwd sshd >/dev/null || %{_sbindir}/useradd -r -g sshd -d /var/lib/sshd %exclude %{_bindir}/*.chk %exclude %{_sbindir}/*.chk %exclude %{_libexecdir}/ssh/sftp-server.chk -%dir %attr(755,root,root) /var/lib/sshd -%doc README.SuSE README.kerberos ChangeLog OVERVIEW README TODO LICENCE CREDITS +%dir %attr(755,root,root) %{_localstatedir}/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} -%doc sshd.init -%attr(0644,root,root) %config %{_unitdir}/sshd.service +%attr(0644,root,root) %{_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) %doc %{_mandir}/man1/* -%attr(0444,root,root) %doc %{_mandir}/man5/* -%attr(0444,root,root) %doc %{_mandir}/man8/* +%attr(0444,root,root) %{_mandir}/man1/* +%attr(0444,root,root) %{_mandir}/man5/* +%attr(0444,root,root) %{_mandir}/man8/* %dir %{_sysconfdir}/slp.reg.d %config %{_sysconfdir}/slp.reg.d/ssh.reg -/var/adm/fillup-templates/sysconfig.ssh +%{_localstatedir}/adm/fillup-templates/sysconfig.ssh %if %{has_fw_dir} -%if %{needs_all_dirs} %dir %{_fwdir} %dir %{_fwdefdir} -%endif %config %{_fwdefdir}/sshd %endif From b83f96744f5549a5ebc5d5a41d4d555d718a17fc1ce3e04cbd5cec1aefbd4d8b Mon Sep 17 00:00:00 2001 From: Petr Cerny Date: Wed, 10 Feb 2016 15:40:35 +0000 Subject: [PATCH 2/5] Accepting request 358392 from home:elvigia:branches:network - 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. OBS-URL: https://build.opensuse.org/request/show/358392 OBS-URL: https://build.opensuse.org/package/show/network/openssh?expand=0&rev=96 --- openssh-alloc_size.patch | 28 ++++++++++++++++++++++++++++ openssh-allow_getrandom.patch | 12 ++++++++++++ openssh-fix-b64_xx-detection.patch | 24 ++++++++++++++++++++++++ openssh.changes | 11 +++++++++++ openssh.spec | 7 +++++++ 5 files changed, 82 insertions(+) create mode 100644 openssh-alloc_size.patch create mode 100644 openssh-allow_getrandom.patch create mode 100644 openssh-fix-b64_xx-detection.patch diff --git a/openssh-alloc_size.patch b/openssh-alloc_size.patch new file mode 100644 index 0000000..369ad72 --- /dev/null +++ b/openssh-alloc_size.patch @@ -0,0 +1,28 @@ +--- 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) diff --git a/openssh-allow_getrandom.patch b/openssh-allow_getrandom.patch new file mode 100644 index 0000000..d95f1e1 --- /dev/null +++ b/openssh-allow_getrandom.patch @@ -0,0 +1,12 @@ +--- 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 diff --git a/openssh-fix-b64_xx-detection.patch b/openssh-fix-b64_xx-detection.patch new file mode 100644 index 0000000..5ccd89a --- /dev/null +++ b/openssh-fix-b64_xx-detection.patch @@ -0,0 +1,24 @@ +--- 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 ]) ++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@ diff --git a/openssh.changes b/openssh.changes index 11b0e0e..3fa3171 100644 --- a/openssh.changes +++ b/openssh.changes @@ -1,3 +1,14 @@ +------------------------------------------------------------------- +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 diff --git a/openssh.spec b/openssh.spec index 2ebdb33..844a12a 100644 --- a/openssh.spec +++ b/openssh.spec @@ -93,6 +93,9 @@ 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 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 @@ -181,7 +184,11 @@ cryptomodule. %patch36 -p1 %patch37 -p2 %patch39 -p1 +%patch40 -p1 +%patch41 -p1 +%patch42 -p1 %patch17 -p1 + cp %{SOURCE3} %{SOURCE4} . %build From c818e705cac15273b16eb877a3c08095c523cfa7974a1c74c9b12e79578e6328 Mon Sep 17 00:00:00 2001 From: Petr Cerny Date: Wed, 17 Feb 2016 19:00:04 +0000 Subject: [PATCH 3/5] bothed update, DO NOT TOUCH UNITL PROPERLY REVIEWED OBS-URL: https://build.opensuse.org/package/show/network/openssh?expand=0&rev=97 --- openssh-askpass-gnome.spec => openssh-askpass-gnome.spe_ | 0 openssh.spec => openssh.spe_ | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename openssh-askpass-gnome.spec => openssh-askpass-gnome.spe_ (100%) rename openssh.spec => openssh.spe_ (100%) diff --git a/openssh-askpass-gnome.spec b/openssh-askpass-gnome.spe_ similarity index 100% rename from openssh-askpass-gnome.spec rename to openssh-askpass-gnome.spe_ diff --git a/openssh.spec b/openssh.spe_ similarity index 100% rename from openssh.spec rename to openssh.spe_ From 13651d3d21a9b9dc6cc2a9cebe73a7bf8b65da0bcca7c78e100c96ddf2e5abbc Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Wed, 6 Apr 2016 11:34:51 +0000 Subject: [PATCH 4/5] 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 --- CVE-2016-0777_CVE-2016-0778.patch | 34 + README.SUSE => README.SuSE | 2 +- ...h-6.6p1-audit1-remove_duplicit_audit.patch | 33 + ...-audit2-better_audit_of_user_actions.patch | 867 ++++++ ...ssh-6.6p1-audit3-key_auth_usage-fips.patch | 61 + openssh-6.6p1-audit3-key_auth_usage.patch | 506 ++++ openssh-6.6p1-audit4-kex_results-fips.patch | 82 + openssh-6.6p1-audit4-kex_results.patch | 701 +++++ ...6.6p1-audit5-session_key_destruction.patch | 983 ++++++ ...-6.6p1-audit6-server_key_destruction.patch | 742 +++++ openssh-6.6p1-audit7-libaudit_compat.patch | 107 + ...h-6.6p1-audit8-libaudit_dns_timeouts.patch | 47 + openssh-6.6p1-blocksigalrm.patch | 42 +- openssh-6.6p1-curve25519-6.6.1p1.patch | 205 ++ openssh-6.6p1-disable-openssl-abi-check.patch | 27 +- openssh-6.6p1-eal3.patch | 64 +- openssh-6.6p1-fingerprint_hash.patch | 730 +++++ openssh-6.6p1-fips-checks.patch | 529 ++++ openssh-6.6p1-fips.patch | 1420 +++++---- openssh-6.6p1-gssapi_key_exchange.patch | 2658 ++++++++++++----- openssh-6.6p1-gssapimitm.patch | 324 +- openssh-6.6p1-ldap.patch | 602 ++-- openssh-6.6p1-no_fork-no_pid_file.patch | 24 + openssh-6.6p1-pam-check-locks.patch | 161 +- openssh-6.6p1-seccomp_getuid.patch | 27 +- openssh-6.6p1-seed-prng.patch | 285 +- openssh-6.6p1-sftp_force_permissions.patch | 110 +- openssh-6.6p1-sftp_homechroot.patch | 299 +- openssh-6.6p1.tar.gz | 3 + openssh-6.6p1.tar.gz.asc | 14 + openssh-6.7p1-audit.patch | 2360 --------------- openssh-7.1p2.tar.gz | 3 - openssh-7.1p2.tar.gz.asc | 14 - openssh-alloc_size.patch | 28 - openssh-allow_getrandom.patch | 12 - openssh-askpass-gnome.changes | 6 - ...s-gnome.spe_ => openssh-askpass-gnome.spec | 16 +- openssh-fix-b64_xx-detection.patch | 24 - openssh.changes | 91 - openssh.spe_ => openssh.spec | 232 +- 40 files changed, 9926 insertions(+), 4549 deletions(-) create mode 100644 CVE-2016-0777_CVE-2016-0778.patch rename README.SUSE => README.SuSE (90%) create mode 100644 openssh-6.6p1-audit1-remove_duplicit_audit.patch create mode 100644 openssh-6.6p1-audit2-better_audit_of_user_actions.patch create mode 100644 openssh-6.6p1-audit3-key_auth_usage-fips.patch create mode 100644 openssh-6.6p1-audit3-key_auth_usage.patch create mode 100644 openssh-6.6p1-audit4-kex_results-fips.patch create mode 100644 openssh-6.6p1-audit4-kex_results.patch create mode 100644 openssh-6.6p1-audit5-session_key_destruction.patch create mode 100644 openssh-6.6p1-audit6-server_key_destruction.patch create mode 100644 openssh-6.6p1-audit7-libaudit_compat.patch create mode 100644 openssh-6.6p1-audit8-libaudit_dns_timeouts.patch create mode 100644 openssh-6.6p1-curve25519-6.6.1p1.patch create mode 100644 openssh-6.6p1-fingerprint_hash.patch create mode 100644 openssh-6.6p1-fips-checks.patch create mode 100644 openssh-6.6p1-no_fork-no_pid_file.patch create mode 100644 openssh-6.6p1.tar.gz create mode 100644 openssh-6.6p1.tar.gz.asc delete mode 100644 openssh-6.7p1-audit.patch delete mode 100644 openssh-7.1p2.tar.gz delete mode 100644 openssh-7.1p2.tar.gz.asc delete mode 100644 openssh-alloc_size.patch delete mode 100644 openssh-allow_getrandom.patch rename openssh-askpass-gnome.spe_ => openssh-askpass-gnome.spec (98%) delete mode 100644 openssh-fix-b64_xx-detection.patch rename openssh.spe_ => openssh.spec (75%) diff --git a/CVE-2016-0777_CVE-2016-0778.patch b/CVE-2016-0777_CVE-2016-0778.patch new file mode 100644 index 0000000..ca2c704 --- /dev/null +++ b/CVE-2016-0777_CVE-2016-0778.patch @@ -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); + } diff --git a/README.SUSE b/README.SuSE similarity index 90% rename from README.SUSE rename to README.SuSE index 1552003..10b49da 100644 --- a/README.SUSE +++ b/README.SuSE @@ -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: diff --git a/openssh-6.6p1-audit1-remove_duplicit_audit.patch b/openssh-6.6p1-audit1-remove_duplicit_audit.patch new file mode 100644 index 0000000..96d9c54 --- /dev/null +++ b/openssh-6.6p1-audit1-remove_duplicit_audit.patch @@ -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); diff --git a/openssh-6.6p1-audit2-better_audit_of_user_actions.patch b/openssh-6.6p1-audit2-better_audit_of_user_actions.patch new file mode 100644 index 0000000..656bbe3 --- /dev/null +++ b/openssh-6.6p1-audit2-better_audit_of_user_actions.patch @@ -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 + #include + #include + + #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); + } diff --git a/openssh-6.6p1-audit3-key_auth_usage-fips.patch b/openssh-6.6p1-audit3-key_auth_usage-fips.patch new file mode 100644 index 0000000..ac95216 --- /dev/null +++ b/openssh-6.6p1-audit3-key_auth_usage-fips.patch @@ -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. + */ + diff --git a/openssh-6.6p1-audit3-key_auth_usage.patch b/openssh-6.6p1-audit3-key_auth_usage.patch new file mode 100644 index 0000000..1471ec8 --- /dev/null +++ b/openssh-6.6p1-audit3-key_auth_usage.patch @@ -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 *); diff --git a/openssh-6.6p1-audit4-kex_results-fips.patch b/openssh-6.6p1-audit4-kex_results-fips.patch new file mode 100644 index 0000000..7f781d7 --- /dev/null +++ b/openssh-6.6p1-audit4-kex_results-fips.patch @@ -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 + #include + int allow_severity; + int deny_severity; + #endif /* LIBWRAP */ + + #ifndef O_NOCTTY diff --git a/openssh-6.6p1-audit4-kex_results.patch b/openssh-6.6p1-audit4-kex_results.patch new file mode 100644 index 0000000..d6bb569 --- /dev/null +++ b/openssh-6.6p1-audit4-kex_results.patch @@ -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 + #include ++#include + + #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 ++ */ ++ ++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 : "", + 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(); diff --git a/openssh-6.6p1-audit5-session_key_destruction.patch b/openssh-6.6p1-audit5-session_key_destruction.patch new file mode 100644 index 0000000..cee4029 --- /dev/null +++ b/openssh-6.6p1-audit5-session_key_destruction.patch @@ -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 + */ + ++#include ++ + 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 + #include + #include + #include + #include + #include + + #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); + } diff --git a/openssh-6.6p1-audit6-server_key_destruction.patch b/openssh-6.6p1-audit6-server_key_destruction.patch new file mode 100644 index 0000000..73821e8 --- /dev/null +++ b/openssh-6.6p1-audit6-server_key_destruction.patch @@ -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); diff --git a/openssh-6.6p1-audit7-libaudit_compat.patch b/openssh-6.6p1-audit7-libaudit_compat.patch new file mode 100644 index 0000000..ce46452 --- /dev/null +++ b/openssh-6.6p1-audit7-libaudit_compat.patch @@ -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 + */ + + #include "includes.h" + #if defined(USE_LINUX_AUDIT) + #include ++#include "compat-libaudit.h" + #include + #include + + #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 ++ * Rickard E. (Rik) Faith ++ */ ++#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_ */ ++ diff --git a/openssh-6.6p1-audit8-libaudit_dns_timeouts.patch b/openssh-6.6p1-audit8-libaudit_dns_timeouts.patch new file mode 100644 index 0000000..c199c65 --- /dev/null +++ b/openssh-6.6p1-audit8-libaudit_dns_timeouts.patch @@ -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; diff --git a/openssh-6.6p1-blocksigalrm.patch b/openssh-6.6p1-blocksigalrm.patch index 2727eaf..1cd7f05 100644 --- a/openssh-6.6p1-blocksigalrm.patch +++ b/openssh-6.6p1-blocksigalrm.patch @@ -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 + #include + #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) + # include #endif + #include "xmalloc.h" #include "log.h" +#include 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 diff --git a/openssh-6.6p1-curve25519-6.6.1p1.patch b/openssh-6.6p1-curve25519-6.6.1p1.patch new file mode 100644 index 0000000..7eb8086 --- /dev/null +++ b/openssh-6.6p1-curve25519-6.6.1p1.patch @@ -0,0 +1,205 @@ +# Date: Sun, 20 Apr 2014 17:14:08 +1000 (EST) +# From: Damien Miller +# To: openssh-unix-dev@mindrot.org +# Subject: bad bignum encoding for curve25519-sha256@libssh.org +# Message-ID: +# +# 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 + * Copyright (c) 1995 Tatu Ylonen , 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 diff --git a/openssh-6.6p1-disable-openssl-abi-check.patch b/openssh-6.6p1-disable-openssl-abi-check.patch index ff94de7..61ce8d5 100644 --- a/openssh-6.6p1-disable-openssl-abi-check.patch +++ b/openssh-6.6p1-disable-openssl-abi-check.patch @@ -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"); diff --git a/openssh-6.6p1-eal3.patch b/openssh-6.6p1-eal3.patch index 871b50c..a3058d3 100644 --- a/openssh-6.6p1-eal3.patch +++ b/openssh-6.6p1-eal3.patch @@ -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 diff --git a/openssh-6.6p1-fingerprint_hash.patch b/openssh-6.6p1-fingerprint_hash.patch new file mode 100644 index 0000000..7a0a76f --- /dev/null +++ b/openssh-6.6p1-fingerprint_hash.patch @@ -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 + +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; + } diff --git a/openssh-6.6p1-fips-checks.patch b/openssh-6.6p1-fips-checks.patch new file mode 100644 index 0000000..3c78a2a --- /dev/null +++ b/openssh-6.6p1-fips-checks.patch @@ -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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "digest.h" ++#include "fips.h" ++ ++#include ++ ++#define PROC_NAME_LEN 64 ++ ++static const char *argv0; ++ ++void ++print_help_exit(int ev) ++{ ++ fprintf(stderr, "%s <-c|-w> \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 ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include + + #include ++#include ++ ++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; diff --git a/openssh-6.6p1-fips.patch b/openssh-6.6p1-fips.patch index a7573a7..21e675f 100644 --- a/openssh-6.6p1-fips.patch +++ b/openssh-6.6p1-fips.patch @@ -1,22 +1,247 @@ -Index: openssh-7.1p2/cipher.c -=================================================================== ---- openssh-7.1p2.orig/cipher.c -+++ openssh-7.1p2/cipher.c -@@ -39,6 +39,8 @@ +# comply with FIPS 140-2 by using only approved crypto algorithms +# when OpenSSL is detected to be running in FIPS mode +# +# HG changeset patch +# Parent 844066cb9c0ec2b10eb1ace7134f7bced7cc802d + +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 +@@ -71,17 +71,18 @@ LIBSSH_OBJS=authfd.o authfile.o bufaux.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 \ + 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 ++ sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o blocks.o \ ++ fips.o - #include + SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ + sshconnect.o sshconnect1.o sshconnect2.o mux.o \ + roaming_common.o roaming_client.o -+#include + 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/auth-rsa.c b/openssh-6.6p1/auth-rsa.c +--- a/openssh-6.6p1/auth-rsa.c ++++ b/openssh-6.6p1/auth-rsa.c +@@ -44,16 +44,18 @@ + #include "ssh-gss.h" + #endif + #include "monitor_wrap.h" + #include "ssh.h" + #include "misc.h" + + #include "digest.h" + ++#include "fips.h" + - #include + /* import */ + extern ServerOptions options; + + /* + * Session identifier that is used to bind key exchange and authentication + * responses to a particular session. + */ + extern u_char session_id[16]; +@@ -84,45 +86,52 @@ auth_rsa_generate_challenge(Key *key) + if (BN_mod(challenge, challenge, key->rsa->n, ctx) == 0) + fatal("auth_rsa_generate_challenge: BN_mod failed"); + BN_CTX_free(ctx); + + return challenge; + } + + int +-auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16]) ++auth_rsa_verify_response(Key *key, BIGNUM *challenge, ++ u_char response[SSH_DIGEST_MAX_LENGTH]) + { +- u_char buf[32], mdbuf[16]; ++ 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; + + /* 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); + } + +- /* The response is MD5 of decrypted challenge plus session id. */ ++ dgst = fips_correct_dgst(SSH_DIGEST_MD5); ++ dgst_len = ssh_digest_bytes(dgst); ++ ++ /* The response is a hash of decrypted challenge plus session id. ++ * Normally this is MD5, in FIPS mode a stronger function is used. */ + len = BN_num_bytes(challenge); +- if (len <= 0 || len > 32) ++ if (len <= 0 || (unsigned int)len > (2 * dgst_len)) + fatal("%s: bad challenge length %d", __func__, len); +- memset(buf, 0, 32); +- BN_bn2bin(challenge, buf + 32 - len); +- if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL || +- ssh_digest_update(md, buf, 32) < 0 || +- ssh_digest_update(md, session_id, 16) < 0 || ++ memset(buf, 0, sizeof(buf)); ++ BN_bn2bin(challenge, buf + 2 * dgst_len - len); ++ 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, 16) != 0) { ++ if (timingsafe_bcmp(response, mdbuf, dgst_len) != 0) { + /* Wrong answer. */ + return (0); + } + /* Correct answer. */ + return (1); + } + + /* +@@ -130,17 +139,17 @@ auth_rsa_verify_response(Key *key, BIGNU + * and returns true (non-zero) if the client gave the correct answer to + * our challenge; returns zero if the client gives a wrong answer. + */ + + int + auth_rsa_challenge_dialog(Key *key) + { + BIGNUM *challenge, *encrypted_challenge; +- u_char response[16]; ++ u_char response[SSH_DIGEST_MAX_LENGTH]; + int i, success; + + if ((encrypted_challenge = BN_new()) == NULL) + fatal("auth_rsa_challenge_dialog: BN_new() failed"); + + challenge = PRIVSEP(auth_rsa_generate_challenge(key)); + + /* Encrypt the challenge with the public key. */ +@@ -150,17 +159,17 @@ auth_rsa_challenge_dialog(Key *key) + packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE); + packet_put_bignum(encrypted_challenge); + packet_send(); + BN_clear_free(encrypted_challenge); + packet_write_wait(); + + /* Wait for a response. */ + packet_read_expect(SSH_CMSG_AUTH_RSA_RESPONSE); +- for (i = 0; i < 16; i++) ++ for (i = 0; i < ssh_digest_bytes(fips_dgst_min()); i++) + response[i] = (u_char)packet_get_char(); + packet_check_eom(); + + success = PRIVSEP(auth_rsa_verify_response(key, challenge, response)); + BN_clear_free(challenge); + return (success); + } + +diff --git a/openssh-6.6p1/cipher-ctr.c b/openssh-6.6p1/cipher-ctr.c +--- a/openssh-6.6p1/cipher-ctr.c ++++ b/openssh-6.6p1/cipher-ctr.c +@@ -22,16 +22,18 @@ #include - #include -@@ -99,6 +101,26 @@ static const struct sshcipher ciphers[] + #include + + #include + + #include "xmalloc.h" + #include "log.h" + ++#include "fips.h" ++ + /* compatibility with old or broken OpenSSL versions */ + #include "openbsd-compat/openssl-compat.h" + + #ifndef USE_BUILTIN_RIJNDAEL + #include + #endif + + struct ssh_aes_ctr_ctx +@@ -134,13 +136,15 @@ evp_aes_128_ctr(void) + aes_ctr.iv_len = AES_BLOCK_SIZE; + aes_ctr.key_len = 16; + aes_ctr.init = ssh_aes_ctr_init; + aes_ctr.cleanup = ssh_aes_ctr_cleanup; + aes_ctr.do_cipher = ssh_aes_ctr; + #ifndef SSH_OLD_EVP + aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | + EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV; ++ if (fips_mode()) ++ aes_ctr.flags |= EVP_CIPH_FLAG_FIPS; + #endif + return (&aes_ctr); + } + + #endif /* OPENSSL_HAVE_EVPCTR */ +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 +@@ -45,16 +45,18 @@ + + #include "xmalloc.h" + #include "log.h" + #include "misc.h" + #include "cipher.h" + #include "buffer.h" + #include "digest.h" + ++#include "fips.h" ++ + /* 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 { +@@ -66,17 +68,17 @@ struct Cipher { + 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[] = { ++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", + SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 1, EVP_bf_cbc }, +@@ -99,27 +101,67 @@ static const struct Cipher ciphers[] = { + { "aes256-gcm@openssh.com", + SSH_CIPHER_SSH2, 16, 32, 12, 16, 0, 0, EVP_aes_256_gcm }, + #endif + { "chacha20-poly1305@openssh.com", + SSH_CIPHER_SSH2, 8, 64, 0, 16, 0, CFLAG_CHACHAPOLY, NULL }, { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL } }; -+static const struct sshcipher fips_ciphers[] = { ++static const struct Cipher ciphers_fips140_2[] = { + { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null }, ++ { "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des }, ++ + { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 0, 0, 1, EVP_des_ede3_cbc }, + { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 1, EVP_aes_128_cbc }, + { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 1, EVP_aes_192_cbc }, @@ -37,205 +262,449 @@ Index: openssh-7.1p2/cipher.c + /*--*/ - /* Returns a comma-separated list of supported ciphers. */ -@@ -109,7 +131,7 @@ cipher_alg_list(char sep, int auth_only) ++/* Returns array of ciphers available depending on selected FIPS mode */ ++static struct Cipher * ++fips_select_ciphers(void) ++{ ++ int fips = fips_mode(); ++ switch (fips) { ++ case 0: ++ return ciphers_all; ++ case 1: ++ return ciphers_fips140_2; ++ default: ++ /* should not be reached */ ++ fatal("Fatal error: incorrect FIPS mode '%i' at %s:%u", ++ fips, __FILE__, __LINE__); ++ return NULL; ++ } ++} ++ + /* Returns a list of supported ciphers separated by the specified char. */ + char * + cipher_alg_list(char sep, int auth_only) + { + char *ret = NULL; size_t nlen, rlen = 0; - const struct sshcipher *c; + const Cipher *c; - for (c = ciphers; c->name != NULL; c++) { -+ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) { ++ for (c = fips_select_ciphers(); c->name != NULL; c++) { if (c->number != SSH_CIPHER_SSH2) continue; if (auth_only && c->auth_len == 0) -@@ -193,7 +215,7 @@ const struct sshcipher * + continue; + if (ret != NULL) + ret[rlen++] = sep; + nlen = strlen(c->name); + ret = xrealloc(ret, 1, rlen + nlen + 2); +@@ -189,27 +231,27 @@ cipher_mask_ssh1(int client) + } + return mask; + } + + const Cipher * cipher_by_name(const char *name) { - const struct sshcipher *c; + const Cipher *c; - for (c = ciphers; c->name != NULL; c++) -+ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) ++ for (c = fips_select_ciphers(); c->name != NULL; c++) if (strcmp(c->name, name) == 0) return c; return NULL; -@@ -203,7 +225,7 @@ const struct sshcipher * + } + + const Cipher * cipher_by_number(int id) { - const struct sshcipher *c; + const Cipher *c; - for (c = ciphers; c->name != NULL; c++) -+ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) ++ for (c = fips_select_ciphers(); c->name != NULL; c++) if (c->number == id) return c; return NULL; -@@ -244,7 +266,7 @@ cipher_number(const char *name) - const struct sshcipher *c; + } + + #define CIPHER_SEP "," + int + ciphers_valid(const char *names) +@@ -241,17 +283,17 @@ ciphers_valid(const char *names) + */ + + int + cipher_number(const char *name) + { + const Cipher *c; if (name == NULL) return -1; - for (c = ciphers; c->name != NULL; c++) -+ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) ++ for (c = fips_select_ciphers(); c->name != NULL; c++) if (strcasecmp(c->name, name) == 0) return c->number; return -1; -Index: openssh-7.1p2/cipher-ctr.c -=================================================================== ---- openssh-7.1p2.orig/cipher-ctr.c -+++ openssh-7.1p2/cipher-ctr.c -@@ -138,7 +138,8 @@ evp_aes_128_ctr(void) - aes_ctr.do_cipher = ssh_aes_ctr; - #ifndef SSH_OLD_EVP - aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | -- EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV; -+ EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV | -+ EVP_CIPH_FLAG_FIPS; - #endif - return (&aes_ctr); } -Index: openssh-7.1p2/dh.h -=================================================================== ---- openssh-7.1p2.orig/dh.h -+++ openssh-7.1p2/dh.h -@@ -46,6 +46,7 @@ u_int dh_estimate(int); - /* Min and max values from RFC4419. */ - #define DH_GRP_MIN 1024 -+#define DH_GRP_MIN_FIPS 2048 - #define DH_GRP_MAX 8192 + char * + cipher_name(int id) + { +@@ -429,23 +471,24 @@ cipher_cleanup(CipherContext *cc) + * Selects the cipher, and keys if by computing the MD5 checksum of the + * passphrase and using the resulting 16 bytes as the key. + */ + + void + cipher_set_key_string(CipherContext *cc, const Cipher *cipher, + const char *passphrase, int do_encrypt) + { +- u_char digest[16]; ++ u_char digest[SSH_DIGEST_MAX_LENGTH]; ++ int dgst = fips_correct_dgst(SSH_DIGEST_MD5); + +- if (ssh_digest_memory(SSH_DIGEST_MD5, passphrase, strlen(passphrase), ++ if (ssh_digest_memory(dgst, passphrase, strlen(passphrase), + digest, sizeof(digest)) < 0) + fatal("%s: md5 failed", __func__); + +- cipher_init(cc, cipher, digest, 16, NULL, 0, do_encrypt); ++ cipher_init(cc, cipher, digest, ssh_digest_bytes(dgst), NULL, 0, do_encrypt); + + explicit_bzero(digest, sizeof(digest)); + } /* -Index: openssh-7.1p2/entropy.c -=================================================================== ---- openssh-7.1p2.orig/entropy.c -+++ openssh-7.1p2/entropy.c -@@ -218,6 +218,8 @@ seed_rng(void) - fatal("OpenSSL version mismatch. Built against %lx, you " - "have %lx", (u_long)OPENSSL_VERSION_NUMBER, SSLeay()); - #endif -+ /* clean the PRNG status when exiting the program */ -+ atexit(RAND_cleanup); - #ifndef OPENSSL_PRNG_ONLY - if (RAND_status() == 1) { - debug3("RNG is ready, skipping seeding"); -Index: openssh-7.1p2/kex.c -=================================================================== ---- openssh-7.1p2.orig/kex.c -+++ openssh-7.1p2/kex.c -@@ -35,6 +35,7 @@ + * Exports an IV from the CipherContext required to export the key + * state back from the unprivileged child to the privileged parent + * process. +diff --git a/openssh-6.6p1/fips.c b/openssh-6.6p1/fips.c +new file mode 100644 +--- /dev/null ++++ b/openssh-6.6p1/fips.c +@@ -0,0 +1,128 @@ ++/* ++ * Copyright (c) 2012 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 ++ * 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. ++ */ ++ ++#include "includes.h" ++ ++#include "fips.h" ++ ++#include "digest.h" ++#include "key.h" ++#include "log.h" ++ ++#include ++ ++static int fips_state = -1; ++ ++int ++fips_mode() ++{ ++ if (-1 == fips_state) { ++ fips_state = FIPS_mode(); ++ if (fips_state) ++ debug("FIPS mode initialized"); ++ } ++ return fips_state; ++} ++ ++enum fp_type ++fips_correct_fp_type(enum fp_type fp) ++{ ++ int fips; ++ enum fp_type fp_fix = fp; ++ ++ fips = fips_mode(); ++ switch (fips) { ++ case 0: ++ break; ++ case 1: ++ if (SSH_FP_MD5 == fp) { ++ fp_fix = SSH_FP_SHA1; ++ debug("MD5 not allowed in FIPS 140-2 mode, " ++ "using SHA-1 for key fingerprints instead."); ++ } ++ break; ++ default: ++ /* should not be reached */ ++ fatal("Fatal error: incorrect FIPS mode '%i' at %s:%u", ++ fips, __FILE__, __LINE__); ++ } ++ ++ return fp_fix; ++} ++ ++int ++fips_correct_dgst(int digest) ++{ ++ int fips; ++ int rv = -1; ++ ++ fips = fips_mode(); ++ switch (fips) { ++ case 0: ++ rv = digest; ++ break; ++ case 1: ++ switch (digest) { ++ case SSH_DIGEST_MD5: ++ case SSH_DIGEST_RIPEMD160: ++ debug("MD5/RIPEMD160 digests not allowed in FIPS 140-2 mode" ++ "using SHA-1 instead."); ++ rv = SSH_DIGEST_SHA1; ++ break; ++ default: ++ rv = digest; ++ break; ++ } ++ break; ++ default: ++ /* should not be reached */ ++ fatal("Fatal error: incorrect FIPS mode '%i' at %s:%u", ++ fips, __FILE__, __LINE__); ++ } ++ ++ return rv; ++} ++ ++int ++fips_dgst_min(void) ++{ ++ int fips; ++ int dgst; ++ ++ fips = fips_mode(); ++ switch (fips) { ++ case 0: ++ dgst = SSH_DIGEST_MD5; ++ break; ++ case 1: ++ dgst = SSH_DIGEST_SHA1; ++ break; ++ default: ++ /* should not be reached */ ++ fatal("Fatal error: incorrect FIPS mode '%i' at %s:%u", ++ fips, __FILE__, __LINE__); ++ } ++ return dgst; ++} ++ +diff --git a/openssh-6.6p1/fips.h b/openssh-6.6p1/fips.h +new file mode 100644 +--- /dev/null ++++ b/openssh-6.6p1/fips.h +@@ -0,0 +1,33 @@ ++/* ++ * Copyright (c) 2012 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 ++ * 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. ++ */ ++#ifndef FIPS_H ++#define FIPS_H ++ ++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/hmac.c b/openssh-6.6p1/hmac.c +--- a/openssh-6.6p1/hmac.c ++++ b/openssh-6.6p1/hmac.c +@@ -139,17 +139,17 @@ ssh_hmac_free(struct ssh_hmac_ctx *ctx) + /* cc -DTEST hmac.c digest.c buffer.c cleanup.c fatal.c log.c xmalloc.c -lcrypto */ + static void + hmac_test(void *key, size_t klen, void *m, size_t mlen, u_char *e, size_t elen) + { + struct ssh_hmac_ctx *ctx; + size_t i; + u_char digest[16]; - #ifdef WITH_OPENSSL - #include -+#include - #endif +- if ((ctx = ssh_hmac_start(SSH_DIGEST_MD5)) == NULL) ++ if ((ctx = ssh_hmac_start(fips_correct_dgst(SSH_DIGEST_MD5))) == NULL) + printf("ssh_hmac_start failed"); + if (ssh_hmac_init(ctx, key, klen) < 0 || + ssh_hmac_update(ctx, m, mlen) < 0 || + ssh_hmac_final(ctx, digest, sizeof(digest)) < 0) + printf("ssh_hmac_xxx failed"); + ssh_hmac_free(ctx); + if (memcmp(e, digest, elen)) { +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 +@@ -638,19 +638,21 @@ kex_get_newkeys(int mode) + } + + void + derive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus, + u_int8_t cookie[8], u_int8_t id[16]) + { + u_int8_t nbuf[2048], obuf[SSH_DIGEST_MAX_LENGTH]; + int len; ++ int digest; + struct ssh_digest_ctx *hashctx; + +- if ((hashctx = ssh_digest_start(SSH_DIGEST_MD5)) == NULL) ++ digest = fips_correct_dgst(SSH_DIGEST_MD5); ++ if ((hashctx = ssh_digest_start(digest)) == NULL) + fatal("%s: ssh_digest_start", __func__); + + len = BN_num_bytes(host_modulus); + if (len < (512 / 8) || (u_int)len > sizeof(nbuf)) + fatal("%s: bad host modulus (len %d)", __func__, len); + BN_bn2bin(host_modulus, nbuf); + if (ssh_digest_update(hashctx, nbuf, len) != 0) + fatal("%s: ssh_digest_update failed", __func__); +@@ -659,17 +661,17 @@ derive_ssh1_session_id(BIGNUM *host_modu + if (len < (512 / 8) || (u_int)len > sizeof(nbuf)) + fatal("%s: bad server modulus (len %d)", __func__, len); + BN_bn2bin(server_modulus, nbuf); + if (ssh_digest_update(hashctx, nbuf, len) != 0 || + ssh_digest_update(hashctx, cookie, 8) != 0) + fatal("%s: ssh_digest_update failed", __func__); + if (ssh_digest_final(hashctx, obuf, sizeof(obuf)) != 0) + fatal("%s: ssh_digest_final failed", __func__); +- memcpy(id, obuf, ssh_digest_bytes(SSH_DIGEST_MD5)); ++ memcpy(id, obuf, ssh_digest_bytes(digest)); + + explicit_bzero(nbuf, sizeof(nbuf)); + explicit_bzero(obuf, sizeof(obuf)); + } + + #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) + void + dump_digest(char *msg, u_char *digest, int len) +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 +@@ -53,16 +53,18 @@ + #include "rsa.h" + #include "uuencode.h" + #include "buffer.h" + #include "log.h" + #include "misc.h" #include "ssh2.h" -@@ -108,6 +109,25 @@ static const struct kexalg kexalgs[] = { - { NULL, -1, -1, -1}, - }; + #include "digest.h" -+static const struct kexalg kexalgs_fips[] = { -+ { KEX_DH14, KEX_DH_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, -+ { KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, -+#ifdef HAVE_EVP_SHA256 -+ { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, SSH_DIGEST_SHA256 }, -+#endif -+#ifdef OPENSSL_HAS_ECC -+ { KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2, -+ NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, -+ { KEX_ECDH_SHA2_NISTP384, KEX_ECDH_SHA2, NID_secp384r1, -+ SSH_DIGEST_SHA384 }, -+# ifdef OPENSSL_HAS_NISTP521 -+ { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1, -+ SSH_DIGEST_SHA512 }, -+# endif -+#endif -+ { NULL, -1, -1, -1}, -+}; ++#include "fips.h" + - char * - kex_alg_list(char sep) + static int to_blob(const Key *, u_char **, u_int *, int); + static Key *key_from_blob2(const u_char *, u_int, int); + + static struct KeyCert * + cert_new(void) { -@@ -135,7 +155,7 @@ kex_alg_by_name(const char *name) - { - const struct kexalg *k; + struct KeyCert *cert; -- for (k = kexalgs; k->name != NULL; k++) { -+ for (k = (FIPS_mode() ? kexalgs_fips : kexalgs); k->name != NULL; k++) { - if (strcmp(k->name, name) == 0) - return k; - #ifdef GSSAPI -@@ -161,7 +181,10 @@ kex_names_valid(const char *names) - for ((p = strsep(&cp, ",")); p && *p != '\0'; - (p = strsep(&cp, ","))) { - if (kex_alg_by_name(p) == NULL) { -- error("Unsupported KEX algorithm \"%.100s\"", p); -+ if (FIPS_mode()) -+ error("\"%.100s\" is not allowed in FIPS mode", p); -+ else -+ error("Unsupported KEX algorithm \"%.100s\"", p); - free(s); - return 0; - } -Index: openssh-7.1p2/kexgexc.c -=================================================================== ---- openssh-7.1p2.orig/kexgexc.c -+++ openssh-7.1p2/kexgexc.c -@@ -28,6 +28,7 @@ +@@ -664,16 +666,19 @@ key_fp_type_select(void) + 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; - #ifdef WITH_OPENSSL - -+#include - #include - #include - -@@ -63,7 +64,7 @@ kexgex_client(struct ssh *ssh) - - nbits = dh_estimate(kex->dh_need * 8); - -- kex->min = DH_GRP_MIN; -+ kex->min = FIPS_mode() ? DH_GRP_MIN_FIPS : DH_GRP_MIN; - kex->max = DH_GRP_MAX; - kex->nbits = nbits; - if (datafellows & SSH_BUG_DHGEX_LARGE) -Index: openssh-7.1p2/kexgexs.c -=================================================================== ---- openssh-7.1p2.orig/kexgexs.c -+++ openssh-7.1p2/kexgexs.c -@@ -83,9 +83,9 @@ input_kex_dh_gex_request(int type, u_int - kex->nbits = nbits; - kex->min = min; - kex->max = max; -- min = MAX(DH_GRP_MIN, min); -+ min = MAX(FIPS_mode() ? DH_GRP_MIN_FIPS : DH_GRP_MIN, min); - max = MIN(DH_GRP_MAX, max); -- nbits = MAX(DH_GRP_MIN, nbits); -+ nbits = MAX(FIPS_mode() ? DH_GRP_MIN_FIPS : DH_GRP_MIN, nbits); - nbits = MIN(DH_GRP_MAX, nbits); - - if (kex->max < kex->min || kex->nbits < kex->min || -Index: openssh-7.1p2/mac.c -=================================================================== ---- openssh-7.1p2.orig/mac.c -+++ openssh-7.1p2/mac.c -@@ -27,6 +27,8 @@ - - #include - -+#include ++ if (fips_mode()) ++ fp = fips_correct_fp_type(fp); + - #include - #include + fp_defined = 1; + } + return fp; + } -@@ -54,7 +56,7 @@ struct macalg { + /* + * string lengths must be less or equal to SSH_FP_TYPE_STRLEN (defined in + * key.h) as to fit into the fingerprint string buffer +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 +@@ -39,33 +39,35 @@ + #include "kex.h" + #include "mac.h" + #include "misc.h" + + #include "digest.h" + #include "hmac.h" + #include "umac.h" + ++#include "fips.h" ++ + #include "openbsd-compat/openssl-compat.h" + + #define SSH_DIGEST 1 /* SSH_DIGEST_XXX */ + #define SSH_UMAC 2 /* UMAC (not integrated with OpenSSL) */ + #define SSH_UMAC128 3 + + struct macalg { + char *name; + int type; + int alg; + int truncatebits; /* truncate digest if != 0 */ + int key_len; /* just for UMAC */ + int len; /* just for UMAC */ int etm; /* Encrypt-then-MAC */ }; -static const struct macalg macs[] = { -+static const struct macalg all_macs[] = { ++static const struct macalg macs_all[] = { /* Encrypt-and-MAC (encrypt-and-authenticate) variants */ { "hmac-sha1", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 0 }, { "hmac-sha1-96", SSH_DIGEST, SSH_DIGEST_SHA1, 96, 0, 0, 0 }, -@@ -85,6 +87,24 @@ static const struct macalg macs[] = { + #ifdef HAVE_EVP_SHA256 + { "hmac-sha2-256", SSH_DIGEST, SSH_DIGEST_SHA256, 0, 0, 0, 0 }, + { "hmac-sha2-512", SSH_DIGEST, SSH_DIGEST_SHA512, 0, 0, 0, 0 }, + #endif + { "hmac-md5", SSH_DIGEST, SSH_DIGEST_MD5, 0, 0, 0, 0 }, +@@ -86,25 +88,59 @@ static const struct macalg macs[] = { + { "hmac-md5-96-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_MD5, 96, 0, 0, 1 }, + { "hmac-ripemd160-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_RIPEMD160, 0, 0, 0, 1 }, + { "umac-64-etm@openssh.com", SSH_UMAC, 0, 0, 128, 64, 1 }, + { "umac-128-etm@openssh.com", SSH_UMAC128, 0, 0, 128, 128, 1 }, + { NULL, 0, 0, 0, 0, 0, 0 } }; -+static const struct macalg fips_macs[] = { ++static const struct macalg macs_fips140_2[] = { + /* Encrypt-and-MAC (encrypt-and-authenticate) variants */ + { "hmac-sha1", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 0 }, +#ifdef HAVE_EVP_SHA256 @@ -244,410 +713,347 @@ Index: openssh-7.1p2/mac.c +#endif + + /* Encrypt-then-MAC variants */ -+ { "hmac-sha1-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 1 }, +#ifdef HAVE_EVP_SHA256 + { "hmac-sha2-256-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA256, 0, 0, 0, 1 }, + { "hmac-sha2-512-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA512, 0, 0, 0, 1 }, +#endif -+ + { NULL, 0, 0, 0, 0, 0, 0 } +}; ++ ++/* Returns array of macs available depending on selected FIPS mode */ ++static struct macalg * ++fips_select_macs(void) ++{ ++ int fips = fips_mode(); ++ switch (fips) { ++ case 0: ++ return macs_all; ++ case 1: ++ return macs_fips140_2; ++ default: ++ /* should not be reached */ ++ fatal("Fatal error: incorrect FIPS mode '%i' at %s:%u", ++ fips, __FILE__, __LINE__); ++// return NULL; ++ } ++} + /* Returns a list of supported MACs separated by the specified char. */ char * mac_alg_list(char sep) -@@ -93,7 +113,7 @@ mac_alg_list(char sep) + { + char *ret = NULL; size_t nlen, rlen = 0; const struct macalg *m; - for (m = macs; m->name != NULL; m++) { -+ for (m = FIPS_mode() ? fips_macs : all_macs; m->name != NULL; m++) { ++ for (m = fips_select_macs(); m->name != NULL; m++) { if (ret != NULL) ret[rlen++] = sep; nlen = strlen(m->name); -@@ -132,7 +152,7 @@ mac_setup(struct sshmac *mac, char *name + ret = xrealloc(ret, 1, rlen + nlen + 2); + memcpy(ret + rlen, m->name, nlen + 1); + rlen += nlen; + } + return ret; +@@ -128,17 +164,17 @@ mac_setup_by_alg(Mac *mac, const struct + mac->etm = macalg->etm; + } + + int + mac_setup(Mac *mac, char *name) { const struct macalg *m; - for (m = macs; m->name != NULL; m++) { -+ for (m = FIPS_mode() ? fips_macs : all_macs; m->name != NULL; m++) { ++ for (m = fips_select_macs(); m->name != NULL; m++) { if (strcmp(name, m->name) != 0) continue; - if (mac != NULL) -Index: openssh-7.1p2/Makefile.in -=================================================================== ---- openssh-7.1p2.orig/Makefile.in -+++ openssh-7.1p2/Makefile.in -@@ -165,25 +165,25 @@ libssh.a: $(LIBSSH_OBJS) - $(RANLIB) $@ + if (mac != NULL) { + mac_setup_by_alg(mac, m); + debug2("mac_setup: setup %s", name); + } + return (0); + } +diff --git a/openssh-6.6p1/myproposal.h b/openssh-6.6p1/myproposal.h +--- a/openssh-6.6p1/myproposal.h ++++ b/openssh-6.6p1/myproposal.h +@@ -104,16 +104,20 @@ - ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS) -- $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHLIBS) $(LIBS) $(GSSLIBS) -+ $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(SSHLIBS) $(LIBS) $(GSSLIBS) - - sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS) -- $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS) -+ $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS) - - scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o -- $(LD) -o $@ scp.o progressmeter.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -+ $(LD) -o $@ scp.o progressmeter.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) - - ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o -- $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -+ $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) - - ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o ssh-pkcs11-client.o -- $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -+ $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) - - ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o -- $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -+ $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) - - ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o roaming_dummy.o readconf.o -- $(LD) -o $@ ssh-keysign.o readconf.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -+ $(LD) -o $@ ssh-keysign.o readconf.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) - - ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-pkcs11-helper.o ssh-pkcs11.o - $(LD) -o $@ ssh-pkcs11-helper.o ssh-pkcs11.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) -@@ -192,7 +192,7 @@ ssh-ldap-helper$(EXEEXT): $(LIBCOMPAT) l - $(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) -+ $(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS) - - sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o - $(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -Index: openssh-7.1p2/myproposal.h -=================================================================== ---- openssh-7.1p2.orig/myproposal.h -+++ openssh-7.1p2/myproposal.h -@@ -138,6 +138,28 @@ - "hmac-sha1-96," \ - "hmac-md5-96" - -+#define KEX_DEFAULT_KEX_FIPS \ -+ KEX_ECDH_METHODS \ -+ KEX_SHA256_METHODS \ -+ "diffie-hellman-group-exchange-sha1," \ -+ "diffie-hellman-group14-sha1" -+#define KEX_FIPS_ENCRYPT \ + #define KEX_DEFAULT_ENCRYPT \ + "aes128-ctr,aes192-ctr,aes256-ctr," \ + "arcfour256,arcfour128," \ + AESGCM_CIPHER_MODES \ + "chacha20-poly1305@openssh.com," \ + "aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc," \ + "aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se" ++#define KEX_FIPS_140_2_ENCRYPT \ + "aes128-ctr,aes192-ctr,aes256-ctr," \ + "aes128-cbc,3des-cbc," \ + "aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se" -+#ifdef HAVE_EVP_SHA256 -+#define KEX_FIPS_MAC \ + + #define KEX_DEFAULT_MAC \ + "hmac-md5-etm@openssh.com," \ + "hmac-sha1-etm@openssh.com," \ + "umac-64-etm@openssh.com," \ + "umac-128-etm@openssh.com," \ + "hmac-sha2-256-etm@openssh.com," \ + "hmac-sha2-512-etm@openssh.com," \ +@@ -124,16 +128,19 @@ + "hmac-sha1," \ + "umac-64@openssh.com," \ + "umac-128@openssh.com," \ + SHA2_HMAC_MODES \ + "hmac-ripemd160," \ + "hmac-ripemd160@openssh.com," \ + "hmac-sha1-96," \ + "hmac-md5-96" ++#define KEX_FIPS_140_2_MAC \ + "hmac-sha1," \ -+ "hmac-sha2-256," \ -+ "hmac-sha2-512," \ -+ "hmac-sha1-etm@openssh.com," \ -+ "hmac-sha2-256-etm@openssh.com," \ -+ "hmac-sha2-512-etm@openssh.com" -+#else -+#define KEX_FIPS_MAC \ -+ "hmac-sha1" -+#endif ++ SHA2_HMAC_MODES \ + + #define KEX_DEFAULT_COMP "none,zlib@openssh.com,zlib" + #define KEX_DEFAULT_LANG "" + + + static char *myproposal[PROPOSAL_MAX] = { + KEX_DEFAULT_KEX, + KEX_DEFAULT_PK_ALG, +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 +@@ -100,16 +100,18 @@ + #include "mac.h" + #include "sshpty.h" + #include "match.h" + #include "msg.h" + #include "uidswap.h" + #include "roaming.h" + #include "version.h" + ++#include "fips.h" + - #else - - #define KEX_SERVER_KEX \ -Index: openssh-7.1p2/readconf.c -=================================================================== ---- openssh-7.1p2.orig/readconf.c -+++ openssh-7.1p2/readconf.c -@@ -1905,9 +1905,12 @@ fill_default_options(Options * options) - options->fingerprint_hash = SSH_FP_HASH_DEFAULT; - if (options->update_hostkeys == -1) - options->update_hostkeys = 0; -- if (kex_assemble_names(KEX_CLIENT_ENCRYPT, &options->ciphers) != 0 || -- kex_assemble_names(KEX_CLIENT_MAC, &options->macs) != 0 || -- kex_assemble_names(KEX_CLIENT_KEX, &options->kex_algorithms) != 0 || -+ if (kex_assemble_names((FIPS_mode() ? KEX_FIPS_ENCRYPT -+ : KEX_CLIENT_ENCRYPT), &options->ciphers) != 0 || -+ kex_assemble_names((FIPS_mode() ? KEX_FIPS_MAC -+ : KEX_CLIENT_MAC), &options->macs) != 0 || -+ kex_assemble_names((FIPS_mode() ? KEX_DEFAULT_KEX_FIPS -+ : KEX_CLIENT_KEX), &options->kex_algorithms) != 0 || - kex_assemble_names(KEX_DEFAULT_PK_ALG, - &options->hostbased_key_types) != 0 || - kex_assemble_names(KEX_DEFAULT_PK_ALG, -Index: openssh-7.1p2/servconf.c -=================================================================== ---- openssh-7.1p2.orig/servconf.c -+++ openssh-7.1p2/servconf.c -@@ -354,9 +354,12 @@ fill_default_server_options(ServerOption - if (options->fingerprint_hash == -1) - options->fingerprint_hash = SSH_FP_HASH_DEFAULT; - -- if (kex_assemble_names(KEX_SERVER_ENCRYPT, &options->ciphers) != 0 || -- kex_assemble_names(KEX_SERVER_MAC, &options->macs) != 0 || -- kex_assemble_names(KEX_SERVER_KEX, &options->kex_algorithms) != 0 || -+ if (kex_assemble_names((FIPS_mode() ? KEX_FIPS_ENCRYPT -+ : KEX_SERVER_ENCRYPT), &options->ciphers) != 0 || -+ kex_assemble_names((FIPS_mode() ? KEX_FIPS_MAC -+ : KEX_SERVER_MAC), &options->macs) != 0 || -+ kex_assemble_names((FIPS_mode() ? KEX_DEFAULT_KEX_FIPS -+ : KEX_SERVER_KEX), &options->kex_algorithms) != 0 || - kex_assemble_names(KEX_DEFAULT_PK_ALG, - &options->hostbased_key_types) != 0 || - kex_assemble_names(KEX_DEFAULT_PK_ALG, -@@ -2316,8 +2319,10 @@ dump_config(ServerOptions *o) - /* string arguments */ - dump_cfg_string(sPidFile, o->pid_file); - dump_cfg_string(sXAuthLocation, o->xauth_location); -- dump_cfg_string(sCiphers, o->ciphers ? o->ciphers : KEX_SERVER_ENCRYPT); -- dump_cfg_string(sMacs, o->macs ? o->macs : KEX_SERVER_MAC); -+ dump_cfg_string(sCiphers, o->ciphers ? o->ciphers : FIPS_mode() -+ ? KEX_FIPS_ENCRYPT : KEX_SERVER_ENCRYPT); -+ dump_cfg_string(sMacs, o->macs ? o->macs : FIPS_mode() -+ ? KEX_FIPS_MAC : KEX_SERVER_MAC); - dump_cfg_string(sBanner, o->banner); - dump_cfg_string(sForceCommand, o->adm_forced_command); - dump_cfg_string(sChrootDirectory, o->chroot_directory); -@@ -2332,8 +2337,8 @@ dump_config(ServerOptions *o) - dump_cfg_string(sAuthorizedPrincipalsCommand, o->authorized_principals_command); - dump_cfg_string(sAuthorizedPrincipalsCommandUser, o->authorized_principals_command_user); - dump_cfg_string(sHostKeyAgent, o->host_key_agent); -- dump_cfg_string(sKexAlgorithms, -- o->kex_algorithms ? o->kex_algorithms : KEX_SERVER_KEX); -+ dump_cfg_string(sKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : -+ FIPS_mode() ? KEX_DEFAULT_KEX_FIPS : KEX_SERVER_KEX); - dump_cfg_string(sHostbasedAcceptedKeyTypes, o->hostbased_key_types ? - o->hostbased_key_types : KEX_DEFAULT_PK_ALG); - dump_cfg_string(sHostKeyAlgorithms, o->hostkeyalgorithms ? -Index: openssh-7.1p2/ssh.c -=================================================================== ---- openssh-7.1p2.orig/ssh.c -+++ openssh-7.1p2/ssh.c -@@ -75,6 +75,8 @@ - #include - #include + #ifdef ENABLE_PKCS11 + #include "ssh-pkcs11.h" #endif -+#include -+#include - #include "openbsd-compat/openssl-compat.h" - #include "openbsd-compat/sys-queue.h" -@@ -522,6 +524,14 @@ main(int ac, char **av) - sanitise_stdfd(); - - __progname = ssh_get_progname(av[0]); -+ SSLeay_add_all_algorithms(); -+ if (access("/etc/system-fips", F_OK) == 0) -+ if (! FIPSCHECK_verify(NULL, NULL)){ -+ if (FIPS_mode()) -+ fatal("FIPS integrity verification test failed."); -+ else -+ logit("FIPS integrity verification test failed."); -+ } + extern char *__progname; + /* Saves a copy of argv for setproctitle emulation */ #ifndef HAVE_SETPROCTITLE - /* Prepare for later setproctitle emulation */ -@@ -599,6 +609,9 @@ main(int ac, char **av) - "ACD:E:F:GI:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) { +@@ -499,16 +501,18 @@ main(int ac, char **av) + logfile = NULL; + argv0 = av[0]; + + again: + while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx" + "ACD:E:F:I:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) { switch (opt) { case '1': -+ if (FIPS_mode()) { ++ if (fips_mode()) + fatal("Protocol 1 not allowed in the FIPS mode."); -+ } options.protocol = SSH_PROTO_1; break; case '2': -@@ -940,7 +953,6 @@ main(int ac, char **av) + options.protocol = SSH_PROTO_2; + break; + case '4': + options.address_family = AF_INET; + break; +@@ -826,16 +830,22 @@ main(int ac, char **av) + if (!host) + usage(); + host_arg = xstrdup(host); - #ifdef WITH_OPENSSL -- OpenSSL_add_all_algorithms(); + OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); - #endif - -@@ -1114,6 +1126,10 @@ main(int ac, char **av) - - seed_rng(); - -+ if (FIPS_mode()) { -+ logit("FIPS mode initialized"); -+ } -+ - if (options.user == NULL) - options.user = xstrdup(pw->pw_name); - -@@ -1191,6 +1207,12 @@ main(int ac, char **av) - - timeout_ms = options.connection_timeout * 1000; + if (FIPS_mode()) { + options.protocol &= SSH_PROTO_2; + if (options.protocol == 0) -+ fatal("Protocol 2 disabled by configuration but required in the FIPS mode."); ++ fatal("Protocol 2 disabled by configuration but required in the FIPS mode"); + } + - /* Open a connection to the remote host. */ - if (ssh_connect(host, addrs, &hostaddr, options.port, - options.address_family, options.connection_attempts, -Index: openssh-7.1p2/sshconnect2.c -=================================================================== ---- openssh-7.1p2.orig/sshconnect2.c -+++ openssh-7.1p2/sshconnect2.c -@@ -44,6 +44,8 @@ - #include - #endif + /* Initialize the command to execute on remote host. */ + buffer_init(&command); -+#include + /* + * Save the command to execute on the remote host in a buffer. There + * is no limit on the length of the command, except by the maximum + * packet size. Also sets the tty flag if there is no command. + */ +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 +@@ -66,16 +66,18 @@ + #include "match.h" + #include "dispatch.h" + #include "canohost.h" + #include "msg.h" + #include "pathnames.h" + #include "uidswap.h" + #include "hostfile.h" + ++#include "fips.h" + - #include "openbsd-compat/sys-queue.h" - - #include "xmalloc.h" -@@ -170,20 +172,25 @@ ssh_kex2(char *host, struct sockaddr *ho - #ifdef GSSAPI - if (options.gss_keyex) { -- /* Add the GSSAPI mechanisms currently supported on this -- * client to the key exchange algorithm proposal */ -- orig = options.kex_algorithms; -- -- if (options.gss_trust_dns) -- gss_host = (char *)get_canonical_hostname(1); -- else -- gss_host = host; -- -- gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity); -- if (gss) { -- debug("Offering GSSAPI proposal: %s", gss); -- xasprintf(&options.kex_algorithms, -- "%s,%s", gss, orig); -+ if (FIPS_mode()) { -+ logit("Disabling GSSAPIKeyExchange. Not usable in FIPS mode"); -+ options.gss_keyex = 0; -+ } else { -+ /* Add the GSSAPI mechanisms currently supported on this -+ * client to the key exchange algorithm proposal */ -+ orig = options.kex_algorithms; + #include "ssh-gss.h" + #endif + + /* import */ + extern char *client_version_string; + extern char *server_version_string; + extern Options options; +@@ -163,31 +165,41 @@ ssh_kex2(char *host, struct sockaddr *ho + + if (options.ciphers == (char *)-1) { + logit("No valid ciphers for protocol version 2 given, using defaults."); + options.ciphers = NULL; + } + if (options.ciphers != NULL) { + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; ++ } else if (fips_mode()) { ++ /* TODO: use intersection of FIPS ciphers and those requested in ++ * configuration */ ++ myproposal[PROPOSAL_ENC_ALGS_CTOS] = ++ myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_FIPS_140_2_ENCRYPT; + } + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); + myproposal[PROPOSAL_ENC_ALGS_STOC] = + compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_STOC]); + if (options.compression) { + myproposal[PROPOSAL_COMP_ALGS_CTOS] = + myproposal[PROPOSAL_COMP_ALGS_STOC] = "zlib@openssh.com,zlib,none"; + } else { + myproposal[PROPOSAL_COMP_ALGS_CTOS] = + myproposal[PROPOSAL_COMP_ALGS_STOC] = "none,zlib@openssh.com,zlib"; + } + if (options.macs != NULL) { + myproposal[PROPOSAL_MAC_ALGS_CTOS] = + myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; ++ } else if (fips_mode()) { ++ /* TODO: use intersection of FIPS macs and those requested in ++ * configuration */ ++ myproposal[PROPOSAL_MAC_ALGS_CTOS] = ++ myproposal[PROPOSAL_MAC_ALGS_STOC] = KEX_FIPS_140_2_MAC; + } + if (options.hostkeyalgorithms != NULL) + myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = + compat_pkalg_proposal(options.hostkeyalgorithms); + else { + /* Prefer algorithms that we already have keys for */ + myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = + compat_pkalg_proposal( +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 +@@ -117,16 +117,18 @@ + #ifdef GSSAPI + #include "ssh-gss.h" + #endif + #include "monitor_wrap.h" + #include "roaming.h" + #include "ssh-sandbox.h" + #include "version.h" + ++#include "fips.h" + -+ if (options.gss_trust_dns) -+ gss_host = (char *)get_canonical_hostname(1); -+ else -+ gss_host = host; -+ -+ gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity); -+ if (gss) { -+ debug("Offering GSSAPI proposal: %s", gss); -+ xasprintf(&options.kex_algorithms, -+ "%s,%s", gss, orig); -+ } + #ifdef LIBWRAP + #include + #include + int allow_severity; + int deny_severity; + #endif /* LIBWRAP */ + + #ifndef O_NOCTTY +@@ -1723,16 +1725,20 @@ main(int ac, char **av) + case KEY_ECDSA: + case KEY_ED25519: + sensitive_data.have_ssh2_key = 1; + break; } + debug("private host key: #%d type %d %s", i, keytype, + key_type(key ? key : pubkey)); } - #endif -Index: openssh-7.1p2/sshd.c -=================================================================== ---- openssh-7.1p2.orig/sshd.c -+++ openssh-7.1p2/sshd.c -@@ -66,6 +66,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -77,6 +78,8 @@ - #include - #include - #include -+#include -+#include - #include "openbsd-compat/openssl-compat.h" - #endif - -@@ -1536,6 +1539,18 @@ main(int ac, char **av) - #endif - __progname = ssh_get_progname(av[0]); - -+ SSLeay_add_all_algorithms(); -+ if (access("/etc/system-fips", F_OK) == 0) -+ if (! FIPSCHECK_verify(NULL, NULL)) { -+ openlog(__progname, LOG_PID, LOG_AUTHPRIV); -+ if (FIPS_mode()) { -+ syslog(LOG_CRIT, "FIPS integrity verification test failed."); -+ cleanup_exit(255); -+ } -+ else -+ syslog(LOG_INFO, "FIPS integrity verification test failed."); -+ closelog(); -+ } - /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */ - saved_argc = ac; - rexec_argc = ac; -@@ -1692,7 +1707,7 @@ main(int ac, char **av) - else - closefrom(REEXEC_DEVCRYPTO_RESERVED_FD); - --#ifdef WITH_OPENSSL -+#if 0 /* FIPS */ - OpenSSL_add_all_algorithms(); - #endif - -@@ -1888,6 +1903,10 @@ main(int ac, char **av) - sshkey_type(pubkey) : sshkey_ssh_name(pubkey), fp); - free(fp); - } -+ if ((options.protocol & SSH_PROTO_1) && FIPS_mode()) { ++ if ((options.protocol & SSH_PROTO_1) && fips_mode()) { + logit("Disabling protocol version 1. Not allowed in the FIPS mode."); + options.protocol &= ~SSH_PROTO_1; + } if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) { logit("Disabling protocol version 1. Could not load host key"); options.protocol &= ~SSH_PROTO_1; -@@ -2056,6 +2075,10 @@ main(int ac, char **av) - /* Reinitialize the log (because of the fork above). */ - log_init(__progname, options.log_level, options.log_facility, log_stderr); - -+ if (FIPS_mode()) { -+ logit("FIPS mode initialized"); -+ } -+ - /* Chdir to the root directory so that the current disk can be - unmounted if desired. */ - if (chdir("/") == -1) -@@ -2654,10 +2677,14 @@ do_ssh2_kex(void) - if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0) - orig = NULL; - -- if (options.gss_keyex) -- gss = ssh_gssapi_server_mechanisms(); -- else -- gss = NULL; -+ if (options.gss_keyex) { -+ if (FIPS_mode()) { -+ logit("Disabling GSSAPIKeyExchange. Not usable in FIPS mode"); -+ options.gss_keyex = 0; -+ } else { -+ gss = ssh_gssapi_server_mechanisms(); -+ } -+ } - - if (gss && orig) - xasprintf(&newstr, "%s,%s", gss, orig); -Index: openssh-7.1p2/sshkey.c -=================================================================== ---- openssh-7.1p2.orig/sshkey.c -+++ openssh-7.1p2/sshkey.c -@@ -35,6 +35,7 @@ - #include - #include - #include -+#include - #endif - - #include "crypto_api.h" -@@ -1555,6 +1556,8 @@ rsa_generate_private_key(u_int bits, RSA } - if (!BN_set_word(f4, RSA_F4) || - !RSA_generate_key_ex(private, bits, f4, NULL)) { -+ if (FIPS_mode()) -+ logit("%s: the key length might be unsupported by FIPS mode approved key generation method", __func__); - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; + if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) { + logit("Disabling protocol version 2. Could not load host key"); + options.protocol &= ~SSH_PROTO_2; + } +@@ -2370,30 +2376,30 @@ do_ssh1_kex(void) + } + if (rsafail) { + int bytes = BN_num_bytes(session_key_int); + u_char *buf = xmalloc(bytes); + struct ssh_digest_ctx *md; + + logit("do_connection: generating a fake encryption key"); + BN_bn2bin(session_key_int, buf); +- if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL || ++ if ((md = ssh_digest_start(fips_correct_dgst(SSH_DIGEST_MD5))) == NULL || + ssh_digest_update(md, buf, bytes) < 0 || + ssh_digest_update(md, sensitive_data.ssh1_cookie, + SSH_SESSION_KEY_LENGTH) < 0 || + ssh_digest_final(md, session_key, sizeof(session_key)) < 0) +- fatal("%s: md5 failed", __func__); ++ fatal("%s: hash failed", __func__); + ssh_digest_free(md); +- if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL || ++ if ((md = ssh_digest_start(fips_correct_dgst(SSH_DIGEST_MD5))) == NULL || + ssh_digest_update(md, session_key, 16) < 0 || + ssh_digest_update(md, sensitive_data.ssh1_cookie, + SSH_SESSION_KEY_LENGTH) < 0 || + ssh_digest_final(md, session_key + 16, + sizeof(session_key) - 16) < 0) +- fatal("%s: md5 failed", __func__); ++ 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(); +@@ -2441,25 +2447,31 @@ sshd_hostkey_sign(Key *privkey, Key *pub + static void + do_ssh2_kex(void) + { + Kex *kex; + + if (options.ciphers != NULL) { + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; ++ } else if (fips_mode()) { ++ myproposal[PROPOSAL_ENC_ALGS_CTOS] = ++ myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_FIPS_140_2_ENCRYPT; + } + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); + myproposal[PROPOSAL_ENC_ALGS_STOC] = + compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_STOC]); + + if (options.macs != NULL) { + myproposal[PROPOSAL_MAC_ALGS_CTOS] = + myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; ++ } else if (fips_mode()) { ++ myproposal[PROPOSAL_MAC_ALGS_CTOS] = ++ myproposal[PROPOSAL_MAC_ALGS_STOC] = KEX_FIPS_140_2_MAC; + } + if (options.compression == COMP_NONE) { + myproposal[PROPOSAL_COMP_ALGS_CTOS] = + 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"; } diff --git a/openssh-6.6p1-gssapi_key_exchange.patch b/openssh-6.6p1-gssapi_key_exchange.patch index 418917a..dc2fb22 100644 --- a/openssh-6.6p1-gssapi_key_exchange.patch +++ b/openssh-6.6p1-gssapi_key_exchange.patch @@ -1,38 +1,260 @@ -Index: openssh-7.1p2/auth2.c -=================================================================== ---- openssh-7.1p2.orig/auth2.c -+++ openssh-7.1p2/auth2.c -@@ -70,6 +70,7 @@ extern Authmethod method_passwd; - extern Authmethod method_kbdint; - extern Authmethod method_hostbased; - #ifdef GSSAPI -+extern Authmethod method_gsskeyex; - extern Authmethod method_gssapi; - extern Authmethod method_gssapi_old; - #endif -@@ -78,6 +79,7 @@ Authmethod *authmethods[] = { - &method_none, - &method_pubkey, - #ifdef GSSAPI -+ &method_gsskeyex, - &method_gssapi, - &method_gssapi_old, - #endif -Index: openssh-7.1p2/auth2-gss.c -=================================================================== ---- openssh-7.1p2.orig/auth2-gss.c -+++ openssh-7.1p2/auth2-gss.c -@@ -31,6 +31,7 @@ - #include +# HG changeset patch +# Parent 0b2761bdc8c2071a11ca24387c3f58be2fdbaa5e + +diff --git a/openssh-6.6p1/ChangeLog.gssapi b/openssh-6.6p1/ChangeLog.gssapi +new file mode 100644 +--- /dev/null ++++ b/openssh-6.6p1/ChangeLog.gssapi +@@ -0,0 +1,113 @@ ++20110101 ++ - Finally update for OpenSSH 5.6p1 ++ - Add GSSAPIServerIdentity option from Jim Basney ++ ++20100308 ++ - [ Makefile.in, key.c, key.h ] ++ Updates for OpenSSH 5.4p1 ++ - [ servconf.c ] ++ Include GSSAPI options in the sshd -T configuration dump, and flag ++ some older configuration options as being unsupported. Thanks to Colin ++ Watson. ++ - ++ ++20100124 ++ - [ sshconnect2.c ] ++ Adapt to deal with additional element in Authmethod structure. Thanks to ++ Colin Watson ++ ++20090615 ++ - [ gss-genr.c gss-serv.c kexgssc.c kexgsss.c monitor.c sshconnect2.c ++ sshd.c ] ++ Fix issues identified by Greg Hudson following a code review ++ Check return value of gss_indicate_mechs ++ Protect GSSAPI calls in monitor, so they can only be used if enabled ++ Check return values of bignum functions in key exchange ++ Use BN_clear_free to clear other side's DH value ++ Make ssh_gssapi_id_kex more robust ++ Only configure kex table pointers if GSSAPI is enabled ++ Don't leak mechanism list, or gss mechanism list ++ Cast data.length before printing ++ If serverkey isn't provided, use an empty string, rather than NULL ++ ++20090201 ++ - [ gss-genr.c gss-serv.c kex.h kexgssc.c readconf.c readconf.h ssh-gss.h ++ ssh_config.5 sshconnet2.c ] ++ Add support for the GSSAPIClientIdentity option, which allows the user ++ to specify which GSSAPI identity to use to contact a given server ++ ++20080404 ++ - [ gss-serv.c ] ++ Add code to actually implement GSSAPIStrictAcceptCheck, which had somehow ++ been omitted from a previous version of this patch. Reported by Borislav ++ Stoichkov ++ ++20070317 ++ - [ gss-serv-krb5.c ] ++ Remove C99ism, where new_ccname was being declared in the middle of a ++ function ++ ++20061220 ++ - [ servconf.c ] ++ Make default for GSSAPIStrictAcceptorCheck be Yes, to match previous, and ++ documented, behaviour. Reported by Dan Watson. ++ ++20060910 ++ - [ gss-genr.c kexgssc.c kexgsss.c kex.h monitor.c sshconnect2.c sshd.c ++ ssh-gss.h ] ++ add support for gss-group14-sha1 key exchange mechanisms ++ - [ gss-serv.c servconf.c servconf.h sshd_config sshd_config.5 ] ++ Add GSSAPIStrictAcceptorCheck option to allow the disabling of ++ acceptor principal checking on multi-homed machines. ++ ++ - [ sshd_config ssh_config ] ++ Add settings for GSSAPIKeyExchange and GSSAPITrustDNS to the sample ++ configuration files ++ - [ kexgss.c kegsss.c sshconnect2.c sshd.c ] ++ Code cleanup. Replace strlen/xmalloc/snprintf sequences with xasprintf() ++ Limit length of error messages displayed by client ++ ++20060909 ++ - [ gss-genr.c gss-serv.c ] ++ move ssh_gssapi_acquire_cred() and ssh_gssapi_server_ctx to be server ++ only, where they belong ++ ++ ++20060829 ++ - [ gss-serv-krb5.c ] ++ Fix CCAPI credentials cache name when creating KRB5CCNAME environment ++ variable ++ ++20060828 ++ - [ gss-genr.c ] ++ Avoid Heimdal context freeing problem ++ ++ ++20060818 ++ - [ gss-genr.c ssh-gss.h sshconnect2.c ] ++ Make sure that SPENGO is disabled ++ ++ ++20060421 ++ - [ gssgenr.c, sshconnect2.c ] ++ a few type changes (signed versus unsigned, int versus size_t) to ++ fix compiler errors/warnings ++ (from jbasney AT ncsa.uiuc.edu) ++ - [ kexgssc.c, sshconnect2.c ] ++ fix uninitialized variable warnings ++ (from jbasney AT ncsa.uiuc.edu) ++ - [ gssgenr.c ] ++ pass oid to gss_display_status (helpful when using GSSAPI mechglue) ++ (from jbasney AT ncsa.uiuc.edu) ++ ++ - [ gss-serv-krb5.c ] ++ #ifdef HAVE_GSSAPI_KRB5 should be #ifdef HAVE_GSSAPI_KRB5_H ++ (from jbasney AT ncsa.uiuc.edu) ++ ++ - [ readconf.c, readconf.h, ssh_config.5, sshconnect2.c ++ add client-side GssapiKeyExchange option ++ (from jbasney AT ncsa.uiuc.edu) ++ - [ sshconnect2.c ] ++ add support for GssapiTrustDns option for gssapi-with-mic ++ (from jbasney AT ncsa.uiuc.edu) ++ +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 +@@ -67,16 +67,17 @@ LIBSSH_OBJS=authfd.o authfile.o bufaux.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 \ + 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 \ ++ kexgssc.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 \ + auditstub.o - #include -+#include +@@ -86,17 +87,17 @@ SSHOBJS= ssh.o readconf.o clientloop.o s - #include "xmalloc.h" - #include "key.h" -@@ -53,6 +54,40 @@ static int input_gssapi_mic(int type, u_ - static int input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt); - static int input_gssapi_errtok(int, u_int32_t, void *); + 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 \ + auth.o auth1.o auth2.o auth-options.o session.o \ + auth-chall.o auth2-chall.o groupaccess.o \ + auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \ + auth2-none.o auth2-passwd.o auth2-pubkey.o \ +- monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o kexecdhs.o \ ++ monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o kexecdhs.o kexgsss.o \ + 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 + +diff --git a/openssh-6.6p1/auth-krb5.c b/openssh-6.6p1/auth-krb5.c +--- a/openssh-6.6p1/auth-krb5.c ++++ b/openssh-6.6p1/auth-krb5.c +@@ -177,18 +177,23 @@ auth_krb5_password(Authctxt *authctxt, c + if (problem) + goto out; + #endif + + authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); + + len = strlen(authctxt->krb5_ticket_file) + 6; + authctxt->krb5_ccname = xmalloc(len); ++#ifdef USE_CCAPI ++ snprintf(authctxt->krb5_ccname, len, "API:%s", ++ authctxt->krb5_ticket_file); ++#else + snprintf(authctxt->krb5_ccname, len, "FILE:%s", + authctxt->krb5_ticket_file); ++#endif + + #ifdef USE_PAM + if (options.use_pam) + do_pam_putenv("KRB5CCNAME", authctxt->krb5_ccname); + #endif + + out: + restore_uid(); +@@ -238,35 +243,42 @@ krb5_cleanup_proc(Authctxt *authctxt) + } + + #ifndef HEIMDAL + krb5_error_code + ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) { + int tmpfd, ret, oerrno; + char ccname[40]; + mode_t old_umask; ++#ifdef USE_CCAPI ++ char cctemplate[] = "API:krb5cc_%d"; ++#else ++ char cctemplate[] = "FILE:/tmp/krb5cc_%d_XXXXXXXXXX"; ++#endif + + ret = snprintf(ccname, sizeof(ccname), +- "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid()); ++ cctemplate, geteuid()); + if (ret < 0 || (size_t)ret >= sizeof(ccname)) + return ENOMEM; + ++#ifndef USE_CCAPI + old_umask = umask(0177); + tmpfd = mkstemp(ccname + strlen("FILE:")); + oerrno = errno; + umask(old_umask); + if (tmpfd == -1) { + logit("mkstemp(): %.100s", strerror(oerrno)); + return oerrno; + } + + if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) { + oerrno = errno; + logit("fchmod(): %.100s", strerror(oerrno)); + close(tmpfd); + return oerrno; + } + close(tmpfd); ++#endif + + return (krb5_cc_resolve(ctx, ccname, ccache)); + } + #endif /* !HEIMDAL */ + #endif /* KRB5 */ +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 +@@ -1,12 +1,12 @@ + /* $OpenBSD: auth2-gss.c,v 1.21 2014/02/26 20:28:44 djm Exp $ */ + + /* +- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. ++ * Copyright (c) 2001-2007 Simon Wilkinson. 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 +@@ -47,16 +47,50 @@ + + extern ServerOptions options; + + static void input_gssapi_token(int type, u_int32_t plen, void *ctxt); + static void input_gssapi_mic(int type, u_int32_t plen, void *ctxt); + static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt); + static void input_gssapi_errtok(int, u_int32_t, void *); +/* + * The 'gssapi_keyex' userauth mechanism. @@ -71,7 +293,17 @@ Index: openssh-7.1p2/auth2-gss.c /* * We only support those mechanisms that we know about (ie ones that we know * how to check local user kuserok and the like) -@@ -238,7 +273,8 @@ input_gssapi_exchange_complete(int type, + */ + static int + userauth_gssapi(Authctxt *authctxt) + { + gss_OID_desc goid = {0, NULL}; +@@ -239,17 +273,18 @@ input_gssapi_exchange_complete(int type, + + /* + * We don't need to check the status, because we're only enabled in + * the dispatcher once the exchange is complete + */ packet_check_eom(); @@ -81,7 +313,17 @@ Index: openssh-7.1p2/auth2-gss.c authctxt->postponed = 0; dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); -@@ -274,7 +310,8 @@ input_gssapi_mic(int type, u_int32_t ple + dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); + dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL); + dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); + userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL); + } +@@ -274,31 +309,38 @@ input_gssapi_mic(int type, u_int32_t ple + + ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service, + "gssapi-with-mic"); + + gssbuf.value = buffer_ptr(&b); gssbuf.length = buffer_len(&b); if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic)))) @@ -91,8 +333,15 @@ Index: openssh-7.1p2/auth2-gss.c else logit("GSSAPI MIC check failed"); -@@ -290,6 +327,12 @@ input_gssapi_mic(int type, u_int32_t ple - return 0; + buffer_free(&b); + free(mic.value); + + authctxt->postponed = 0; + dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); + dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); + dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL); + dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); + userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL); } +Authmethod method_gsskeyex = { @@ -104,13 +353,52 @@ Index: openssh-7.1p2/auth2-gss.c Authmethod method_gssapi = { "gssapi-with-mic", userauth_gssapi, -Index: openssh-7.1p2/clientloop.c -=================================================================== ---- openssh-7.1p2.orig/clientloop.c -+++ openssh-7.1p2/clientloop.c -@@ -115,6 +115,10 @@ - #include "ssherr.h" - #include "hostfile.h" + &options.gss_authentication + }; + + Authmethod method_gssapi_old = { + "gssapi", +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 +@@ -64,24 +64,26 @@ extern Buffer loginmsg; + /* methods */ + + 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_gsskeyex; + extern Authmethod method_gssapi; + extern Authmethod method_gssapi_old; + #endif + + Authmethod *authmethods[] = { + &method_none, + &method_pubkey, + #ifdef GSSAPI ++ &method_gsskeyex, + &method_gssapi, + &method_gssapi_old, + #endif + &method_passwd, + &method_kbdint, + &method_hostbased, + NULL + }; +diff --git a/openssh-6.6p1/clientloop.c b/openssh-6.6p1/clientloop.c +--- a/openssh-6.6p1/clientloop.c ++++ b/openssh-6.6p1/clientloop.c +@@ -106,16 +106,20 @@ + #include "authfd.h" + #include "atomicio.h" + #include "sshpty.h" + #include "misc.h" + #include "match.h" + #include "msg.h" + #include "roaming.h" +#ifdef GSSAPI +#include "ssh-gss.h" @@ -119,7 +407,17 @@ Index: openssh-7.1p2/clientloop.c /* import options */ extern Options options; -@@ -1610,6 +1614,15 @@ client_loop(int have_pty, int escape_cha + /* Flag indicating that stdin should be redirected from /dev/null. */ + extern int stdin_null_flag; + + /* Flag indicating that no shell has been requested */ + extern int no_shell_flag; +@@ -1603,16 +1607,25 @@ client_loop(int have_pty, int escape_cha + &max_fd2, &nalloc, rekeying); + + if (quit_pending) + break; + /* Do channel operations unless rekeying in progress. */ if (!rekeying) { channel_after_select(readset, writeset); @@ -134,12 +432,21 @@ Index: openssh-7.1p2/clientloop.c + if (need_rekeying || packet_need_rekeying()) { debug("need rekeying"); - active_state->kex->done = 0; -Index: openssh-7.1p2/configure.ac -=================================================================== ---- openssh-7.1p2.orig/configure.ac -+++ openssh-7.1p2/configure.ac -@@ -625,6 +625,30 @@ main() { if (NSVersionOfRunTimeLibrary(" + xxx_kex->done = 0; + kex_send_kexinit(xxx_kex); + need_rekeying = 0; + } + } + +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 +@@ -579,16 +579,40 @@ main() { if (NSVersionOfRunTimeLibrary(" + AC_DEFINE([BROKEN_GLOB], [1], [OS X glob does not do what we expect]) + AC_DEFINE_UNQUOTED([BIND_8_COMPAT], [1], + [Define if your resolver libs need this for getrrsetbyname]) + AC_DEFINE([SSH_TUN_FREEBSD], [1], [Open tunnel devices the FreeBSD way]) + AC_DEFINE([SSH_TUN_COMPAT_AF], [1], [Use tunnel device compatibility to OpenBSD]) AC_DEFINE([SSH_TUN_PREPEND_AF], [1], [Prepend the address family to IP tunnel traffic]) @@ -170,11 +477,34 @@ Index: openssh-7.1p2/configure.ac m4_pattern_allow([AU_IPv]) AC_CHECK_DECL([AU_IPv4], [], AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records]) -Index: openssh-7.1p2/gss-genr.c -=================================================================== ---- openssh-7.1p2.orig/gss-genr.c -+++ openssh-7.1p2/gss-genr.c -@@ -41,12 +41,167 @@ + [#include ] + AC_DEFINE([LASTLOG_WRITE_PUTUTXLINE], [1], + [Define if pututxline updates lastlog too]) + ) + AC_DEFINE([SPT_TYPE], [SPT_REUSEARGV], +diff --git a/openssh-6.6p1/gss-genr.c b/openssh-6.6p1/gss-genr.c +--- a/openssh-6.6p1/gss-genr.c ++++ b/openssh-6.6p1/gss-genr.c +@@ -1,12 +1,12 @@ + /* $OpenBSD: gss-genr.c,v 1.22 2013/11/08 00:39:15 djm Exp $ */ + + /* +- * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. ++ * Copyright (c) 2001-2009 Simon Wilkinson. 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 +@@ -34,22 +34,177 @@ + #include + #include + #include + + #include "xmalloc.h" #include "buffer.h" #include "log.h" #include "ssh2.h" @@ -342,7 +672,17 @@ Index: openssh-7.1p2/gss-genr.c /* Check that the OID in a data stream matches that in the context */ int ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len) -@@ -199,7 +354,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int de + { + return (ctx != NULL && ctx->oid != GSS_C_NO_OID && + ctx->oid->length == len && + memcmp(ctx->oid->elements, data, len) == 0); + } +@@ -192,17 +347,17 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int de + int deleg_flag = 0; + + if (deleg_creds) { + deleg_flag = GSS_C_DELEG_FLAG; + debug("Delegating credentials"); } ctx->major = gss_init_sec_context(&ctx->minor, @@ -351,7 +691,17 @@ Index: openssh-7.1p2/gss-genr.c GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag, 0, NULL, recv_tok, NULL, send_tok, flags, NULL); -@@ -229,8 +384,42 @@ ssh_gssapi_import_name(Gssctxt *ctx, con + if (GSS_ERROR(ctx->major)) + ssh_gssapi_error(ctx); + + return (ctx->major); + } +@@ -222,60 +377,173 @@ ssh_gssapi_import_name(Gssctxt *ctx, con + &gssbuf, GSS_C_NT_HOSTBASED_SERVICE, &ctx->name))) + ssh_gssapi_error(ctx); + + free(gssbuf.value); + return (ctx->major); } OM_uint32 @@ -394,7 +744,7 @@ Index: openssh-7.1p2/gss-genr.c if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context, GSS_C_QOP_DEFAULT, buffer, hash))) ssh_gssapi_error(ctx); -@@ -238,6 +427,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer + return (ctx->major); } @@ -414,7 +764,13 @@ Index: openssh-7.1p2/gss-genr.c void ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service, const char *context) -@@ -251,11 +453,16 @@ ssh_gssapi_buildmic(Buffer *b, const cha + { + buffer_init(b); + buffer_put_string(b, session_id2, session_id2_len); + buffer_put_char(b, SSH2_MSG_USERAUTH_REQUEST); + buffer_put_cstring(b, user); + buffer_put_cstring(b, service); + buffer_put_cstring(b, context); } int @@ -432,7 +788,9 @@ Index: openssh-7.1p2/gss-genr.c /* RFC 4462 says we MUST NOT do SPNEGO */ if (oid->length == spnego_oid.length && -@@ -265,6 +472,10 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx + (memcmp(oid->elements, spnego_oid.elements, oid->length) == 0)) + return 0; /* false */ + ssh_gssapi_build_ctx(ctx); ssh_gssapi_set_oid(*ctx, oid); major = ssh_gssapi_import_name(*ctx, host); @@ -443,7 +801,9 @@ Index: openssh-7.1p2/gss-genr.c if (!GSS_ERROR(major)) { major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, NULL); -@@ -274,10 +485,66 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx + gss_release_buffer(&minor, &token); + if ((*ctx)->context != GSS_C_NO_CONTEXT) + gss_delete_sec_context(&minor, &(*ctx)->context, GSS_C_NO_BUFFER); } @@ -463,6 +823,7 @@ Index: openssh-7.1p2/gss-genr.c + static OM_uint32 last_call = 0; + OM_uint32 lifetime, now, major, minor; + int equal; ++ gss_cred_usage_t usage = GSS_C_INITIATE; + + now = time(NULL); + @@ -511,25 +872,193 @@ Index: openssh-7.1p2/gss-genr.c +} + #endif /* GSSAPI */ -Index: openssh-7.1p2/gss-serv.c -=================================================================== ---- openssh-7.1p2.orig/gss-serv.c -+++ openssh-7.1p2/gss-serv.c -@@ -45,17 +45,19 @@ +diff --git a/openssh-6.6p1/gss-serv-krb5.c b/openssh-6.6p1/gss-serv-krb5.c +--- a/openssh-6.6p1/gss-serv-krb5.c ++++ b/openssh-6.6p1/gss-serv-krb5.c +@@ -1,12 +1,12 @@ + /* $OpenBSD: gss-serv-krb5.c,v 1.8 2013/07/20 01:55:13 djm Exp $ */ + + /* +- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. ++ * Copyright (c) 2001-2007 Simon Wilkinson. 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 +@@ -117,16 +117,17 @@ static void + ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) + { + krb5_ccache ccache; + krb5_error_code problem; + krb5_principal princ; + OM_uint32 maj_status, min_status; + int len; + const char *errmsg; ++ const char *new_ccname; + + if (client->creds == NULL) { + debug("No credentials stored"); + return; + } + + if (ssh_gssapi_krb5_init() == 0) + return; +@@ -175,37 +176,108 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl + + if ((maj_status = gss_krb5_copy_ccache(&min_status, + client->creds, ccache))) { + logit("gss_krb5_copy_ccache() failed"); + krb5_cc_destroy(krb_context, ccache); + return; + } + +- client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache)); ++ new_ccname = krb5_cc_get_name(krb_context, ccache); ++ + client->store.envvar = "KRB5CCNAME"; +- len = strlen(client->store.filename) + 6; +- client->store.envval = xmalloc(len); +- snprintf(client->store.envval, len, "FILE:%s", client->store.filename); ++#ifdef USE_CCAPI ++ xasprintf(&client->store.envval, "API:%s", new_ccname); ++ client->store.filename = NULL; ++#else ++ xasprintf(&client->store.envval, "FILE:%s", new_ccname); ++ client->store.filename = xstrdup(new_ccname); ++#endif + + #ifdef USE_PAM + if (options.use_pam) + do_pam_putenv(client->store.envvar, client->store.envval); + #endif + + krb5_cc_close(krb_context, ccache); + + return; + } + ++int ++ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store, ++ ssh_gssapi_client *client) ++{ ++ krb5_ccache ccache = NULL; ++ krb5_principal principal = NULL; ++ char *name = NULL; ++ krb5_error_code problem; ++ OM_uint32 maj_status, min_status; ++ ++ if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) { ++ logit("krb5_cc_resolve(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ return 0; ++ } ++ ++ /* Find out who the principal in this cache is */ ++ if ((problem = krb5_cc_get_principal(krb_context, ccache, ++ &principal))) { ++ logit("krb5_cc_get_principal(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ if ((problem = krb5_unparse_name(krb_context, principal, &name))) { ++ logit("krb5_unparse_name(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ krb5_free_principal(krb_context, principal); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ ++ if (strcmp(name,client->exportedname.value)!=0) { ++ debug("Name in local credentials cache differs. Not storing"); ++ krb5_free_principal(krb_context, principal); ++ krb5_cc_close(krb_context, ccache); ++ krb5_free_unparsed_name(krb_context, name); ++ return 0; ++ } ++ krb5_free_unparsed_name(krb_context, name); ++ ++ /* Name matches, so lets get on with it! */ ++ ++ if ((problem = krb5_cc_initialize(krb_context, ccache, principal))) { ++ logit("krb5_cc_initialize(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ krb5_free_principal(krb_context, principal); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ krb5_free_principal(krb_context, principal); ++ ++ if ((maj_status = gss_krb5_copy_ccache(&min_status, client->creds, ++ ccache))) { ++ logit("gss_krb5_copy_ccache() failed. Sorry!"); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ return 1; ++} ++ + ssh_gssapi_mech gssapi_kerberos_mech = { + "toWM5Slw5Ew8Mqkay+al2g==", + "Kerberos", + {9, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02"}, + NULL, + &ssh_gssapi_krb5_userok, + NULL, +- &ssh_gssapi_krb5_storecreds ++ &ssh_gssapi_krb5_storecreds, ++ &ssh_gssapi_krb5_updatecreds + }; + + #endif /* KRB5 */ + + #endif /* GSSAPI */ +diff --git a/openssh-6.6p1/gss-serv.c b/openssh-6.6p1/gss-serv.c +--- a/openssh-6.6p1/gss-serv.c ++++ b/openssh-6.6p1/gss-serv.c +@@ -1,12 +1,12 @@ + /* $OpenBSD: gss-serv.c,v 1.26 2014/02/26 20:28:44 djm Exp $ */ + + /* +- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. ++ * Copyright (c) 2001-2009 Simon Wilkinson. 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 +@@ -40,25 +40,30 @@ + #include "buffer.h" + #include "key.h" + #include "hostfile.h" + #include "auth.h" + #include "log.h" + #include "channels.h" #include "session.h" #include "misc.h" - #include "servconf.h" ++#include "servconf.h" +#include "uidswap.h" #include "ssh-gss.h" +#include "monitor_wrap.h" - - extern ServerOptions options; ++ ++extern ServerOptions options; static ssh_gssapi_client gssapi_client = { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, - GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL, NULL}}; -+ GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME, {NULL, NULL, NULL}, 0, 0}; ++ GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME, NULL, {NULL, NULL, NULL, NULL, NULL}, 0, 0}; ssh_gssapi_mech gssapi_null_mech = - { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL}; @@ -537,7 +1066,71 @@ Index: openssh-7.1p2/gss-serv.c #ifdef KRB5 extern ssh_gssapi_mech gssapi_kerberos_mech; -@@ -142,6 +144,29 @@ ssh_gssapi_server_ctx(Gssctxt **ctx, gss + #endif + + ssh_gssapi_mech* supported_mechs[]= { + #ifdef KRB5 + &gssapi_kerberos_mech, +@@ -95,59 +100,91 @@ ssh_gssapi_test_oid_supported(OM_uint32 + /* Privileged (called from ssh_gssapi_server_ctx) */ + static OM_uint32 + ssh_gssapi_acquire_cred(Gssctxt *ctx) + { + OM_uint32 status; + char lname[MAXHOSTNAMELEN]; + gss_OID_set oidset; + +- gss_create_empty_oid_set(&status, &oidset); +- gss_add_oid_set_member(&status, ctx->oid, &oidset); ++ if (options.gss_strict_acceptor) { ++ gss_create_empty_oid_set(&status, &oidset); ++ gss_add_oid_set_member(&status, ctx->oid, &oidset); + +- if (gethostname(lname, MAXHOSTNAMELEN)) { +- gss_release_oid_set(&status, &oidset); +- return (-1); +- } ++ if (gethostname(lname, MAXHOSTNAMELEN)) { ++ gss_release_oid_set(&status, &oidset); ++ return (-1); ++ } + +- if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) { ++ if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) { ++ gss_release_oid_set(&status, &oidset); ++ return (ctx->major); ++ } ++ ++ if ((ctx->major = gss_acquire_cred(&ctx->minor, ++ ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, ++ NULL, NULL))) ++ ssh_gssapi_error(ctx); ++ + gss_release_oid_set(&status, &oidset); + return (ctx->major); ++ } else { ++ ctx->name = GSS_C_NO_NAME; ++ ctx->creds = GSS_C_NO_CREDENTIAL; + } +- +- if ((ctx->major = gss_acquire_cred(&ctx->minor, +- ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, NULL, NULL))) +- ssh_gssapi_error(ctx); +- +- gss_release_oid_set(&status, &oidset); +- return (ctx->major); ++ return GSS_S_COMPLETE; + } + + /* Privileged */ + OM_uint32 + ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid) + { + if (*ctx) + ssh_gssapi_delete_ctx(ctx); + ssh_gssapi_build_ctx(ctx); + ssh_gssapi_set_oid(*ctx, oid); + return (ssh_gssapi_acquire_cred(*ctx)); } /* Unprivileged */ @@ -567,7 +1160,9 @@ Index: openssh-7.1p2/gss-serv.c void ssh_gssapi_supported_oids(gss_OID_set *oidset) { -@@ -151,7 +176,9 @@ ssh_gssapi_supported_oids(gss_OID_set *o + int i = 0; + OM_uint32 min_status; + int present; gss_OID_set supported; gss_create_empty_oid_set(&min_status, oidset); @@ -578,14 +1173,25 @@ Index: openssh-7.1p2/gss-serv.c while (supported_mechs[i]->name != NULL) { if (GSS_ERROR(gss_test_oid_set_member(&min_status, -@@ -277,8 +304,48 @@ OM_uint32 + &supported_mechs[i]->oid, supported, &present))) + present = 0; + if (present) + gss_add_oid_set_member(&min_status, + &supported_mechs[i]->oid, oidset); +@@ -263,32 +300,79 @@ ssh_gssapi_parse_ename(Gssctxt *ctx, gss + /* Extract the client details from a given context. This can only reliably + * be called once for a context */ + + /* Privileged (called from accept_secure_ctx) */ + OM_uint32 ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) { int i = 0; + int equal = 0; + gss_name_t new_name = GSS_C_NO_NAME; + gss_buffer_desc ename = GSS_C_EMPTY_BUFFER; -+ + +- gss_buffer_desc ename; + if (options.gss_store_rekey && client->used && ctx->client_creds) { + if (client->mech->oid.length != ctx->oid->length || + (memcmp(client->mech->oid.elements, @@ -600,8 +1206,7 @@ Index: openssh-7.1p2/gss-serv.c + ssh_gssapi_error(ctx); + return (ctx->major); + } - -- gss_buffer_desc ename; ++ + ctx->major = gss_compare_name(&ctx->minor, client->name, + new_name, &equal); + @@ -628,7 +1233,14 @@ Index: openssh-7.1p2/gss-serv.c client->mech = NULL; -@@ -293,6 +360,13 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g + while (supported_mechs[i]->name != NULL) { + if (supported_mechs[i]->oid.length == ctx->oid->length && + (memcmp(supported_mechs[i]->oid.elements, + ctx->oid->elements, ctx->oid->length) == 0)) + client->mech = supported_mechs[i]; + i++; + } + if (client->mech == NULL) return GSS_S_FAILURE; @@ -642,7 +1254,17 @@ Index: openssh-7.1p2/gss-serv.c if ((ctx->major = gss_display_name(&ctx->minor, ctx->client, &client->displayname, NULL))) { ssh_gssapi_error(ctx); -@@ -310,6 +384,8 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g + return (ctx->major); + } + + if ((ctx->major = gss_export_name(&ctx->minor, ctx->client, + &ename))) { +@@ -296,16 +380,18 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g + return (ctx->major); + } + + if ((ctx->major = ssh_gssapi_parse_ename(ctx,&ename, + &client->exportedname))) { return (ctx->major); } @@ -651,33 +1273,17 @@ Index: openssh-7.1p2/gss-serv.c /* We can't copy this structure, so we just move the pointer to it */ client->creds = ctx->client_creds; ctx->client_creds = GSS_C_NO_CREDENTIAL; -@@ -320,11 +396,20 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g - void - ssh_gssapi_cleanup_creds(void) - { -- if (gssapi_client.store.filename != NULL) { -- /* Unlink probably isn't sufficient */ -- debug("removing gssapi cred file\"%s\"", -- gssapi_client.store.filename); -- unlink(gssapi_client.store.filename); -+ krb5_ccache ccache = NULL; -+ krb5_error_code problem; -+ -+ if (gssapi_client.store.data != NULL) { -+ if ((problem = krb5_cc_resolve(gssapi_client.store.data, gssapi_client.store.envval, &ccache))) { -+ debug("%s: krb5_cc_resolve(): %.100s", __func__, -+ krb5_get_err_text(gssapi_client.store.data, problem)); -+ } else if ((problem = krb5_cc_destroy(gssapi_client.store.data, ccache))) { -+ debug("%s: krb5_cc_resolve(): %.100s", __func__, -+ krb5_get_err_text(gssapi_client.store.data, problem)); -+ } else { -+ krb5_free_context(gssapi_client.store.data); -+ gssapi_client.store.data = NULL; -+ } - } + return (ctx->major); } -@@ -357,7 +442,7 @@ ssh_gssapi_do_child(char ***envp, u_int + /* As user - called on fatal/exit */ + void +@@ -343,45 +429,124 @@ ssh_gssapi_do_child(char ***envp, u_int + gssapi_client.store.envval); + child_set_env(envp, envsizep, gssapi_client.store.envvar, + gssapi_client.store.envval); + } + } /* Privileged */ int @@ -686,7 +1292,9 @@ Index: openssh-7.1p2/gss-serv.c { OM_uint32 lmin; -@@ -367,9 +452,11 @@ ssh_gssapi_userok(char *user) + if (gssapi_client.exportedname.length == 0 || + gssapi_client.exportedname.value == NULL) { + debug("No suitable client data"); return 0; } if (gssapi_client.mech && gssapi_client.mech->userok) @@ -696,15 +1304,21 @@ Index: openssh-7.1p2/gss-serv.c + gssapi_client.store.owner = pw; return 1; - else { -+ } else { ++ } else { /* Destroy delegated credentials if userok fails */ gss_release_buffer(&lmin, &gssapi_client.displayname); gss_release_buffer(&lmin, &gssapi_client.exportedname); -@@ -383,14 +470,90 @@ ssh_gssapi_userok(char *user) + gss_release_cred(&lmin, &gssapi_client.creds); + explicit_bzero(&gssapi_client, + sizeof(ssh_gssapi_client)); + return 0; + } + else + debug("ssh_gssapi_userok: Unknown GSSAPI mechanism"); return (0); } --/* Privileged */ + /* Privileged */ -OM_uint32 -ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) +/* These bits are only used for rekeying. The unpriviledged child is running @@ -797,142 +1411,15 @@ Index: openssh-7.1p2/gss-serv.c } #endif -Index: openssh-7.1p2/gss-serv-krb5.c -=================================================================== ---- openssh-7.1p2.orig/gss-serv-krb5.c -+++ openssh-7.1p2/gss-serv-krb5.c -@@ -121,7 +121,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl - krb5_error_code problem; - krb5_principal princ; - OM_uint32 maj_status, min_status; -- int len; -+ const char *new_ccname, *new_cctype; - const char *errmsg; - - if (client->creds == NULL) { -@@ -181,11 +181,26 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl - return; - } - -- client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache)); -+ new_cctype = krb5_cc_get_type(krb_context, ccache); -+ new_ccname = krb5_cc_get_name(krb_context, ccache); -+ - client->store.envvar = "KRB5CCNAME"; -- len = strlen(client->store.filename) + 6; -- client->store.envval = xmalloc(len); -- snprintf(client->store.envval, len, "FILE:%s", client->store.filename); -+#ifdef USE_CCAPI -+ xasprintf(&client->store.envval, "API:%s", new_ccname); -+ client->store.filename = NULL; -+#else -+ if (new_ccname[0] == ':') -+ new_ccname++; -+ xasprintf(&client->store.envval, "%s:%s", new_cctype, new_ccname); -+ if (strcmp(new_cctype, "DIR") == 0) { -+ char *p; -+ p = strrchr(client->store.envval, '/'); -+ if (p) -+ *p = '\0'; -+ } -+ if ((strcmp(new_cctype, "FILE") == 0) || (strcmp(new_cctype, "DIR") == 0)) -+ client->store.filename = xstrdup(new_ccname); -+#endif - - #ifdef USE_PAM - if (options.use_pam) -@@ -194,9 +209,76 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl - - krb5_cc_close(krb_context, ccache); - -+ client->store.data = krb_context; -+ - return; - } - -+int -+ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store, -+ ssh_gssapi_client *client) -+{ -+ krb5_ccache ccache = NULL; -+ krb5_principal principal = NULL; -+ char *name = NULL; -+ krb5_error_code problem; -+ OM_uint32 maj_status, min_status; -+ -+ if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) { -+ logit("krb5_cc_resolve(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ return 0; -+ } -+ -+ /* Find out who the principal in this cache is */ -+ if ((problem = krb5_cc_get_principal(krb_context, ccache, -+ &principal))) { -+ logit("krb5_cc_get_principal(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ if ((problem = krb5_unparse_name(krb_context, principal, &name))) { -+ logit("krb5_unparse_name(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ krb5_free_principal(krb_context, principal); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ -+ if (strcmp(name,client->exportedname.value)!=0) { -+ debug("Name in local credentials cache differs. Not storing"); -+ krb5_free_principal(krb_context, principal); -+ krb5_cc_close(krb_context, ccache); -+ krb5_free_unparsed_name(krb_context, name); -+ return 0; -+ } -+ krb5_free_unparsed_name(krb_context, name); -+ -+ /* Name matches, so lets get on with it! */ -+ -+ if ((problem = krb5_cc_initialize(krb_context, ccache, principal))) { -+ logit("krb5_cc_initialize(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ krb5_free_principal(krb_context, principal); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ krb5_free_principal(krb_context, principal); -+ -+ if ((maj_status = gss_krb5_copy_ccache(&min_status, client->creds, -+ ccache))) { -+ logit("gss_krb5_copy_ccache() failed. Sorry!"); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ return 1; -+} -+ - ssh_gssapi_mech gssapi_kerberos_mech = { - "toWM5Slw5Ew8Mqkay+al2g==", - "Kerberos", -@@ -204,7 +286,8 @@ ssh_gssapi_mech gssapi_kerberos_mech = { - NULL, - &ssh_gssapi_krb5_userok, - NULL, -- &ssh_gssapi_krb5_storecreds -+ &ssh_gssapi_krb5_storecreds, -+ &ssh_gssapi_krb5_updatecreds - }; - - #endif /* KRB5 */ -Index: openssh-7.1p2/kex.c -=================================================================== ---- openssh-7.1p2.orig/kex.c -+++ openssh-7.1p2/kex.c -@@ -56,6 +56,10 @@ +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 +@@ -47,16 +47,20 @@ + #include "mac.h" + #include "match.h" + #include "dispatch.h" + #include "monitor.h" + #include "roaming.h" #include "digest.h" #include "audit.h" @@ -943,36 +1430,106 @@ Index: openssh-7.1p2/kex.c #if OPENSSL_VERSION_NUMBER >= 0x00907000L # if defined(HAVE_EVP_SHA256) # define evp_ssh_sha256 EVP_sha256 -@@ -96,6 +100,11 @@ static const struct kexalg kexalgs[] = { - #if defined(HAVE_EVP_SHA256) || !defined(WITH_OPENSSL) + # else + extern const EVP_MD *evp_ssh_sha256(void); + # endif + #endif + +@@ -86,16 +90,21 @@ static const struct kexalg kexalgs[] = { + { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1, + SSH_DIGEST_SHA512 }, + # endif + #endif + { KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, + #ifdef HAVE_EVP_SHA256 { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, - #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ + #endif +#ifdef GSSAPI -+ { KEX_GSS_GEX_SHA1_ID, KEX_GSS_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, -+ { KEX_GSS_GRP1_SHA1_ID, KEX_GSS_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, -+ { KEX_GSS_GRP14_SHA1_ID, KEX_GSS_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, ++ { KEX_GSS_GEX_SHA1_ID, KEX_GSS_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, ++ { KEX_GSS_GRP1_SHA1_ID, KEX_GSS_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, ++ { KEX_GSS_GRP14_SHA1_ID, KEX_GSS_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, +#endif { NULL, -1, -1, -1}, }; -@@ -129,6 +138,12 @@ kex_alg_by_name(const char *name) - for (k = kexalgs; k->name != NULL; k++) { - if (strcmp(k->name, name) == 0) - return k; + char * + kex_alg_list(char sep) + { + char *ret = NULL; + size_t nlen, rlen = 0; +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 +@@ -71,16 +71,19 @@ enum kex_modes { + + enum kex_exchange { + KEX_DH_GRP1_SHA1, + KEX_DH_GRP14_SHA1, + KEX_DH_GEX_SHA1, + KEX_DH_GEX_SHA256, + KEX_ECDH_SHA2, + KEX_C25519_SHA256, ++ KEX_GSS_GRP1_SHA1, ++ KEX_GSS_GRP14_SHA1, ++ KEX_GSS_GEX_SHA1, + KEX_MAX + }; + + #define KEX_INIT_SENT 0x0001 + + typedef struct Kex Kex; + typedef struct Mac Mac; + typedef struct Comp Comp; +@@ -130,16 +133,22 @@ struct Kex { + int kex_type; + int roaming; + Buffer my; + Buffer peer; + sig_atomic_t done; + int flags; + int hash_alg; + int ec_nid; +#ifdef GSSAPI -+ if (strncmp(name, "gss-", 4) == 0) { -+ if (strncmp(k->name, name, strlen(k->name)) == 0) -+ return k; -+ } ++ int gss_deleg_creds; ++ int gss_trust_dns; ++ char *gss_host; ++ char *gss_client; +#endif - } - return NULL; - } -Index: openssh-7.1p2/kexgssc.c -=================================================================== + char *client_version_string; + char *server_version_string; + int (*verify_host_key)(Key *); + Key *(*load_host_public_key)(int); + Key *(*load_host_private_key)(int); + int (*host_key_index)(Key *); + void (*sign)(Key *, Key *, u_char **, u_int *, u_char *, u_int); + void (*kex[KEX_MAX])(Kex *); +@@ -163,16 +172,21 @@ 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); ++ ++#ifdef GSSAPI ++void kexgss_client(Kex *); ++void kexgss_server(Kex *); ++#endif + + 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 *); +diff --git a/openssh-6.6p1/kexgssc.c b/openssh-6.6p1/kexgssc.c +new file mode 100644 --- /dev/null -+++ openssh-7.1p2/kexgssc.c -@@ -0,0 +1,338 @@ ++++ b/openssh-6.6p1/kexgssc.c +@@ -0,0 +1,334 @@ +/* + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. + * @@ -1017,23 +1574,22 @@ Index: openssh-7.1p2/kexgssc.c +#include "log.h" +#include "packet.h" +#include "dh.h" -+#include "digest.h" + +#include "ssh-gss.h" + -+int -+kexgss_client(struct ssh *ssh) { ++void ++kexgss_client(Kex *kex) { + gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; + gss_buffer_desc recv_tok, gssbuf, msg_tok, *token_ptr; + Gssctxt *ctxt; + OM_uint32 maj_status, min_status, ret_flags; -+ u_int klen, kout, slen = 0, strlen; ++ u_int klen, kout, slen = 0, hashlen, strlen; + DH *dh; + BIGNUM *dh_server_pub = NULL; + BIGNUM *shared_secret = NULL; + BIGNUM *p = NULL; + BIGNUM *g = NULL; -+ u_char *kbuf; ++ u_char *kbuf, *hash; + u_char *serverhostkey = NULL; + u_char *empty = ""; + char *msg; @@ -1041,23 +1597,21 @@ Index: openssh-7.1p2/kexgssc.c + int type = 0; + int first = 1; + int nbits = 0, min = DH_GRP_MIN, max = DH_GRP_MAX; -+ u_char hash[SSH_DIGEST_MAX_LENGTH]; -+ size_t hashlen; + + /* Initialise our GSSAPI world */ + ssh_gssapi_build_ctx(&ctxt); -+ if (ssh_gssapi_id_kex(ctxt, ssh->kex->name, ssh->kex->kex_type) ++ if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type) + == GSS_C_NO_OID) + fatal("Couldn't identify host exchange"); + -+ if (ssh_gssapi_import_name(ctxt, ssh->kex->gss_host)) ++ if (ssh_gssapi_import_name(ctxt, kex->gss_host)) + fatal("Couldn't import hostname"); + -+ if (ssh->kex->gss_client && -+ ssh_gssapi_client_identity(ctxt, ssh->kex->gss_client)) ++ if (kex->gss_client && ++ ssh_gssapi_client_identity(ctxt, kex->gss_client)) + fatal("Couldn't acquire client credentials"); + -+ switch (ssh->kex->kex_type) { ++ switch (kex->kex_type) { + case KEX_GSS_GRP1_SHA1: + dh = dh_new_group1(); + break; @@ -1066,7 +1620,7 @@ Index: openssh-7.1p2/kexgssc.c + break; + case KEX_GSS_GEX_SHA1: + debug("Doing group exchange\n"); -+ nbits = dh_estimate(ssh->kex->we_need * 8); ++ nbits = dh_estimate(kex->we_need * 8); + packet_start(SSH2_MSG_KEXGSS_GROUPREQ); + packet_put_int(min); + packet_put_int(nbits); @@ -1091,11 +1645,11 @@ Index: openssh-7.1p2/kexgssc.c + dh = dh_new_group(g, p); + break; + default: -+ fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type); ++ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); + } + + /* Step 1 - e is dh->pub_key */ -+ dh_gen_key(dh, ssh->kex->we_need * 8); ++ dh_gen_key(dh, kex->we_need * 8); + + /* This is f, we initialise it now to make life easier */ + dh_server_pub = BN_new(); @@ -1108,7 +1662,7 @@ Index: openssh-7.1p2/kexgssc.c + debug("Calling gss_init_sec_context"); + + maj_status = ssh_gssapi_init_ctx(ctxt, -+ ssh->kex->gss_deleg_creds, token_ptr, &send_tok, ++ kex->gss_deleg_creds, token_ptr, &send_tok, + &ret_flags); + + if (GSS_ERROR(maj_status)) { @@ -1228,7 +1782,7 @@ Index: openssh-7.1p2/kexgssc.c + klen = DH_size(dh); + kbuf = xmalloc(klen); + kout = DH_compute_key(kbuf, dh_server_pub, dh); -+ if ((int)kout < 0) ++ if (kout < 0) + fatal("DH_compute_key: failed"); + + shared_secret = BN_new(); @@ -1241,39 +1795,38 @@ Index: openssh-7.1p2/kexgssc.c + memset(kbuf, 0, klen); + free(kbuf); + -+ hashlen = sizeof(hash); -+ switch (ssh->kex->kex_type) { ++ switch (kex->kex_type) { + case KEX_GSS_GRP1_SHA1: + case KEX_GSS_GRP14_SHA1: -+ kex_dh_hash( ssh->kex->client_version_string, -+ ssh->kex->server_version_string, -+ buffer_ptr(ssh->kex->my), buffer_len(ssh->kex->my), -+ buffer_ptr(ssh->kex->peer), buffer_len(ssh->kex->peer), ++ kex_dh_hash( kex->client_version_string, ++ kex->server_version_string, ++ buffer_ptr(&kex->my), buffer_len(&kex->my), ++ buffer_ptr(&kex->peer), buffer_len(&kex->peer), + (serverhostkey ? serverhostkey : empty), slen, + dh->pub_key, /* e */ + dh_server_pub, /* f */ + shared_secret, /* K */ -+ hash, &hashlen ++ &hash, &hashlen + ); + break; + case KEX_GSS_GEX_SHA1: + kexgex_hash( -+ ssh->kex->hash_alg, -+ ssh->kex->client_version_string, -+ ssh->kex->server_version_string, -+ buffer_ptr(ssh->kex->my), buffer_len(ssh->kex->my), -+ buffer_ptr(ssh->kex->peer), buffer_len(ssh->kex->peer), ++ kex->hash_alg, ++ kex->client_version_string, ++ kex->server_version_string, ++ buffer_ptr(&kex->my), buffer_len(&kex->my), ++ buffer_ptr(&kex->peer), buffer_len(&kex->peer), + (serverhostkey ? serverhostkey : empty), slen, + min, nbits, max, + dh->p, dh->g, + dh->pub_key, + dh_server_pub, + shared_secret, -+ hash, &hashlen ++ &hash, &hashlen + ); + break; + default: -+ fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type); ++ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); + } + + gssbuf.value = hash; @@ -1291,13 +1844,13 @@ Index: openssh-7.1p2/kexgssc.c + BN_clear_free(dh_server_pub); + + /* save session id */ -+ if (ssh->kex->session_id == NULL) { -+ ssh->kex->session_id_len = hashlen; -+ ssh->kex->session_id = xmalloc(ssh->kex->session_id_len); -+ memcpy(ssh->kex->session_id, hash, ssh->kex->session_id_len); ++ if (kex->session_id == NULL) { ++ kex->session_id_len = hashlen; ++ kex->session_id = xmalloc(kex->session_id_len); ++ memcpy(kex->session_id, hash, kex->session_id_len); + } + -+ if (ssh->kex->gss_deleg_creds) ++ if (kex->gss_deleg_creds) + ssh_gssapi_credentials_updated(ctxt); + + if (gss_kex_context == NULL) @@ -1305,17 +1858,17 @@ Index: openssh-7.1p2/kexgssc.c + else + ssh_gssapi_delete_ctx(&ctxt); + -+ kex_derive_keys_bn(ssh, hash, hashlen, shared_secret); ++ kex_derive_keys_bn(kex, hash, hashlen, shared_secret); + BN_clear_free(shared_secret); -+ return kex_send_newkeys(ssh); ++ kex_finish(kex); +} + +#endif /* GSSAPI */ -Index: openssh-7.1p2/kexgsss.c -=================================================================== +diff --git a/openssh-6.6p1/kexgsss.c b/openssh-6.6p1/kexgsss.c +new file mode 100644 --- /dev/null -+++ openssh-7.1p2/kexgsss.c -@@ -0,0 +1,295 @@ ++++ b/openssh-6.6p1/kexgsss.c +@@ -0,0 +1,288 @@ +/* + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. + * @@ -1360,15 +1913,12 @@ Index: openssh-7.1p2/kexgsss.c +#include "dh.h" +#include "ssh-gss.h" +#include "monitor_wrap.h" -+#include "misc.h" /* servconf.h needs misc.h for struct ForwardOptions */ +#include "servconf.h" -+#include "ssh-gss.h" -+#include "digest.h" + +extern ServerOptions options; + -+int -+kexgss_server(struct ssh *ssh) ++void ++kexgss_server(Kex *kex) +{ + OM_uint32 maj_status, min_status; + @@ -1383,8 +1933,8 @@ Index: openssh-7.1p2/kexgsss.c + gss_buffer_desc gssbuf, recv_tok, msg_tok; + gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; + Gssctxt *ctxt = NULL; -+ u_int slen, klen, kout; -+ u_char *kbuf; ++ u_int slen, klen, kout, hashlen; ++ u_char *kbuf, *hash; + DH *dh; + int min = -1, max = -1, nbits = -1; + BIGNUM *shared_secret = NULL; @@ -1392,8 +1942,6 @@ Index: openssh-7.1p2/kexgsss.c + int type = 0; + gss_OID oid; + char *mechs; -+ u_char hash[SSH_DIGEST_MAX_LENGTH]; -+ size_t hashlen; + + /* Initialise GSSAPI */ + @@ -1405,8 +1953,8 @@ Index: openssh-7.1p2/kexgsss.c + if ((mechs = ssh_gssapi_server_mechanisms())) + free(mechs); + -+ debug2("%s: Identifying %s", __func__, ssh->kex->name); -+ oid = ssh_gssapi_id_kex(NULL, ssh->kex->name, ssh->kex->kex_type); ++ debug2("%s: Identifying %s", __func__, kex->name); ++ oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type); + if (oid == GSS_C_NO_OID) + fatal("Unknown gssapi mechanism"); + @@ -1415,7 +1963,7 @@ Index: openssh-7.1p2/kexgsss.c + if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) + fatal("Unable to acquire credentials for the server"); + -+ switch (ssh->kex->kex_type) { ++ switch (kex->kex_type) { + case KEX_GSS_GRP1_SHA1: + dh = dh_new_group1(); + break; @@ -1446,10 +1994,10 @@ Index: openssh-7.1p2/kexgsss.c + packet_write_wait(); + break; + default: -+ fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type); ++ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); + } + -+ dh_gen_key(dh, ssh->kex->we_need * 8); ++ dh_gen_key(dh, kex->we_need * 8); + + do { + debug("Wait SSH2_MSG_GSSAPI_INIT"); @@ -1519,7 +2067,7 @@ Index: openssh-7.1p2/kexgsss.c + klen = DH_size(dh); + kbuf = xmalloc(klen); + kout = DH_compute_key(kbuf, dh_client_pub, dh); -+ if ((int)kout < 0) ++ if (kout < 0) + fatal("DH_compute_key: failed"); + + shared_secret = BN_new(); @@ -1532,44 +2080,43 @@ Index: openssh-7.1p2/kexgsss.c + memset(kbuf, 0, klen); + free(kbuf); + -+ hashlen = sizeof(hash); -+ switch (ssh->kex->kex_type) { ++ switch (kex->kex_type) { + case KEX_GSS_GRP1_SHA1: + case KEX_GSS_GRP14_SHA1: + kex_dh_hash( -+ ssh->kex->client_version_string, ssh->kex->server_version_string, -+ buffer_ptr(ssh->kex->peer), buffer_len(ssh->kex->peer), -+ buffer_ptr(ssh->kex->my), buffer_len(ssh->kex->my), ++ kex->client_version_string, kex->server_version_string, ++ buffer_ptr(&kex->peer), buffer_len(&kex->peer), ++ buffer_ptr(&kex->my), buffer_len(&kex->my), + NULL, 0, /* Change this if we start sending host keys */ + dh_client_pub, dh->pub_key, shared_secret, -+ hash, &hashlen ++ &hash, &hashlen + ); + break; + case KEX_GSS_GEX_SHA1: + kexgex_hash( -+ ssh->kex->hash_alg, -+ ssh->kex->client_version_string, ssh->kex->server_version_string, -+ buffer_ptr(ssh->kex->peer), buffer_len(ssh->kex->peer), -+ buffer_ptr(ssh->kex->my), buffer_len(ssh->kex->my), ++ kex->hash_alg, ++ kex->client_version_string, kex->server_version_string, ++ buffer_ptr(&kex->peer), buffer_len(&kex->peer), ++ buffer_ptr(&kex->my), buffer_len(&kex->my), + NULL, 0, + min, nbits, max, + dh->p, dh->g, + dh_client_pub, + dh->pub_key, + shared_secret, -+ hash, &hashlen ++ &hash, &hashlen + ); + break; + default: -+ fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type); ++ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); + } + + BN_clear_free(dh_client_pub); + -+ if (ssh->kex->session_id == NULL) { -+ ssh->kex->session_id_len = hashlen; -+ ssh->kex->session_id = xmalloc(ssh->kex->session_id_len); -+ memcpy(ssh->kex->session_id, hash, ssh->kex->session_id_len); ++ if (kex->session_id == NULL) { ++ kex->session_id_len = hashlen; ++ kex->session_id = xmalloc(kex->session_id_len); ++ memcpy(kex->session_id, hash, kex->session_id_len); + } + + gssbuf.value = hash; @@ -1600,83 +2147,68 @@ Index: openssh-7.1p2/kexgsss.c + + DH_free(dh); + -+ kex_derive_keys_bn(ssh, hash, hashlen, shared_secret); ++ kex_derive_keys_bn(kex, hash, hashlen, shared_secret); + BN_clear_free(shared_secret); -+ kex_send_newkeys(ssh); ++ kex_finish(kex); + + /* If this was a rekey, then save out any delegated credentials we + * just exchanged. */ + if (options.gss_store_rekey) + ssh_gssapi_rekey_creds(); -+ return 0; +} +#endif /* GSSAPI */ -Index: openssh-7.1p2/kex.h -=================================================================== ---- openssh-7.1p2.orig/kex.h -+++ openssh-7.1p2/kex.h -@@ -93,6 +93,11 @@ enum kex_exchange { - KEX_DH_GEX_SHA256, - KEX_ECDH_SHA2, - KEX_C25519_SHA256, -+#ifdef GSSAPI -+ KEX_GSS_GRP1_SHA1, -+ KEX_GSS_GRP14_SHA1, -+ KEX_GSS_GEX_SHA1, -+#endif - KEX_MAX +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 +@@ -1053,16 +1053,18 @@ static const struct keytype keytypes[] = + # endif + #endif /* OPENSSL_HAS_ECC */ + { "ssh-rsa-cert-v00@openssh.com", "RSA-CERT-V00", + KEY_RSA_CERT_V00, 0, 1 }, + { "ssh-dss-cert-v00@openssh.com", "DSA-CERT-V00", + KEY_DSA_CERT_V00, 0, 1 }, + { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", + KEY_ED25519_CERT, 0, 1 }, ++ { "null", "null", ++ KEY_NULL, 0, 0 }, + { NULL, NULL, -1, -1, 0 } }; -@@ -139,6 +144,12 @@ struct kex { - u_int flags; - int hash_alg; - int ec_nid; -+#ifdef GSSAPI -+ int gss_deleg_creds; -+ int gss_trust_dns; -+ char *gss_host; -+ char *gss_client; -+#endif - char *client_version_string; - char *server_version_string; - char *failed_choice; -@@ -186,6 +197,10 @@ int kexecdh_client(struct ssh *); - int kexecdh_server(struct ssh *); - int kexc25519_client(struct ssh *); - int kexc25519_server(struct ssh *); -+#ifdef GSSAPI -+int kexgss_client(struct ssh *); -+int kexgss_server(struct ssh *); -+#endif + const char * + key_type(const Key *k) + { + const struct keytype *kt; - void newkeys_destroy(struct newkeys *newkeys); +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 +@@ -41,16 +41,17 @@ enum types { + KEY_ECDSA, + KEY_ED25519, + KEY_RSA_CERT, + KEY_DSA_CERT, + KEY_ECDSA_CERT, + KEY_ED25519_CERT, + KEY_RSA_CERT_V00, + KEY_DSA_CERT_V00, ++ KEY_NULL, + KEY_UNSPEC + }; + enum fp_type { + SSH_FP_SHA1, + SSH_FP_MD5, + SSH_FP_SHA256 + }; + enum fp_rep { +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 +@@ -173,16 +173,18 @@ int mm_answer_pam_respond(int, Buffer *) + int mm_answer_pam_free_ctx(int, Buffer *); + #endif -Index: openssh-7.1p2/Makefile.in -=================================================================== ---- openssh-7.1p2.orig/Makefile.in -+++ openssh-7.1p2/Makefile.in -@@ -84,6 +84,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ - readpass.o rsa.o ttymodes.o xmalloc.o addrmatch.o \ - atomicio.o key.o dispatch.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 \ -+ kexgssc.o \ - msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ - ssh-pkcs11.o smult_curve25519_ref.o \ - poly1305.o chacha.o cipher-chachapoly.o \ -@@ -105,7 +106,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passw - auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \ - auth2-none.o auth2-passwd.o auth2-pubkey.o \ - monitor_mm.o monitor.o monitor_wrap.o auth-krb5.o \ -- auth2-gss.o gss-serv.o gss-serv-krb5.o \ -+ auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.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 \ -Index: openssh-7.1p2/monitor.c -=================================================================== ---- openssh-7.1p2.orig/monitor.c -+++ openssh-7.1p2/monitor.c -@@ -160,6 +160,8 @@ int mm_answer_gss_setup_ctx(int, Buffer + #ifdef GSSAPI + 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 *); @@ -1685,7 +2217,17 @@ Index: openssh-7.1p2/monitor.c #endif #ifdef SSH_AUDIT_EVENTS -@@ -246,11 +248,18 @@ struct mon_table mon_dispatch_proto20[] + 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 *); +@@ -254,21 +256,28 @@ struct mon_table mon_dispatch_proto20[] + #endif + {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed}, + {MONITOR_REQ_KEYVERIFY, MON_AUTH, mm_answer_keyverify}, + #ifdef GSSAPI + {MONITOR_REQ_GSSSETUP, MON_ISAUTH, mm_answer_gss_setup_ctx}, {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx}, {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok}, {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic}, @@ -1701,10 +2243,20 @@ Index: openssh-7.1p2/monitor.c + {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign}, + {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds}, +#endif - #ifdef WITH_OPENSSL {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, - #endif -@@ -379,6 +388,10 @@ monitor_child_preauth(Authctxt *_authctx + {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}, +@@ -381,16 +390,20 @@ monitor_child_preauth(Authctxt *_authctx + authctxt->loginmsg = &loginmsg; + + if (compat20) { + mon_dispatch = mon_dispatch_proto20; + /* Permit requests for moduli and signatures */ monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); @@ -1715,7 +2267,17 @@ Index: openssh-7.1p2/monitor.c } else { mon_dispatch = mon_dispatch_proto15; -@@ -487,6 +500,10 @@ monitor_child_postauth(struct monitor *p + monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1); + } + + /* The first few requests do not require asynchronous access */ + while (!authenticated) { +@@ -486,16 +499,20 @@ monitor_child_postauth(struct monitor *p + + if (compat20) { + mon_dispatch = mon_dispatch_postauth20; + + /* Permit requests for moduli and signatures */ monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); @@ -1726,10 +2288,20 @@ Index: openssh-7.1p2/monitor.c } else { mon_dispatch = mon_dispatch_postauth15; monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); -@@ -1944,6 +1961,13 @@ monitor_apply_keystate(struct monitor *p - # endif - #endif /* WITH_OPENSSL */ - kex->kex[KEX_C25519_SHA256] = kexc25519_server; + } + if (!no_pty_flag) { + monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1); + } +@@ -1909,16 +1926,23 @@ mm_get_kex(Buffer *m) + fatal("mm_get_get: internal error: bad session id"); + kex->we_need = buffer_get_int(m); + kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; + kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; + kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; + kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; + kex->kex[KEX_ECDH_SHA2] = kexecdh_server; + kex->kex[KEX_C25519_SHA256] = kexc25519_server; +#ifdef GSSAPI + if (options.gss_keyex) { + kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; @@ -1737,10 +2309,20 @@ Index: openssh-7.1p2/monitor.c + kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; + } +#endif - kex->load_host_public_key=&get_hostkey_public_by_type; - kex->load_host_private_key=&get_hostkey_private_by_type; - kex->host_key_index=&get_hostkey_index; -@@ -2059,6 +2083,9 @@ mm_answer_gss_setup_ctx(int sock, Buffer + kex->server = 1; + kex->hostkey_type = buffer_get_int(m); + kex->kex_type = buffer_get_int(m); + blob = buffer_get_string(m, &bloblen); + buffer_init(&kex->my); + buffer_append(&kex->my, blob, bloblen); + free(blob); + blob = buffer_get_string(m, &bloblen); +@@ -2133,16 +2157,19 @@ monitor_reinit(struct monitor *mon) + #ifdef GSSAPI + int + mm_answer_gss_setup_ctx(int sock, Buffer *m) + { + gss_OID_desc goid; OM_uint32 major; u_int len; @@ -1750,7 +2332,17 @@ Index: openssh-7.1p2/monitor.c goid.elements = buffer_get_string(m, &len); goid.length = len; -@@ -2086,6 +2113,9 @@ mm_answer_gss_accept_ctx(int sock, Buffe + major = ssh_gssapi_server_ctx(&gsscontext, &goid); + + free(goid.elements); + + buffer_clear(m); +@@ -2160,16 +2187,19 @@ int + mm_answer_gss_accept_ctx(int sock, Buffer *m) + { + gss_buffer_desc in; + gss_buffer_desc out = GSS_C_EMPTY_BUFFER; + OM_uint32 major, minor; OM_uint32 flags = 0; /* GSI needs this */ u_int len; @@ -1760,7 +2352,17 @@ Index: openssh-7.1p2/monitor.c in.value = buffer_get_string(m, &len); in.length = len; major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags); -@@ -2103,6 +2133,7 @@ mm_answer_gss_accept_ctx(int sock, Buffe + free(in.value); + + buffer_clear(m); + buffer_put_int(m, major); + buffer_put_string(m, out.value, out.length); +@@ -2177,27 +2207,31 @@ mm_answer_gss_accept_ctx(int sock, Buffe + mm_request_send(sock, MONITOR_ANS_GSSSTEP, m); + + gss_release_buffer(&minor, &out); + + if (major == GSS_S_COMPLETE) { monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0); monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); @@ -1768,7 +2370,11 @@ Index: openssh-7.1p2/monitor.c } return (0); } -@@ -2114,6 +2145,9 @@ mm_answer_gss_checkmic(int sock, Buffer + + int + mm_answer_gss_checkmic(int sock, Buffer *m) + { + gss_buffer_desc gssbuf, mic; OM_uint32 ret; u_int len; @@ -1778,7 +2384,17 @@ Index: openssh-7.1p2/monitor.c gssbuf.value = buffer_get_string(m, &len); gssbuf.length = len; mic.value = buffer_get_string(m, &len); -@@ -2140,7 +2174,11 @@ mm_answer_gss_userok(int sock, Buffer *m + mic.length = len; + + ret = ssh_gssapi_checkmic(gsscontext, &gssbuf, &mic); + + free(gssbuf.value); +@@ -2214,29 +2248,101 @@ mm_answer_gss_checkmic(int sock, Buffer + return (0); + } + + int + mm_answer_gss_userok(int sock, Buffer *m) { int authenticated; @@ -1791,7 +2407,12 @@ Index: openssh-7.1p2/monitor.c buffer_clear(m); buffer_put_int(m, authenticated); -@@ -2153,6 +2191,74 @@ mm_answer_gss_userok(int sock, Buffer *m + + debug3("%s: sending result %d", __func__, authenticated); + mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m); + + auth_method = "gssapi-with-mic"; + /* Monitor loop will terminate if authenticated */ return (authenticated); } @@ -1866,24 +2487,43 @@ Index: openssh-7.1p2/monitor.c #endif /* GSSAPI */ #ifdef SSH_AUDIT_EVENTS -Index: openssh-7.1p2/monitor.h -=================================================================== ---- openssh-7.1p2.orig/monitor.h -+++ openssh-7.1p2/monitor.h -@@ -56,6 +56,8 @@ enum monitor_reqtype { - MONITOR_REQ_GSSUSEROK = 46, MONITOR_ANS_GSSUSEROK = 47, - MONITOR_REQ_GSSCHECKMIC = 48, MONITOR_ANS_GSSCHECKMIC = 49, - MONITOR_REQ_TERM = 50, -+ MONITOR_REQ_GSSSIGN = 82, MONITOR_ANS_GSSSIGN = 83, -+ MONITOR_REQ_GSSUPCREDS = 84, MONITOR_ANS_GSSUPCREDS = 85, + int + mm_answer_audit_unsupported_body(int sock, Buffer *m) + { + int what; - MONITOR_REQ_PAM_START = 100, - MONITOR_REQ_PAM_ACCOUNT = 102, MONITOR_ANS_PAM_ACCOUNT = 103, -Index: openssh-7.1p2/monitor_wrap.c -=================================================================== ---- openssh-7.1p2.orig/monitor_wrap.c -+++ openssh-7.1p2/monitor_wrap.c -@@ -1102,7 +1102,7 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss +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 +@@ -65,16 +65,19 @@ enum monitor_reqtype { + 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, + ++ MONITOR_REQ_GSSSIGN = 201, MONITOR_ANS_GSSSIGN = 202, ++ MONITOR_REQ_GSSUPCREDS = 203, MONITOR_ANS_GSSUPCREDS = 204, ++ + }; + + struct mm_master; + struct monitor { + int m_recvfd; + int m_sendfd; + int m_log_recvfd; + int m_log_sendfd; +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 +@@ -1303,33 +1303,78 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss + &m); + + major = buffer_get_int(&m); + buffer_free(&m); + return(major); } int @@ -1892,7 +2532,16 @@ Index: openssh-7.1p2/monitor_wrap.c { Buffer m; int authenticated = 0; -@@ -1119,6 +1119,51 @@ mm_ssh_gssapi_userok(char *user) + + buffer_init(&m); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, &m); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUSEROK, + &m); + + authenticated = buffer_get_int(&m); + + buffer_free(&m); debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not "); return (authenticated); } @@ -1930,25 +2579,34 @@ Index: openssh-7.1p2/monitor_wrap.c + buffer_put_cstring(&m, store->filename ? store->filename : ""); + buffer_put_cstring(&m, store->envvar ? store->envvar : ""); + buffer_put_cstring(&m, store->envval ? store->envval : ""); -+ ++ + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUPCREDS, &m); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUPCREDS, &m); + + ok = buffer_get_int(&m); + + buffer_free(&m); -+ ++ + return (ok); +} + #endif /* GSSAPI */ #ifdef SSH_AUDIT_EVENTS -Index: openssh-7.1p2/monitor_wrap.h -=================================================================== ---- openssh-7.1p2.orig/monitor_wrap.h -+++ openssh-7.1p2/monitor_wrap.h -@@ -59,8 +59,10 @@ BIGNUM *mm_auth_rsa_generate_challenge(K + void + mm_audit_unsupported_body(int what) + { + Buffer m; + +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 +@@ -54,18 +54,20 @@ int mm_user_key_verify(Key *, u_char *, + 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 *); @@ -1960,41 +2618,71 @@ Index: openssh-7.1p2/monitor_wrap.h #endif #ifdef USE_PAM -Index: openssh-7.1p2/readconf.c -=================================================================== ---- openssh-7.1p2.orig/readconf.c -+++ openssh-7.1p2/readconf.c -@@ -147,6 +147,8 @@ typedef enum { + void mm_start_pam(struct Authctxt *); + u_int mm_do_pam_account(void); + 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 **); +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 +@@ -136,16 +136,18 @@ typedef enum { + oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs, + oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication, + oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, + oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, + oHostKeyAlgorithms, oBindAddress, oPKCS11Provider, oClearAllForwardings, oNoHostAuthenticationForLocalhost, oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, oAddressFamily, oGssAuthentication, oGssDelegateCreds, oGssEnableMITM, + oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey, -+ oGssServerIdentity, ++ oGssServerIdentity, oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, oSendEnv, oControlPath, oControlMaster, oControlPersist, oHashKnownHosts, -@@ -192,11 +194,20 @@ static struct { + oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, + oVisualHostKey, oUseRoaming, + oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass, + oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, + oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, +@@ -178,22 +180,31 @@ static struct { + { "challengeresponseauthentication", oChallengeResponseAuthentication }, + { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */ + { "tisauthentication", oChallengeResponseAuthentication }, /* alias */ + { "kerberosauthentication", oUnsupported }, + { "kerberostgtpassing", oUnsupported }, { "afstokenpassing", oUnsupported }, #if defined(GSSAPI) { "gssapiauthentication", oGssAuthentication }, + { "gssapikeyexchange", oGssKeyEx }, { "gssapidelegatecredentials", oGssDelegateCreds }, + { "gssapienablemitmattack", oGssEnableMITM }, + { "gssapitrustdns", oGssTrustDns }, + { "gssapiclientidentity", oGssClientIdentity }, + { "gssapiserveridentity", oGssServerIdentity }, + { "gssapirenewalforcesrekey", oGssRenewalRekey }, - { "gssapienablemitmattack", oGssEnableMITM }, #else { "gssapiauthentication", oUnsupported }, + { "gssapikeyexchange", oUnsupported }, { "gssapidelegatecredentials", oUnsupported }, + { "gssapienablemitmattack", oUnsupported }, + { "gssapitrustdns", oUnsupported }, + { "gssapiclientidentity", oUnsupported }, + { "gssapirenewalforcesrekey", oUnsupported }, - { "gssapienablemitmattack", oUnsupported }, #endif { "fallbacktorsh", oDeprecated }, -@@ -896,9 +907,29 @@ parse_time: + { "usersh", oDeprecated }, + { "identityfile", oIdentityFile }, + { "identityfile2", oIdentityFile }, /* obsolete */ + { "identitiesonly", oIdentitiesOnly }, + { "hostname", oHostName }, + { "hostkeyalias", oHostKeyAlias }, +@@ -838,24 +849,44 @@ parse_time: + case oChallengeResponseAuthentication: + intptr = &options->challenge_response_authentication; + goto parse_flag; + + case oGssAuthentication: intptr = &options->gss_authentication; goto parse_flag; @@ -2005,39 +2693,65 @@ Index: openssh-7.1p2/readconf.c case oGssDelegateCreds: intptr = &options->gss_deleg_creds; goto parse_flag; -+ -+ case oGssTrustDns: -+ intptr = &options->gss_trust_dns; -+ goto parse_flag; -+ -+ case oGssClientIdentity: -+ charptr = &options->gss_client_identity; -+ goto parse_string; -+ -+ case oGssServerIdentity: -+ charptr = &options->gss_server_identity; -+ goto parse_string; -+ -+ case oGssRenewalRekey: -+ intptr = &options->gss_renewal_rekey; -+ goto parse_flag; case oGssEnableMITM: intptr = &options->gss_enable_mitm; -@@ -1607,7 +1638,12 @@ initialize_options(Options * options) + goto parse_flag; + ++ case oGssTrustDns: ++ intptr = &options->gss_trust_dns; ++ goto parse_flag; ++ ++ case oGssClientIdentity: ++ charptr = &options->gss_client_identity; ++ goto parse_string; ++ ++ case oGssServerIdentity: ++ charptr = &options->gss_server_identity; ++ goto parse_string; ++ ++ case oGssRenewalRekey: ++ intptr = &options->gss_renewal_rekey; ++ goto parse_flag; ++ + case oBatchMode: + intptr = &options->batch_mode; + goto parse_flag; + + case oCheckHostIP: + intptr = &options->check_host_ip; + goto parse_flag; + +@@ -1498,18 +1529,23 @@ initialize_options(Options * options) + options->exit_on_forward_failure = -1; + 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_keyex = -1; options->gss_deleg_creds = -1; -+ options->gss_trust_dns = -1; -+ options->gss_renewal_rekey = -1; -+ options->gss_client_identity = NULL; -+ options->gss_server_identity = NULL; options->gss_enable_mitm = -1; ++ options->gss_trust_dns = -1; ++ options->gss_renewal_rekey = -1; ++ options->gss_client_identity = NULL; ++ options->gss_server_identity = NULL; options->password_authentication = -1; options->kbd_interactive_authentication = -1; -@@ -1736,8 +1772,14 @@ fill_default_options(Options * options) + options->kbd_interactive_devices = NULL; + options->rhosts_rsa_authentication = -1; + options->hostbased_authentication = -1; + options->batch_mode = -1; + options->check_host_ip = -1; + options->strict_host_key_checking = -1; +@@ -1618,20 +1654,26 @@ fill_default_options(Options * options) + if (options->rsa_authentication == -1) + options->rsa_authentication = 1; + 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; @@ -2045,111 +2759,78 @@ Index: openssh-7.1p2/readconf.c + options->gss_keyex = 0; if (options->gss_deleg_creds == -1) options->gss_deleg_creds = 0; + if (options->gss_enable_mitm == -1) + options->gss_enable_mitm = 0; + if (options->gss_trust_dns == -1) + options->gss_trust_dns = 0; + if (options->gss_renewal_rekey == -1) + options->gss_renewal_rekey = 0; - if (options->gss_enable_mitm == -1) - options->gss_enable_mitm = 0; if (options->password_authentication == -1) -Index: openssh-7.1p2/readconf.h -=================================================================== ---- openssh-7.1p2.orig/readconf.h -+++ openssh-7.1p2/readconf.h -@@ -45,7 +45,12 @@ typedef struct { + options->password_authentication = 1; + if (options->kbd_interactive_authentication == -1) + 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 +@@ -49,18 +49,23 @@ typedef struct { + int rhosts_rsa_authentication; /* Try rhosts with RSA + * 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_keyex; /* Try GSS key exchange */ ++ int gss_keyex; /* Try GSS key exchange */ int gss_deleg_creds; /* Delegate GSS credentials */ -+ int gss_trust_dns; /* Trust DNS for GSS canonicalization */ -+ int gss_renewal_rekey; /* Credential renewal forces rekey */ + int gss_enable_mitm; /* Enable old style gssapi auth */ ++ int gss_trust_dns; /* Trust DNS for GSS canonicalization */ ++ int gss_renewal_rekey; /* Credential renewal forces rekey */ + char *gss_client_identity; /* Principal to initiate GSSAPI with */ + char *gss_server_identity; /* GSSAPI target principal */ - int gss_enable_mitm; /* Enable old style gssapi auth */ int password_authentication; /* Try password * authentication. */ -Index: openssh-7.1p2/regress/cert-hostkey.sh -=================================================================== ---- openssh-7.1p2.orig/regress/cert-hostkey.sh -+++ openssh-7.1p2/regress/cert-hostkey.sh -@@ -46,7 +46,7 @@ touch $OBJ/host_revoked_plain - touch $OBJ/host_revoked_cert - cp $OBJ/host_ca_key.pub $OBJ/host_revoked_ca - --PLAIN_TYPES=`$SSH -Q key-plain | sed 's/^ssh-dss/ssh-dsa/g;s/^ssh-//'` -+PLAIN_TYPES=`$SSH -Q key-plain | grep -v null | sed 's/^ssh-dss/ssh-dsa/g;s/^ssh-//'` - - # Prepare certificate, plain key and CA KRLs - ${SSHKEYGEN} -kf $OBJ/host_krl_empty || fatal "KRL init failed" -Index: openssh-7.1p2/regress/cert-userkey.sh -=================================================================== ---- openssh-7.1p2.orig/regress/cert-userkey.sh -+++ openssh-7.1p2/regress/cert-userkey.sh -@@ -7,7 +7,7 @@ rm -f $OBJ/authorized_keys_$USER $OBJ/us - cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak - cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak - --PLAIN_TYPES=`$SSH -Q key-plain | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'` -+PLAIN_TYPES=`$SSH -Q key-plain | grep -v null | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'` - - kname() { - n=`echo "$1" | sed 's/^dsa/ssh-dss/;s/^rsa/ssh-rsa/;s/^ed/ssh-ed/'` -Index: openssh-7.1p2/regress/kextype.sh -=================================================================== ---- openssh-7.1p2.orig/regress/kextype.sh -+++ openssh-7.1p2/regress/kextype.sh -@@ -14,6 +14,9 @@ echo "KexAlgorithms=$KEXOPT" >> $OBJ/ssh - - tries="1 2 3 4" - for k in `${SSH} -Q kex`; do -+ if [ $k = "gss-gex-sha1-" -o $k = "gss-group1-sha1-" -o $k = "gss-group14-sha1-" ]; then -+ continue -+ fi - verbose "kex $k" - for i in $tries; do - ${SSH} -F $OBJ/ssh_proxy -o KexAlgorithms=$k x true -Index: openssh-7.1p2/regress/rekey.sh -=================================================================== ---- openssh-7.1p2.orig/regress/rekey.sh -+++ openssh-7.1p2/regress/rekey.sh -@@ -38,6 +38,9 @@ increase_datafile_size 300 - - opts="" - for i in `${SSH} -Q kex`; do -+ if [ $i = "gss-gex-sha1-" -o $i = "gss-group1-sha1-" -o $i = "gss-group14-sha1-" ]; then -+ continue -+ fi - opts="$opts KexAlgorithms=$i" - done - for i in `${SSH} -Q cipher`; do -@@ -56,6 +59,9 @@ done - if ${SSH} -Q cipher-auth | grep '^.*$' >/dev/null 2>&1 ; then - for c in `${SSH} -Q cipher-auth`; do - for kex in `${SSH} -Q kex`; do -+ if [ $kex = "gss-gex-sha1-" -o $kex = "gss-group1-sha1-" -o $kex = "gss-group14-sha1-" ]; then -+ continue -+ fi - verbose "client rekey $c $kex" - ssh_data_rekeying "KexAlgorithms=$kex" -oRekeyLimit=256k -oCiphers=$c - done -Index: openssh-7.1p2/servconf.c -=================================================================== ---- openssh-7.1p2.orig/servconf.c -+++ openssh-7.1p2/servconf.c -@@ -118,9 +118,11 @@ initialize_server_options(ServerOptions + int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ + 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,18 +104,21 @@ initialize_server_options(ServerOptions + options->hostbased_uses_name_from_packet_only = -1; + 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_keyex = -1; options->gss_cleanup_creds = -1; - options->gss_strict_acceptor = -1; options->gss_enable_mitm = -1; ++ options->gss_strict_acceptor = -1; + options->gss_store_rekey = -1; options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->challenge_response_authentication = -1; -@@ -279,10 +281,14 @@ 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; +@@ -243,20 +246,26 @@ fill_default_server_options(ServerOption + if (options->kerberos_or_local_passwd == -1) + options->kerberos_or_local_passwd = 1; + 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; @@ -2157,33 +2838,57 @@ Index: openssh-7.1p2/servconf.c + options->gss_keyex = 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_store_rekey == -1) -+ options->gss_store_rekey = 0; if (options->gss_enable_mitm == -1) options->gss_enable_mitm = 0; ++ if (options->gss_strict_acceptor == -1) ++ options->gss_strict_acceptor = 1; ++ if (options->gss_store_rekey == -1) ++ options->gss_store_rekey = 0; if (options->password_authentication == -1) -@@ -418,7 +424,7 @@ typedef enum { - sHostKeyAlgorithms, - sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, - sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, sGssEnableMITM, -- sAcceptEnv, sPermitTunnel, -+ sGssKeyEx, sGssStoreRekey, sAcceptEnv, sPermitTunnel, + options->password_authentication = 1; + if (options->kbd_interactive_authentication == -1) + 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; +@@ -342,16 +351,17 @@ typedef enum { + 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, sGssEnableMITM, ++ sGssStrictAcceptor, sGssKeyEx, sGssStoreRekey, sMatch, sPermitOpen, sForceCommand, sChrootDirectory, sUsePrivilegeSeparation, sAllowAgentForwarding, sHostCertificate, -@@ -495,12 +501,18 @@ static struct { + sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, + sKexAlgorithms, sIPQoS, sVersionAddendum, + sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, + sAuthenticationMethods, sHostKeyAgent, + sDeprecated, sUnsupported +@@ -411,21 +421,31 @@ static struct { + { "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 }, ++ { "gssapicleanupcreds", sGssCleanupCreds, SSHCFG_GLOBAL }, ++ { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL }, + { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL }, + { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL }, #else { "gssapiauthentication", sUnsupported, SSHCFG_ALL }, { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, - { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL }, { "gssapienablemitmattack", sUnsupported }, ++ { "gssapicleanupcreds", sUnsupported, SSHCFG_GLOBAL }, ++ { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL }, + { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL }, + { "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL }, #endif @@ -2192,7 +2897,17 @@ Index: openssh-7.1p2/servconf.c { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, -@@ -1244,6 +1256,10 @@ process_server_config_line(ServerOptions + { "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */ + { "checkmail", sDeprecated, SSHCFG_GLOBAL }, + { "listenaddress", sListenAddress, SSHCFG_GLOBAL }, + { "addressfamily", sAddressFamily, SSHCFG_GLOBAL }, + { "printmotd", sPrintMotd, SSHCFG_GLOBAL }, +@@ -1094,24 +1114,36 @@ process_server_config_line(ServerOptions + case sKerberosGetAFSToken: + intptr = &options->kerberos_get_afs_token; + goto parse_flag; + + case sGssAuthentication: intptr = &options->gss_authentication; goto parse_flag; @@ -2203,10 +2918,15 @@ Index: openssh-7.1p2/servconf.c case sGssCleanupCreds: intptr = &options->gss_cleanup_creds; goto parse_flag; -@@ -1256,6 +1272,10 @@ process_server_config_line(ServerOptions + + case sGssEnableMITM: intptr = &options->gss_enable_mitm; goto parse_flag; ++ case sGssStrictAcceptor: ++ intptr = &options->gss_strict_acceptor; ++ goto parse_flag; ++ + case sGssStoreRekey: + intptr = &options->gss_store_rekey; + goto parse_flag; @@ -2214,37 +2934,214 @@ Index: openssh-7.1p2/servconf.c case sPasswordAuthentication: intptr = &options->password_authentication; goto parse_flag; -@@ -2264,6 +2284,9 @@ dump_config(ServerOptions *o) + + case sKbdInteractiveAuthentication: + intptr = &options->kbd_interactive_authentication; + goto parse_flag; + +@@ -2007,17 +2039,20 @@ dump_config(ServerOptions *o) + dump_cfg_fmtint(sKerberosOrLocalPasswd, o->kerberos_or_local_passwd); + dump_cfg_fmtint(sKerberosTicketCleanup, o->kerberos_ticket_cleanup); + # ifdef USE_AFS + dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token); + # endif + #endif #ifdef GSSAPI dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); - dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); + dump_cfg_fmtint(sGssKeyEx, o->gss_keyex); + dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); + dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor); + dump_cfg_fmtint(sGssStoreRekey, o->gss_store_rekey); #endif dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication); dump_cfg_fmtint(sKbdInteractiveAuthentication, -Index: openssh-7.1p2/servconf.h -=================================================================== ---- openssh-7.1p2.orig/servconf.h -+++ openssh-7.1p2/servconf.h -@@ -118,9 +118,11 @@ typedef struct { + o->kbd_interactive_authentication); + dump_cfg_fmtint(sChallengeResponseAuthentication, + o->challenge_response_authentication); + dump_cfg_fmtint(sPrintMotd, o->print_motd); + dump_cfg_fmtint(sPrintLastLog, o->print_lastlog); +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 +@@ -107,18 +107,21 @@ typedef struct { + * authentication mechanism, + * 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_keyex; /* If true, permit GSSAPI key exchange */ ++ int gss_keyex; /* If true, permit GSSAPI key exchange */ 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_store_rekey; + int gss_enable_mitm; /* If true, enable old style GSSAPI */ ++ int gss_strict_acceptor; /* If true, restrict the GSSAPI acceptor name */ ++ int gss_store_rekey; int password_authentication; /* If true, permit password * authentication. */ int kbd_interactive_authentication; /* If true, permit */ -Index: openssh-7.1p2/ssh_config.5 -=================================================================== ---- openssh-7.1p2.orig/ssh_config.5 -+++ openssh-7.1p2/ssh_config.5 -@@ -749,11 +749,43 @@ Specifies whether user authentication ba + 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-gss.h b/openssh-6.6p1/ssh-gss.h +--- a/openssh-6.6p1/ssh-gss.h ++++ b/openssh-6.6p1/ssh-gss.h +@@ -1,11 +1,11 @@ + /* $OpenBSD: ssh-gss.h,v 1.11 2014/02/26 20:28:44 djm Exp $ */ + /* +- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. ++ * Copyright (c) 2001-2009 Simon Wilkinson. 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 +@@ -56,53 +56,70 @@ + #define SSH2_MSG_USERAUTH_GSSAPI_TOKEN 61 + #define SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE 63 + #define SSH2_MSG_USERAUTH_GSSAPI_ERROR 64 + #define SSH2_MSG_USERAUTH_GSSAPI_ERRTOK 65 + #define SSH2_MSG_USERAUTH_GSSAPI_MIC 66 + + #define SSH_GSS_OIDTYPE 0x06 + ++#define SSH2_MSG_KEXGSS_INIT 30 ++#define SSH2_MSG_KEXGSS_CONTINUE 31 ++#define SSH2_MSG_KEXGSS_COMPLETE 32 ++#define SSH2_MSG_KEXGSS_HOSTKEY 33 ++#define SSH2_MSG_KEXGSS_ERROR 34 ++#define SSH2_MSG_KEXGSS_GROUPREQ 40 ++#define SSH2_MSG_KEXGSS_GROUP 41 ++#define KEX_GSS_GRP1_SHA1_ID "gss-group1-sha1-" ++#define KEX_GSS_GRP14_SHA1_ID "gss-group14-sha1-" ++#define KEX_GSS_GEX_SHA1_ID "gss-gex-sha1-" ++ + typedef struct { + char *filename; + char *envvar; + char *envval; ++ struct passwd *owner; + void *data; + } ssh_gssapi_ccache; + + typedef struct { + gss_buffer_desc displayname; + gss_buffer_desc exportedname; + gss_cred_id_t creds; ++ gss_name_t name; + struct ssh_gssapi_mech_struct *mech; + ssh_gssapi_ccache store; ++ int used; ++ int updated; + } ssh_gssapi_client; + + typedef struct ssh_gssapi_mech_struct { + char *enc_name; + char *name; + gss_OID_desc oid; + int (*dochild) (ssh_gssapi_client *); + int (*userok) (ssh_gssapi_client *, char *); + int (*localname) (ssh_gssapi_client *, char **); + void (*storecreds) (ssh_gssapi_client *); ++ int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *); + } ssh_gssapi_mech; + + typedef struct { + OM_uint32 major; /* both */ + OM_uint32 minor; /* both */ + gss_ctx_id_t context; /* both */ + gss_name_t name; /* both */ + gss_OID oid; /* client */ + gss_cred_id_t creds; /* server */ + gss_name_t client; /* server */ +- gss_cred_id_t client_creds; /* server */ ++ gss_cred_id_t client_creds; /* both */ + } Gssctxt; + + extern ssh_gssapi_mech *supported_mechs[]; ++extern Gssctxt *gss_kex_context; + + int ssh_gssapi_check_oid(Gssctxt *, void *, size_t); + void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t); + void ssh_gssapi_set_oid(Gssctxt *, gss_OID); + void ssh_gssapi_supported_oids(gss_OID_set *); + ssh_gssapi_mech *ssh_gssapi_get_ctype(Gssctxt *); + void ssh_gssapi_prepare_supported_oids(void); + OM_uint32 ssh_gssapi_test_oid_supported(OM_uint32 *, gss_OID, int *); +@@ -114,21 +131,35 @@ OM_uint32 ssh_gssapi_accept_ctx(Gssctxt + gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *); + OM_uint32 ssh_gssapi_getclient(Gssctxt *, ssh_gssapi_client *); + void ssh_gssapi_error(Gssctxt *); + char *ssh_gssapi_last_error(Gssctxt *, OM_uint32 *, OM_uint32 *); + void ssh_gssapi_build_ctx(Gssctxt **); + void ssh_gssapi_delete_ctx(Gssctxt **); + OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); + void ssh_gssapi_buildmic(Buffer *, const char *, const char *, const char *); +-int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *); ++int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *, const char *); ++OM_uint32 ssh_gssapi_client_identity(Gssctxt *, const char *); ++int ssh_gssapi_credentials_updated(Gssctxt *); + + /* In the server */ ++typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *, ++ const char *); ++char *ssh_gssapi_client_mechanisms(const char *, const char *); ++char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *, ++ const char *); ++gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int); ++int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *, ++ const char *); + OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID); +-int ssh_gssapi_userok(char *name); ++int ssh_gssapi_userok(char *name, struct passwd *); + OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); + void ssh_gssapi_do_child(char ***, u_int *); + void ssh_gssapi_cleanup_creds(void); + void ssh_gssapi_storecreds(void); + ++char *ssh_gssapi_server_mechanisms(void); ++int ssh_gssapi_oid_table_ok(); ++ ++int ssh_gssapi_update_creds(ssh_gssapi_ccache *store); + #endif /* GSSAPI */ + + #endif /* _SSH_GSS_H */ +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 +@@ -32,16 +32,18 @@ Host * + ForwardX11Trusted yes + + # RhostsRSAAuthentication no + # RSAAuthentication yes + # PasswordAuthentication yes + # HostbasedAuthentication no + # GSSAPIAuthentication no + # GSSAPIDelegateCredentials no ++# GSSAPIKeyExchange no ++# GSSAPITrustDNS no + # BatchMode no + # CheckHostIP yes + # AddressFamily any + # ConnectTimeout 0 + # StrictHostKeyChecking ask + # IdentityFile ~/.ssh/identity + # IdentityFile ~/.ssh/id_rsa + # IdentityFile ~/.ssh/id_dsa +diff --git a/openssh-6.6p1/ssh_config.5 b/openssh-6.6p1/ssh_config.5 +--- a/openssh-6.6p1/ssh_config.5 ++++ b/openssh-6.6p1/ssh_config.5 +@@ -677,21 +677,53 @@ host key database, separated by whitespa + The default is + .Pa /etc/ssh/ssh_known_hosts , + .Pa /etc/ssh/ssh_known_hosts2 . + .It Cm GSSAPIAuthentication + Specifies whether user authentication based on GSSAPI is allowed. The default is .Dq no . Note that this option applies to protocol version 2 only. @@ -2289,26 +3186,22 @@ Index: openssh-7.1p2/ssh_config.5 .It Cm HashKnownHosts Indicates that .Xr ssh 1 -Index: openssh-7.1p2/ssh_config -=================================================================== ---- openssh-7.1p2.orig/ssh_config -+++ openssh-7.1p2/ssh_config -@@ -37,6 +37,8 @@ ForwardX11Trusted yes - # HostbasedAuthentication no - # GSSAPIAuthentication no - # GSSAPIDelegateCredentials no -+# GSSAPIKeyExchange no -+# GSSAPITrustDNS no - # BatchMode no - # CheckHostIP yes - # AddressFamily any -Index: openssh-7.1p2/sshconnect2.c -=================================================================== ---- openssh-7.1p2.orig/sshconnect2.c -+++ openssh-7.1p2/sshconnect2.c -@@ -160,9 +160,34 @@ ssh_kex2(char *host, struct sockaddr *ho - struct kex *kex; - int r; + should hash host names and addresses when they are added to + .Pa ~/.ssh/known_hosts . + These hashed names may be used normally by + .Xr ssh 1 + and +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 +@@ -155,19 +155,44 @@ order_hostkeyalgs(char *host, struct soc + return ret; + } + + void + ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) + { + Kex *kex; +#ifdef GSSAPI + char *orig = NULL, *gss = NULL; @@ -2322,7 +3215,7 @@ Index: openssh-7.1p2/sshconnect2.c + if (options.gss_keyex) { + /* Add the GSSAPI mechanisms currently supported on this + * client to the key exchange algorithm proposal */ -+ orig = options.kex_algorithms; ++ orig = myproposal[PROPOSAL_KEX_ALGS]; + + if (options.gss_trust_dns) + gss_host = (char *)get_canonical_hostname(1); @@ -2332,18 +3225,28 @@ Index: openssh-7.1p2/sshconnect2.c + gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity); + if (gss) { + debug("Offering GSSAPI proposal: %s", gss); -+ xasprintf(&options.kex_algorithms, ++ xasprintf(&myproposal[PROPOSAL_KEX_ALGS], + "%s,%s", gss, orig); + } + } +#endif + - myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal( - options.kex_algorithms); - myproposal[PROPOSAL_ENC_ALGS_CTOS] = -@@ -193,6 +218,17 @@ ssh_kex2(char *host, struct sockaddr *ho + if (options.ciphers == (char *)-1) { + logit("No valid ciphers for protocol version 2 given, using defaults."); + options.ciphers = NULL; + } + if (options.ciphers != NULL) { + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; + } else if (fips_mode()) { +@@ -205,32 +230,63 @@ ssh_kex2(char *host, struct sockaddr *ho + 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]); +#ifdef GSSAPI + /* If we've got GSSAPI algorithms, then we also support the @@ -2359,10 +3262,15 @@ Index: openssh-7.1p2/sshconnect2.c if (options.rekey_limit || options.rekey_interval) packet_set_rekey_limits((u_int32_t)options.rekey_limit, (time_t)options.rekey_interval); -@@ -210,11 +246,31 @@ ssh_kex2(char *host, struct sockaddr *ho + + /* start key exchange */ + kex = kex_setup(myproposal); + kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; + kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; + kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; + kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; kex->kex[KEX_ECDH_SHA2] = kexecdh_client; - # endif - #endif + kex->kex[KEX_C25519_SHA256] = kexc25519_client; +#ifdef GSSAPI + if (options.gss_keyex) { + kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client; @@ -2370,7 +3278,6 @@ Index: openssh-7.1p2/sshconnect2.c + kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client; + } +#endif - kex->kex[KEX_C25519_SHA256] = kexc25519_client; kex->client_version_string=client_version_string; kex->server_version_string=server_version_string; kex->verify_host_key=&verify_host_key_callback; @@ -2384,22 +3291,40 @@ Index: openssh-7.1p2/sshconnect2.c + kex->gss_host = options.gss_server_identity; + } else { + kex->gss_host = gss_host; -+ } ++ } + } +#endif + - dispatch_run(DISPATCH_BLOCK, &kex->done, active_state); + xxx_kex = kex; + + dispatch_run(DISPATCH_BLOCK, &kex->done, kex); if (options.use_roaming && !kex->roaming) { -@@ -306,6 +362,7 @@ int input_gssapi_token(int type, u_int32 - int input_gssapi_hash(int type, u_int32_t, void *); - int input_gssapi_error(int, u_int32_t, void *); - int input_gssapi_errtok(int, u_int32_t, void *); + debug("Roaming not allowed by server"); + options.use_roaming = 0; + } +@@ -310,31 +366,37 @@ int userauth_hostbased(Authctxt *); + + #ifdef GSSAPI + int userauth_gssapi(Authctxt *authctxt); + void input_gssapi_response(int type, u_int32_t, void *); + void input_gssapi_token(int type, u_int32_t, void *); + void input_gssapi_hash(int type, u_int32_t, void *); + void input_gssapi_error(int, u_int32_t, void *); + void input_gssapi_errtok(int, u_int32_t, void *); +int userauth_gsskeyex(Authctxt *authctxt); #endif void userauth(Authctxt *, char *); -@@ -321,6 +378,11 @@ static char *authmethods_get(void); + + static int sign_and_send_pubkey(Authctxt *, Identity *); + static void pubkey_prepare(Authctxt *); + static void pubkey_cleanup(Authctxt *); + static Key *load_identity_file(char *, int); + + static Authmethod *authmethod_get(char *authlist); + static Authmethod *authmethod_lookup(const char *name); + static char *authmethods_get(void); Authmethod authmethods[] = { #ifdef GSSAPI @@ -2411,7 +3336,17 @@ Index: openssh-7.1p2/sshconnect2.c {"gssapi-with-mic", userauth_gssapi, NULL, -@@ -632,19 +694,31 @@ userauth_gssapi(Authctxt *authctxt) + &options.gss_authentication, + NULL}, + {"gssapi", + userauth_gssapi, + NULL, +@@ -626,29 +688,41 @@ done: + int + userauth_gssapi(Authctxt *authctxt) + { + Gssctxt *gssctxt = NULL; + static gss_OID_set gss_supported = NULL; static u_int mech = 0; OM_uint32 min; int ok = 0; @@ -2445,7 +3380,17 @@ Index: openssh-7.1p2/sshconnect2.c ok = 1; /* Mechanism works */ } else { mech++; -@@ -743,8 +817,8 @@ input_gssapi_response(int type, u_int32_ + } + } + + if (!ok) + return 0; +@@ -737,18 +811,18 @@ process_gssapi_token(void *ctxt, gss_buf + } + + /* ARGSUSED */ + void + input_gssapi_response(int type, u_int32_t plen, void *ctxt) { Authctxt *authctxt = ctxt; Gssctxt *gssctxt; @@ -2456,9 +3401,19 @@ Index: openssh-7.1p2/sshconnect2.c if (authctxt == NULL) fatal("input_gssapi_response: no authentication context"); -@@ -857,6 +931,48 @@ input_gssapi_error(int type, u_int32_t p + gssctxt = authctxt->methoddata; + + /* Setup our OID */ + oidv = packet_get_string(&oidlen); + +@@ -847,16 +921,58 @@ input_gssapi_error(int type, u_int32_t p + lang=packet_get_string(NULL); + + packet_check_eom(); + + debug("Server GSSAPI Error:\n%s", msg); + free(msg); free(lang); - return 0; } + +int @@ -2505,23 +3460,41 @@ Index: openssh-7.1p2/sshconnect2.c #endif /* GSSAPI */ int -Index: openssh-7.1p2/sshd.c -=================================================================== ---- openssh-7.1p2.orig/sshd.c -+++ openssh-7.1p2/sshd.c -@@ -1019,8 +1019,9 @@ notify_hostkeys(struct ssh *ssh) - } - debug3("%s: sent %d hostkeys", __func__, nkeys); - if (nkeys == 0) -- fatal("%s: no hostkeys", __func__); -- packet_send(); -+ debug3("%s: no hostkeys", __func__); -+ else -+ packet_send(); - sshbuf_free(buf); - } + userauth_none(Authctxt *authctxt) + { + /* initial userauth request */ + packet_start(SSH2_MSG_USERAUTH_REQUEST); + packet_put_cstring(authctxt->server_user); +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 +@@ -123,16 +123,20 @@ + #include "roaming.h" + #include "ssh-sandbox.h" + #include "version.h" -@@ -1891,10 +1892,13 @@ main(int ac, char **av) + #include "fips.h" + + #include "audit.h" + ++#ifdef USE_SECURITY_SESSION_API ++#include ++#endif ++ + #ifdef LIBWRAP + #include + #include + int allow_severity; + int deny_severity; + #endif /* LIBWRAP */ + + #ifndef O_NOCTTY +@@ -1804,20 +1808,23 @@ main(int ac, char **av) + if ((options.protocol & SSH_PROTO_1) && fips_mode()) { + logit("Disabling protocol version 1. Not allowed in the FIPS mode."); + options.protocol &= ~SSH_PROTO_1; + } + if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) { logit("Disabling protocol version 1. Could not load host key"); options.protocol &= ~SSH_PROTO_1; } @@ -2535,7 +3508,159 @@ Index: openssh-7.1p2/sshd.c if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) { logit("sshd: no hostkeys available -- exiting."); exit(1); -@@ -2635,6 +2639,48 @@ do_ssh2_kex(void) + } + + /* + * Load certificates. They are stored in an array at identical + * indices to the public keys that they relate to. +@@ -2007,16 +2014,70 @@ main(int ac, char **av) + /* Accept a connection and return in a forked child */ + server_accept_loop(&sock_in, &sock_out, + &newsock, config_s); + } + + /* This is the child processing a new connection. */ + setproctitle("%s", "[accepted]"); + ++#ifdef USE_SECURITY_SESSION_API ++ /* ++ * Create a new security session for use by the new user login if ++ * the current session is the root session or we are not launched ++ * by inetd (eg: debugging mode or server mode). We do not ++ * necessarily need to create a session if we are launched from ++ * inetd because Panther xinetd will create a session for us. ++ * ++ * The only case where this logic will fail is if there is an ++ * inetd running in a non-root session which is not creating ++ * new sessions for us. Then all the users will end up in the ++ * same session (bad). ++ * ++ * When the client exits, the session will be destroyed for us ++ * automatically. ++ * ++ * We must create the session before any credentials are stored ++ * (including AFS pags, which happens a few lines below). ++ */ ++ { ++ OSStatus err = 0; ++ SecuritySessionId sid = 0; ++ SessionAttributeBits sattrs = 0; ++ ++ err = SessionGetInfo(callerSecuritySession, &sid, &sattrs); ++ if (err) ++ error("SessionGetInfo() failed with error %.8X", ++ (unsigned) err); ++ else ++ debug("Current Session ID is %.8X / Session Attributes are %.8X", ++ (unsigned) sid, (unsigned) sattrs); ++ ++ if (inetd_flag && !(sattrs & sessionIsRoot)) ++ debug("Running in inetd mode in a non-root session... " ++ "assuming inetd created the session for us."); ++ else { ++ debug("Creating new security session..."); ++ err = SessionCreate(0, sessionHasTTY | sessionIsRemote); ++ if (err) ++ error("SessionCreate() failed with error %.8X", ++ (unsigned) err); ++ ++ err = SessionGetInfo(callerSecuritySession, &sid, ++ &sattrs); ++ if (err) ++ error("SessionGetInfo() failed with error %.8X", ++ (unsigned) err); ++ else ++ debug("New Session ID is %.8X / Session Attributes are %.8X", ++ (unsigned) sid, (unsigned) sattrs); ++ } ++ } ++#endif ++ + /* + * Create a new session and process group since the 4.4BSD + * setlogin() affects the entire process group. We don't + * want the child to be able to affect the parent. + */ + #if !defined(SSHD_ACQUIRES_CTTY) + /* + * If setsid is called, on some platforms sshd will later acquire a +@@ -2134,16 +2195,70 @@ main(int ac, char **av) + } + #endif /* LIBWRAP */ + + /* Log the connection. */ + verbose("Connection from %s port %d on %s port %d", + remote_ip, remote_port, + get_local_ipaddr(sock_in), get_local_port()); + ++#ifdef USE_SECURITY_SESSION_API ++ /* ++ * Create a new security session for use by the new user login if ++ * the current session is the root session or we are not launched ++ * by inetd (eg: debugging mode or server mode). We do not ++ * necessarily need to create a session if we are launched from ++ * inetd because Panther xinetd will create a session for us. ++ * ++ * The only case where this logic will fail is if there is an ++ * inetd running in a non-root session which is not creating ++ * new sessions for us. Then all the users will end up in the ++ * same session (bad). ++ * ++ * When the client exits, the session will be destroyed for us ++ * automatically. ++ * ++ * We must create the session before any credentials are stored ++ * (including AFS pags, which happens a few lines below). ++ */ ++ { ++ OSStatus err = 0; ++ SecuritySessionId sid = 0; ++ SessionAttributeBits sattrs = 0; ++ ++ err = SessionGetInfo(callerSecuritySession, &sid, &sattrs); ++ if (err) ++ error("SessionGetInfo() failed with error %.8X", ++ (unsigned) err); ++ else ++ debug("Current Session ID is %.8X / Session Attributes are %.8X", ++ (unsigned) sid, (unsigned) sattrs); ++ ++ if (inetd_flag && !(sattrs & sessionIsRoot)) ++ debug("Running in inetd mode in a non-root session... " ++ "assuming inetd created the session for us."); ++ else { ++ debug("Creating new security session..."); ++ err = SessionCreate(0, sessionHasTTY | sessionIsRemote); ++ if (err) ++ error("SessionCreate() failed with error %.8X", ++ (unsigned) err); ++ ++ err = SessionGetInfo(callerSecuritySession, &sid, ++ &sattrs); ++ if (err) ++ error("SessionGetInfo() failed with error %.8X", ++ (unsigned) err); ++ else ++ debug("New Session ID is %.8X / Session Attributes are %.8X", ++ (unsigned) sid, (unsigned) sattrs); ++ } ++ } ++#endif ++ + /* + * We don't want to listen forever unless the other side + * successfully authenticates itself. So we set up an alarm which is + * cleared after successful authentication. A limit of zero + * indicates no limit. Note that we don't set the alarm in debugging + * mode; it is just annoying to have the server exit just when you + * are about to discover the bug. + */ +@@ -2562,24 +2677,73 @@ do_ssh2_kex(void) + + 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()); @@ -2582,11 +3707,12 @@ Index: openssh-7.1p2/sshd.c +#endif + /* start key exchange */ - if ((r = kex_setup(active_state, myproposal)) != 0) - fatal("kex_setup: %s", ssh_err(r)); -@@ -2649,6 +2695,13 @@ do_ssh2_kex(void) - # endif - #endif + kex = kex_setup(myproposal); + kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; + kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; + kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; + kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; + kex->kex[KEX_ECDH_SHA2] = kexecdh_server; kex->kex[KEX_C25519_SHA256] = kexc25519_server; +#ifdef GSSAPI + if (options.gss_keyex) { @@ -2598,11 +3724,42 @@ Index: openssh-7.1p2/sshd.c kex->server = 1; kex->client_version_string=client_version_string; kex->server_version_string=server_version_string; -Index: openssh-7.1p2/sshd_config.5 -=================================================================== ---- openssh-7.1p2.orig/sshd_config.5 -+++ openssh-7.1p2/sshd_config.5 -@@ -620,6 +620,12 @@ Specifies whether user authentication ba + kex->load_host_public_key=&get_hostkey_public_by_type; + kex->load_host_private_key=&get_hostkey_private_by_type; + kex->host_key_index=&get_hostkey_index; + kex->sign = sshd_hostkey_sign; + +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 +@@ -79,16 +79,18 @@ PasswordAuthentication no + #KerberosAuthentication no + #KerberosOrLocalPasswd yes + #KerberosTicketCleanup yes + #KerberosGetAFSToken no + + # GSSAPI options + #GSSAPIAuthentication no + #GSSAPICleanupCredentials yes ++#GSSAPIStrictAcceptorCheck yes ++#GSSAPIKeyExchange no + + # Set this to 'yes' to enable support for the deprecated 'gssapi' authentication + # mechanism to OpenSSH 3.8p1. The newer 'gssapi-with-mic' mechanism is included + # in this release. The use of 'gssapi' is deprecated due to the presence of + # potential man-in-the-middle attacks, which 'gssapi-with-mic' is not susceptible to. + #GSSAPIEnableMITMAttack no + + +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 +@@ -487,22 +487,50 @@ to force remote port forwardings to bind + to allow the client to select the address to which the forwarding is bound. + The default is + .Dq no . + .It Cm GSSAPIAuthentication + Specifies whether user authentication based on GSSAPI is allowed. The default is .Dq no . Note that this option applies to protocol version 2 only. @@ -2615,167 +3772,36 @@ Index: openssh-7.1p2/sshd_config.5 .It Cm GSSAPICleanupCredentials Specifies whether to automatically destroy the user's credentials cache on logout. -@@ -641,6 +647,11 @@ machine's default store. - This facility is provided to assist with operation on multi homed machines. The default is .Dq yes . + Note that this option applies to protocol version 2 only. ++.It Cm GSSAPIStrictAcceptorCheck ++Determines whether to be strict about the identity of the GSSAPI acceptor ++a client authenticates against. If ++.Dq yes ++then the client must authenticate against the ++.Pa host ++service on the current hostname. If ++.Dq no ++then the client may authenticate against any service key stored in the ++machine's default store. This facility is provided to assist with operation ++on multi homed machines. ++The default is ++.Dq yes . ++Note that this option applies only to protocol version 2 GSSAPI connections, ++and setting it to ++.Dq no ++may only work with recent Kerberos GSSAPI libraries. +.It Cm GSSAPIStoreCredentialsOnRekey +Controls whether the user's GSSAPI credentials should be updated following a +successful connection rekeying. This option can be used to accepted renewed +or updated credentials from a compatible client. The default is +.Dq no . - .It Cm HostbasedAcceptedKeyTypes - Specifies the key types that will be accepted for hostbased authentication - as a comma-separated pattern list. -Index: openssh-7.1p2/sshd_config -=================================================================== ---- openssh-7.1p2.orig/sshd_config -+++ openssh-7.1p2/sshd_config -@@ -84,6 +84,8 @@ PasswordAuthentication no - # GSSAPI options - #GSSAPIAuthentication no - #GSSAPICleanupCredentials yes -+#GSSAPIStrictAcceptorCheck yes -+#GSSAPIKeyExchange no - - # Set this to 'yes' to enable support for the deprecated 'gssapi' authentication - # mechanism to OpenSSH 3.8p1. The newer 'gssapi-with-mic' mechanism is included -Index: openssh-7.1p2/ssh-gss.h -=================================================================== ---- openssh-7.1p2.orig/ssh-gss.h -+++ openssh-7.1p2/ssh-gss.h -@@ -1,6 +1,6 @@ - /* $OpenBSD: ssh-gss.h,v 1.11 2014/02/26 20:28:44 djm Exp $ */ - /* -- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. -+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions -@@ -61,10 +61,22 @@ - - #define SSH_GSS_OIDTYPE 0x06 - -+#define SSH2_MSG_KEXGSS_INIT 30 -+#define SSH2_MSG_KEXGSS_CONTINUE 31 -+#define SSH2_MSG_KEXGSS_COMPLETE 32 -+#define SSH2_MSG_KEXGSS_HOSTKEY 33 -+#define SSH2_MSG_KEXGSS_ERROR 34 -+#define SSH2_MSG_KEXGSS_GROUPREQ 40 -+#define SSH2_MSG_KEXGSS_GROUP 41 -+#define KEX_GSS_GRP1_SHA1_ID "gss-group1-sha1-" -+#define KEX_GSS_GRP14_SHA1_ID "gss-group14-sha1-" -+#define KEX_GSS_GEX_SHA1_ID "gss-gex-sha1-" -+ - typedef struct { - char *filename; - char *envvar; - char *envval; -+ struct passwd *owner; - void *data; - } ssh_gssapi_ccache; - -@@ -72,8 +84,11 @@ typedef struct { - gss_buffer_desc displayname; - gss_buffer_desc exportedname; - gss_cred_id_t creds; -+ gss_name_t name; - struct ssh_gssapi_mech_struct *mech; - ssh_gssapi_ccache store; -+ int used; -+ int updated; - } ssh_gssapi_client; - - typedef struct ssh_gssapi_mech_struct { -@@ -84,6 +99,7 @@ typedef struct ssh_gssapi_mech_struct { - int (*userok) (ssh_gssapi_client *, char *); - int (*localname) (ssh_gssapi_client *, char **); - void (*storecreds) (ssh_gssapi_client *); -+ int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *); - } ssh_gssapi_mech; - - typedef struct { -@@ -94,10 +110,11 @@ typedef struct { - gss_OID oid; /* client */ - gss_cred_id_t creds; /* server */ - gss_name_t client; /* server */ -- gss_cred_id_t client_creds; /* server */ -+ gss_cred_id_t client_creds; /* both */ - } Gssctxt; - - extern ssh_gssapi_mech *supported_mechs[]; -+extern Gssctxt *gss_kex_context; - - int ssh_gssapi_check_oid(Gssctxt *, void *, size_t); - void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t); -@@ -119,16 +136,32 @@ void ssh_gssapi_build_ctx(Gssctxt **); - void ssh_gssapi_delete_ctx(Gssctxt **); - OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); - void ssh_gssapi_buildmic(Buffer *, const char *, const char *, const char *); --int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *); -+int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *, const char *); -+OM_uint32 ssh_gssapi_client_identity(Gssctxt *, const char *); -+int ssh_gssapi_credentials_updated(Gssctxt *); - - /* In the server */ -+typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *, -+ const char *); -+char *ssh_gssapi_client_mechanisms(const char *, const char *); -+char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *, -+ const char *); -+gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int); -+int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *, -+ const char *); - OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID); --int ssh_gssapi_userok(char *name); -+int ssh_gssapi_userok(char *name, struct passwd *); - OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); - void ssh_gssapi_do_child(char ***, u_int *); - void ssh_gssapi_cleanup_creds(void); - void ssh_gssapi_storecreds(void); - -+char *ssh_gssapi_server_mechanisms(void); -+int ssh_gssapi_oid_table_ok(); -+ -+int ssh_gssapi_update_creds(ssh_gssapi_ccache *store); -+ -+void ssh_gssapi_rekey_creds(void); - #endif /* GSSAPI */ - - #endif /* _SSH_GSS_H */ -Index: openssh-7.1p2/sshkey.c -=================================================================== ---- openssh-7.1p2.orig/sshkey.c -+++ openssh-7.1p2/sshkey.c -@@ -112,6 +112,7 @@ static const struct keytype keytypes[] = - # endif /* OPENSSL_HAS_NISTP521 */ - # endif /* OPENSSL_HAS_ECC */ - #endif /* WITH_OPENSSL */ -+ { "null", "null", KEY_NULL, 0, 0 }, - { NULL, NULL, -1, -1, 0 } - }; - -Index: openssh-7.1p2/sshkey.h -=================================================================== ---- openssh-7.1p2.orig/sshkey.h -+++ openssh-7.1p2/sshkey.h -@@ -62,6 +62,7 @@ enum sshkey_types { - KEY_DSA_CERT, - KEY_ECDSA_CERT, - KEY_ED25519_CERT, -+ KEY_NULL, - KEY_UNSPEC - }; - -Index: openssh-7.1p2/auth.c -=================================================================== ---- openssh-7.1p2.orig/auth.c -+++ openssh-7.1p2/auth.c -@@ -354,6 +354,7 @@ auth_root_allowed(const char *method) - case PERMIT_NO_PASSWD: - if (strcmp(method, "publickey") == 0 || - strcmp(method, "hostbased") == 0 || -+ strcmp(method, "gssapi-keyex") == 0 || - strcmp(method, "gssapi-with-mic") == 0) - return 1; - break; + .It Cm HostbasedAuthentication + Specifies whether rhosts or /etc/hosts.equiv authentication together + with successful public key client host authentication is allowed + (host-based authentication). + This option is similar to + .Cm RhostsRSAAuthentication + and applies to protocol version 2 only. + The default is diff --git a/openssh-6.6p1-gssapimitm.patch b/openssh-6.6p1-gssapimitm.patch index 2a9278d..8684527 100644 --- a/openssh-6.6p1-gssapimitm.patch +++ b/openssh-6.6p1-gssapimitm.patch @@ -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 diff --git a/openssh-6.6p1-ldap.patch b/openssh-6.6p1-ldap.patch index 5e3f7a1..a91ff94 100644 --- a/openssh-6.6p1-ldap.patch +++ b/openssh-6.6p1-ldap.patch @@ -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 +# +# 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 ++ AuthorizedKeysCommand "@LIBEXECDIR@/ssh-ldap-wrapper" ++ AuthorizedKeysCommandRunAs + * 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 +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 @@ -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 -+ -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 +#include -+#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 + #include + #include + #include + #include + + #include +@@ -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 -+# -+# 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 -+# -+# 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 ) ) diff --git a/openssh-6.6p1-no_fork-no_pid_file.patch b/openssh-6.6p1-no_fork-no_pid_file.patch new file mode 100644 index 0000000..9ad6c49 --- /dev/null +++ b/openssh-6.6p1-no_fork-no_pid_file.patch @@ -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); diff --git a/openssh-6.6p1-pam-check-locks.patch b/openssh-6.6p1-pam-check-locks.patch index dacd3a5..1ac4580 100644 --- a/openssh-6.6p1-pam-check-locks.patch +++ b/openssh-6.6p1-pam-check-locks.patch @@ -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 diff --git a/openssh-6.6p1-seccomp_getuid.patch b/openssh-6.6p1-seccomp_getuid.patch index 328f37b..28efbcd 100644 --- a/openssh-6.6p1-seccomp_getuid.patch +++ b/openssh-6.6p1-seccomp_getuid.patch @@ -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), diff --git a/openssh-6.6p1-seed-prng.patch b/openssh-6.6p1-seed-prng.patch index 257f497..9a99148 100644 --- a/openssh-6.6p1-seed-prng.patch +++ b/openssh-6.6p1-seed-prng.patch @@ -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 @@ -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 + #endif + #ifdef HAVE_SYS_TIME_H + # include #endif #include "openbsd-compat/sys-tree.h" #include "openbsd-compat/sys-queue.h" @@ -383,7 +489,17 @@ Index: b/sshd.c #include #include -@@ -214,6 +216,13 @@ struct { + #include + #include + #ifdef HAVE_PATHS_H + #include + #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 diff --git a/openssh-6.6p1-sftp_force_permissions.patch b/openssh-6.6p1-sftp_force_permissions.patch index e1a6c5c..697662c 100644 --- a/openssh-6.6p1-sftp_force_permissions.patch +++ b/openssh-6.6p1-sftp_force_permissions.patch @@ -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); + diff --git a/openssh-6.6p1-sftp_homechroot.patch b/openssh-6.6p1-sftp_homechroot.patch index e9af539..71f9c83 100644 --- a/openssh-6.6p1-sftp_homechroot.patch +++ b/openssh-6.6p1-sftp_homechroot.patch @@ -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 + #include #include #include #include @@ -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 , diff --git a/openssh-6.6p1.tar.gz b/openssh-6.6p1.tar.gz new file mode 100644 index 0000000..f9e5859 --- /dev/null +++ b/openssh-6.6p1.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:48c1f0664b4534875038004cc4f3555b8329c2a81c1df48db5c517800de203bb +size 1282502 diff --git a/openssh-6.6p1.tar.gz.asc b/openssh-6.6p1.tar.gz.asc new file mode 100644 index 0000000..defd54e --- /dev/null +++ b/openssh-6.6p1.tar.gz.asc @@ -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----- diff --git a/openssh-6.7p1-audit.patch b/openssh-6.7p1-audit.patch deleted file mode 100644 index 3d0e959..0000000 --- a/openssh-6.7p1-audit.patch +++ /dev/null @@ -1,2360 +0,0 @@ -Index: openssh-7.1p2/audit-bsm.c -=================================================================== ---- openssh-7.1p2.orig/audit-bsm.c -+++ openssh-7.1p2/audit-bsm.c -@@ -375,10 +375,23 @@ audit_connection_from(const char *host, - #endif - } - --void -+int - audit_run_command(const char *command) - { - /* not implemented */ -+ return 0; -+} -+ -+void -+audit_end_command(int handle, const char *command) -+{ -+ /* not implemented */ -+} -+ -+void -+audit_count_session_open(void) -+{ -+ /* not necessary */ - } - - void -@@ -393,6 +406,12 @@ audit_session_close(struct logininfo *li - /* not implemented */ - } - -+int -+audit_keyusage(int host_user, const char *type, unsigned bits, char *fp, int rv) -+{ -+ /* not implemented */ -+} -+ - void - audit_event(ssh_audit_event_t event) - { -@@ -454,4 +473,40 @@ audit_event(ssh_audit_event_t event) - debug("%s: unhandled event %d", __func__, event); - } - } -+ -+void -+audit_unsupported_body(int what) -+{ -+ /* not implemented */ -+} -+ -+void -+audit_kex_body(int ctos, char *enc, char *mac, char *compress, char *pfs, pid_t pid, uid_t uid) -+{ -+ /* 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 */ -Index: openssh-7.1p2/audit.c -=================================================================== ---- openssh-7.1p2.orig/audit.c -+++ openssh-7.1p2/audit.c -@@ -28,6 +28,7 @@ - - #include - #include -+#include - - #ifdef SSH_AUDIT_EVENTS - -@@ -36,6 +37,11 @@ - #include "key.h" - #include "hostfile.h" - #include "auth.h" -+#include "ssh-gss.h" -+#include "monitor_wrap.h" -+#include "xmalloc.h" -+#include "misc.h" -+#include "servconf.h" - - /* - * Care must be taken when using this since it WILL NOT be initialized when -@@ -43,6 +49,7 @@ - * audit_event(CONNECTION_ABANDON) is called. Test for NULL before using. - */ - extern Authctxt *the_authctxt; -+extern ServerOptions options; - - /* Maybe add the audit class to struct Authmethod? */ - ssh_audit_event_t -@@ -71,13 +78,10 @@ audit_classify_auth(const char *method) - const char * - audit_username(void) - { -- static const char unknownuser[] = "(unknown user)"; -- static const char invaliduser[] = "(invalid user)"; -+ static const char unknownuser[] = "(unknown)"; - -- if (the_authctxt == NULL || the_authctxt->user == NULL) -+ if (the_authctxt == NULL || the_authctxt->user == NULL || !the_authctxt->valid) - return (unknownuser); -- if (!the_authctxt->valid) -- return (invaliduser); - return (the_authctxt->user); - } - -@@ -111,6 +115,40 @@ audit_event_lookup(ssh_audit_event_t ev) - return(event_lookup[i].name); - } - -+void -+audit_key(int host_user, int *rv, const Key *key) -+{ -+ char *fp; -+ const char *crypto_name; -+ -+ fp = sshkey_fingerprint(key, options.fingerprint_hash, 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); -+} -+ -+void -+audit_unsupported(int what) -+{ -+ PRIVSEP(audit_unsupported_body(what)); -+} -+ -+void -+audit_kex(int ctos, char *enc, char *mac, char *comp, char *pfs) -+{ -+ PRIVSEP(audit_kex_body(ctos, enc, mac, comp, pfs, 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. -@@ -140,6 +178,17 @@ audit_event(ssh_audit_event_t event) - } - - /* -+ * Called when a child process has called, or will soon call, -+ * audit_session_open. -+ */ -+void -+audit_count_session_open(void) -+{ -+ debug("audit count session open euid %d user %s", geteuid(), -+ audit_username()); -+} -+ -+/* - * Called when a user session is started. Argument is the tty allocated to - * the session, or NULL if no tty was allocated. - * -@@ -174,13 +223,91 @@ audit_session_close(struct logininfo *li - /* - * This will be called when a user runs a non-interactive command. Note that - * it may be called multiple times for a single connection since SSH2 allows -- * multiple sessions within a single connection. -+ * multiple sessions within a single connection. Returns a "handle" for -+ * audit_end_command. - */ --void -+int - audit_run_command(const char *command) - { - debug("audit run command euid %d user %s command '%.200s'", geteuid(), - audit_username(), command); -+ return 0; -+} -+ -+/* -+ * This will be called when the non-interactive command finishes. Note that -+ * it may be called multiple times for a single connection since SSH2 allows -+ * multiple sessions within a single connection. "handle" should come from -+ * the corresponding audit_run_command. -+ */ -+void -+audit_end_command(int handle, const char *command) -+{ -+ debug("audit end nopty exec euid %d user %s command '%.200s'", geteuid(), -+ audit_username(), command); -+} -+ -+/* -+ * This will be called when user is successfully autherized by the RSA1/RSA/DSA key. -+ * -+ * Type is the key type, len is the key length(byte) and fp is the fingerprint of the key. -+ */ -+int -+audit_keyusage(int host_user, const char *type, unsigned bits, char *fp, int rv) -+{ -+ debug("audit %s key usage euid %d user %s key type %s key length %d fingerprint %s%s, result %d", -+ host_user ? "pubkey" : "hostbased", geteuid(), audit_username(), type, bits, -+ sshkey_fingerprint_prefix(), fp, rv); -+} -+ -+/* -+ * This will be called when the protocol negotiation fails. -+ */ -+void -+audit_unsupported_body(int what) -+{ -+ debug("audit unsupported protocol euid %d type %d", geteuid(), what); -+} -+ -+/* -+ * This will be called on succesfull protocol negotiation. -+ */ -+void -+audit_kex_body(int ctos, char *enc, char *mac, char *compress, char *pfs, pid_t pid, -+ uid_t uid) -+{ -+ debug("audit protocol negotiation euid %d direction %d cipher %s mac %s compresion %s pfs %s from pid %ld uid %u", -+ (unsigned)geteuid(), ctos, enc, mac, compress, pfs, (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); -+} -+ -+/* -+ * 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 */ -Index: openssh-7.1p2/audit.h -=================================================================== ---- openssh-7.1p2.orig/audit.h -+++ openssh-7.1p2/audit.h -@@ -28,6 +28,7 @@ - # define _SSH_AUDIT_H - - #include "loginrec.h" -+#include "key.h" - - enum ssh_audit_event_type { - SSH_LOGIN_EXCEED_MAXTRIES, -@@ -47,11 +48,25 @@ enum ssh_audit_event_type { - }; - typedef enum ssh_audit_event_type ssh_audit_event_t; - -+int listening_for_clients(void); -+ - void audit_connection_from(const char *, int); - void audit_event(ssh_audit_event_t); -+void audit_count_session_open(void); - 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 *); -+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 *, char *); -+void audit_unsupported_body(int); -+void audit_kex_body(int, char *, 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 */ -Index: openssh-7.1p2/audit-linux.c -=================================================================== ---- openssh-7.1p2.orig/audit-linux.c -+++ openssh-7.1p2/audit-linux.c -@@ -35,13 +35,25 @@ - - #include "log.h" - #include "audit.h" -+#include "key.h" -+#include "hostfile.h" -+#include "auth.h" -+#include "misc.h" /* servconf.h needs misc.h for struct ForwardOptions */ -+#include "servconf.h" - #include "canohost.h" -+#include "packet.h" -+#include "cipher.h" - -+#define AUDIT_LOG_SIZE 256 -+ -+extern ServerOptions options; -+extern Authctxt *the_authctxt; -+extern u_int utmp_len; - const char* audit_username(void); - --int --linux_audit_record_event(int uid, const char *username, -- const char *hostname, const char *ip, const char *ttyn, int success) -+static void -+linux_audit_user_logxxx(int uid, const char *username, -+ const char *hostname, const char *ip, const char *ttyn, int success, int event) - { - int audit_fd, rc, saved_errno; - -@@ -49,11 +61,11 @@ linux_audit_record_event(int uid, const - if (audit_fd < 0) { - if (errno == EINVAL || errno == EPROTONOSUPPORT || - errno == EAFNOSUPPORT) -- return 1; /* No audit support in kernel */ -+ return; /* No audit support in kernel */ - else -- return 0; /* Must prevent login */ -+ goto fatal_report; /* Must prevent login */ - } -- rc = audit_log_acct_message(audit_fd, AUDIT_USER_LOGIN, -+ rc = audit_log_acct_message(audit_fd, event, - NULL, "login", username ? username : "(unknown)", - username == NULL ? uid : -1, hostname, ip, ttyn, success); - saved_errno = errno; -@@ -65,35 +77,154 @@ linux_audit_record_event(int uid, const - if ((rc == -EPERM) && (geteuid() != 0)) - rc = 0; - errno = saved_errno; -- return (rc >= 0); -+ if (rc < 0) { -+fatal_report: -+ fatal("linux_audit_write_entry failed: %s", strerror(errno)); -+ } - } - -+static void -+linux_audit_user_auth(int uid, const char *username, -+ const char *hostname, const char *ip, const char *ttyn, int success, int event) -+{ -+ int audit_fd, rc, saved_errno; -+ static const char *event_name[] = { -+ "maxtries exceeded", -+ "root denied", -+ "success", -+ "none", -+ "password", -+ "challenge-response", -+ "pubkey", -+ "hostbased", -+ "gssapi", -+ "invalid user", -+ "nologin", -+ "connection closed", -+ "connection abandoned", -+ "unknown" -+ }; -+ -+ audit_fd = audit_open(); -+ if (audit_fd < 0) { -+ if (errno == EINVAL || errno == EPROTONOSUPPORT || -+ errno == EAFNOSUPPORT) -+ return; /* No audit support in kernel */ -+ else -+ goto fatal_report; /* Must prevent login */ -+ } -+ -+ if ((event < 0) || (event > SSH_AUDIT_UNKNOWN)) -+ event = SSH_AUDIT_UNKNOWN; -+ -+ rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH, -+ NULL, event_name[event], username ? username : "(unknown)", -+ username == NULL ? uid : -1, hostname, ip, ttyn, success); -+ saved_errno = errno; -+ close(audit_fd); -+ /* -+ * Do not report error if the error is EPERM and sshd is run as non -+ * root user. -+ */ -+ if ((rc == -EPERM) && (geteuid() != 0)) -+ rc = 0; -+ errno = saved_errno; -+ if (rc < 0) { -+fatal_report: -+ fatal("linux_audit_write_entry failed: %s", strerror(errno)); -+ } -+} -+ -+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; -+ /* is the fingerprint_prefix() still needed? -+ snprintf(buf, sizeof(buf), "key algo=%s size=%d fp=%s%s rport=%d", -+ type, bits, sshkey_fingerprint_prefix(), fp, get_remote_port()); -+ */ -+ 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 */ -+} - --void -+int - audit_run_command(const char *command) - { -- /* not implemented */ -+ if (!user_login_count++) -+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns), -+ NULL, "ssh", 1, AUDIT_USER_LOGIN); -+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns), -+ NULL, "ssh", 1, AUDIT_USER_START); -+ return 0; -+} -+ -+void -+audit_end_command(int handle, const char *command) -+{ -+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns), -+ NULL, "ssh", 1, AUDIT_USER_END); -+ if (user_login_count && !--user_login_count) -+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns), -+ NULL, "ssh", 1, AUDIT_USER_LOGOUT); -+} -+ -+void -+audit_count_session_open(void) -+{ -+ user_login_count++; - } - - void - audit_session_open(struct logininfo *li) - { -- if (linux_audit_record_event(li->uid, NULL, li->hostname, -- NULL, li->line, 1) == 0) -- fatal("linux_audit_write_entry failed: %s", strerror(errno)); -+ if (!user_login_count++) -+ linux_audit_user_logxxx(li->uid, NULL, li->hostname, -+ NULL, li->line, 1, AUDIT_USER_LOGIN); -+ linux_audit_user_logxxx(li->uid, NULL, li->hostname, -+ NULL, li->line, 1, AUDIT_USER_START); - } - - void - audit_session_close(struct logininfo *li) - { -- /* not implemented */ -+ linux_audit_user_logxxx(li->uid, NULL, li->hostname, -+ NULL, li->line, 1, AUDIT_USER_END); -+ if (user_login_count && !--user_login_count) -+ linux_audit_user_logxxx(li->uid, NULL, li->hostname, -+ NULL, li->line, 1, AUDIT_USER_LOGOUT); - } - - void -@@ -101,21 +232,43 @@ audit_event(ssh_audit_event_t event) - { - switch(event) { - case SSH_AUTH_SUCCESS: -- case SSH_CONNECTION_CLOSE: -+ linux_audit_user_auth(-1, audit_username(), NULL, -+ get_remote_ipaddr(), "ssh", 1, event); -+ break; -+ - case SSH_NOLOGIN: -- case SSH_LOGIN_EXCEED_MAXTRIES: - case SSH_LOGIN_ROOT_DENIED: -+ linux_audit_user_auth(-1, audit_username(), NULL, -+ get_remote_ipaddr(), "ssh", 0, event); -+ linux_audit_user_logxxx(-1, audit_username(), NULL, -+ get_remote_ipaddr(), "ssh", 0, AUDIT_USER_LOGIN); - break; - -+ case SSH_LOGIN_EXCEED_MAXTRIES: - case SSH_AUTH_FAIL_NONE: - case SSH_AUTH_FAIL_PASSWD: - case SSH_AUTH_FAIL_KBDINT: - case SSH_AUTH_FAIL_PUBKEY: - case SSH_AUTH_FAIL_HOSTBASED: - case SSH_AUTH_FAIL_GSSAPI: -+ linux_audit_user_auth(-1, audit_username(), NULL, -+ get_remote_ipaddr(), "ssh", 0, event); -+ break; -+ -+ case SSH_CONNECTION_CLOSE: -+ if (user_login_count) { -+ while (user_login_count--) -+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns), -+ NULL, "ssh", 1, AUDIT_USER_END); -+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns), -+ NULL, "ssh", 1, AUDIT_USER_LOGOUT); -+ } -+ break; -+ -+ case SSH_CONNECTION_ABANDON: - case SSH_INVALID_USER: -- linux_audit_record_event(-1, audit_username(), NULL, -- get_remote_ipaddr(), "sshd", 0); -+ linux_audit_user_logxxx(-1, audit_username(), NULL, -+ get_remote_ipaddr(), "ssh", 0, AUDIT_USER_LOGIN); - break; - - default: -@@ -123,4 +276,135 @@ audit_event(ssh_audit_event_t event) - } - } - -+void -+audit_unsupported_body(int what) -+{ -+#ifdef AUDIT_CRYPTO_SESSION -+ char buf[AUDIT_LOG_SIZE]; -+ const static char *name[] = { "cipher", "mac", "comp" }; -+ char *s; -+ int audit_fd; -+ -+ snprintf(buf, sizeof(buf), "op=unsupported-%s direction=? cipher=? ksize=? rport=%d laddr=%s lport=%d ", -+ name[what], get_remote_port(), (s = get_local_ipaddr(packet_get_connection_in())), -+ get_local_port()); -+ 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 -+} -+ -+const static char *direction[] = { "from-server", "from-client", "both" }; -+ -+void -+audit_kex_body(int ctos, char *enc, char *mac, char *compress, char *pfs, pid_t pid, -+ uid_t uid) -+{ -+#ifdef AUDIT_CRYPTO_SESSION -+ char buf[AUDIT_LOG_SIZE]; -+ int audit_fd, audit_ok; -+ const struct sshcipher *cipher = cipher_by_name(enc); -+ char *s; -+ -+ snprintf(buf, sizeof(buf), "op=start direction=%s cipher=%s ksize=%d mac=%s pfs=%s spid=%jd suid=%jd rport=%d laddr=%s lport=%d ", -+ direction[ctos], enc, cipher ? 8 * cipher->key_len : 0, mac, pfs, -+ (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 -+} -+ -+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"); -+} -+ -+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 */ -Index: openssh-7.1p2/auditstub.c -=================================================================== ---- /dev/null -+++ openssh-7.1p2/auditstub.c -@@ -0,0 +1,50 @@ -+/* $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 -+ */ -+ -+#include -+ -+void -+audit_unsupported(int n) -+{ -+} -+ -+void -+audit_kex(int ctos, char *enc, char *mac, char *comp, char *pfs) -+{ -+} -+ -+void -+audit_session_key_free(int ctos) -+{ -+} -+ -+void -+audit_session_key_free_body(int ctos, pid_t pid, uid_t uid) -+{ -+} -Index: openssh-7.1p2/auth2.c -=================================================================== ---- openssh-7.1p2.orig/auth2.c -+++ openssh-7.1p2/auth2.c -@@ -241,9 +241,6 @@ input_userauth_request(int type, u_int32 - } 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) -Index: openssh-7.1p2/auth2-hostbased.c -=================================================================== ---- openssh-7.1p2.orig/auth2-hostbased.c -+++ openssh-7.1p2/auth2-hostbased.c -@@ -138,7 +138,7 @@ userauth_hostbased(Authctxt *authctxt) - /* test for allowed key and correct signature */ - authenticated = 0; - if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) && -- PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), -+ PRIVSEP(hostbased_key_verify(key, sig, slen, buffer_ptr(&b), - buffer_len(&b))) == 1) - authenticated = 1; - -@@ -155,6 +155,18 @@ done: - return authenticated; - } - -+int -+hostbased_key_verify(const Key *key, const u_char *sig, u_int slen, const u_char *data, u_int datalen) -+{ -+ int rv; -+ -+ rv = key_verify(key, sig, slen, data, datalen); -+#ifdef SSH_AUDIT_EVENTS -+ audit_key(0, &rv, key); -+#endif -+ return rv; -+} -+ - /* return 1 if given hostkey is allowed */ - int - hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, -Index: openssh-7.1p2/auth2-pubkey.c -=================================================================== ---- openssh-7.1p2.orig/auth2-pubkey.c -+++ openssh-7.1p2/auth2-pubkey.c -@@ -173,7 +173,7 @@ userauth_pubkey(Authctxt *authctxt) - /* test for correct signature */ - authenticated = 0; - if (PRIVSEP(user_key_allowed(authctxt->pw, key, 1)) && -- 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; - /* Record the successful key to prevent reuse */ -@@ -251,6 +251,18 @@ pubkey_auth_info(Authctxt *authctxt, con - free(extra); - } - -+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; -+} -+ - /* - * Splits 's' into an argument vector. Handles quoted string and basic - * escape characters (\\, \", \'). Caller must free the argument vector -Index: openssh-7.1p2/auth.c -=================================================================== ---- openssh-7.1p2.orig/auth.c -+++ openssh-7.1p2/auth.c -@@ -645,9 +645,6 @@ getpwnamallow(const char *user) - record_failed_login(user, - get_canonical_hostname(options.use_dns), "ssh"); - #endif --#ifdef SSH_AUDIT_EVENTS -- audit_event(SSH_INVALID_USER); --#endif /* SSH_AUDIT_EVENTS */ - return (NULL); - } - if (!allowed_user(pw)) -Index: openssh-7.1p2/auth.h -=================================================================== ---- openssh-7.1p2.orig/auth.h -+++ openssh-7.1p2/auth.h -@@ -192,6 +192,7 @@ void abandon_challenge_response(Authctxt - - char *expand_authorized_keys(const char *, struct passwd *pw); - char *authorized_principals_file(struct passwd *); -+int user_key_verify(const Key *, const u_char *, u_int, const u_char *, u_int); - - FILE *auth_openkeyfile(const char *, struct passwd *, int); - FILE *auth_openprincipals(const char *, struct passwd *, int); -@@ -210,6 +211,7 @@ int get_hostkey_index(Key *, int, struc - int ssh1_session_key(BIGNUM *); - int sshd_hostkey_sign(Key *, Key *, u_char **, size_t *, - const u_char *, size_t, 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))); -Index: openssh-7.1p2/auth-rsa.c -=================================================================== ---- openssh-7.1p2.orig/auth-rsa.c -+++ openssh-7.1p2/auth-rsa.c -@@ -95,7 +95,10 @@ auth_rsa_verify_response(Key *key, BIGNU - { - u_char buf[32], mdbuf[16]; - struct ssh_digest_ctx *md; -- int len; -+ int len, rv; -+#ifdef SSH_AUDIT_EVENTS -+ char *fp; -+#endif - - /* don't allow short keys */ - if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { -@@ -119,12 +122,18 @@ auth_rsa_verify_response(Key *key, BIGNU - ssh_digest_free(md); - - /* Verify that the response is the original challenge. */ -- if (timingsafe_bcmp(response, mdbuf, 16) != 0) { -- /* Wrong answer. */ -- return (0); -+ rv = timingsafe_bcmp(response, mdbuf, 16) == 0; -+ -+#ifdef SSH_AUDIT_EVENTS -+ fp = sshkey_fingerprint(key, options.fingerprint_hash, 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; - } - - /* -Index: openssh-7.1p2/cipher.c -=================================================================== ---- openssh-7.1p2.orig/cipher.c -+++ openssh-7.1p2/cipher.c -@@ -57,26 +57,6 @@ extern const EVP_CIPHER *evp_ssh1_3des(v - extern int ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int); - #endif - --struct sshcipher { -- 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) --#define CFLAG_AESCTR (1<<2) --#define CFLAG_NONE (1<<3) --#ifdef WITH_OPENSSL -- const EVP_CIPHER *(*evptype)(void); --#else -- void *ignored; --#endif --}; -- - static const struct sshcipher ciphers[] = { - #ifdef WITH_SSH1 - { "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc }, -Index: openssh-7.1p2/cipher.h -=================================================================== ---- openssh-7.1p2.orig/cipher.h -+++ openssh-7.1p2/cipher.h -@@ -62,7 +62,26 @@ - #define CIPHER_ENCRYPT 1 - #define CIPHER_DECRYPT 0 - --struct sshcipher; -+struct sshcipher { -+ 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) -+#define CFLAG_AESCTR (1<<2) -+#define CFLAG_NONE (1<<3) -+#ifdef WITH_OPENSSL -+ const EVP_CIPHER *(*evptype)(void); -+#else -+ void *ignored; -+#endif -+}; -+ - struct sshcipher_ctx { - int plaintext; - int encrypt; -Index: openssh-7.1p2/kex.c -=================================================================== ---- openssh-7.1p2.orig/kex.c -+++ openssh-7.1p2/kex.c -@@ -54,6 +54,7 @@ - #include "ssherr.h" - #include "sshbuf.h" - #include "digest.h" -+#include "audit.h" - - #if OPENSSL_VERSION_NUMBER >= 0x00907000L - # if defined(HAVE_EVP_SHA256) -@@ -534,8 +535,12 @@ choose_enc(struct sshenc *enc, char *cli - { - char *name = match_list(client, server, NULL); - -- if (name == NULL) -+ if (name == NULL) { -+#ifdef SSH_AUDIT_EVENTS -+ audit_unsupported(0); -+#endif - return SSH_ERR_NO_CIPHER_ALG_MATCH; -+ } - if ((enc->cipher = cipher_by_name(name)) == NULL) - return SSH_ERR_INTERNAL_ERROR; - enc->name = name; -@@ -553,8 +558,12 @@ choose_mac(struct ssh *ssh, struct sshma - { - char *name = match_list(client, server, NULL); - -- if (name == NULL) -+ if (name == NULL) { -+#ifdef SSH_AUDIT_EVENTS -+ audit_unsupported(1); -+#endif - return SSH_ERR_NO_MAC_ALG_MATCH; -+ } - if (mac_setup(mac, name) < 0) - return SSH_ERR_INTERNAL_ERROR; - /* truncate the key */ -@@ -571,8 +580,12 @@ choose_comp(struct sshcomp *comp, char * - { - char *name = match_list(client, server, NULL); - -- if (name == NULL) -+ if (name == NULL) { -+#ifdef SSH_AUDIT_EVENTS -+ audit_unsupported(2); -+#endif - return SSH_ERR_NO_COMPRESS_ALG_MATCH; -+ } - if (strcmp(name, "zlib@openssh.com") == 0) { - comp->type = COMP_DELAYED; - } else if (strcmp(name, "zlib") == 0) { -@@ -738,6 +751,10 @@ kex_choose_conf(struct ssh *ssh) - dh_need = MAX(dh_need, newkeys->enc.block_size); - dh_need = MAX(dh_need, newkeys->enc.iv_len); - dh_need = MAX(dh_need, newkeys->mac.key_len); -+ debug("kex: %s need=%d dh_need=%d", kex->name, need, dh_need); -+#ifdef SSH_AUDIT_EVENTS -+ audit_kex(mode, newkeys->enc.name, newkeys->mac.name, newkeys->comp.name, kex->name); -+#endif - } - /* XXX need runden? */ - kex->we_need = need; -@@ -913,3 +930,34 @@ dump_digest(char *msg, u_char *digest, i - sshbuf_dump_data(digest, len, stderr); - } - #endif -+ -+static void -+enc_destroy(struct sshenc *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(struct newkeys *newkeys) -+{ -+ if (newkeys == NULL) -+ return; -+ -+ enc_destroy(&newkeys->enc); -+ mac_destroy(&newkeys->mac); -+ memset(&newkeys->comp, 0, sizeof(newkeys->comp)); -+} -+ -Index: openssh-7.1p2/kex.h -=================================================================== ---- openssh-7.1p2.orig/kex.h -+++ openssh-7.1p2/kex.h -@@ -187,6 +187,8 @@ int kexecdh_server(struct ssh *); - int kexc25519_client(struct ssh *); - int kexc25519_server(struct ssh *); - -+void newkeys_destroy(struct newkeys *newkeys); -+ - int kex_dh_hash(const char *, const char *, - const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, - const BIGNUM *, const BIGNUM *, const BIGNUM *, u_char *, size_t *); -Index: openssh-7.1p2/key.h -=================================================================== ---- openssh-7.1p2.orig/key.h -+++ openssh-7.1p2/key.h -@@ -50,6 +50,7 @@ typedef struct sshkey Key; - #define key_ecdsa_bits_to_nid sshkey_ecdsa_bits_to_nid - #define key_ecdsa_key_to_nid sshkey_ecdsa_key_to_nid - #define key_is_cert sshkey_is_cert -+#define key_is_private sshkey_is_private - #define key_type_plain sshkey_type_plain - #define key_curve_name_to_nid sshkey_curve_name_to_nid - #define key_curve_nid_to_bits sshkey_curve_nid_to_bits -Index: openssh-7.1p2/mac.c -=================================================================== ---- openssh-7.1p2.orig/mac.c -+++ openssh-7.1p2/mac.c -@@ -226,6 +226,20 @@ mac_clear(struct sshmac *mac) - mac->umac_ctx = NULL; - } - -+void -+mac_destroy(struct sshmac *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 -Index: openssh-7.1p2/mac.h -=================================================================== ---- openssh-7.1p2.orig/mac.h -+++ openssh-7.1p2/mac.h -@@ -47,5 +47,6 @@ int mac_init(struct sshmac *); - int mac_compute(struct sshmac *, u_int32_t, const u_char *, int, - u_char *, size_t); - void mac_clear(struct sshmac *); -+void mac_destroy(struct sshmac *); - - #endif /* SSHMAC_H */ -Index: openssh-7.1p2/Makefile.in -=================================================================== ---- openssh-7.1p2.orig/Makefile.in -+++ openssh-7.1p2/Makefile.in -@@ -91,7 +91,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ - sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o blocks.o \ - kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ - kexdhc.o kexgexc.o kexecdhc.o kexc25519c.o \ -- kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o -+ kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o auditstub.o - - SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ - sshconnect.o sshconnect1.o sshconnect2.o mux.o \ -Index: openssh-7.1p2/monitor.c -=================================================================== ---- openssh-7.1p2.orig/monitor.c -+++ openssh-7.1p2/monitor.c -@@ -102,6 +102,7 @@ - #include "ssh2.h" - #include "roaming.h" - #include "authfd.h" -+#include "audit.h" - #include "match.h" - #include "ssherr.h" - -@@ -117,6 +118,8 @@ extern Buffer auth_debug; - extern int auth_debug_init; - extern Buffer loginmsg; - -+extern void destroy_sensitive_data(int); -+ - /* State exported from the child */ - static struct sshbuf *child_state; - -@@ -162,6 +165,11 @@ 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 *); -@@ -218,6 +226,10 @@ struct mon_table mon_dispatch_proto20[] - #endif - #ifdef SSH_AUDIT_EVENTS - {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, -+ {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, -+ {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, -+ {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}, -@@ -249,6 +261,11 @@ struct mon_table mon_dispatch_postauth20 - #ifdef SSH_AUDIT_EVENTS - {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, - {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command}, -+ {MONITOR_REQ_AUDIT_END_COMMAND, MON_PERMIT, mm_answer_audit_end_command}, -+ {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} - }; -@@ -281,6 +298,10 @@ struct mon_table mon_dispatch_proto15[] - #endif - #ifdef SSH_AUDIT_EVENTS - {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, -+ {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, -+ {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, -+ {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 - #endif /* WITH_SSH1 */ - {0, 0, NULL} -@@ -294,6 +315,11 @@ struct mon_table mon_dispatch_postauth15 - #ifdef SSH_AUDIT_EVENTS - {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, - {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT|MON_ONCE, mm_answer_audit_command}, -+ {MONITOR_REQ_AUDIT_END_COMMAND, MON_PERMIT, mm_answer_audit_end_command}, -+ {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 - #endif /* WITH_SSH1 */ - {0, 0, NULL} -@@ -1414,9 +1440,11 @@ mm_answer_keyverify(int sock, Buffer *m) - Key *key; - u_char *signature, *data, *blob; - u_int signaturelen, datalen, bloblen; -+ int type = 0; - int verified = 0; - int valid_data = 0; - -+ type = buffer_get_int(m); - blob = buffer_get_string(m, &bloblen); - signature = buffer_get_string(m, &signaturelen); - data = buffer_get_string(m, &datalen); -@@ -1424,6 +1452,8 @@ mm_answer_keyverify(int sock, Buffer *m) - if (hostbased_cuser == NULL || hostbased_chost == NULL || - !monitor_allowed_key(blob, bloblen)) - fatal("%s: bad key, not previously allowed", __func__); -+ if (type != key_blobtype) -+ fatal("%s: bad key type", __func__); - - key = key_from_blob(blob, bloblen); - if (key == NULL) -@@ -1444,7 +1474,17 @@ mm_answer_keyverify(int sock, Buffer *m) - if (!valid_data) - fatal("%s: bad signature data blob", __func__); - -- verified = key_verify(key, signature, signaturelen, data, datalen); -+ switch (key_blobtype) { -+ case MM_USERKEY: -+ verified = user_key_verify(key, signature, signaturelen, data, datalen); -+ break; -+ case MM_HOSTKEY: -+ verified = hostbased_key_verify(key, signature, signaturelen, data, datalen); -+ break; -+ default: -+ verified = 0; -+ break; -+ } - debug3("%s: key %p signature %s", - __func__, key, (verified == 1) ? "verified" : "unverified"); - -@@ -1505,6 +1545,12 @@ mm_session_close(Session *s) - debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd); - session_pty_cleanup2(s); - } -+#ifdef SSH_AUDIT_EVENTS -+ if (s->command != NULL) { -+ debug3("%s: command %d", __func__, s->command_handle); -+ session_end_command2(s); -+ } -+#endif - session_unused(s->self); - } - -@@ -1787,6 +1833,8 @@ mm_answer_term(int sock, Buffer *req) - sshpam_cleanup(); - #endif - -+ destroy_sensitive_data(0); -+ - while (waitpid(pmonitor->m_pid, &status, 0) == -1) - if (errno != EINTR) - exit(1); -@@ -1829,11 +1877,43 @@ mm_answer_audit_command(int socket, Buff - { - u_int len; - char *cmd; -+ Session *s; - - debug3("%s entering", __func__); - cmd = buffer_get_string(m, &len); -+ - /* sanity check command, if so how? */ -- audit_run_command(cmd); -+ s = session_new(); -+ if (s == NULL) -+ fatal("%s: error allocating a session", __func__); -+ s->command = cmd; -+ s->command_handle = audit_run_command(cmd); -+ -+ buffer_clear(m); -+ buffer_put_int(m, s->self); -+ -+ mm_request_send(socket, MONITOR_ANS_AUDIT_COMMAND, m); -+ -+ return (0); -+} -+ -+int -+mm_answer_audit_end_command(int socket, Buffer *m) -+{ -+ int handle; -+ u_int len; -+ char *cmd; -+ Session *s; -+ -+ debug3("%s entering", __func__); -+ handle = buffer_get_int(m); -+ cmd = buffer_get_string(m, &len); -+ -+ s = session_by_id(handle); -+ if (s == NULL || s->ttyfd != -1 || s->command == NULL || -+ strcmp(s->command, cmd) != 0) -+ fatal("%s: invalid handle", __func__); -+ mm_session_close(s); - free(cmd); - return (0); - } -@@ -1883,6 +1963,7 @@ monitor_apply_keystate(struct monitor *p - void - mm_get_keystate(struct monitor *pmonitor) - { -+ Buffer m; - debug3("%s: Waiting for new keys", __func__); - - if ((child_state = sshbuf_new()) == NULL) -@@ -1890,6 +1971,21 @@ mm_get_keystate(struct monitor *pmonitor - mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, - child_state); - debug3("%s: GOT new keys", __func__); -+ -+#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) -+ ; -+ - } - - -@@ -2059,3 +2155,86 @@ mm_answer_gss_userok(int sock, Buffer *m - } - #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, *pfs; -+ 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); -+ pfs = buffer_get_string(m, &len); -+ pid = buffer_get_int64(m); -+ uid = buffer_get_int64(m); -+ -+ audit_kex_body(ctos, cipher, mac, compress, pfs, pid, uid); -+ -+ free(cipher); -+ free(mac); -+ free(compress); -+ free(pfs); -+ 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; -+} -+ -+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); -+ -+ return 0; -+} -+#endif /* SSH_AUDIT_EVENTS */ -Index: openssh-7.1p2/monitor.h -=================================================================== ---- openssh-7.1p2.orig/monitor.h -+++ openssh-7.1p2/monitor.h -@@ -63,7 +63,13 @@ 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_REQ_AUDIT_EVENT = 112, -+ MONITOR_REQ_AUDIT_COMMAND = 114, MONITOR_ANS_AUDIT_COMMAND = 115, -+ MONITOR_REQ_AUDIT_END_COMMAND = 116, -+ MONITOR_REQ_AUDIT_UNSUPPORTED = 118, MONITOR_ANS_AUDIT_UNSUPPORTED = 119, -+ MONITOR_REQ_AUDIT_KEX = 120, MONITOR_ANS_AUDIT_KEX = 121, -+ MONITOR_REQ_AUDIT_SESSION_KEY_FREE = 122, MONITOR_ANS_AUDIT_SESSION_KEY_FREE = 123, -+ MONITOR_REQ_AUDIT_SERVER_KEY_FREE = 124 - - }; - -Index: openssh-7.1p2/monitor_wrap.c -=================================================================== ---- openssh-7.1p2.orig/monitor_wrap.c -+++ openssh-7.1p2/monitor_wrap.c -@@ -443,7 +443,7 @@ mm_key_allowed(enum mm_keytype type, cha - */ - - int --mm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen) -+mm_key_verify(enum mm_keytype type, Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen) - { - Buffer m; - u_char *blob; -@@ -457,6 +457,7 @@ mm_key_verify(Key *key, u_char *sig, u_i - return (0); - - buffer_init(&m); -+ buffer_put_int(&m, type); - buffer_put_string(&m, blob, len); - buffer_put_string(&m, sig, siglen); - buffer_put_string(&m, data, datalen); -@@ -474,6 +475,18 @@ mm_key_verify(Key *key, u_char *sig, u_i - return (verified); - } - -+int -+mm_hostbased_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen) -+{ -+ return mm_key_verify(MM_HOSTKEY, key, sig, siglen, data, datalen); -+} -+ -+int -+mm_user_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen) -+{ -+ return mm_key_verify(MM_USERKEY, key, sig, siglen, data, datalen); -+} -+ - void - mm_send_keystate(struct monitor *monitor) - { -@@ -986,10 +999,11 @@ mm_audit_event(ssh_audit_event_t event) - buffer_free(&m); - } - --void -+int - mm_audit_run_command(const char *command) - { - Buffer m; -+ int handle; - - debug3("%s entering command %s", __func__, command); - -@@ -997,6 +1011,26 @@ mm_audit_run_command(const char *command - buffer_put_cstring(&m, command); - - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, &m); -+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_COMMAND, &m); -+ -+ handle = buffer_get_int(&m); -+ buffer_free(&m); -+ -+ return (handle); -+} -+ -+void -+mm_audit_end_command(int handle, const char *command) -+{ -+ Buffer m; -+ -+ debug3("%s entering command %s", __func__, command); -+ -+ buffer_init(&m); -+ buffer_put_int(&m, handle); -+ buffer_put_cstring(&m, command); -+ -+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_END_COMMAND, &m); - buffer_free(&m); - } - #endif /* SSH_AUDIT_EVENTS */ -@@ -1087,3 +1121,70 @@ mm_ssh_gssapi_userok(char *user) - } - #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, char *fps, pid_t pid, -+ uid_t uid) -+{ -+ Buffer m; -+ -+ buffer_init(&m); -+ buffer_put_int(&m, ctos); -+ buffer_put_cstring(&m, cipher); -+ buffer_put_cstring(&m, (mac ? mac : "")); -+ buffer_put_cstring(&m, compress); -+ buffer_put_cstring(&m, fps); -+ 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); -+} -+ -+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); -+} -+ -+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); -+ buffer_free(&m); -+} -+#endif /* SSH_AUDIT_EVENTS */ -Index: openssh-7.1p2/monitor_wrap.h -=================================================================== ---- openssh-7.1p2.orig/monitor_wrap.h -+++ openssh-7.1p2/monitor_wrap.h -@@ -49,7 +49,8 @@ int mm_key_allowed(enum mm_keytype, char - int mm_user_key_allowed(struct passwd *, Key *, int); - 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 *); -@@ -74,7 +75,12 @@ void mm_sshpam_free_ctx(void *); - #ifdef SSH_AUDIT_EVENTS - #include "audit.h" - void mm_audit_event(ssh_audit_event_t); --void mm_audit_run_command(const char *); -+int mm_audit_run_command(const char *); -+void mm_audit_end_command(int, const char *); -+void mm_audit_unsupported_body(int); -+void mm_audit_kex_body(int, char *, char *, char *, char *, pid_t, uid_t); -+void mm_audit_session_key_free_body(int, pid_t, uid_t); -+void mm_audit_destroy_sensitive_data(const char *, pid_t, uid_t); - #endif - - struct Session; -Index: openssh-7.1p2/packet.c -=================================================================== ---- openssh-7.1p2.orig/packet.c -+++ openssh-7.1p2/packet.c -@@ -67,6 +67,7 @@ - #include "key.h" /* typedefs XXX */ - - #include "xmalloc.h" -+#include "audit.h" - #include "crc32.h" - #include "deattack.h" - #include "compat.h" -@@ -447,6 +448,13 @@ ssh_packet_get_connection_out(struct ssh - return ssh->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); -+} -+ - /* - * Returns the IP-address of the remote host as a string. The returned - * string must not be freed. -@@ -477,13 +485,6 @@ ssh_packet_close(struct ssh *ssh) - if (!state->initialized) - return; - state->initialized = 0; -- if (state->connection_in == state->connection_out) { -- shutdown(state->connection_out, SHUT_RDWR); -- close(state->connection_out); -- } else { -- close(state->connection_in); -- close(state->connection_out); -- } - sshbuf_free(state->input); - sshbuf_free(state->output); - sshbuf_free(state->outgoing_packet); -@@ -515,14 +516,24 @@ ssh_packet_close(struct ssh *ssh) - inflateEnd(stream); - } - } -- if ((r = cipher_cleanup(&state->send_context)) != 0) -- error("%s: cipher_cleanup failed: %s", __func__, ssh_err(r)); -- if ((r = cipher_cleanup(&state->receive_context)) != 0) -- error("%s: cipher_cleanup failed: %s", __func__, ssh_err(r)); -+ if (packet_state_has_keys(state)) { -+ if ((r = cipher_cleanup(&state->send_context)) != 0) -+ error("%s: cipher_cleanup failed: %s", __func__, ssh_err(r)); -+ if ((r = cipher_cleanup(&state->receive_context)) != 0) -+ error("%s: cipher_cleanup failed: %s", __func__, ssh_err(r)); -+ audit_session_key_free(2); -+ } - if (ssh->remote_ipaddr) { - free(ssh->remote_ipaddr); - ssh->remote_ipaddr = NULL; - } -+ if (state->connection_in == state->connection_out) { -+ shutdown(state->connection_out, SHUT_RDWR); -+ close(state->connection_out); -+ } else { -+ close(state->connection_in); -+ close(state->connection_out); -+ } - free(ssh->state); - ssh->state = NULL; - } -@@ -942,6 +953,7 @@ ssh_set_newkeys(struct ssh *ssh, int mod - } - if (state->newkeys[mode] != NULL) { - debug("set_newkeys: rekeying"); -+ audit_session_key_free(mode); - if ((r = cipher_cleanup(cc)) != 0) - return r; - enc = &state->newkeys[mode]->enc; -@@ -2291,6 +2303,75 @@ ssh_packet_get_output(struct ssh *ssh) - return (void *)ssh->state->output; - } - -+static void -+newkeys_destroy_and_free(struct newkeys *newkeys) -+{ -+ if (newkeys == NULL) -+ return; -+ -+ free(newkeys->enc.name); -+ -+ if (newkeys->mac.enabled) { -+ mac_clear(&newkeys->mac); -+ free(newkeys->mac.name); -+ } -+ -+ free(newkeys->comp.name); -+ -+ newkeys_destroy(newkeys); -+ free(newkeys); -+} -+ -+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); -+ state->input = NULL; -+ buffer_free(state->output); -+ state->output = NULL; -+ buffer_free(state->outgoing_packet); -+ state->outgoing_packet = NULL; -+ buffer_free(state->incoming_packet); -+ state->incoming_packet = NULL; -+ if( state->compression_buffer ) { -+ buffer_free(state->compression_buffer); -+ state->compression_buffer = NULL; -+ } -+ 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 = (active_state != NULL && packet_state_has_keys(active_state->state)) -+ || (backup_state != NULL && packet_state_has_keys(backup_state->state)); -+ if (active_state != NULL) -+ packet_destroy_state(active_state->state); -+ if (backup_state != NULL) -+ packet_destroy_state(backup_state->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 -+ } -+} -+ - /* XXX TODO update roaming to new API (does not work anyway) */ - /* - * Save the state for the real connection, and use a separate state when -@@ -2300,18 +2381,12 @@ void - ssh_packet_backup_state(struct ssh *ssh, - struct ssh *backup_state) - { -- struct ssh *tmp; -- - close(ssh->state->connection_in); - ssh->state->connection_in = -1; - close(ssh->state->connection_out); - ssh->state->connection_out = -1; -- if (backup_state) -- tmp = backup_state; -- else -- tmp = ssh_alloc_session_state(); - backup_state = ssh; -- ssh = tmp; -+ ssh = ssh_alloc_session_state(); - } - - /* XXX FIXME FIXME FIXME */ -@@ -2330,9 +2405,7 @@ ssh_packet_restore_state(struct ssh *ssh - backup_state = ssh; - ssh = tmp; - ssh->state->connection_in = backup_state->state->connection_in; -- backup_state->state->connection_in = -1; - ssh->state->connection_out = backup_state->state->connection_out; -- backup_state->state->connection_out = -1; - len = sshbuf_len(backup_state->state->input); - if (len > 0) { - if ((r = sshbuf_putb(ssh->state->input, -@@ -2341,6 +2414,11 @@ ssh_packet_restore_state(struct ssh *ssh - sshbuf_reset(backup_state->state->input); - add_recv_bytes(len); - } -+ backup_state->state->connection_in = -1; -+ backup_state->state->connection_out = -1; -+ packet_destroy_state(backup_state->state); -+ free(backup_state); -+ backup_state = NULL; - } - - /* Reset after_authentication and reset compression in post-auth privsep */ -Index: openssh-7.1p2/packet.h -=================================================================== ---- openssh-7.1p2.orig/packet.h -+++ openssh-7.1p2/packet.h -@@ -189,7 +189,7 @@ int sshpkt_get_end(struct ssh *ssh); - const u_char *sshpkt_ptr(struct ssh *, size_t *lenp); - - /* OLD API */ --extern struct ssh *active_state; -+extern struct ssh *active_state, *backup_state; - #include "opacket.h" - - #if !defined(WITH_OPENSSL) -@@ -203,4 +203,5 @@ extern struct ssh *active_state; - # undef EC_POINT - #endif - -+void packet_destroy_all(int, int); - #endif /* PACKET_H */ -Index: openssh-7.1p2/sandbox-seccomp-filter.c -=================================================================== ---- openssh-7.1p2.orig/sandbox-seccomp-filter.c -+++ openssh-7.1p2/sandbox-seccomp-filter.c -@@ -150,6 +150,12 @@ static const struct sock_filter preauth_ - #ifdef __NR_gettimeofday - SC_ALLOW(gettimeofday), - #endif -+#ifdef SSH_AUDIT_EVENTS -+ SC_ALLOW(getuid), -+#ifdef __NR_getuid32 /* not defined on x86_64 */ -+ SC_ALLOW(getuid32), -+#endif -+#endif - #ifdef __NR_madvise - SC_ALLOW(madvise), - #endif -Index: openssh-7.1p2/session.c -=================================================================== ---- openssh-7.1p2.orig/session.c -+++ openssh-7.1p2/session.c -@@ -139,7 +139,7 @@ extern int log_stderr; - extern int debug_flag; - extern u_int utmp_len; - extern int startup_pipe; --extern void destroy_sensitive_data(void); -+extern void destroy_sensitive_data(int); - extern Buffer loginmsg; - - /* original command from peer. */ -@@ -729,6 +729,14 @@ do_exec_pty(Session *s, const char *comm - /* Parent. Close the slave side of the pseudo tty. */ - close(ttyfd); - -+#ifndef HAVE_OSF_SIA -+ /* do_login in the child did not affect state in this process, -+ compensate. From an architectural standpoint, this is extremely -+ ugly. */ -+ if (!(options.use_login && command == NULL)) -+ audit_count_session_open(); -+#endif -+ - /* Enter interactive session. */ - s->ptymaster = ptymaster; - packet_set_interactive(1, -@@ -823,15 +831,19 @@ do_exec(Session *s, const char *command) - 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->ptyfd == -1) -+ s->command_handle = PRIVSEP(audit_run_command(s->command)); - #endif - if (s->ttyfd != -1) - ret = do_exec_pty(s, command); -@@ -1684,7 +1696,10 @@ do_child(Session *s, const char *command - int r = 0; - - /* remove hostkey from the child's memory */ -- destroy_sensitive_data(); -+ destroy_sensitive_data(1); -+ /* Don't audit this - both us and the parent would be talking to the -+ monitor over a single socket, with no synchronization. */ -+ packet_destroy_all(0, 1); - - /* Force a password change */ - if (s->authctxt->force_pwchange) { -@@ -1911,6 +1926,7 @@ session_unused(int id) - sessions[id].ttyfd = -1; - sessions[id].ptymaster = -1; - sessions[id].x11_chanids = NULL; -+ sessions[id].command_handle = -1; - sessions[id].next_unused = sessions_first_unused; - sessions_first_unused = id; - } -@@ -1993,6 +2009,19 @@ session_open(Authctxt *authctxt, int cha - } - - Session * -+session_by_id(int id) -+{ -+ if (id >= 0 && id < sessions_nalloc) { -+ Session *s = &sessions[id]; -+ if (s->used) -+ return s; -+ } -+ debug("session_by_id: unknown id %d", id); -+ session_dump(); -+ return NULL; -+} -+ -+Session * - session_by_tty(char *tty) - { - int i; -@@ -2509,6 +2538,32 @@ session_exit_message(Session *s, int sta - chan_write_failed(c); - } - -+#ifdef SSH_AUDIT_EVENTS -+void -+session_end_command2(Session *s) -+{ -+ if (s->command != NULL) { -+ if (s->command_handle != -1) -+ 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) { -+ if (s->command_handle != -1) -+ 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) - { -@@ -2549,6 +2604,10 @@ session_close(Session *s) - - 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); -@@ -2763,6 +2822,15 @@ do_authenticated2(Authctxt *authctxt) - server_loop2(authctxt); - } - -+static void -+do_cleanup_one_session(Session *s) -+{ -+ session_pty_cleanup2(s); -+#ifdef SSH_AUDIT_EVENTS -+ session_end_command2(s); -+#endif -+} -+ - void - do_cleanup(Authctxt *authctxt) - { -@@ -2811,5 +2879,5 @@ do_cleanup(Authctxt *authctxt) - * or if running in monitor. - */ - if (!use_privsep || mm_is_monitor()) -- session_destroy_all(session_pty_cleanup2); -+ session_destroy_all(do_cleanup_one_session); - } -Index: openssh-7.1p2/session.h -=================================================================== ---- openssh-7.1p2.orig/session.h -+++ openssh-7.1p2/session.h -@@ -61,6 +61,12 @@ struct Session { - char *name; - char *val; - } *env; -+ -+ /* exec */ -+#ifdef SSH_AUDIT_EVENTS -+ int command_handle; -+ char *command; -+#endif - }; - - void do_authenticated(Authctxt *); -@@ -73,8 +79,10 @@ void session_close_by_pid(pid_t, int); - void session_close_by_channel(int, void *); - void session_destroy_all(void (*)(Session *)); - void session_pty_cleanup2(Session *); -+void session_end_command2(Session *); - - Session *session_new(void); -+Session *session_by_id(int); - Session *session_by_tty(char *); - void session_close(Session *); - void do_setusercontext(struct passwd *); -Index: openssh-7.1p2/sshd.c -=================================================================== ---- openssh-7.1p2.orig/sshd.c -+++ openssh-7.1p2/sshd.c -@@ -122,6 +122,7 @@ - #endif - #include "monitor_wrap.h" - #include "roaming.h" -+#include "audit.h" - #include "ssh-sandbox.h" - #include "version.h" - #include "ssherr.h" -@@ -254,7 +255,7 @@ Buffer loginmsg; - struct passwd *privsep_pw = NULL; - - /* Prototypes for various functions defined later in this file. */ --void destroy_sensitive_data(void); -+void destroy_sensitive_data(int); - void demote_sensitive_data(void); - - #ifdef WITH_SSH1 -@@ -275,6 +276,15 @@ close_listen_socks(void) - num_listen_socks = -1; - } - -+/* -+ * Is this process listening for clients (i.e. not specific to any specific -+ * client connection?) -+ */ -+int listening_for_clients(void) -+{ -+ return num_listen_socks > 0; -+} -+ - static void - close_startup_pipes(void) - { -@@ -554,22 +564,45 @@ sshd_exchange_identification(int sock_in - } - } - --/* Destroy the host and server keys. They will no longer be needed. */ -+/* -+ * Destroy the host and server keys. They will no longer be needed. Careful, -+ * this can be called from cleanup_exit() - i.e. from just about anywhere. -+ */ - void --destroy_sensitive_data(void) -+destroy_sensitive_data(int privsep) - { - int i; -+ pid_t pid; -+ uid_t uid; - - if (sensitive_data.server_key) { - key_free(sensitive_data.server_key); - sensitive_data.server_key = NULL; - } -+ pid = getpid(); -+ uid = getuid(); - for (i = 0; i < options.num_host_key_files; i++) { - if (sensitive_data.host_keys[i]) { -+ char *fp; -+ -+ if (key_is_private(sensitive_data.host_keys[i])) -+ fp = sshkey_fingerprint(sensitive_data.host_keys[i], options.fingerprint_hash, 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; - } -@@ -583,6 +616,8 @@ void - demote_sensitive_data(void) - { - Key *tmp; -+ pid_t pid; -+ uid_t uid; - int i; - - if (sensitive_data.server_key) { -@@ -591,13 +626,25 @@ demote_sensitive_data(void) - sensitive_data.server_key = tmp; - } - -+ pid = getpid(); -+ uid = getuid(); - for (i = 0; i < options.num_host_key_files; i++) { - if (sensitive_data.host_keys[i]) { -+ char *fp; -+ -+ if (key_is_private(sensitive_data.host_keys[i])) -+ fp = sshkey_fingerprint(sensitive_data.host_keys[i], options.fingerprint_hash, 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 */ - } -@@ -667,7 +714,7 @@ privsep_preauth(Authctxt *authctxt) - - if (use_privsep == PRIVSEP_ON) - box = ssh_sandbox_init(pmonitor); -- pid = fork(); -+ pmonitor->m_pid = pid = fork(); - if (pid == -1) { - fatal("fork of unprivileged child failed"); - } else if (pid != 0) { -@@ -751,6 +798,12 @@ privsep_postauth(Authctxt *authctxt) - else if (pmonitor->m_pid != 0) { - verbose("User child is on pid %ld", (long)pmonitor->m_pid); - buffer_clear(&loginmsg); -+ if (*pmonitor->m_pkex != NULL ){ -+ newkeys_destroy((*pmonitor->m_pkex)->newkeys[MODE_OUT]); -+ newkeys_destroy((*pmonitor->m_pkex)->newkeys[MODE_IN]); -+ audit_session_key_free_body(2, getpid(), getuid()); -+ packet_destroy_all(0, 0); -+ } - monitor_child_postauth(pmonitor); - - /* NEVERREACHED */ -@@ -1273,6 +1326,7 @@ server_accept_loop(int *sock_in, int *so - if (received_sigterm) { - logit("Received signal %d; terminating.", - (int) received_sigterm); -+ destroy_sensitive_data(0); - close_listen_socks(); - if (options.pid_file != NULL) - unlink(options.pid_file); -@@ -2216,6 +2270,7 @@ main(int ac, char **av) - */ - if (use_privsep) { - mm_send_keystate(pmonitor); -+ packet_destroy_all(1, 1); - exit(0); - } - -@@ -2258,7 +2313,7 @@ main(int ac, char **av) - privsep_postauth(authctxt); - /* the monitor process [priv] will not return */ - if (!compat20) -- destroy_sensitive_data(); -+ destroy_sensitive_data(0); - } - - packet_set_timeout(options.client_alive_interval, -@@ -2272,6 +2327,9 @@ main(int ac, char **av) - do_authenticated(authctxt); - - /* The connection has been terminated. */ -+ packet_destroy_all(1, 1); -+ destroy_sensitive_data(1); -+ - packet_get_bytes(&ibytes, &obytes); - verbose("Transferred: sent %llu, received %llu bytes", - (unsigned long long)obytes, (unsigned long long)ibytes); -@@ -2432,6 +2490,10 @@ do_ssh1_kex(void) - if (cookie[i] != packet_get_char()) - packet_disconnect("IP Spoofing check bytes do not match."); - -+#ifdef SSH_AUDIT_EVENTS -+ audit_kex(2, cipher_name(cipher_type), "crc", "none", "none"); -+#endif -+ - debug("Encryption type: %.200s", cipher_name(cipher_type)); - - /* Get the encrypted integer. */ -@@ -2491,7 +2553,7 @@ do_ssh1_kex(void) - } - - /* Destroy the private and public keys. No longer. */ -- destroy_sensitive_data(); -+ destroy_sensitive_data(1); - - if (use_privsep) - mm_ssh1_session_id(session_id); -@@ -2614,6 +2676,16 @@ do_ssh2_kex(void) - void - cleanup_exit(int i) - { -+ static int in_cleanup = 0; -+ int is_privsep_child; -+ -+ /* cleanup_exit can be called at the very least from the privsep -+ wrappers used for auditing. Make sure we don't recurse -+ indefinitely. */ -+ if (in_cleanup) -+ _exit(i); -+ in_cleanup = 1; -+ - if (the_authctxt) { - do_cleanup(the_authctxt); - if (use_privsep && privsep_is_preauth && -@@ -2625,9 +2697,14 @@ cleanup_exit(int i) - pmonitor->m_pid, strerror(errno)); - } - } -+ is_privsep_child = use_privsep && pmonitor != NULL && pmonitor->m_pid == 0; -+ 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 (!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); -Index: openssh-7.1p2/sshkey.c -=================================================================== ---- openssh-7.1p2.orig/sshkey.c -+++ openssh-7.1p2/sshkey.c -@@ -299,6 +299,33 @@ sshkey_type_is_valid_ca(int type) - } - - int -+sshkey_is_private(const struct sshkey *k) -+{ -+ switch (k->type) { -+#ifdef WITH_OPENSSL -+ case KEY_RSA_CERT: -+ case KEY_RSA1: -+ case KEY_RSA: -+ return k->rsa->d != NULL; -+ 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 /* OPENSSL_HAS_ECC */ -+#endif /* WITH_OPENSSL */ -+ case KEY_ED25519_CERT: -+ case KEY_ED25519: -+ return (k->ed25519_pk != NULL); -+ default: -+ /* fatal("key_is_private: bad key type %d", k->type); */ -+ return 0; -+ } -+} -+ -+int - sshkey_is_cert(const struct sshkey *k) - { - if (k == NULL) -Index: openssh-7.1p2/sshkey.h -=================================================================== ---- openssh-7.1p2.orig/sshkey.h -+++ openssh-7.1p2/sshkey.h -@@ -132,6 +132,7 @@ u_int sshkey_size(const struct sshkey - int sshkey_generate(int type, u_int bits, struct sshkey **keyp); - int sshkey_from_private(const struct sshkey *, struct sshkey **); - int sshkey_type_from_name(const char *); -+int sshkey_is_private(const struct sshkey *); - int sshkey_is_cert(const struct sshkey *); - int sshkey_type_is_cert(int); - int sshkey_type_plain(int); diff --git a/openssh-7.1p2.tar.gz b/openssh-7.1p2.tar.gz deleted file mode 100644 index fccea51..0000000 --- a/openssh-7.1p2.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:dd75f024dcf21e06a0d6421d582690bf987a1f6323e32ad6619392f3bfde6bbd -size 1475829 diff --git a/openssh-7.1p2.tar.gz.asc b/openssh-7.1p2.tar.gz.asc deleted file mode 100644 index 95644fa..0000000 --- a/openssh-7.1p2.tar.gz.asc +++ /dev/null @@ -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----- diff --git a/openssh-alloc_size.patch b/openssh-alloc_size.patch deleted file mode 100644 index 369ad72..0000000 --- a/openssh-alloc_size.patch +++ /dev/null @@ -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) diff --git a/openssh-allow_getrandom.patch b/openssh-allow_getrandom.patch deleted file mode 100644 index d95f1e1..0000000 --- a/openssh-allow_getrandom.patch +++ /dev/null @@ -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 diff --git a/openssh-askpass-gnome.changes b/openssh-askpass-gnome.changes index 34c72ba..3a8dbfa 100644 --- a/openssh-askpass-gnome.changes +++ b/openssh-askpass-gnome.changes @@ -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 diff --git a/openssh-askpass-gnome.spe_ b/openssh-askpass-gnome.spec similarity index 98% rename from openssh-askpass-gnome.spe_ rename to openssh-askpass-gnome.spec index fcf802e..6410b72 100644 --- a/openssh-askpass-gnome.spe_ +++ b/openssh-askpass-gnome.spec @@ -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 diff --git a/openssh-fix-b64_xx-detection.patch b/openssh-fix-b64_xx-detection.patch deleted file mode 100644 index 5ccd89a..0000000 --- a/openssh-fix-b64_xx-detection.patch +++ /dev/null @@ -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 ]) -+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@ diff --git a/openssh.changes b/openssh.changes index 3fa3171..74240a0 100644 --- a/openssh.changes +++ b/openssh.changes @@ -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 diff --git a/openssh.spe_ b/openssh.spec similarity index 75% rename from openssh.spe_ rename to openssh.spec index 844a12a..d44cb90 100644 --- a/openssh.spe_ +++ b/openssh.spec @@ -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 From 60455145053c3e62edfff7f14d80d523bfabd94b0e764fe2e2fb961df92d3427 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Fri, 8 Apr 2016 12:39:18 +0000 Subject: [PATCH 5/5] Accepting request 385260 from home:kukuk:branches:network - openssh-6.6p1-ldap.patch: replace TRUE/FALSE with 1/0, since this defines did come via an indirect header inclusion and are not everywhere defined. OBS-URL: https://build.opensuse.org/request/show/385260 OBS-URL: https://build.opensuse.org/package/show/network/openssh?expand=0&rev=99 --- openssh-6.6p1-ldap.patch | 10 +++++----- openssh.changes | 7 +++++++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/openssh-6.6p1-ldap.patch b/openssh-6.6p1-ldap.patch index a91ff94..6d6d6c7 100644 --- a/openssh-6.6p1-ldap.patch +++ b/openssh-6.6p1-ldap.patch @@ -798,7 +798,7 @@ new file mode 100644 + timeout.tv_sec = options.bind_timelimit; + timeout.tv_usec = 0; + result = NULL; -+ if ((rc = ldap_result (ld, msgid, FALSE, &timeout, &result)) < 1) { ++ if ((rc = ldap_result (ld, msgid, 0, &timeout, &result)) < 1) { + error ("ldap_result %s", ldap_err2string (ldap_get_lderrno (ld, 0, 0))); + ldap_msgfree (result); + return LDAP_OPERATIONS_ERROR; @@ -899,7 +899,7 @@ new file mode 100644 + } + + if (options.ssl_on != SSL_OFF) { -+ if ((ld = ldapssl_init (options.host, options.port, TRUE)) == NULL) ++ if ((ld = ldapssl_init (options.host, options.port, 1)) == NULL) + fatal ("ldapssl_init failed"); + debug3 ("LDAPssl init"); + } @@ -1103,7 +1103,7 @@ new file mode 100644 + + timeout.tv_sec = options.bind_timelimit; + timeout.tv_usec = 0; -+ if ((rc = ldap_result (ld, msgid, FALSE, &timeout, &result)) < 1) { ++ if ((rc = ldap_result (ld, msgid, 0, &timeout, &result)) < 1) { + ld_errno = ldap_get_lderrno (ld, 0, 0); + + error ("ldap_result %s", ldap_err2string (ld_errno)); @@ -1114,7 +1114,7 @@ new file mode 100644 + +#if defined(HAVE_LDAP_PARSE_RESULT) && defined(HAVE_LDAP_CONTROLS_FREE) + controls = NULL; -+ if ((parserc = ldap_parse_result (ld, result, &rc, 0, 0, 0, &controls, TRUE)) != LDAP_SUCCESS) ++ if ((parserc = ldap_parse_result (ld, result, &rc, 0, 0, 0, &controls, 1)) != LDAP_SUCCESS) + fatal ("ldap_parse_result %s", ldap_err2string (parserc)); + debug3 ("LDAP parse result OK"); + @@ -1122,7 +1122,7 @@ new file mode 100644 + ldap_controls_free (controls); + } +#else -+ rc = ldap_result2error (session->ld, result, TRUE); ++ rc = ldap_result2error (session->ld, result, 1); +#endif + if (rc != LDAP_SUCCESS) + fatal ("error trying to bind as user \"%s\" (%s)", diff --git a/openssh.changes b/openssh.changes index 74240a0..b001797 100644 --- a/openssh.changes +++ b/openssh.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +Wed Apr 6 11:42:35 UTC 2016 - kukuk@suse.com + +- openssh-6.6p1-ldap.patch: replace TRUE/FALSE with 1/0, since + this defines did come via an indirect header inclusion and are + not everywhere defined. + ------------------------------------------------------------------- Thu Jan 14 15:35:55 UTC 2016 - astieger@suse.com