From f8987c9e1f3e937cfed2631f0487fcd78b9cc2c2 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Nov 03 2016 06:05:36 +0000 Subject: import openssh-6.6.1p1-31.el7 --- diff --git a/SOURCES/openssh-5.1p1-scp-manpage.patch b/SOURCES/openssh-5.1p1-scp-manpage.patch deleted file mode 100644 index e314a05..0000000 --- a/SOURCES/openssh-5.1p1-scp-manpage.patch +++ /dev/null @@ -1,18 +0,0 @@ -diff -up openssh-5.1p1/scp.1.manpage openssh-5.1p1/scp.1 ---- openssh-5.1p1/scp.1.manpage 2008-07-12 09:12:49.000000000 +0200 -+++ openssh-5.1p1/scp.1 2008-07-23 19:18:15.000000000 +0200 -@@ -66,6 +66,14 @@ treating file names containing - as host specifiers. - Copies between two remote hosts are also permitted. - .Pp -+When copying a source file to a target file which already exists, -+.Nm -+will replace the contents of the target file (keeping the inode). -+.Pp -+If the target file does not yet exist, an empty file with the target -+file name is created, then filled with the source file contents. -+No attempt is made at "near-atomic" transfer using temporary files. -+.Pp - The options are as follows: - .Bl -tag -width Ds - .It Fl 1 diff --git a/SOURCES/openssh-5.8p1-getaddrinfo.patch b/SOURCES/openssh-5.8p1-getaddrinfo.patch deleted file mode 100644 index 76deaef..0000000 --- a/SOURCES/openssh-5.8p1-getaddrinfo.patch +++ /dev/null @@ -1,24 +0,0 @@ -diff -up openssh-5.6p1/channels.c.getaddrinfo openssh-5.6p1/channels.c ---- openssh-5.6p1/channels.c.getaddrinfo 2012-02-14 16:12:54.427852524 +0100 -+++ openssh-5.6p1/channels.c 2012-02-14 16:13:22.818928690 +0100 -@@ -3275,6 +3275,9 @@ x11_create_display_inet(int x11_display_ - memset(&hints, 0, sizeof(hints)); - hints.ai_family = IPv4or6; - hints.ai_flags = x11_use_localhost ? 0: AI_PASSIVE; -+#ifdef AI_ADDRCONFIG -+ hints.ai_flags |= AI_ADDRCONFIG; -+#endif - hints.ai_socktype = SOCK_STREAM; - snprintf(strport, sizeof strport, "%d", port); - if ((gaierr = getaddrinfo(NULL, strport, &hints, &aitop)) != 0) { -diff -up openssh-5.6p1/sshconnect.c.getaddrinfo openssh-5.6p1/sshconnect.c ---- openssh-5.6p1/sshconnect.c.getaddrinfo 2012-02-14 16:09:25.057964291 +0100 -+++ openssh-5.6p1/sshconnect.c 2012-02-14 16:09:25.106047007 +0100 -@@ -343,6 +343,7 @@ ssh_connect(const char *host, struct soc - memset(&hints, 0, sizeof(hints)); - hints.ai_family = family; - hints.ai_socktype = SOCK_STREAM; -+ hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG; - snprintf(strport, sizeof strport, "%u", port); - if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) - fatal("%s: Could not resolve hostname %.100s: %s", __progname, diff --git a/SOURCES/openssh-5.8p1-glob.patch b/SOURCES/openssh-5.8p1-glob.patch deleted file mode 100644 index 4b1d8a7..0000000 --- a/SOURCES/openssh-5.8p1-glob.patch +++ /dev/null @@ -1,25 +0,0 @@ -diff -up openssh-5.8p1/sftp-glob.c.glob openssh-5.8p1/sftp-glob.c ---- openssh-5.8p1/sftp-glob.c.glob 2011-03-07 20:17:34.000000000 +0100 -+++ openssh-5.8p1/sftp-glob.c 2011-03-07 20:18:47.000000000 +0100 -@@ -145,5 +145,5 @@ remote_glob(struct sftp_conn *conn, cons - memset(&cur, 0, sizeof(cur)); - cur.conn = conn; - -- return(glob(pattern, flags | GLOB_ALTDIRFUNC, errfunc, pglob)); -+ return(glob(pattern, flags | GLOB_LIMIT | GLOB_ALTDIRFUNC, errfunc, pglob)); - } -diff --git a/openbsd-compat/glob.c b/openbsd-compat/glob.c -index 742b4b9..acae399 100644 ---- a/openbsd-compat/glob.c -+++ b/openbsd-compat/glob.c -@@ -130,8 +130,8 @@ typedef char Char; - #define M_CLASS META(':') - #define ismeta(c) (((c)&M_QUOTE) != 0) - --#define GLOB_LIMIT_MALLOC 65536 --#define GLOB_LIMIT_STAT 128 -+#define GLOB_LIMIT_MALLOC 65536*64 -+#define GLOB_LIMIT_STAT 128*64 - #define GLOB_LIMIT_READDIR 16384 - - /* Limit of recursion during matching attempts. */ diff --git a/SOURCES/openssh-6.6p1-AuthenticationMethods.patch b/SOURCES/openssh-6.6p1-AuthenticationMethods.patch new file mode 100644 index 0000000..de7f59d --- /dev/null +++ b/SOURCES/openssh-6.6p1-AuthenticationMethods.patch @@ -0,0 +1,110 @@ +diff -up openssh-6.6p1/servconf.c.auth_meth openssh-6.6p1/servconf.c +--- openssh-6.6p1/servconf.c.auth_meth 2016-06-24 13:39:30.022263557 +0200 ++++ openssh-6.6p1/servconf.c 2016-06-24 13:48:35.879948274 +0200 +@@ -327,6 +327,14 @@ fill_default_server_options(ServerOption + if (use_privsep == -1) + use_privsep = PRIVSEP_NOSANDBOX; + ++ /* Similar handling for AuthenticationMethods=any */ ++ if (options->num_auth_methods == 1 && ++ strcmp(options->auth_methods[0], "any") == 0) { ++ free(options->auth_methods[0]); ++ options->auth_methods[0] = NULL; ++ options->num_auth_methods = 0; ++ } ++ + #ifndef HAVE_MMAP + if (use_privsep && options->compression == 1) { + error("This platform does not support both privilege " +@@ -1680,22 +1688,42 @@ process_server_config_line(ServerOptions + break; + + case sAuthenticationMethods: +- if (cp == NULL || *cp == '\0') +- fatal("%.200s line %d: Missing argument.", filename, linenum); +- if (*activep && options->num_auth_methods == 0) { ++ if (options->num_auth_methods == 0) { ++ value = 0; /* seen "any" pseudo-method */ ++ value2 = 0; /* sucessfully parsed any method */ + while ((arg = strdelim(&cp)) && *arg != '\0') { + if (options->num_auth_methods >= + MAX_AUTH_METHODS) + fatal("%s line %d: " + "too many authentication methods.", + filename, linenum); +- if (auth2_methods_valid(arg, 0) != 0) ++ if (strcmp(arg, "any") == 0) { ++ if (options->num_auth_methods > 0) { ++ fatal("%s line %d: \"any\" " ++ "must appear alone in " ++ "AuthenticationMethods", ++ filename, linenum); ++ } ++ value = 1; ++ } else if (value) { ++ fatal("%s line %d: \"any\" must appear " ++ "alone in AuthenticationMethods", ++ filename, linenum); ++ } else if (auth2_methods_valid(arg, 0) != 0) { + fatal("%s line %d: invalid " + "authentication method list.", + filename, linenum); ++ } ++ value2 = 1; ++ if (!*activep) ++ continue; + options->auth_methods[ + options->num_auth_methods++] = xstrdup(arg); + } ++ if (value2 == 0) { ++ fatal("%s line %d: no AuthenticationMethods " ++ "specified", filename, linenum); ++ } + } + return 0; + +@@ -2195,11 +2221,13 @@ dump_cfg_strarray_oneline(ServerOpCodes code, u_int count, char **vals) + { + u_int i; + +- if (count <= 0) ++ if (count <= 0 && code != sAuthenticationMethods) + return; + printf("%s", lookup_opcode_name(code)); + for (i = 0; i < count; i++) + printf(" %s", vals[i]); ++ if (code == sAuthenticationMethods && count == 0) ++ printf(" any"); + printf("\n"); + } + +diff -up openssh-6.6p1/sshd_config.5.auth_meth openssh-6.6p1/sshd_config.5 +--- openssh-6.6p1/sshd_config.5.auth_meth 2016-06-24 13:39:30.007263566 +0200 ++++ openssh-6.6p1/sshd_config.5 2016-06-24 13:39:30.021263557 +0200 +@@ -172,9 +172,12 @@ for more information on patterns. + Specifies the authentication methods that must be successfully completed + for a user to be granted access. + This option must be followed by one or more comma-separated lists of +-authentication method names. +-Successful authentication requires completion of every method in at least +-one of these lists. ++authentication method names, or by the single string ++.Dq any ++to indicate the default behaviour of accepting any single authentication ++method. ++if the default is overridden, then successful authentication requires ++completion of every method in at least one of these lists. + .Pp + For example, an argument of + .Dq publickey,password publickey,keyboard-interactive +@@ -202,7 +205,9 @@ This option is only available for SSH pr + error if enabled if protocol 1 is also enabled. + Note that each authentication method listed should also be explicitly enabled + in the configuration. +-The default is not to require multiple authentication; successful completion ++The default ++.Dq any ++is not to require multiple authentication; successful completion + of a single authentication method is sufficient. + .It Cm AuthorizedKeysCommand + Specifies a program to be used to look up the user's public keys. diff --git a/SOURCES/openssh-6.6p1-CVE-2015-8325.patch b/SOURCES/openssh-6.6p1-CVE-2015-8325.patch new file mode 100644 index 0000000..4224051 --- /dev/null +++ b/SOURCES/openssh-6.6p1-CVE-2015-8325.patch @@ -0,0 +1,32 @@ +From 85bdcd7c92fe7ff133bbc4e10a65c91810f88755 Mon Sep 17 00:00:00 2001 +From: Damien Miller +Date: Wed, 13 Apr 2016 10:39:57 +1000 +Subject: ignore PAM environment vars when UseLogin=yes + +If PAM is configured to read user-specified environment variables +and UseLogin=yes in sshd_config, then a hostile local user may +attack /bin/login via LD_PRELOAD or similar environment variables +set via PAM. + +CVE-2015-8325, found by Shayan Sadigh, via Colin Watson +--- + session.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/session.c b/session.c +index 4859245..4653b09 100644 +--- a/session.c ++++ b/session.c +@@ -1322,7 +1322,7 @@ do_setup_env(Session *s, const char *shell) + * Pull in any environment variables that may have + * been set by PAM. + */ +- if (options.use_pam) { ++ if (options.use_pam && !options.use_login) { + char **p; + + p = fetch_pam_child_environment(); +-- +cgit v0.11.2 + + diff --git a/SOURCES/openssh-6.6p1-ControlPersist-stderr.patch b/SOURCES/openssh-6.6p1-ControlPersist-stderr.patch new file mode 100644 index 0000000..1cffa1b --- /dev/null +++ b/SOURCES/openssh-6.6p1-ControlPersist-stderr.patch @@ -0,0 +1,53 @@ +From d2d6bf864e52af8491a60dd507f85b74361f5da3 Mon Sep 17 00:00:00 2001 +From: "djm@openbsd.org" +Date: Fri, 29 Apr 2016 08:07:53 +0000 +Subject: [PATCH] upstream commit + +close ControlPersist background process stderr when not + in debug mode or when logging to a file or syslog. bz#1988 ok dtucker + +Upstream-ID: 4fb726f0fdcb155ad419913cea10dc4afd409d24 +--- + log.c | 4 ++-- + ssh.c | 8 +++++--- + 2 files changed, 7 insertions(+), 5 deletions(-) + +diff --git a/log.c b/log.c +index ad12930..277afda 100644 +--- a/log.c ++++ b/log.c +@@ -342,7 +342,7 @@ log_change_level(LogLevel new_log_level) + int + log_is_on_stderr(void) + { +- return log_on_stderr; ++ return log_on_stderr && log_stderr_fd == STDERR_FILENO; + } + + /* redirect what would usually get written to stderr to specified file */ +diff --git a/ssh.c b/ssh.c +index a999d50..a881ba1 100644 +--- a/ssh.c ++++ b/ssh.c +@@ -1395,7 +1395,7 @@ static void + control_persist_detach(void) + { + pid_t pid; +- int devnull; ++ int devnull, keep_stderr; + + debug("%s: backgrounding master process", __func__); + +@@ -1426,8 +1426,10 @@ control_persist_detach(void) + error("%s: open(\"/dev/null\"): %s", __func__, + strerror(errno)); + } else { ++ keep_stderr = log_is_on_stderr() && debug_flag; + if (dup2(devnull, STDIN_FILENO) == -1 || +- dup2(devnull, STDOUT_FILENO) == -1) ++ dup2(devnull, STDOUT_FILENO) == -1 || ++ (!keep_stderr && dup2(devnull, STDERR_FILENO) == -1)) + error("%s: dup2: %s", __func__, strerror(errno)); + if (devnull > STDERR_FILENO) + close(devnull); + diff --git a/SOURCES/openssh-6.6p1-audit-race-condition.patch b/SOURCES/openssh-6.6p1-audit-race-condition.patch new file mode 100644 index 0000000..5fffe10 --- /dev/null +++ b/SOURCES/openssh-6.6p1-audit-race-condition.patch @@ -0,0 +1,122 @@ +diff -up openssh-6.6p1/monitor_wrap.c.audit-race openssh-6.6p1/monitor_wrap.c +--- openssh-6.6p1/monitor_wrap.c.audit-race 2016-02-23 13:43:59.958203930 +0100 ++++ openssh-6.6p1/monitor_wrap.c 2016-02-23 13:43:59.959203930 +0100 +@@ -1456,4 +1456,31 @@ mm_audit_destroy_sensitive_data(const ch + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_SERVER_KEY_FREE, &m); + buffer_free(&m); + } ++ ++int mm_forward_audit_messages(int fdin) ++{ ++ static char fb[256]; ++ size_t fblen; ++ do { ++ fblen = atomicio(read, fdin, fb, sizeof(fb)); ++ if (fblen == 0) { ++ // atomicio read returns EPIPE also with EOF ++ if (errno != EPIPE) { ++ error("%s: Failed to read the messages from child", __func__); ++ return -1; ++ } ++ return 0; ++ } ++ fblen = atomicio(vwrite, pmonitor->m_recvfd, fb, fblen); ++ if (fblen == 0 && errno != EPIPE) { ++ error("%s: Failed to pass the messages to the monitor", __func__); ++ return -1; ++ } ++ } while(fblen > 0); ++ return 0; ++} ++void mm_set_monitor_pipe(int fd) ++{ ++ pmonitor->m_recvfd = fd; ++} + #endif /* SSH_AUDIT_EVENTS */ +diff -up openssh-6.6p1/monitor_wrap.h.audit-race openssh-6.6p1/monitor_wrap.h +--- openssh-6.6p1/monitor_wrap.h.audit-race 2016-02-23 13:43:59.958203930 +0100 ++++ openssh-6.6p1/monitor_wrap.h 2016-02-23 13:43:59.959203930 +0100 +@@ -86,6 +86,8 @@ void mm_audit_unsupported_body(int); + void mm_audit_kex_body(int, char *, char *, char *, char *, pid_t, uid_t); + void mm_audit_session_key_free_body(int, pid_t, uid_t); + void mm_audit_destroy_sensitive_data(const char *, pid_t, uid_t); ++int mm_forward_audit_messages(int); ++void mm_set_monitor_pipe(int); + #endif + + struct Session; +diff -up openssh-6.6p1/session.c.audit-race openssh-6.6p1/session.c +--- openssh-6.6p1/session.c.audit-race 2016-02-23 13:43:59.954203931 +0100 ++++ openssh-6.6p1/session.c 2016-02-23 13:45:14.758194058 +0100 +@@ -158,6 +159,10 @@ static Session *sessions = NULL; + login_cap_t *lc; + #endif + ++#ifdef SSH_AUDIT_EVENTS ++int paudit[2]; ++#endif ++ + static int is_child = 0; + + static int have_dev_log = 1; +@@ -891,6 +896,8 @@ do_exec(Session *s, const char *command) + } + if (s->command != NULL && s->ptyfd == -1) + s->command_handle = PRIVSEP(audit_run_command(s->command)); ++ if (pipe(paudit) < 0) ++ fatal("pipe: %s", strerror(errno)); + #endif + if (s->ttyfd != -1) + ret = do_exec_pty(s, command); +@@ -906,6 +913,20 @@ do_exec(Session *s, const char *command) + */ + buffer_clear(&loginmsg); + ++#ifdef SSH_AUDIT_EVENTS ++ close(paudit[1]); ++ if (use_privsep && ret == 0) { ++ /* ++ * Read the audit messages from forked child and send them ++ * back to monitor. We don't want to communicate directly, ++ * because the messages might get mixed up. ++ * Continue after the pipe gets closed (all messages sent). ++ */ ++ ret = mm_forward_audit_messages(paudit[0]); ++ } ++ close(paudit[0]); ++#endif /* SSH_AUDIT_EVENTS */ ++ + return ret; + } + +@@ -1718,12 +1739,27 @@ do_child(Session *s, const char *command + struct passwd *pw = s->pw; + int r = 0; + ++#ifdef SSH_AUDIT_EVENTS ++ close(paudit[0]); ++ /* Hack the monitor pipe to avoid race condition with parent */ ++ if (use_privsep) ++ mm_set_monitor_pipe(paudit[1]); ++#endif ++ + /* remove hostkey from the child's memory */ +- 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. */ ++ destroy_sensitive_data(use_privsep); ++ /* ++ * We can audit this, because we hacked the pipe to direct the ++ * messages over postauth child. But this message requires answer ++ * which we can't do using one-way pipe. ++ */ + packet_destroy_all(0, 1); + ++#ifdef SSH_AUDIT_EVENTS ++ /* Notify parent that we are done */ ++ close(paudit[1]); ++#endif ++ + /* Force a password change */ + if (s->authctxt->force_pwchange) { + do_setusercontext(pw); diff --git a/SOURCES/openssh-6.6p1-audit.patch b/SOURCES/openssh-6.6p1-audit.patch index dd0c06e..66f7438 100644 --- a/SOURCES/openssh-6.6p1-audit.patch +++ b/SOURCES/openssh-6.6p1-audit.patch @@ -855,9 +855,9 @@ index 95d678e..48aede4 100644 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) + buffer_len(&b))) == 1) { authenticated = 1; - + authctxt->last_details = pubkey; @@ -154,6 +154,18 @@ done: return authenticated; } @@ -887,9 +887,9 @@ index cb0f931..6d1c872 100644 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) + buffer_len(&b))) == 1) { + authctxt->last_details = pubkey; authenticated = 1; - buffer_free(&b); @@ -231,6 +231,18 @@ pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...) free(extra); } diff --git a/SOURCES/openssh-6.6p1-chroot-capabilities.patch b/SOURCES/openssh-6.6p1-chroot-capabilities.patch new file mode 100644 index 0000000..4fb3f21 --- /dev/null +++ b/SOURCES/openssh-6.6p1-chroot-capabilities.patch @@ -0,0 +1,100 @@ +diff -up openssh-6.6p1/configure.ac.chroot-cap openssh-6.6p1/configure.ac +--- openssh-6.6p1/configure.ac.chroot-cap 2016-07-28 10:08:11.183483309 +0200 ++++ openssh-6.6p1/configure.ac 2016-07-28 10:08:11.273483277 +0200 +@@ -4783,6 +4783,37 @@ if test -n "$conf_lastlog_location"; the + [Define if you want to specify the path to your lastlog file]) + fi + ++AC_ARG_WITH(libcap-ng, ++ [ --with-libcap-ng=[auto/yes/no] Add Libcap-ng support [default=auto]],, ++ with_libcap_ng=auto) ++ ++dnl libcap-ng detection ++if test x$with_libcap_ng = xno ; then ++ have_libcap_ng=no; ++else ++ # Start by checking for header file ++ AC_CHECK_HEADER(cap-ng.h, capng_headers=yes, capng_headers=no) ++ ++ # See if we have libcap-ng library ++ AC_CHECK_LIB(cap-ng, capng_clear, CAPNG_LDADD=-lcap-ng,) ++ ++ # Check results are usable ++ if test x$with_libcap_ng = xyes -a x$CAPNG_LDADD = x ; then ++ AC_MSG_ERROR(libcap-ng support was requested and the library was not found) ++ fi ++ if test x$CAPNG_LDADD != x -a $capng_headers = no ; then ++ AC_MSG_ERROR(libcap-ng libraries found but headers are missing) ++ fi ++fi ++AC_MSG_CHECKING(whether to use libcap-ng) ++if test x$CAPNG_LDADD != x ; then ++ AC_DEFINE(HAVE_LIBCAP_NG,1,[libcap-ng support]) ++ SSHDLIBS="$SSHDLIBS -lcap-ng" ++ AC_MSG_RESULT(yes) ++else ++ AC_MSG_RESULT(no) ++fi ++ + dnl utmp detection + AC_MSG_CHECKING([if your system defines UTMP_FILE]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +diff -up openssh-6.6p1/session.c.chroot-cap openssh-6.6p1/session.c +--- openssh-6.6p1/session.c.chroot-cap 2016-07-28 10:08:11.269483278 +0200 ++++ openssh-6.6p1/session.c 2016-07-28 10:09:10.458455211 +0200 +@@ -95,6 +95,10 @@ + #include "monitor_wrap.h" + #include "sftp.h" + ++#ifdef HAVE_LIBCAP_NG ++#include ++#endif ++ + #if defined(KRB5) && defined(USE_AFS) + #include + #endif +@@ -1569,6 +1573,7 @@ void + do_setusercontext(struct passwd *pw) + { + char *chroot_path, *tmp; ++ int dropped_suid = -1; + + platform_setusercontext(pw); + +@@ -1602,10 +1607,24 @@ do_setusercontext(struct passwd *pw) + pw->pw_uid); + chroot_path = percent_expand(tmp, "h", pw->pw_dir, + "u", pw->pw_name, (char *)NULL); ++#ifdef HAVE_LIBCAP_NG ++ /* drop suid soon, retain SYS_CHROOT capability */ ++ capng_clear(CAPNG_SELECT_BOTH); ++ capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED, CAP_SYS_CHROOT); ++ if ((dropped_suid = capng_change_id(pw->pw_uid, pw->pw_gid, CAPNG_DROP_SUPP_GRP | CAPNG_CLEAR_BOUNDING)) != 0) ++ logit("capng_change_id() = %d (failure): Try to drop UID later", dropped_suid); ++#endif + #ifdef WITH_SELINUX + sshd_selinux_copy_context(); + #endif + safely_chroot(chroot_path, pw->pw_uid); ++#ifdef HAVE_LIBCAP_NG ++ /* Drop chroot capability. Already used */ ++ if (dropped_suid == 0) { ++ capng_clear(CAPNG_SELECT_BOTH); ++ capng_apply(CAPNG_SELECT_BOTH); ++ } ++#endif + free(tmp); + free(chroot_path); + /* Make sure we don't attempt to chroot again */ +@@ -1629,8 +1648,9 @@ do_setusercontext(struct passwd *pw) + fatal("set_id(%s) Failed", pw->pw_name); + } + # endif /* USE_LIBIAF */ +- /* Permanently switch to the desired uid. */ +- permanently_set_uid(pw); ++ /* Permanently switch to the desired uid if not yet done. */ ++ if (dropped_suid != 0) ++ permanently_set_uid(pw); + #endif + + #ifdef WITH_SELINUX diff --git a/SOURCES/openssh-6.6p1-ctr-cavstest.patch b/SOURCES/openssh-6.6p1-ctr-cavstest.patch index 1997fa6..3b0d744 100644 --- a/SOURCES/openssh-6.6p1-ctr-cavstest.patch +++ b/SOURCES/openssh-6.6p1-ctr-cavstest.patch @@ -21,7 +21,7 @@ index 4ab6717..581b121 100644 canohost.o channels.o cipher.o cipher-aes.o \ @@ -180,6 +181,9 @@ ssh-ldap-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ldapconf.o ldapbody.o ldapmisc.o ssh-keycat$(EXEEXT): $(LIBCOMPAT) $(SSHDOBJS) libssh.a ssh-keycat.o - $(LD) -o $@ ssh-keycat.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(SSHDLIBS) $(SSHLIBS) + $(LD) -o $@ ssh-keycat.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(KEYCATLIBS) $(SSHLIBS) +ctr-cavstest$(EXEEXT): $(LIBCOMPAT) libssh.a ctr-cavstest.o + $(LD) -o $@ ctr-cavstest.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS) diff --git a/SOURCES/openssh-6.6p1-expose-auth-information.patch b/SOURCES/openssh-6.6p1-expose-auth-information.patch new file mode 100644 index 0000000..ed508fd --- /dev/null +++ b/SOURCES/openssh-6.6p1-expose-auth-information.patch @@ -0,0 +1,512 @@ +diff -up openssh-6.6p1/auth2.c.expose-auth openssh-6.6p1/auth2.c +--- openssh-6.6p1/auth2.c.expose-auth 2016-06-27 12:19:39.134443822 +0200 ++++ openssh-6.6p1/auth2.c 2016-06-27 12:19:39.178443747 +0200 +@@ -309,6 +309,7 @@ userauth_finish(Authctxt *authctxt, int + const char *submethod) + { + char *methods; ++ char *prev_auth_details; + int partial = 0; + + if (!authctxt->valid && authenticated) +@@ -339,6 +340,18 @@ userauth_finish(Authctxt *authctxt, int + if (authctxt->postponed) + return; + ++ if (authenticated || partial) { ++ prev_auth_details = authctxt->auth_details; ++ xasprintf(&authctxt->auth_details, "%s%s%s%s%s", ++ prev_auth_details ? prev_auth_details : "", ++ prev_auth_details ? ", " : "", method, ++ authctxt->last_details ? ": " : "", ++ authctxt->last_details ? authctxt->last_details : ""); ++ free(authctxt->last_details); ++ authctxt->last_details = NULL; ++ free(prev_auth_details); ++ } ++ + #ifdef USE_PAM + if (options.use_pam && authenticated) { + if (!PRIVSEP(do_pam_account())) { +diff -up openssh-6.6p1/auth2-gss.c.expose-auth openssh-6.6p1/auth2-gss.c +--- openssh-6.6p1/auth2-gss.c.expose-auth 2016-06-27 12:19:39.102443877 +0200 ++++ openssh-6.6p1/auth2-gss.c 2016-06-27 12:19:39.179443745 +0200 +@@ -272,6 +272,9 @@ input_gssapi_exchange_complete(int type, + authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, + authctxt->pw)); + ++ if (authenticated) ++ authctxt->last_details = ssh_gssapi_get_displayname(); ++ + authctxt->postponed = 0; + dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); + dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); +@@ -317,6 +320,9 @@ input_gssapi_mic(int type, u_int32_t ple + else + logit("GSSAPI MIC check failed"); + ++ if (authenticated) ++ authctxt->last_details = ssh_gssapi_get_displayname(); ++ + buffer_free(&b); + if (micuser != authctxt->user) + free(micuser); +diff -up openssh-6.6p1/auth2-hostbased.c.expose-auth openssh-6.6p1/auth2-hostbased.c +--- openssh-6.6p1/auth2-hostbased.c.expose-auth 2016-06-27 12:19:39.051443964 +0200 ++++ openssh-6.6p1/auth2-hostbased.c 2016-06-27 12:19:39.179443745 +0200 +@@ -58,7 +58,7 @@ userauth_hostbased(Authctxt *authctxt) + { + Buffer b; + Key *key = NULL; +- char *pkalg, *cuser, *chost, *service; ++ char *pkalg, *cuser, *chost, *service, *pubkey; + u_char *pkblob, *sig; + u_int alen, blen, slen; + int pktype; +@@ -131,15 +131,21 @@ userauth_hostbased(Authctxt *authctxt) + buffer_dump(&b); + #endif + +- pubkey_auth_info(authctxt, key, +- "client user \"%.100s\", client host \"%.100s\"", cuser, chost); ++ pubkey = key_format_oneline(key); ++ auth_info(authctxt, ++ "%s, client user \"%.100s\", client host \"%.100s\"", ++ pubkey, 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), +- buffer_len(&b))) == 1) ++ buffer_len(&b))) == 1) { + authenticated = 1; ++ authctxt->last_details = pubkey; ++ } else { ++ free(pubkey); ++ } + + buffer_free(&b); + done: +diff -up openssh-6.6p1/auth2-pubkey.c.expose-auth openssh-6.6p1/auth2-pubkey.c +--- openssh-6.6p1/auth2-pubkey.c.expose-auth 2016-06-27 12:19:39.068443935 +0200 ++++ openssh-6.6p1/auth2-pubkey.c 2016-06-27 12:19:39.179443745 +0200 +@@ -75,7 +75,7 @@ userauth_pubkey(Authctxt *authctxt) + { + Buffer b; + Key *key = NULL; +- char *pkalg, *userstyle; ++ char *pkalg, *userstyle, *pubkey; + u_char *pkblob, *sig; + u_int alen, blen, slen; + int have_sig, pktype; +@@ -155,14 +155,19 @@ userauth_pubkey(Authctxt *authctxt) + #ifdef DEBUG_PK + buffer_dump(&b); + #endif +- pubkey_auth_info(authctxt, key, NULL); ++ pubkey = key_format_oneline(key); ++ auth_info(authctxt, "%s", pubkey); + + /* test for correct signature */ + authenticated = 0; + if (PRIVSEP(user_key_allowed(authctxt->pw, key)) && + PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), +- buffer_len(&b))) == 1) ++ buffer_len(&b))) == 1) { ++ authctxt->last_details = pubkey; + authenticated = 1; ++ } else { ++ free(pubkey); ++ } + buffer_free(&b); + free(sig); + } else { +@@ -200,7 +205,7 @@ done: + void + pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...) + { +- char *fp, *extra; ++ char *extra, *pubkey; + va_list ap; + int i; + +@@ -210,24 +215,13 @@ pubkey_auth_info(Authctxt *authctxt, con + i = vasprintf(&extra, fmt, ap); + va_end(ap); + if (i < 0 || extra == NULL) +- fatal("%s: vasprintf failed", __func__); ++ fatal("%s: vasprintf failed", __func__); + } + +- if (key_is_cert(key)) { +- fp = key_fingerprint(key->cert->signature_key, +- SSH_FP_MD5, 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); +- auth_info(authctxt, "%s %s%s%s", key_type(key), fp, +- extra == NULL ? "" : ", ", extra == NULL ? "" : extra); +- free(fp); +- } ++ pubkey = key_format_oneline(key); ++ auth_info(authctxt, "%s%s%s", pubkey, extra == NULL ? "" : ", ", ++ extra == NULL ? "" : extra); ++ free(pubkey); + free(extra); + } + +diff -up openssh-6.6p1/auth.h.expose-auth openssh-6.6p1/auth.h +--- openssh-6.6p1/auth.h.expose-auth 2016-06-27 12:19:39.144443805 +0200 ++++ openssh-6.6p1/auth.h 2016-06-27 12:19:39.179443745 +0200 +@@ -78,6 +78,9 @@ struct Authctxt { + #endif + Buffer *loginmsg; + void *methoddata; ++ ++ char *last_details; ++ char *auth_details; + }; + /* + * Every authentication method has to handle authentication requests for +diff -up openssh-6.6p1/auth-pam.c.expose-auth openssh-6.6p1/auth-pam.c +--- openssh-6.6p1/auth-pam.c.expose-auth 2016-06-27 12:19:39.049443967 +0200 ++++ openssh-6.6p1/auth-pam.c 2016-06-27 12:19:39.179443745 +0200 +@@ -688,6 +688,11 @@ sshpam_init_ctx(Authctxt *authctxt) + return (NULL); + } + ++ /* Notify PAM about any already successful auth methods */ ++ if (options.expose_auth_methods >= EXPOSE_AUTHMETH_PAMONLY && ++ authctxt->auth_details) ++ do_pam_putenv("SSH_USER_AUTH", authctxt->auth_details); ++ + ctxt = xcalloc(1, sizeof *ctxt); + + /* Start the authentication thread */ +diff -up openssh-6.6p1/gss-serv.c.expose-auth openssh-6.6p1/gss-serv.c +--- openssh-6.6p1/gss-serv.c.expose-auth 2016-06-27 12:19:39.160443778 +0200 ++++ openssh-6.6p1/gss-serv.c 2016-06-27 12:19:39.180443743 +0200 +@@ -471,6 +471,16 @@ ssh_gssapi_userok(char *user, struct pas + return (0); + } + ++/* Privileged */ ++char* ++ssh_gssapi_get_displayname(void) ++{ ++ if (gssapi_client.displayname.length != 0 && ++ gssapi_client.displayname.value != NULL) ++ return strdup((char *)gssapi_client.displayname.value); ++ return NULL; ++} ++ + /* These bits are only used for rekeying. The unpriviledged child is running + * as the user, the monitor is root. + * +diff -up openssh-6.6p1/key.c.expose-auth openssh-6.6p1/key.c +--- openssh-6.6p1/key.c.expose-auth 2016-06-27 12:19:39.105443872 +0200 ++++ openssh-6.6p1/key.c 2016-06-27 12:19:39.180443743 +0200 +@@ -57,6 +57,7 @@ + #include "misc.h" + #include "ssh2.h" + #include "digest.h" ++#include "xmalloc.h" + + static int to_blob(const Key *, u_char **, u_int *, int); + static Key *key_from_blob2(const u_char *, u_int, int); +@@ -628,6 +629,30 @@ key_fingerprint(const Key *k, enum fp_ty + return retval; + } + ++char * ++key_format_oneline(const Key *key) ++{ ++ char *fp, *result; ++ ++ if (key_is_cert(key)) { ++ fp = key_fingerprint(key->cert->signature_key, SSH_FP_MD5, ++ SSH_FP_HEX); ++ xasprintf(&result, "%s ID %s (serial %llu) CA %s %s", ++ key_type(key), key->cert->key_id, ++ (unsigned long long)key->cert->serial, ++ key_type(key->cert->signature_key), ++ fp == NULL ? "(null)" : fp); ++ free(fp); ++ } else { ++ fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); ++ xasprintf(&result, "%s %s", key_type(key), ++ fp == NULL ? "(null)" : fp); ++ free(fp); ++ } ++ ++ return result; ++} ++ + enum fp_type + key_fingerprint_selection(void) + { +diff -up openssh-6.6p1/key.h.expose-auth openssh-6.6p1/key.h +--- openssh-6.6p1/key.h.expose-auth 2016-06-27 12:19:43.322436657 +0200 ++++ openssh-6.6p1/key.h 2016-06-27 12:20:25.898363835 +0200 +@@ -108,6 +108,7 @@ u_char *key_fingerprint_raw(const Key * + enum fp_type key_fingerprint_selection(void); + char *key_selected_fingerprint(Key *, enum fp_rep); + char *key_fingerprint_prefix(void); ++char *key_format_oneline(const Key *k); + const char *key_type(const Key *); + const char *key_cert_type(const Key *); + int key_write(const Key *, FILE *); +diff -up openssh-6.6p1/monitor.c.expose-auth openssh-6.6p1/monitor.c +--- openssh-6.6p1/monitor.c.expose-auth 2016-06-27 12:19:39.165443769 +0200 ++++ openssh-6.6p1/monitor.c 2016-06-27 12:19:39.180443743 +0200 +@@ -357,6 +357,7 @@ monitor_child_preauth(Authctxt *_authctx + { + struct mon_table *ent; + int authenticated = 0, partial = 0; ++ char *prev_auth_details; + + debug3("preauth child monitor started"); + +@@ -394,6 +395,18 @@ monitor_child_preauth(Authctxt *_authctx + auth_submethod = NULL; + authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1); + ++ if (authenticated) { ++ prev_auth_details = authctxt->auth_details; ++ xasprintf(&authctxt->auth_details, "%s%s%s%s%s", ++ prev_auth_details ? prev_auth_details : "", ++ prev_auth_details ? ", " : "", auth_method, ++ authctxt->last_details ? ": " : "", ++ authctxt->last_details ? authctxt->last_details : ""); ++ free(authctxt->last_details); ++ authctxt->last_details = NULL; ++ free(prev_auth_details); ++ } ++ + /* Special handling for multiple required authentications */ + if (options.num_auth_methods != 0) { + if (!compat20) +@@ -1432,6 +1445,9 @@ mm_answer_keyverify(int sock, Buffer *m) + debug3("%s: key %p signature %s", + __func__, key, (verified == 1) ? "verified" : "unverified"); + ++ if (verified == 1) ++ authctxt->last_details = key_format_oneline(key); ++ + key_free(key); + free(blob); + free(signature); +@@ -2224,6 +2240,9 @@ mm_answer_gss_userok(int sock, Buffer *m + + auth_method = "gssapi-with-mic"; + ++ if (authenticated) ++ authctxt->last_details = ssh_gssapi_get_displayname(); ++ + /* Monitor loop will terminate if authenticated */ + return (authenticated); + } +diff -up openssh-6.6p1/servconf.c.expose-auth openssh-6.6p1/servconf.c +--- openssh-6.6p1/servconf.c.expose-auth 2016-06-27 12:19:39.177443748 +0200 ++++ openssh-6.6p1/servconf.c 2016-06-27 12:19:39.181443742 +0200 +@@ -161,6 +161,7 @@ initialize_server_options(ServerOptions + options->version_addendum = NULL; + options->use_kuserok = -1; + options->enable_k5users = -1; ++ options->expose_auth_methods = -1; + } + + void +@@ -322,6 +323,8 @@ fill_default_server_options(ServerOption + options->use_kuserok = 1; + if (options->enable_k5users == -1) + options->enable_k5users = 0; ++ if (options->expose_auth_methods == -1) ++ options->expose_auth_methods = EXPOSE_AUTHMETH_NEVER; + + /* Turn privilege separation on by default */ + if (use_privsep == -1) +@@ -380,6 +383,7 @@ typedef enum { + sKexAlgorithms, sIPQoS, sVersionAddendum, + sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, + sAuthenticationMethods, sHostKeyAgent, ++ sExposeAuthenticationMethods, + sDeprecated, sUnsupported + } ServerOpCodes; + +@@ -523,6 +527,7 @@ static struct { + { "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL }, + { "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL }, + { "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL }, ++ { "exposeauthenticationmethods", sExposeAuthenticationMethods, SSHCFG_ALL }, + { NULL, sBadOption, 0 } + }; + +@@ -869,6 +874,12 @@ static const struct multistate multistat + { "local", FORWARD_LOCAL }, + { NULL, -1 } + }; ++static const struct multistate multistate_exposeauthmeth[] = { ++ { "never", EXPOSE_AUTHMETH_NEVER }, ++ { "pam-only", EXPOSE_AUTHMETH_PAMONLY }, ++ { "pam-and-env", EXPOSE_AUTHMETH_PAMENV }, ++ { NULL, -1} ++}; + + int + process_server_config_line(ServerOptions *options, char *line, +@@ -1727,6 +1738,11 @@ process_server_config_line(ServerOptions + } + return 0; + ++ case sExposeAuthenticationMethods: ++ intptr = &options->expose_auth_methods; ++ multistate_ptr = multistate_exposeauthmeth; ++ goto parse_multistate; ++ + case sDeprecated: + logit("%s line %d: Deprecated option %s", + filename, linenum, arg); +@@ -1883,6 +1899,7 @@ copy_set_server_options(ServerOptions *d + M_CP_INTOPT(enable_k5users); + M_CP_INTOPT(rekey_limit); + M_CP_INTOPT(rekey_interval); ++ M_CP_INTOPT(expose_auth_methods); + + /* M_CP_STROPT and M_CP_STRARRAYOPT should not appear before here */ + #define M_CP_STROPT(n) do {\ +@@ -1971,6 +1988,8 @@ fmt_intarg(ServerOpCodes code, int val) + return fmt_multistate_int(val, multistate_privsep); + case sAllowTcpForwarding: + return fmt_multistate_int(val, multistate_tcpfwd); ++ case sExposeAuthenticationMethods: ++ return fmt_multistate_int(val, multistate_exposeauthmeth); + case sProtocol: + switch (val) { + case SSH_PROTO_1: +@@ -2182,6 +2201,7 @@ dump_config(ServerOptions *o) + dump_cfg_strarray(sAcceptEnv, o->num_accept_env, o->accept_env); + dump_cfg_strarray_oneline(sAuthenticationMethods, + o->num_auth_methods, o->auth_methods); ++ dump_cfg_fmtint(sExposeAuthenticationMethods, o->expose_auth_methods); + + /* other arguments */ + for (i = 0; i < o->num_subsystems; i++) +diff -up openssh-6.6p1/servconf.h.expose-auth openssh-6.6p1/servconf.h +--- openssh-6.6p1/servconf.h.expose-auth 2016-06-27 12:19:39.162443774 +0200 ++++ openssh-6.6p1/servconf.h 2016-06-27 12:19:39.181443742 +0200 +@@ -48,6 +48,11 @@ + #define FORWARD_LOCAL (1<<1) + #define FORWARD_ALLOW (FORWARD_REMOTE|FORWARD_LOCAL) + ++/* Expose AuthenticationMethods */ ++#define EXPOSE_AUTHMETH_NEVER 0 ++#define EXPOSE_AUTHMETH_PAMONLY 1 ++#define EXPOSE_AUTHMETH_PAMENV 2 ++ + #define DEFAULT_AUTH_FAIL_MAX 6 /* Default for MaxAuthTries */ + #define DEFAULT_SESSIONS_MAX 10 /* Default for MaxSessions */ + +@@ -190,6 +195,8 @@ typedef struct { + + u_int num_auth_methods; + char *auth_methods[MAX_AUTH_METHODS]; ++ ++ int expose_auth_methods; /* EXPOSE_AUTHMETH_* above */ + } ServerOptions; + + /* Information about the incoming connection as used by Match */ +diff -up openssh-6.6p1/session.c.expose-auth openssh-6.6p1/session.c +--- openssh-6.6p1/session.c.expose-auth 2016-06-27 12:19:39.171443759 +0200 ++++ openssh-6.6p1/session.c 2016-06-27 12:19:39.181443742 +0200 +@@ -1196,6 +1196,12 @@ copy_environment(char **source, char *** + } + *var_val++ = '\0'; + ++ if (options.expose_auth_methods < EXPOSE_AUTHMETH_PAMENV && ++ strcmp(var_name, "SSH_USER_AUTH") == 0) { ++ free(var_name); ++ continue; ++ } ++ + debug3("Copy environment: %s=%s", var_name, var_val); + child_set_env(env, envsize, var_name, var_val); + +@@ -1375,6 +1381,11 @@ do_setup_env(Session *s, const char *she + } + #endif /* USE_PAM */ + ++ if (options.expose_auth_methods >= EXPOSE_AUTHMETH_PAMENV && ++ s->authctxt->auth_details) ++ child_set_env(&env, &envsize, "SSH_USER_AUTH", ++ s->authctxt->auth_details); ++ + if (auth_sock_name != NULL) + child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME, + auth_sock_name); +@@ -2805,6 +2816,9 @@ do_cleanup(Authctxt *authctxt) + if (authctxt == NULL) + return; + ++ free(authctxt->auth_details); ++ authctxt->auth_details = NULL; ++ + #ifdef USE_PAM + if (options.use_pam) { + sshpam_cleanup(); +diff -up openssh-6.6p1/ssh.1.expose-auth openssh-6.6p1/ssh.1 +--- openssh-6.6p1/ssh.1.expose-auth 2016-06-27 12:19:39.163443772 +0200 ++++ openssh-6.6p1/ssh.1 2016-06-27 12:19:39.181443742 +0200 +@@ -1289,6 +1289,10 @@ server IP address, and server port numbe + This variable contains the original command line if a forced command + is executed. + It can be used to extract the original arguments. ++.It Ev SSH_USER_AUTH ++This variable contains, for SSH2 only, a comma-separated list of authentication ++methods that were successfuly used to authenticate. When possible, these ++methods are extended with detailed information on the credential used. + .It Ev SSH_TTY + This is set to the name of the tty (path to the device) associated + with the current shell or command. +diff -up openssh-6.6p1/sshd_config.5.expose-auth openssh-6.6p1/sshd_config.5 +--- openssh-6.6p1/sshd_config.5.expose-auth 2016-06-27 12:19:39.177443748 +0200 ++++ openssh-6.6p1/sshd_config.5 2016-06-27 12:19:39.182443740 +0200 +@@ -466,6 +466,21 @@ is allowed to log in. + See PATTERNS in + .Xr ssh_config 5 + for more information on patterns. ++.It Cm ExposeAuthenticationMethods ++When using SSH2, this option controls the exposure of the list of ++successful authentication methods to PAM during the authentication ++and to the shell environment via the ++.Cm SSH_USER_AUTH ++variable. See the description of this variable for more details. ++Valid options are: ++.Dq never ++(Do not expose successful authentication methods), ++.Dq pam-only ++(Only expose them to PAM during authentication, not afterwards), ++.Dq pam-and-env ++(Expose them to PAM and keep them in the shell environment). ++The default is ++.Dq never . + .It Cm ForceCommand + Forces the execution of the command specified by + .Cm ForceCommand , +diff -up openssh-6.6p1/ssh-gss.h.expose-auth openssh-6.6p1/ssh-gss.h +--- openssh-6.6p1/ssh-gss.h.expose-auth 2016-06-27 12:19:39.163443772 +0200 ++++ openssh-6.6p1/ssh-gss.h 2016-06-27 12:19:39.182443740 +0200 +@@ -160,6 +160,7 @@ int ssh_gssapi_server_check_mech(Gssctxt + const char *); + OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID); + int ssh_gssapi_userok(char *name, struct passwd *); ++char* ssh_gssapi_get_displayname(void); + 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); diff --git a/SOURCES/openssh-6.6p1-fips.patch b/SOURCES/openssh-6.6p1-fips.patch index 77760db..a9a3145 100644 --- a/SOURCES/openssh-6.6p1-fips.patch +++ b/SOURCES/openssh-6.6p1-fips.patch @@ -55,30 +55,9 @@ diff -up openssh-6.6p1/auth-rsa.c.fips openssh-6.6p1/auth-rsa.c file, linenum, key_type(key), fp); free(fp); diff -up openssh-6.6p1/auth2-pubkey.c.fips openssh-6.6p1/auth2-pubkey.c ---- openssh-6.6p1/auth2-pubkey.c.fips 2015-08-13 15:09:43.345350133 +0200 -+++ openssh-6.6p1/auth2-pubkey.c 2015-08-13 15:09:43.353350119 +0200 -@@ -214,8 +214,7 @@ pubkey_auth_info(Authctxt *authctxt, con - } - - if (key_is_cert(key)) { -- fp = key_fingerprint(key->cert->signature_key, -- SSH_FP_MD5, SSH_FP_HEX); -+ fp = key_selected_fingerprint(key->cert->signature_key, SSH_FP_HEX); - 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, -@@ -223,7 +222,7 @@ pubkey_auth_info(Authctxt *authctxt, con - extra == NULL ? "" : ", ", extra == NULL ? "" : extra); - free(fp); - } else { -- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); -+ fp = key_selected_fingerprint(key, SSH_FP_HEX); - auth_info(authctxt, "%s %s%s%s", key_type(key), fp, - extra == NULL ? "" : ", ", extra == NULL ? "" : extra); - free(fp); diff -up openssh-6.6p1/authfile.c.fips openssh-6.6p1/authfile.c ---- openssh-6.6p1/authfile.c.fips 2015-08-13 15:09:43.213350355 +0200 -+++ openssh-6.6p1/authfile.c 2015-08-13 15:09:43.354350118 +0200 +--- openssh-6.6p1/authfile.c.fips 2016-06-27 09:51:39.334362038 +0200 ++++ openssh-6.6p1/authfile.c 2016-06-27 09:51:39.443361948 +0200 @@ -46,6 +46,7 @@ #include #include @@ -375,7 +354,25 @@ diff -up openssh-6.6p1/key.c.fips openssh-6.6p1/key.c #include #include -@@ -636,9 +637,13 @@ key_fingerprint_selection(void) +@@ -635,7 +636,7 @@ sshkey_format_oneline(const struct sshke + char *fp, *result; + + if (key_is_cert(key)) { +- fp = key_fingerprint(key->cert->signature_key, SSH_FP_MD5, ++ fp = key_selected_fingerprint(key->cert->signature_key, + SSH_FP_HEX); + xasprintf(&result, "%s ID %s (serial %llu) CA %s %s", + key_type(key), key->cert->key_id, +@@ -644,7 +645,7 @@ sshkey_format_oneline(const struct sshke + fp == NULL ? "(null)" : fp); + free(fp); + } else { +- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); ++ fp = key_selected_fingerprint(key, SSH_FP_HEX); + xasprintf(&result, "%s %s", key_type(key), + fp == NULL ? "(null)" : fp); + free(fp); +@@ -661,9 +662,13 @@ key_fingerprint_selection(void) char *env; if (!rv_defined) { @@ -811,3 +808,25 @@ diff -up openssh-6.6p1/sshd.c.fips openssh-6.6p1/sshd.c if (gss && orig) xasprintf(&newstr, "%s,%s", gss, orig); +diff --git a/pam_ssh_agent_auth-0.9.3/pam_user_key_allowed2.c b/pam_ssh_agent_auth-0.9.3/pam_user_key_allowed2.c +index 13b0a6f..3ec2454 100644 +--- a/pam_ssh_agent_auth-0.9.3/pam_user_key_allowed2.c ++++ b/pam_ssh_agent_auth-0.9.3/pam_user_key_allowed2.c +@@ -54,6 +54,7 @@ + #include "secure_filename.h" + #include "uidswap.h" + #include ++#include + + #include "identity.h" + +@@ -103,7 +104,8 @@ pamsshagentauth_check_authkeys_file(FILE * f, char *file, Key * key) + found_key = 1; + logit("matching key found: file/command %s, line %lu", file, + linenum); +- fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); ++ fp = key_fingerprint(found, FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5, ++ SSH_FP_HEX); + logit("Found matching %s key: %s", + key_type(found), fp); + free(fp); diff --git a/SOURCES/openssh-6.6p1-gssKexAlgorithms.patch b/SOURCES/openssh-6.6p1-gssKexAlgorithms.patch index fec7e7f..3854b40 100644 --- a/SOURCES/openssh-6.6p1-gssKexAlgorithms.patch +++ b/SOURCES/openssh-6.6p1-gssKexAlgorithms.patch @@ -396,3 +396,15 @@ index 5e8c6c6..4c670aa 100644 .It Cm HostbasedAuthentication Specifies whether rhosts or /etc/hosts.equiv authentication together with successful public key client host authentication is allowed +diff --git a/kex.h b/kex.h +index db3dde4..17ae43b 100644 +--- a/kex.h ++++ b/kex.h +@@ -158,6 +158,7 @@ struct Kex { + + int kex_names_valid(const char *); + char *kex_alg_list(char); ++int gss_kex_names_valid(const char *); + + Kex *kex_setup(char *[PROPOSAL_MAX]); + void kex_finish(Kex *); diff --git a/SOURCES/openssh-6.6p1-gsskex.patch b/SOURCES/openssh-6.6p1-gsskex.patch index 826acd4..d1ee1ab 100644 --- a/SOURCES/openssh-6.6p1-gsskex.patch +++ b/SOURCES/openssh-6.6p1-gsskex.patch @@ -2811,3 +2811,15 @@ index 95b5f8c..1fb002d 100644 .It Cm HostbasedAuthentication Specifies whether rhosts or /etc/hosts.equiv authentication together with successful public key client host authentication is allowed +diff --git a/ssh-gss.h b/ssh-gss.h +index 132fd0d..39f6645 100644 +--- a/ssh-gss.h ++++ b/ssh-gss.h +@@ -169,6 +169,7 @@ 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(); + #endif /* GSSAPI */ + + #endif /* _SSH_GSS_H */ diff --git a/SOURCES/openssh-6.6p1-k5login_directory.patch b/SOURCES/openssh-6.6p1-k5login_directory.patch new file mode 100644 index 0000000..308c452 --- /dev/null +++ b/SOURCES/openssh-6.6p1-k5login_directory.patch @@ -0,0 +1,87 @@ +diff --git a/auth-krb5.c b/auth-krb5.c +index 2b02a04..19b9364 100644 +--- a/auth-krb5.c ++++ b/auth-krb5.c +@@ -375,6 +375,22 @@ cleanup: + return -1; + } + ++/* ++ * Reads k5login_directory option from the krb5.conf ++ */ ++krb5_error_code ++ssh_krb5_get_k5login_directory(krb5_context ctx, char **k5login_directory) { ++ profile_t p; ++ int ret = 0; ++ ++ ret = krb5_get_profile(ctx, &p); ++ if (ret) ++ return ret; ++ ++ return profile_get_string(p, "libdefaults", "k5login_directory", NULL, NULL, ++ k5login_directory); ++} ++ + krb5_error_code + ssh_krb5_get_cctemplate(krb5_context ctx, char **ccname) { + profile_t p; +diff --git a/auth.h b/auth.h +index f9d191c..c432d2f 100644 +--- a/auth.h ++++ b/auth.h +@@ -222,5 +222,7 @@ int sys_auth_passwd(Authctxt *, const char *); + #if defined(KRB5) && !defined(HEIMDAL) + #include + krb5_error_code ssh_krb5_cc_gen(krb5_context, krb5_ccache *); ++krb5_error_code ssh_krb5_get_k5login_directory(krb5_context ctx, ++ char **k5login_directory); + #endif + #endif +diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c +index a7c0c5f..df8cc9a 100644 +--- a/gss-serv-krb5.c ++++ b/gss-serv-krb5.c +@@ -244,8 +244,27 @@ ssh_gssapi_k5login_exists() + { + char file[MAXPATHLEN]; + struct passwd *pw = the_authctxt->pw; ++ char *k5login_directory = NULL; ++ int ret = 0; ++ ++ ret = ssh_krb5_get_k5login_directory(krb_context, &k5login_directory); ++ debug3("%s: k5login_directory = %s (rv=%d)", __func__, k5login_directory, ret); ++ if (k5login_directory == NULL || ret != 0) { ++ /* If not set, the library will look for k5login ++ * files in the user's home directory, with the filename .k5login. ++ */ ++ snprintf(file, sizeof(file), "%s/.k5login", pw->pw_dir); ++ } else { ++ /* If set, the library will look for a local user's k5login file ++ * within the named directory, with a filename corresponding to the ++ * local username. ++ */ ++ snprintf(file, sizeof(file), "%s%s%s", k5login_directory, ++ k5login_directory[strlen(k5login_directory)-1] != '/' ? "/" : "", ++ pw->pw_name); ++ } ++ debug("%s: Checking existence of file %s", __func__, file); + +- snprintf(file, sizeof(file), "%s/.k5login", pw->pw_dir); + return access(file, F_OK) == 0; + } + +diff --git a/sshd.8 b/sshd.8 +index 5c4f15b..135e290 100644 +--- a/sshd.8 ++++ b/sshd.8 +@@ -806,6 +806,10 @@ rlogin/rsh. + These files enforce GSSAPI/Kerberos authentication access control. + Further details are described in + .Xr ksu 1 . ++The location of the k5login file depends on the configuration option ++.Cm k5login_directory ++in the ++.Xr krb5.conf 5 . + .Pp + .It Pa ~/.ssh/ + This directory is the default location for all user-specific configuration diff --git a/SOURCES/openssh-6.6p1-keycat.patch b/SOURCES/openssh-6.6p1-keycat.patch index d30dedb..49b9798 100644 --- a/SOURCES/openssh-6.6p1-keycat.patch +++ b/SOURCES/openssh-6.6p1-keycat.patch @@ -28,6 +28,14 @@ index 411eadb..4ab6717 100644 SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper PRIVSEP_PATH=@PRIVSEP_PATH@ SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ +@@ -52,6 +52,7 @@ K5LIBS=@K5LIBS@ + GSSLIBS=@GSSLIBS@ + SSHLIBS=@SSHLIBS@ + SSHDLIBS=@SSHDLIBS@ ++KEYCATLIBS=@KEYCATLIBS@ + LIBEDIT=@LIBEDIT@ + AR=@AR@ + AWK=@AWK@ @@ -64,7 +65,7 @@ EXEEXT=@EXEEXT@ MANFMT=@MANFMT@ INSTALL_SSH_LDAP_HELPER=@INSTALL_SSH_LDAP_HELPER@ @@ -42,7 +50,7 @@ index 411eadb..4ab6717 100644 $(LD) -o $@ ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) +ssh-keycat$(EXEEXT): $(LIBCOMPAT) $(SSHDOBJS) libssh.a ssh-keycat.o -+ $(LD) -o $@ ssh-keycat.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(SSHDLIBS) $(SSHLIBS) ++ $(LD) -o $@ ssh-keycat.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(KEYCATLIBS) $(SSHLIBS) + 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) @@ -443,3 +451,41 @@ index 0000000..f8ed7af + } + return ev; +} +diff --git a/configure.ac b/configure.ac +index 3bbccfd..6481f1f 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -2952,6 +2952,7 @@ AC_ARG_WITH([pam], + PAM_MSG="yes" + + SSHDLIBS="$SSHDLIBS -lpam" ++ KEYCATLIBS="$KEYCATLIBS -lpam" + AC_DEFINE([USE_PAM], [1], + [Define if you want to enable PAM support]) + +@@ -2962,6 +2963,7 @@ AC_ARG_WITH([pam], + ;; + *) + SSHDLIBS="$SSHDLIBS -ldl" ++ KEYCATLIBS="$KEYCATLIBS -ldl" + ;; + esac + fi +@@ -4042,6 +4044,7 @@ AC_ARG_WITH([selinux], + ) + AC_SUBST([SSHLIBS]) + AC_SUBST([SSHDLIBS]) ++AC_SUBST([KEYCATLIBS]) + + # Check whether user wants Kerberos 5 support + KRB5_MSG="no" +@@ -5031,6 +5034,9 @@ fi + if test ! -z "${SSHLIBS}"; then + echo " +for ssh: ${SSHLIBS}" + fi ++if test ! -z "${KEYCATLIBS}"; then ++echo " +for ssh-keycat: ${KEYCATLIBS}" ++fi + + echo "" + diff --git a/SOURCES/openssh-6.6p1-permitopen-any-host.patch b/SOURCES/openssh-6.6p1-permitopen-any-host.patch new file mode 100644 index 0000000..ec519b2 --- /dev/null +++ b/SOURCES/openssh-6.6p1-permitopen-any-host.patch @@ -0,0 +1,74 @@ +diff -up openssh-6.6p1/channels.c.permitopen openssh-6.6p1/channels.c +--- openssh-6.6p1/channels.c.permitopen 2016-06-29 15:37:08.780327108 +0200 ++++ openssh-6.6p1/channels.c 2016-06-29 16:04:38.480857525 +0200 +@@ -128,6 +128,9 @@ static int num_adm_permitted_opens = 0; + /* special-case port number meaning allow any port */ + #define FWD_PERMIT_ANY_PORT 0 + ++/* special-case wildcard meaning allow any host */ ++#define FWD_PERMIT_ANY_HOST "*" ++ + /* + * If this is true, all opens are permitted. This is the case on the server + * on which we have to trust the client anyway, and the user could do +@@ -3271,6 +3274,21 @@ port_match(u_short allowedport, u_short + return 0; + } + ++static int ++open_match(ForwardPermission *allowed_open, const char *requestedhost, ++ u_short requestedport) ++{ ++ if (allowed_open->host_to_connect == NULL) ++ return 0; ++ if (allowed_open->port_to_connect != FWD_PERMIT_ANY_PORT && ++ allowed_open->port_to_connect != requestedport) ++ return 0; ++ if (strcmp(allowed_open->host_to_connect, FWD_PERMIT_ANY_HOST) != 0 && ++ strcmp(allowed_open->host_to_connect, requestedhost) != 0) ++ return 0; ++ return 1; ++} ++ + /* Try to start non-blocking connect to next host in cctx list */ + static int + connect_next(struct channel_connect *cctx) +@@ -3391,20 +3409,18 @@ channel_connect_to(const char *host, u_s + permit = all_opens_permitted; + if (!permit) { + for (i = 0; i < num_permitted_opens; i++) +- if (permitted_opens[i].host_to_connect != NULL && +- port_match(permitted_opens[i].port_to_connect, port) && +- strcmp(permitted_opens[i].host_to_connect, host) == 0) ++ if (open_match(&permitted_opens[i], host, port)) { + permit = 1; ++ } + } + + if (num_adm_permitted_opens > 0) { + permit_adm = 0; + for (i = 0; i < num_adm_permitted_opens; i++) +- if (permitted_adm_opens[i].host_to_connect != NULL && +- port_match(permitted_adm_opens[i].port_to_connect, port) && +- strcmp(permitted_adm_opens[i].host_to_connect, host) +- == 0) ++ if (open_match(&permitted_adm_opens[i], host, port)) { + permit_adm = 1; ++ break; ++ } + } + + if (!permit || !permit_adm) { +diff -up openssh-6.6p1/sshd_config.5.permitopen openssh-6.6p1/sshd_config.5 +--- openssh-6.6p1/sshd_config.5.permitopen 2016-06-29 15:37:08.778327110 +0200 ++++ openssh-6.6p1/sshd_config.5 2016-06-29 15:37:08.782327106 +0200 +@@ -1005,6 +1005,9 @@ can be used to remove all restrictions a + An argument of + .Dq none + can be used to prohibit all forwarding requests. ++Wildcard ++.Dq * ++can be used for host or port to allow all hosts or all ports respectively. + By default all port forwarding requests are permitted. + .It Cm PermitRootLogin + Specifies whether root can log in using diff --git a/SOURCES/openssh-6.6p1-s390-closefrom.patch b/SOURCES/openssh-6.6p1-s390-closefrom.patch new file mode 100644 index 0000000..301a523 --- /dev/null +++ b/SOURCES/openssh-6.6p1-s390-closefrom.patch @@ -0,0 +1,52 @@ +Zseries only: Leave the hardware filedescriptors open. + +All filedescriptors above 2 are getting closed when a new +sshd process to handle a new client connection is +spawned. As the process also chroot into an empty filesystem +without any device nodes, there is no chance to reopen the +files. This patch filters out the reqired fds in the +closefrom function so these are skipped in the close loop. + +Author: Harald Freudenberger + +--- + openbsd-compat/bsd-closefrom.c | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +--- a/openbsd-compat/bsd-closefrom.c ++++ b/openbsd-compat/bsd-closefrom.c +@@ -82,7 +82,33 @@ closefrom(int lowfd) + fd = strtol(dent->d_name, &endp, 10); + if (dent->d_name != endp && *endp == '\0' && + fd >= 0 && fd < INT_MAX && fd >= lowfd && fd != dirfd(dirp)) ++#ifdef __s390__ ++ { ++ /* ++ * the filedescriptors used to communicate with ++ * the device drivers to provide hardware support ++ * should survive. HF ++ */ ++ char fpath[PATH_MAX], lpath[PATH_MAX]; ++ len = snprintf(fpath, sizeof(fpath), "%s/%s", ++ fdpath, dent->d_name); ++ if (len > 0 && (size_t)len <= sizeof(fpath)) { ++ len = readlink(fpath, lpath, sizeof(lpath)); ++ if (len > 0) { ++ lpath[len] = 0; ++ if (strstr(lpath, "dev/z90crypt") ++ || strstr(lpath, "dev/zcrypt") ++ || strstr(lpath, "dev/prandom") ++ || strstr(lpath, "dev/shm/icastats")) ++ fd = -1; ++ } ++ } ++ if (fd >= 0) ++ (void) close((int) fd); ++ } ++#else + (void) close((int) fd); ++#endif + } + (void) closedir(dirp); + } else + diff --git a/SOURCES/openssh-6.6p1-sftp-force-permission.patch b/SOURCES/openssh-6.6p1-sftp-force-permission.patch index 2853bdd..a35b7b7 100644 --- a/SOURCES/openssh-6.6p1-sftp-force-permission.patch +++ b/SOURCES/openssh-6.6p1-sftp-force-permission.patch @@ -34,18 +34,35 @@ diff -up openssh-6.6p1/sftp-server.c.sftp-force-mode openssh-6.6p1/sftp-server.c /* SSH2_FXP_INIT received */ static int init_done; -@@ -675,6 +679,10 @@ process_open(u_int32_t id) +@@ -668,6 +672,7 @@ process_open(u_int32_t id) + Attrib *a; + char *name; + int handle, fd, flags, mode, status = SSH2_FX_FAILURE; ++ mode_t old_umask; + + name = get_string(NULL); + pflags = get_int(); /* portable flags */ +@@ -675,6 +680,10 @@ process_open(u_int32_t id) a = get_attrib(); flags = flags_from_portable(pflags); mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666; + if (permforce == 1) { /* Force perm if -m is set */ + mode = permforcemode; -+ (void)umask(0); /* so umask does not interfere */ -+ } ++ old_umask = umask(0); /* so umask does not interfere */ ++ } logit("open \"%s\" flags %s mode 0%o", name, string_from_portable(pflags), mode); if (readonly && -@@ -1430,7 +1438,7 @@ sftp_server_usage(void) +@@ -696,6 +705,8 @@ process_open(u_int32_t id) + } + } + } ++ if (permforce == 1) ++ (void) umask(old_umask); /* restore umask to something sane */ + if (status != SSH2_FX_OK) + send_status(id, status); + free(name); +@@ -1430,7 +1441,7 @@ sftp_server_usage(void) fprintf(stderr, "usage: %s [-ehR] [-d start_directory] [-f log_facility] " "[-l log_level]\n\t[-P blacklisted_requests] " diff --git a/SOURCES/openssh-6.6p1-ssh-copy-id-quiet.patch b/SOURCES/openssh-6.6p1-ssh-copy-id-quiet.patch new file mode 100644 index 0000000..4cce020 --- /dev/null +++ b/SOURCES/openssh-6.6p1-ssh-copy-id-quiet.patch @@ -0,0 +1,11 @@ +diff -up openssh-6.6p1/contrib/ssh-copy-id.quiet openssh-6.6p1/contrib/ssh-copy-id +--- openssh-6.6p1/contrib/ssh-copy-id.quiet 2016-06-27 13:42:47.844393842 +0200 ++++ openssh-6.6p1/contrib/ssh-copy-id 2016-06-27 13:42:57.861398744 +0200 +@@ -215,6 +215,7 @@ populate_new_ids() { + # The point being that if file based, ssh needs the private key, which it cannot + # find if only given the contents of the .pub file in an unrelated tmpfile + ssh -i "${PRIV_ID_FILE:-$L_TMP_ID_FILE}" \ ++ -o LogLevel=INFO \ + -o PreferredAuthentications=publickey \ + -o IdentitiesOnly=yes "$@" exit 2>$L_TMP_ID_FILE.stderr 0) + break; + } +- if (display_number >= MAX_DISPLAYS) { ++ if (display_number >= x11_max_displays || port < X11_PORT_MIN ) { + error("Failed to allocate internet-domain X11 display socket."); + return -1; + } +@@ -3658,7 +3664,7 @@ x11_connect_display(void) + memset(&hints, 0, sizeof(hints)); + hints.ai_family = IPv4or6; + hints.ai_socktype = SOCK_STREAM; +- snprintf(strport, sizeof strport, "%u", 6000 + display_number); ++ snprintf(strport, sizeof strport, "%u", X11_PORT_MIN + display_number); + if ((gaierr = getaddrinfo(buf, strport, &hints, &aitop)) != 0) { + error("%.100s: unknown host. (%s)", buf, + ssh_gai_strerror(gaierr)); +@@ -3674,7 +3680,7 @@ x11_connect_display(void) + /* Connect it to the display. */ + if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0) { + debug2("connect %.100s port %u: %.100s", buf, +- 6000 + display_number, strerror(errno)); ++ X11_PORT_MIN + display_number, strerror(errno)); + close(sock); + continue; + } +@@ -3683,8 +3689,8 @@ x11_connect_display(void) + } + freeaddrinfo(aitop); + if (!ai) { +- error("connect %.100s port %u: %.100s", buf, 6000 + display_number, +- strerror(errno)); ++ error("connect %.100s port %u: %.100s", buf, ++ X11_PORT_MIN + display_number, strerror(errno)); + return -1; + } + set_nodelay(sock); +diff -up openssh-6.6p1/channels.h.x11max openssh-6.6p1/channels.h +--- openssh-6.6p1/channels.h.x11max 2016-06-27 16:28:49.814631678 +0200 ++++ openssh-6.6p1/channels.h 2016-06-27 16:31:18.925557840 +0200 +@@ -281,7 +281,7 @@ int permitopen_port(const char *); + + void channel_set_x11_refuse_time(u_int); + int x11_connect_display(void); +-int x11_create_display_inet(int, int, int, u_int *, int **); ++int x11_create_display_inet(int, int, int, int, u_int *, int **); + void x11_input_open(int, u_int32_t, void *); + void x11_request_forwarding_with_spoofing(int, const char *, const char *, + const char *, int); +diff -up openssh-6.6p1/servconf.c.x11max openssh-6.6p1/servconf.c +--- openssh-6.6p1/servconf.c.x11max 2016-06-27 16:28:49.808631681 +0200 ++++ openssh-6.6p1/servconf.c 2016-06-27 16:30:46.941573678 +0200 +@@ -92,6 +92,7 @@ initialize_server_options(ServerOptions + options->print_lastlog = -1; + options->x11_forwarding = -1; + options->x11_display_offset = -1; ++ options->x11_max_displays = -1; + options->x11_use_localhost = -1; + options->permit_tty = -1; + options->xauth_location = NULL; +@@ -219,6 +220,8 @@ fill_default_server_options(ServerOption + options->x11_forwarding = 0; + if (options->x11_display_offset == -1) + options->x11_display_offset = 10; ++ if (options->x11_max_displays == -1) ++ options->x11_max_displays = DEFAULT_MAX_DISPLAYS; + if (options->x11_use_localhost == -1) + options->x11_use_localhost = 1; + if (options->xauth_location == NULL) +@@ -364,7 +367,7 @@ typedef enum { + sPasswordAuthentication, sKbdInteractiveAuthentication, + sListenAddress, sAddressFamily, + sPrintMotd, sPrintLastLog, sIgnoreRhosts, +- sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, ++ sX11Forwarding, sX11DisplayOffset, sX11MaxDisplays, sX11UseLocalhost, + sPermitTTY, sStrictModes, sEmptyPasswd, sTCPKeepAlive, + sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression, + sRekeyLimit, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, +@@ -476,6 +479,7 @@ static struct { + { "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL }, + { "x11forwarding", sX11Forwarding, SSHCFG_ALL }, + { "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL }, ++ { "x11maxdisplays", sX11MaxDisplays, SSHCFG_ALL }, + { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL }, + { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL }, + { "strictmodes", sStrictModes, SSHCFG_GLOBAL }, +@@ -1202,6 +1206,10 @@ process_server_config_line(ServerOptions + intptr = &options->x11_display_offset; + goto parse_int; + ++ case sX11MaxDisplays: ++ intptr = &options->x11_max_displays; ++ goto parse_int; ++ + case sX11UseLocalhost: + intptr = &options->x11_use_localhost; + goto parse_flag; +@@ -1889,6 +1897,7 @@ copy_set_server_options(ServerOptions *d + M_CP_INTOPT(gateway_ports); + M_CP_INTOPT(x11_display_offset); + M_CP_INTOPT(x11_forwarding); ++ M_CP_INTOPT(x11_max_displays); + M_CP_INTOPT(x11_use_localhost); + M_CP_INTOPT(permit_tty); + M_CP_INTOPT(max_sessions); +@@ -2106,6 +2115,7 @@ dump_config(ServerOptions *o) + dump_cfg_int(sLoginGraceTime, o->login_grace_time); + dump_cfg_int(sKeyRegenerationTime, o->key_regeneration_time); + dump_cfg_int(sX11DisplayOffset, o->x11_display_offset); ++ dump_cfg_int(sX11MaxDisplays, o->x11_max_displays); + dump_cfg_int(sMaxAuthTries, o->max_authtries); + dump_cfg_int(sMaxSessions, o->max_sessions); + dump_cfg_int(sClientAliveInterval, o->client_alive_interval); +diff -up openssh-6.6p1/servconf.h.x11max openssh-6.6p1/servconf.h +--- openssh-6.6p1/servconf.h.x11max 2016-06-27 16:28:49.809631681 +0200 ++++ openssh-6.6p1/servconf.h 2016-06-27 16:28:49.815631678 +0200 +@@ -55,6 +55,7 @@ + + #define DEFAULT_AUTH_FAIL_MAX 6 /* Default for MaxAuthTries */ + #define DEFAULT_SESSIONS_MAX 10 /* Default for MaxSessions */ ++#define DEFAULT_MAX_DISPLAYS 1000 /* Maximum number of fake X11 displays to try. */ + + /* Magic name for internal sftp-server */ + #define INTERNAL_SFTP_NAME "internal-sftp" +@@ -85,6 +86,7 @@ typedef struct { + int x11_forwarding; /* If true, permit inet (spoofing) X11 fwd. */ + int x11_display_offset; /* What DISPLAY number to start + * searching at */ ++ int x11_max_displays; /* Number of displays to search */ + int x11_use_localhost; /* If true, use localhost for fake X11 server. */ + char *xauth_location; /* Location of xauth program */ + int permit_tty; /* If false, deny pty allocation */ +diff -up openssh-6.6p1/session.c.x11max openssh-6.6p1/session.c +--- openssh-6.6p1/session.c.x11max 2016-06-27 16:28:49.809631681 +0200 ++++ openssh-6.6p1/session.c 2016-06-27 16:28:49.815631678 +0200 +@@ -2741,8 +2741,9 @@ session_setup_x11fwd(Session *s) + return 0; + } + if (x11_create_display_inet(options.x11_display_offset, +- options.x11_use_localhost, s->single_connection, +- &s->display_number, &s->x11_chanids) == -1) { ++ options.x11_use_localhost, options.x11_max_displays, ++ s->single_connection, &s->display_number, ++ &s->x11_chanids) == -1) { + debug("x11_create_display_inet failed."); + return 0; + } +diff -up openssh-6.6p1/sshd_config.5.x11max openssh-6.6p1/sshd_config.5 +--- openssh-6.6p1/sshd_config.5.x11max 2016-06-27 16:28:49.809631681 +0200 ++++ openssh-6.6p1/sshd_config.5 2016-06-27 16:32:01.253536879 +0200 +@@ -930,6 +930,7 @@ Available keywords are + .Cm RhostsRSAAuthentication , + .Cm RSAAuthentication , + .Cm X11DisplayOffset , ++.Cm X11MaxDisplays , + .Cm X11Forwarding + and + .Cm X11UseLocalHost . +@@ -1339,6 +1340,12 @@ Specifies the first display number avail + X11 forwarding. + This prevents sshd from interfering with real X11 servers. + The default is 10. ++.It Cm X11MaxDisplays ++Specifies the maximum number of displays available for ++.Xr sshd 8 Ns 's ++X11 forwarding. ++This prevents sshd from exhausting local ports. ++The default is 1000. + .It Cm X11Forwarding + Specifies whether X11 forwarding is permitted. + The argument must be diff --git a/SOURCES/pam_ssh_agent_auth-0.9.3-command.patch b/SOURCES/pam_ssh_agent_auth-0.9.3-command.patch new file mode 100644 index 0000000..88e8d7d --- /dev/null +++ b/SOURCES/pam_ssh_agent_auth-0.9.3-command.patch @@ -0,0 +1,1451 @@ +From b0695cc9f5478daa14d3f451ecdd39ba6e6abe0f Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Tue, 19 Jan 2016 15:29:22 +0100 +Subject: [PATCH] authorized_keys_command + +--- + pam_ssh_agent_auth-0.9.3/CONTRIBUTORS | 2 + + pam_ssh_agent_auth-0.9.3/Makefile.in | 28 +- + pam_ssh_agent_auth-0.9.3/README | 38 +++ + pam_ssh_agent_auth-0.9.3/configure.ac | 27 +- + pam_ssh_agent_auth-0.9.3/get_command_line.c | 113 +++++++ + pam_ssh_agent_auth-0.9.3/get_command_line.h | 40 +++ + pam_ssh_agent_auth-0.9.3/identity.h | 24 ++ + pam_ssh_agent_auth-0.9.3/iterate_ssh_agent_keys.c | 137 ++++++++- + pam_ssh_agent_auth-0.9.3/iterate_ssh_agent_keys.h | 2 +- + pam_ssh_agent_auth-0.9.3/pam_ssh_agent_auth.c | 16 +- + pam_ssh_agent_auth-0.9.3/pam_ssh_agent_auth.pod | 50 ++- + pam_ssh_agent_auth-0.9.3/pam_static_macros.h | 29 ++ + .../pam_user_authorized_keys.c | 23 +- + .../pam_user_authorized_keys.h | 2 +- + pam_ssh_agent_auth-0.9.3/pam_user_key_allowed2.c | 334 ++++++++++++++++----- + pam_ssh_agent_auth-0.9.3/pam_user_key_allowed2.h | 3 +- + pam_ssh_agent_auth-0.9.3/secure_filename.c | 51 +++- + pam_ssh_agent_auth-0.9.3/secure_filename.h | 4 +- + pam_ssh_agent_auth-0.9.3/userauth_pubkey_from_id.c | 20 +- + pam_ssh_agent_auth-0.9.3/userauth_pubkey_from_id.h | 2 +- + 20 files changed, 805 insertions(+), 140 deletions(-) + create mode 100644 pam_ssh_agent_auth-0.9.3/README + create mode 100644 pam_ssh_agent_auth-0.9.3/get_command_line.c + create mode 100644 pam_ssh_agent_auth-0.9.3/get_command_line.h + +diff --git a/pam_ssh_agent_auth-0.9.3/CONTRIBUTORS b/pam_ssh_agent_auth-0.9.3/CONTRIBUTORS +index d5a21cb..22b424a 100644 +--- a/pam_ssh_agent_auth-0.9.3/CONTRIBUTORS ++++ b/pam_ssh_agent_auth-0.9.3/CONTRIBUTORS +@@ -1,3 +1,5 @@ + * Foremost, OpenSSH from which this project is derived. + * Jamie Beverly + * Rafael D'Halleweyn - 2011-06-05 18:56:24 EDT ++* Jan-Pieter Cornet ( johnpc ) - 2012-03-23 03:25:52 PDT ++* chrysn@fsfe.org +diff --git a/pam_ssh_agent_auth-0.9.3/Makefile.in b/pam_ssh_agent_auth-0.9.3/Makefile.in +index 47bb103..4977838 100644 +--- a/pam_ssh_agent_auth-0.9.3/Makefile.in ++++ b/pam_ssh_agent_auth-0.9.3/Makefile.in +@@ -1,4 +1,28 @@ + # $Id: Makefile.in,v 1.289 2008/03/13 01:41:31 djm Exp $ ++# ++# Copyright (c) 2000 Markus Friedl. All rights reserved. ++# Modifications Copyright (c) 2008-2014 Jamie Beverly. 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. ++# + + # uncomment if you run a non bourne compatable shell. Ie. csh + #SHELL = @SH@ +@@ -46,9 +70,9 @@ INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@ + + PAM_MODULES=pam_ssh_agent_auth.so + +-SSHOBJS=xmalloc.o atomicio.o authfd.o bufaux.o bufbn.o buffer.o cleanup.o entropy.o fatal.o key.o log.o misc.o secure_filename.o ssh-dss.o ssh-rsa.o uuencode.o compat.o ++SSHOBJS=xmalloc.o atomicio.o authfd.o bufaux.o bufbn.o buffer.o cleanup.o entropy.o fatal.o key.o log.o misc.o secure_filename.o ssh-dss.o ssh-rsa.o uuencode.o compat.o uidswap.o + +-PAM_SSH_AGENT_AUTH_OBJS=pam_user_key_allowed2.o iterate_ssh_agent_keys.o userauth_pubkey_from_id.o pam_user_authorized_keys.o secure_filename.o ++PAM_SSH_AGENT_AUTH_OBJS=pam_user_key_allowed2.o iterate_ssh_agent_keys.o userauth_pubkey_from_id.o pam_user_authorized_keys.o secure_filename.o get_command_line.o + + + MANPAGES_IN = pam_ssh_agent_auth.pod +diff --git a/pam_ssh_agent_auth-0.9.3/README b/pam_ssh_agent_auth-0.9.3/README +new file mode 100644 +index 0000000..c1a49ef +--- /dev/null ++++ b/pam_ssh_agent_auth-0.9.3/README +@@ -0,0 +1,38 @@ ++pam_ssh_agent_auth is a PAM module which permits PAM authentication via your ++keyring in a forwarded ssh-agent. ++ ++Release 0.10.1 is stable, and has been tested on FreeBSD, Solaris 10, Solaris 11, ++RHEL5, RHEL6, Debian Wheezy, Ubuntu 12.04 (LTS), Ubuntu 13.10, ++and MacOS X 10.7. ++ ++This module can be used to provide authentication for anything run locally that ++supports PAM. It was written specifically with the intention of permitting ++authentication for sudo without password entry, and also has been proven useful ++for use with su as an alternative to wheel. ++ ++It serves as middle ground between the two most common, and suboptimal ++alternatives for large-scale system administration: allowing rootlogin via ssh, ++or using NOPASSWD in sudoers. This module allows for ssh public-key ++authentication, and it does this by leveraging an authentication mechanism you ++are probably already using, ssh-agent. ++ ++There are caveats of course, ssh-agent forwarding has it’s own security risks ++which must be carefully considered for your environment. In cases where there ++are not untrustworthy intermediate servers, and you wish to retain traceability, ++accountability, and required authentication for privileged command invocation, ++the benefits should outweigh the risks. Release 0.10.1 can be downloaded from ++SourceForge: https://sourceforge.net/project/showfiles.php?group_id=249556 ++ ++If you encounter any issues with usability or security, please use the project's ++SourceForge tracker: ++https://sourceforge.net/tracker2/?group_id=249556&atid=1126337 ++ ++Note that if you wish to use this for sudo, you will need a version of sudo that ++preserves the env_keep environment during authentication; and ideally a version ++incorporating my minor patch which ensures RUSER is set during PAM authentication. ++ ++sudo 1.6.8p12 does not work correctly with this PAM module, because it clears the ++environment (even env_keep variables) prior to attempting PAM authentication. ++ ++sudo 1.7.2p1 or later is preferred, as it correctly sets PAM_RUSER for ++authentication. +diff --git a/pam_ssh_agent_auth-0.9.3/configure.ac b/pam_ssh_agent_auth-0.9.3/configure.ac +index 1f372ce..4eb1f32 100644 +--- a/pam_ssh_agent_auth-0.9.3/configure.ac ++++ b/pam_ssh_agent_auth-0.9.3/configure.ac +@@ -18,8 +18,10 @@ AC_INIT(OpenSSH, Portable, openssh-unix-dev@mindrot.org) + AC_REVISION($Revision: 1.397 $) + AC_CONFIG_SRCDIR([pam_ssh_agent_auth.c]) + +-AC_CONFIG_HEADER(config.h) ++AC_CONFIG_SRCDIR([config.h.in]) ++AC_CONFIG_HEADERS([config.h]) + AC_PROG_CC ++AC_C_INLINE + AC_CANONICAL_HOST + AC_C_BIGENDIAN + +@@ -117,7 +119,6 @@ if test -z "$LD" ; then + fi + AC_SUBST(LD) + +-AC_C_INLINE + + AC_CHECK_DECL(LLONG_MAX, have_llong_max=1, , [#include ]) + +@@ -151,7 +152,7 @@ if test "$GCC" = "yes" || test "$GCC" = "egcs"; then + ;; + 2.*) no_attrib_nonnull=1 ;; + 3.*) CFLAGS="$CFLAGS -Wsign-compare" ;; +- 4.*) CFLAGS="$CFLAGS -Wsign-compare -Wno-pointer-sign" ;; ++ 4.*) CFLAGS="$CFLAGS -Wsign-compare -Wall -Wextra" ;; + *) ;; + esac + +@@ -1656,11 +1657,11 @@ fi + + if test "x$check_for_conflicting_getspnam" = "x1"; then + AC_MSG_CHECKING(for conflicting getspnam in shadow.h) +- AC_COMPILE_IFELSE( ++ AC_COMPILE_IFELSE([AC_LANG_SOURCE( + [ + #include + int main(void) {exit(0);} +- ], ++ ])], + [ + AC_MSG_RESULT(no) + ], +@@ -2720,7 +2721,7 @@ fi + dnl make sure we're using the real structure members and not defines + AC_CACHE_CHECK([for msg_accrights field in struct msghdr], + ac_cv_have_accrights_in_msghdr, [ +- AC_COMPILE_IFELSE( ++ AC_COMPILE_IFELSE([AC_LANG_SOURCE( + [ + #include + #include +@@ -2734,7 +2735,7 @@ struct msghdr m; + m.msg_accrights = 0; + exit(0); + } +- ], ++ ])], + [ ac_cv_have_accrights_in_msghdr="yes" ], + [ ac_cv_have_accrights_in_msghdr="no" ] + ) +@@ -2747,7 +2748,7 @@ fi + + AC_CACHE_CHECK([for msg_control field in struct msghdr], + ac_cv_have_control_in_msghdr, [ +- AC_COMPILE_IFELSE( ++ AC_COMPILE_IFELSE([AC_LANG_SOURCE( + [ + #include + #include +@@ -2761,7 +2762,7 @@ struct msghdr m; + m.msg_control = 0; + exit(0); + } +- ], ++ ])], + [ ac_cv_have_control_in_msghdr="yes" ], + [ ac_cv_have_control_in_msghdr="no" ] + ) +@@ -2891,14 +2892,14 @@ AC_SEARCH_LIBS(getrrsetbyname, resolv, + saved_LIBS="$LIBS" + LIBS="$LIBS -lresolv" + AC_MSG_CHECKING(for res_query in -lresolv) +- AC_LINK_IFELSE([ ++ AC_LINK_IFELSE([AC_LANG_SOURCE([ + #include + int main() + { + res_query (0, 0, 0, 0, 0); + return 0; + } +- ], ++ ])], + [LIBS="$LIBS -lresolv" + AC_MSG_RESULT(yes)], + [LIBS="$saved_LIBS" +@@ -2915,7 +2916,7 @@ int main() + ]) + + AC_MSG_CHECKING(if struct __res_state _res is an extern) +-AC_LINK_IFELSE([ ++AC_LINK_IFELSE([AC_LANG_SOURCE([ + #include + #if HAVE_SYS_TYPES_H + # include +@@ -2925,7 +2926,7 @@ AC_LINK_IFELSE([ + #include + extern struct __res_state _res; + int main() { return 0; } +- ], ++ ])], + [AC_MSG_RESULT(yes) + AC_DEFINE(HAVE__RES_EXTERN, 1, + [Define if you have struct __res_state _res as an extern]) +diff --git a/pam_ssh_agent_auth-0.9.3/get_command_line.c b/pam_ssh_agent_auth-0.9.3/get_command_line.c +new file mode 100644 +index 0000000..e880fee +--- /dev/null ++++ b/pam_ssh_agent_auth-0.9.3/get_command_line.c +@@ -0,0 +1,113 @@ ++/* ++ * Copyright (c) 2014, Jamie Beverly. ++ * 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 Jamie Beverly ``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 Jamie Beverly OR ++ * CONTRIBUTORS 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. ++ * ++ * The views and conclusions contained in the software and documentation are those of the ++ * authors and should not be interpreted as representing official policies, either expressed ++ * or implied, of Jamie Beverly. ++ */ ++ ++#include ++#include ++#include ++ ++#include "includes.h" ++#include "xmalloc.h" ++#include "get_command_line.h" ++ ++#ifdef HAVE_PROC_PID_CMDLINE ++ ++static size_t ++proc_pid_cmdline(char *** inargv) ++{ ++ pid_t pid; ++ FILE *f = NULL; ++ char filename[64] = { 0 }, c = '\0'; ++ char ** argv; ++ char argbuf[MAX_LEN_PER_CMDLINE_ARG + 1] = { 0 }; ++ size_t count = 0, len = 0; ++ ++ pid = getpid(); ++ argv = NULL; ++ ++ snprintf(filename, sizeof(filename), "/proc/%d/cmdline", pid); ++ f = fopen(filename, "r"); ++ ++ if (f) { ++ while (!feof(f) && count < MAX_CMDLINE_ARGS) { ++ if (len > MAX_LEN_PER_CMDLINE_ARG) { ++ while (!feof(f) && (c = fgetc(f)) != '\0'); ++ } ++ else { ++ c = fgetc(f); ++ } ++ switch (c) { ++ case EOF: ++ case '\0': ++ if (len > 0) { ++ argv = xrealloc(argv, count + 1, sizeof(*argv)); ++ argv[count] = xcalloc(len + 1, sizeof(*argv[count])); ++ strncpy(argv[count++], argbuf, len); ++ memset(argbuf, '\0', MAX_LEN_PER_CMDLINE_ARG + 1); ++ len = 0; ++ } ++ break; ++ default: ++ argbuf[len++] = c; ++ break; ++ } ++ } ++ fclose(f); ++ } ++ *inargv = argv; ++ return count; ++} ++#endif ++ ++ ++/* ++ * takes a pointer to an unallocated array of arrays of strings, populates the ++ * given pointer with the address of the allocated array of strings collected ++ */ ++size_t ++pamsshagentauth_get_command_line(char *** argv) ++{ ++#ifdef HAVE_PROC_PID_CMDLINE ++ return proc_pid_cmdline(argv); ++#else ++ /* No other supported implementations at this time */ ++ return 0; ++#endif ++} ++ ++void ++pamsshagentauth_free_command_line(char ** argv, size_t n_args) ++{ ++ size_t i; ++ for (i = 0; i < n_args; i++) ++ free(argv[i]); ++ ++ free(argv); ++ return; ++} ++ +diff --git a/pam_ssh_agent_auth-0.9.3/get_command_line.h b/pam_ssh_agent_auth-0.9.3/get_command_line.h +new file mode 100644 +index 0000000..37cd077 +--- /dev/null ++++ b/pam_ssh_agent_auth-0.9.3/get_command_line.h +@@ -0,0 +1,40 @@ ++/* ++ * Copyright (c) 2014, Jamie Beverly. ++ * 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 Jamie Beverly ``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 Jamie Beverly OR ++ * CONTRIBUTORS 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. ++ * ++ * The views and conclusions contained in the software and documentation are those of the ++ * authors and should not be interpreted as representing official policies, either expressed ++ * or implied, of Jamie Beverly. ++ */ ++ ++#ifndef _GET_COMMAND_LINE_H ++#define _GET_COMMAND_LINE_H ++ ++#include "includes.h" ++ ++size_t pamsshagentauth_get_command_line(char ***); ++void pamsshagentauth_free_command_line(char **, size_t); ++#define MAX_CMDLINE_ARGS 255 ++#define MAX_LEN_PER_CMDLINE_ARG 255 ++ ++#endif +diff --git a/pam_ssh_agent_auth-0.9.3/identity.h b/pam_ssh_agent_auth-0.9.3/identity.h +index eb21320..0bde782 100644 +--- a/pam_ssh_agent_auth-0.9.3/identity.h ++++ b/pam_ssh_agent_auth-0.9.3/identity.h +@@ -1,3 +1,27 @@ ++/* ++ * Copyright (c) 2000 Markus Friedl. 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 _IDENTITY_H + #define _IDENTITY_H + #include "includes.h" +diff --git a/pam_ssh_agent_auth-0.9.3/iterate_ssh_agent_keys.c b/pam_ssh_agent_auth-0.9.3/iterate_ssh_agent_keys.c +index 11ab6e2..6b4d531 100644 +--- a/pam_ssh_agent_auth-0.9.3/iterate_ssh_agent_keys.c ++++ b/pam_ssh_agent_auth-0.9.3/iterate_ssh_agent_keys.c +@@ -28,6 +28,8 @@ + */ + + ++#include ++ + #include "includes.h" + #include "config.h" + +@@ -48,26 +50,75 @@ + #include + #include + #include ++#include "ssh2.h" ++#include "misc.h" + + #include "userauth_pubkey_from_id.h" + #include "identity.h" ++#include "get_command_line.h" ++extern char **environ; ++ ++#define PAM_SSH_AGENT_AUTH_REQUESTv1 101 ++ ++static char * ++log_action(char ** action, size_t count) ++{ ++ size_t i; ++ char *buf = NULL; ++ ++ if (count == 0) ++ return NULL; ++ ++ buf = xcalloc((count * MAX_LEN_PER_CMDLINE_ARG) + (count * 3), sizeof(*buf)); ++ for (i = 0; i < count; i++) { ++ strcat(buf, (i > 0) ? " '" : "'"); ++ strncat(buf, action[i], MAX_LEN_PER_CMDLINE_ARG); ++ strcat(buf, "'"); ++ } ++ return buf; ++} ++ ++void ++agent_action(Buffer *buf, char ** action, size_t count) ++{ ++ size_t i; ++ buffer_init(buf); + +-u_char * session_id2 = NULL; +-uint8_t session_id_len = 0; ++ buffer_put_int(buf, count); ++ ++ for (i = 0; i < count; i++) { ++ buffer_put_cstring(buf, action[i]); ++ } ++} + +-u_char * +-session_id2_gen() ++void ++session_id2_gen(Buffer * session_id2, const char * user, ++ const char * ruser, const char * servicename) + { + char *cookie = NULL; + uint8_t i = 0; + uint32_t rnd = 0; ++ uint8_t cookie_len; ++ char hostname[256] = { 0 }; ++ char pwd[1024] = { 0 }; ++ time_t ts; ++ char ** reported_argv = NULL; ++ size_t count = 0; ++ char * action_logbuf = NULL; ++ Buffer action_agentbuf; ++ uint8_t free_logbuf = 0; ++ char * retc; ++ int32_t reti; + + rnd = arc4random(); +- session_id_len = (uint8_t) rnd; ++ cookie_len = ((uint8_t) rnd); ++ while (cookie_len < 16) { ++ cookie_len += 16; /* Add 16 bytes to the size to ensure that while the length is random, the length is always reasonable; ticket #18 */ ++ } + +- cookie = calloc(1,session_id_len); ++ cookie = xcalloc(1, cookie_len); + +- for (i = 0; i < session_id_len; i++) { ++ for (i = 0; i < cookie_len; i++) { + if (i % 4 == 0) { + rnd = arc4random(); + } +@@ -75,7 +126,64 @@ session_id2_gen() + rnd >>= 8; + } + +- return cookie; ++ count = pamsshagentauth_get_command_line(&reported_argv); ++ if (count > 0) { ++ free_logbuf = 1; ++ action_logbuf = log_action(reported_argv, count); ++ agent_action(&action_agentbuf, reported_argv, count); ++ pamsshagentauth_free_command_line(reported_argv, count); ++ } ++ else { ++ action_logbuf = "unknown on this platform"; ++ buffer_init(&action_agentbuf); /* stays empty, means unavailable */ ++ } ++ ++ /* ++ action = getenv("SUDO_COMMAND"); ++ if(!action) { ++ action = getenv("PAM_AUTHORIZED_ACTION"); ++ if(!action) { ++ action = empty; ++ } ++ } ++ */ ++ ++ reti = gethostname(hostname, sizeof(hostname) - 1); ++ retc = getcwd(pwd, sizeof(pwd) - 1); ++ time(&ts); ++ ++ buffer_init(session_id2); ++ ++ buffer_put_int(session_id2, PAM_SSH_AGENT_AUTH_REQUESTv1); ++ /* debug3("cookie: %s", tohex(cookie, cookie_len)); */ ++ buffer_put_string(session_id2, cookie, cookie_len); ++ /* debug3("user: %s", user); */ ++ buffer_put_cstring(session_id2, user); ++ /* debug3("ruser: %s", ruser); */ ++ buffer_put_cstring(session_id2, ruser); ++ /* debug3("servicename: %s", servicename); */ ++ buffer_put_cstring(session_id2, servicename); ++ /* debug3("pwd: %s", pwd); */ ++ if(retc) ++ buffer_put_cstring(session_id2, pwd); ++ else ++ buffer_put_cstring(session_id2, ""); ++ /* debug3("action: %s", action_logbuf); */ ++ buffer_put_string(session_id2, action_agentbuf.buf + action_agentbuf.offset, action_agentbuf.end - action_agentbuf.offset); ++ if (free_logbuf) { ++ free(action_logbuf); ++ buffer_free(&action_agentbuf); ++ } ++ /* debug3("hostname: %s", hostname); */ ++ if(reti >= 0) ++ buffer_put_cstring(session_id2, hostname); ++ else ++ buffer_put_cstring(session_id2, ""); ++ /* debug3("ts: %ld", ts); */ ++ buffer_put_int64(session_id2, (uint64_t) ts); ++ ++ free(cookie); ++ return; + } + + /* +@@ -174,19 +282,21 @@ ssh_get_authentication_connection_for_uid(uid_t uid) + } + + int +-find_authorized_keys(uid_t uid) ++find_authorized_keys(const char * user, const char * ruser, const char * servicename) + { ++ Buffer session_id2 = { 0 }; + Identity *id; + Key *key; + AuthenticationConnection *ac; + char *comment; + uint8_t retval = 0; ++ uid_t uid = getpwnam(ruser)->pw_uid; + + OpenSSL_add_all_digests(); +- session_id2 = session_id2_gen(); ++ session_id2_gen(&session_id2, user, ruser, servicename); + + if ((ac = ssh_get_authentication_connection_for_uid(uid))) { +- verbose("Contacted ssh-agent of user %s (%u)", getpwuid(uid)->pw_name, uid); ++ verbose("Contacted ssh-agent of user %s (%u)", ruser, uid); + for (key = ssh_get_first_identity(ac, &comment, 2); key != NULL; key = ssh_get_next_identity(ac, &comment, 2)) + { + if(key != NULL) { +@@ -194,7 +304,7 @@ find_authorized_keys(uid_t uid) + id->key = key; + id->filename = comment; + id->ac = ac; +- if(userauth_pubkey_from_id(id)) { ++ if(userauth_pubkey_from_id(ruser, id, &session_id2)) { + retval = 1; + } + free(id->filename); +@@ -204,12 +314,13 @@ find_authorized_keys(uid_t uid) + break; + } + } ++ buffer_free(&session_id2); + ssh_close_authentication_connection(ac); + } + else { + verbose("No ssh-agent could be contacted"); + } +- free(session_id2); ++ /*free(session_id2);*/ + EVP_cleanup(); + return retval; + } +diff --git a/pam_ssh_agent_auth-0.9.3/iterate_ssh_agent_keys.h b/pam_ssh_agent_auth-0.9.3/iterate_ssh_agent_keys.h +index ed7549e..e6c75aa 100644 +--- a/pam_ssh_agent_auth-0.9.3/iterate_ssh_agent_keys.h ++++ b/pam_ssh_agent_auth-0.9.3/iterate_ssh_agent_keys.h +@@ -31,6 +31,6 @@ + #ifndef _ITERATE_SSH_AGENT_KEYS_H + #define _ITERATE_SSH_AGENT_KEYS_H + +-int find_authorized_keys(uid_t); ++int find_authorized_keys(const char * user, const char * ruser, const char * servicename); + + #endif +diff --git a/pam_ssh_agent_auth-0.9.3/pam_ssh_agent_auth.c b/pam_ssh_agent_auth-0.9.3/pam_ssh_agent_auth.c +index d3f4325..37309f7 100644 +--- a/pam_ssh_agent_auth-0.9.3/pam_ssh_agent_auth.c ++++ b/pam_ssh_agent_auth-0.9.3/pam_ssh_agent_auth.c +@@ -59,9 +59,12 @@ + #include "pam_user_authorized_keys.h" + + #define strncasecmp_literal(A,B) strncasecmp( A, B, sizeof(B) - 1) ++#define UNUSED(expr) do { (void)(expr); } while (0) + + char *authorized_keys_file = NULL; + uint8_t allow_user_owned_authorized_keys_file = 0; ++char *authorized_keys_command = NULL; ++char *authorized_keys_command_user = NULL; + + #if ! HAVE___PROGNAME || HAVE_BUNDLE + char *__progname; +@@ -90,6 +93,7 @@ pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char **argv) + facility = SYSLOG_FACILITY_AUTHPRIV; + #endif + ++ UNUSED(flags); + pam_get_item(pamh, PAM_SERVICE, (void *) &servicename); + /* + * XXX: +@@ -113,6 +117,12 @@ pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char **argv) + if(strncasecmp_literal(*argv_ptr, "file=") == 0 ) { + authorized_keys_file_input = *argv_ptr + sizeof("file=") - 1; + } ++ if(strncasecmp_literal(*argv_ptr, "authorized_keys_command=") == 0 ) { ++ authorized_keys_command = *argv_ptr + sizeof("authorized_keys_command=") - 1; ++ } ++ if(strncasecmp_literal(*argv_ptr, "authorized_keys_command_user=") == 0 ) { ++ authorized_keys_command_user = *argv_ptr + sizeof("authorized_keys_command_user=") - 1; ++ } + #ifdef ENABLE_SUDO_HACK + if(strncasecmp_literal(*argv_ptr, "sudo_service_name=") == 0) { + strncpy( sudo_service_name, *argv_ptr + sizeof("sudo_service_name=") - 1, sizeof(sudo_service_name) - 1); +@@ -182,7 +192,7 @@ pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char **argv) + /* + * this pw_uid is used to validate the SSH_AUTH_SOCK, and so must be the uid of the ruser invoking the program, not the target-user + */ +- if(find_authorized_keys(getpwnam(ruser)->pw_uid)) { ++ if(find_authorized_keys(user, ruser, servicename)) { /* getpwnam(ruser)->pw_uid)) { */ + logit("Authenticated: `%s' as `%s' using %s", ruser, user, authorized_keys_file); + retval = PAM_SUCCESS; + } else { +@@ -207,6 +217,10 @@ cleanexit: + PAM_EXTERN int __attribute__ ((visibility ("default"))) + pam_sm_setcred(pam_handle_t * pamh, int flags, int argc, const char **argv) + { ++ UNUSED(pamh); ++ UNUSED(flags); ++ UNUSED(argc); ++ UNUSED(argv); + return PAM_SUCCESS; + } + +diff --git a/pam_ssh_agent_auth-0.9.3/pam_ssh_agent_auth.pod b/pam_ssh_agent_auth-0.9.3/pam_ssh_agent_auth.pod +index 4570746..76b1f0f 100644 +--- a/pam_ssh_agent_auth-0.9.3/pam_ssh_agent_auth.pod ++++ b/pam_ssh_agent_auth-0.9.3/pam_ssh_agent_auth.pod +@@ -1,8 +1,12 @@ +-=head1 PAM_SSH_AGENT_AUTH ++=head1 NAME ++ ++pam_ssh_agent_auth - PAM module for granting permissions based on SSH agent requests ++ ++=head1 DESCRIPTION + + This module provides authentication via ssh-agent. If an ssh-agent listening at SSH_AUTH_SOCK can successfully authenticate that it has the secret key for a public key in the specified file, authentication is granted, otherwise authentication fails. + +-=head1 SUMMARY ++=head1 CONFIGURATION + + =over + +@@ -10,7 +14,8 @@ This module provides authentication via ssh-agent. If an ssh-agent listening at + auth sufficient pam_ssh_agent_auth.so file=/etc/security/authorized_keys + + =item /etc/sudoers: +- ++ ++In older versions of sudo (< 1.8.5) it was necessary to set: + Defaults env_keep += "SSH_AUTH_SOCK" + + =back +@@ -33,6 +38,15 @@ Specify the path to the authorized_keys file(s) you would like to use for authen + A flag which enables authorized_keys files to be owned by the invoking user, instead of root. This flag is enabled automatically whenever + the expansions %h or ~ are used. + ++=item authorized_keys_command= ++ ++Specify an external command to run, which should take a single argument, the username of the person being authenticated, and emit to its stdout a file in authorized_keys format. ++This is ideally suited for use with sssd's sss_ssh_authorizedkeys, for authenticating users via authorized_keys stored in ldap or other sssd supported security service. ++ ++=item authorized_keys_command_user= ++ ++Specify a user to run the authorized_keys_command as. If this option is not specified, the authorized_keys_command will be run as the user being authenticated. ++ + =item debug + + A flag which enables verbose logging +@@ -105,4 +119,34 @@ so this file must be owned by root. + + =back + ++=head1 COPYRIGHT ++ ++ Copyright (c) 2008-2014, Jamie Beverly. ++ And is based on openssh, and the included works by Markus Friedl, Darren Tucker, ++ Todd C. Miller, Ben Lindstrom, Tim Rice, Damien Miller, and many others. ++ ++ All rights reserved. ++ ++ See sources for complete attributions. ++ ++ 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 Jamie Beverly ``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 Jamie Beverly OR ++ CONTRIBUTORS 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. ++ + =cut +diff --git a/pam_ssh_agent_auth-0.9.3/pam_static_macros.h b/pam_ssh_agent_auth-0.9.3/pam_static_macros.h +index a4938d3..a991704 100644 +--- a/pam_ssh_agent_auth-0.9.3/pam_static_macros.h ++++ b/pam_ssh_agent_auth-0.9.3/pam_static_macros.h +@@ -1,3 +1,32 @@ ++/* ++ * Copyright (c) 2008, Jamie Beverly. ++ * 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 Jamie Beverly ``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 Jamie Beverly OR ++ * CONTRIBUTORS 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. ++ * ++ * The views and conclusions contained in the software and documentation are those of the ++ * authors and should not be interpreted as representing official policies, either expressed ++ * or implied, of Jamie Beverly. ++ */ ++ + #ifndef __PAM_STATIC_MACROS_H + #define __PAM_STATIC_MACROS_H + +diff --git a/pam_ssh_agent_auth-0.9.3/pam_user_authorized_keys.c b/pam_ssh_agent_auth-0.9.3/pam_user_authorized_keys.c +index 60bef68..abc0a62 100644 +--- a/pam_ssh_agent_auth-0.9.3/pam_user_authorized_keys.c ++++ b/pam_ssh_agent_auth-0.9.3/pam_user_authorized_keys.c +@@ -1,4 +1,4 @@ +-/* ++/* + * Copyright (c) 2008, Jamie Beverly. + * All rights reserved. + * +@@ -80,9 +80,15 @@ + #include "identity.h" + #include "pam_user_key_allowed2.h" + +-extern char *authorized_keys_file; +-extern uint8_t allow_user_owned_authorized_keys_file; +-uid_t authorized_keys_file_allowed_owner_uid; ++extern char *authorized_keys_file; ++ ++extern char *authorized_keys_command; ++ ++extern char *authorized_keys_command_user; ++ ++extern uint8_t allow_user_owned_authorized_keys_file; ++ ++uid_t authorized_keys_file_allowed_owner_uid; + + void + parse_authorized_key_file(const char *user, const char *authorized_keys_file_input) +@@ -137,8 +143,11 @@ parse_authorized_key_file(const char *user, const char *authorized_keys_file_inp + } + + int +-pam_user_key_allowed(Key * key) ++pam_user_key_allowed(const char *ruser, Key * key) + { + return pam_user_key_allowed2(getpwuid(authorized_keys_file_allowed_owner_uid), key, authorized_keys_file) +- || pam_user_key_allowed2(getpwuid(0), key, authorized_keys_file); ++ || pam_user_key_allowed2(getpwuid(0), key, authorized_keys_file) ++ || pam_user_key_command_allowed2(authorized_keys_command, ++ authorized_keys_command_user, ++ getpwnam(ruser), key); + } +diff --git a/pam_ssh_agent_auth-0.9.3/pam_user_authorized_keys.h b/pam_ssh_agent_auth-0.9.3/pam_user_authorized_keys.h +index ae9a4b8..a871bf0 100644 +--- a/pam_ssh_agent_auth-0.9.3/pam_user_authorized_keys.h ++++ b/pam_ssh_agent_auth-0.9.3/pam_user_authorized_keys.h +@@ -32,7 +32,7 @@ + #define _PAM_USER_KEY_ALLOWED_H + + #include "identity.h" +-int pam_user_key_allowed(Key *); ++int pam_user_key_allowed(const char *, Key *); + void parse_authorized_key_file(const char *, const char *); + + #endif +diff --git a/pam_ssh_agent_auth-0.9.3/pam_user_key_allowed2.c b/pam_ssh_agent_auth-0.9.3/pam_user_key_allowed2.c +index c6680e4..4aceecb 100644 +--- a/pam_ssh_agent_auth-0.9.3/pam_user_key_allowed2.c ++++ b/pam_ssh_agent_auth-0.9.3/pam_user_key_allowed2.c +@@ -1,4 +1,4 @@ +-/* ++/* + * Copyright (c) 2000 Markus Friedl. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without +@@ -33,9 +33,14 @@ + + #include + #include ++#include ++#include + + #include + #include ++#include ++#include ++#include + + #include "xmalloc.h" + #include "ssh.h" +@@ -48,87 +53,263 @@ + #include "pathnames.h" + #include "misc.h" + #include "secure_filename.h" ++#include "uidswap.h" ++#include + + #include "identity.h" + + /* return 1 if user allows given key */ + /* Modified slightly from original found in auth2-pubkey.c */ ++static int ++pamsshagentauth_check_authkeys_file(FILE * f, char *file, Key * key) ++{ ++ char line[SSH_MAX_PUBKEY_BYTES]; ++ int found_key = 0; ++ u_long linenum = 0; ++ Key *found; ++ char *fp; ++ ++ found_key = 0; ++ found = key_new(key->type); ++ ++ while(read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) { ++ char *cp = NULL; /* *key_options = NULL; */ ++ ++ /* Skip leading whitespace, empty and comment lines. */ ++ for(cp = line; *cp == ' ' || *cp == '\t'; cp++); ++ if(!*cp || *cp == '\n' || *cp == '#') ++ continue; ++ ++ if(key_read(found, &cp) != 1) { ++ /* no key? check if there are options for this key */ ++ int quoted = 0; ++ ++ verbose("user_key_allowed: check options: '%s'", cp); ++ /* key_options = cp; */ ++ for(; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { ++ if(*cp == '\\' && cp[1] == '"') ++ cp++; /* Skip both */ ++ else if(*cp == '"') ++ quoted = !quoted; ++ } ++ /* Skip remaining whitespace. */ ++ for(; *cp == ' ' || *cp == '\t'; cp++); ++ if(key_read(found, &cp) != 1) { ++ verbose("user_key_allowed: advance: '%s'", cp); ++ /* still no key? advance to next line */ ++ continue; ++ } ++ } ++ if(key_equal(found, key)) { ++ found_key = 1; ++ logit("matching key found: file/command %s, line %lu", file, ++ linenum); ++ fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); ++ logit("Found matching %s key: %s", ++ key_type(found), fp); ++ free(fp); ++ break; ++ } ++ } ++ key_free(found); ++ if(!found_key) ++ verbose("key not found"); ++ return found_key; ++} ++ ++/* ++ * Checks whether key is allowed in file. ++ * returns 1 if the key is allowed or 0 otherwise. ++ */ + int + pam_user_key_allowed2(struct passwd *pw, Key *key, char *file) + { +- char line[SSH_MAX_PUBKEY_BYTES]; +- int found_key = 0; +- FILE *f; +- u_long linenum = 0; +- struct stat st; +- Key *found; +- char *fp; +- +- verbose("trying public key file %s", file); +- +- /* Fail not so quietly if file does not exist */ +- if (stat(file, &st) < 0) { ++ FILE *f; ++ int found_key = 0; ++ struct stat st; ++ char buf[SSH_MAX_PUBKEY_BYTES]; ++ ++ /* Temporarily use the user's uid. */ ++ verbose("trying public key file %s", file); ++ ++ /* Fail not so quietly if file does not exist */ ++ if(stat(file, &st) < 0) { + verbose("File not found: %s", file); +- return 0; +- } +- /* Open the file containing the authorized keys. */ +- f = fopen(file, "r"); +- if (!f) { +- return 0; +- } +- if ( +- secure_filename(f, file, pw, line, sizeof(line)) != 0) { +- fclose(f); +- logit("Authentication refused: %s", line); +- return 0; +- } +- +- found_key = 0; +- found = key_new(key->type); +- +- while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) { +- char *cp, *key_options = NULL; +- +- /* Skip leading whitespace, empty and comment lines. */ +- for (cp = line; *cp == ' ' || *cp == '\t'; cp++) +- ; +- if (!*cp || *cp == '\n' || *cp == '#') +- continue; +- +- if (key_read(found, &cp) != 1) { +- /* no key? check if there are options for this key */ +- int quoted = 0; +- verbose("user_key_allowed: check options: '%s'", cp); +- key_options = cp; +- for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { +- if (*cp == '\\' && cp[1] == '"') +- cp++; /* Skip both */ +- else if (*cp == '"') +- quoted = !quoted; +- } +- /* Skip remaining whitespace. */ +- for (; *cp == ' ' || *cp == '\t'; cp++) +- ; +- if (key_read(found, &cp) != 1) { +- verbose("user_key_allowed: advance: '%s'", cp); +- /* still no key? advance to next line*/ +- continue; +- } +- } +- if (key_equal(found, key)) { +- found_key = 1; +- logit("matching key found: file %s, line %lu", +- file, linenum); +- fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); +- logit("Found matching %s key: %s", +- key_type(found), fp); +- free(fp); +- break; +- } +- } +- fclose(f); +- key_free(found); +- if (!found_key) +- verbose("key not found"); +- return found_key; ++ return 0; ++ } ++ ++ /* Open the file containing the authorized keys. */ ++ f = fopen(file, "r"); ++ if(!f) { ++ return 0; ++ } ++ ++ if(secure_filename(f, file, pw, buf, sizeof(buf)) != 0) { ++ fclose(f); ++ logit("Authentication refused: %s", buf); ++ return 0; ++ } ++ ++ found_key = pamsshagentauth_check_authkeys_file(f, file, key); ++ fclose(f); ++ return found_key; ++} ++ ++/* ++ * Checks whether key is allowed in output of command. ++ * returns 1 if the key is allowed or 0 otherwise. ++ */ ++int ++pam_user_key_command_allowed2(char *authorized_keys_command, ++ char *authorized_keys_command_user, ++ struct passwd *user_pw, Key * key) ++{ ++ FILE *f; ++ int ok, found_key = 0; ++ struct passwd *pw; ++ struct stat st; ++ int status, devnull, p[2], i; ++ pid_t pid; ++ char errmsg[512]; ++ char username[512] = { 0 }; ++ ++ ++ ++ if(authorized_keys_command == NULL || authorized_keys_command[0] != '/') ++ return 0; ++ ++ ++ /* getpwnam of authorized_keys_command_user will overwrite the statics used by getpwnam (including pw_name) */ ++ strncpy(username, user_pw->pw_name, sizeof(username) - 1); ++ ++ /* If no user specified to run commands the default to target user */ ++ if(authorized_keys_command_user == NULL) { ++ pw = user_pw; ++ } ++ else { ++ pw = getpwnam(authorized_keys_command_user); ++ if(pw == NULL) { ++ error("authorized_keys_command_user \"%s\" not found: %s", ++ authorized_keys_command_user, strerror(errno)); ++ return 0; ++ } ++ } ++ ++ temporarily_use_uid(pw); ++ ++ if(stat(authorized_keys_command, &st) < 0) { ++ error ++ ("Could not stat AuthorizedKeysCommand \"%s\": %s", ++ authorized_keys_command, strerror(errno)); ++ goto out; ++ } ++ if(pamsshagentauth_auth_secure_path ++ (authorized_keys_command, &st, NULL, 0, errmsg, sizeof(errmsg)) != 0) { ++ error("Unsafe AuthorizedKeysCommand: %s", errmsg); ++ goto out; ++ } ++ ++ /* open the pipe and read the keys */ ++ if(pipe(p) != 0) { ++ error("%s: pipe: %s", __func__, strerror(errno)); ++ goto out; ++ } ++ ++ debug("Running AuthorizedKeysCommand: \"%s\" as \"%s\" with argument: \"%s\"", ++ authorized_keys_command, pw->pw_name, username); ++ ++ /* ++ * Don't want to call this in the child, where it can fatal() and ++ * run cleanup_exit() code. ++ */ ++ restore_uid(); ++ ++ switch ((pid = fork())) { ++ case -1: /* error */ ++ error("%s: fork: %s", __func__, strerror(errno)); ++ close(p[0]); ++ close(p[1]); ++ return 0; ++ case 0: /* child */ ++ for(i = 0; i < NSIG; i++) ++ signal(i, SIG_DFL); ++ ++ /* do this before the setresuid so thta they can be logged */ ++ if((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) { ++ error("%s: open %s: %s", __func__, _PATH_DEVNULL, ++ strerror(errno)); ++ _exit(1); ++ } ++ if(dup2(devnull, STDIN_FILENO) == -1 || dup2(p[1], STDOUT_FILENO) == -1 ++ || dup2(devnull, STDERR_FILENO) == -1) { ++ error("%s: dup2: %s", __func__, strerror(errno)); ++ _exit(1); ++ } ++#if defined(HAVE_SETRESGID) && !defined(BROKEN_SETRESGID) ++ if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) { ++#else ++ if (setgid(pw->pw_gid) != 0 || setegid(pw->pw_gid) != 0) { ++#endif ++ error("setresgid %u: %s", (u_int) pw->pw_gid, ++ strerror(errno)); ++ _exit(1); ++ } ++ ++#ifdef HAVE_SETRESUID ++ if(setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) { ++#else ++ if (setuid(pw->pw_uid) != 0 || seteuid(pw->pw_uid) != 0) { ++#endif ++ error("setresuid %u: %s", (u_int) pw->pw_uid, ++ strerror(errno)); ++ _exit(1); ++ } ++ ++ close(p[0]); ++ closefrom(STDERR_FILENO + 1); ++ ++ execl(authorized_keys_command, authorized_keys_command, username, (char *)NULL); ++ ++ /* pretty sure this will barf because we are now suid, but since we ++ should't reach this anyway, I'll leave it here */ ++ error("AuthorizedKeysCommand %s exec failed: %s", ++ authorized_keys_command, strerror(errno)); ++ _exit(127); ++ default: /* parent */ ++ break; ++ } ++ ++ temporarily_use_uid(pw); ++ ++ close(p[1]); ++ if((f = fdopen(p[0], "r")) == NULL) { ++ error("%s: fdopen: %s", __func__, strerror(errno)); ++ close(p[0]); ++ /* Don't leave zombie child */ ++ while(waitpid(pid, NULL, 0) == -1 && errno == EINTR); ++ goto out; ++ } ++ ok = pamsshagentauth_check_authkeys_file(f, authorized_keys_command, key); ++ fclose(f); ++ ++ while(waitpid(pid, &status, 0) == -1) { ++ if(errno != EINTR) { ++ error("%s: waitpid: %s", __func__, ++ strerror(errno)); ++ goto out; ++ } ++ } ++ if(WIFSIGNALED(status)) { ++ error("AuthorizedKeysCommand %s exited on signal %d", ++ authorized_keys_command, WTERMSIG(status)); ++ goto out; ++ } else if(WEXITSTATUS(status) != 0) { ++ error("AuthorizedKeysCommand %s returned status %d", ++ authorized_keys_command, WEXITSTATUS(status)); ++ goto out; ++ } ++ found_key = ok; ++ out: ++ restore_uid(); ++ return found_key; + } +diff --git a/pam_ssh_agent_auth-0.9.3/pam_user_key_allowed2.h b/pam_ssh_agent_auth-0.9.3/pam_user_key_allowed2.h +index 416d055..24533a0 100644 +--- a/pam_ssh_agent_auth-0.9.3/pam_user_key_allowed2.h ++++ b/pam_ssh_agent_auth-0.9.3/pam_user_key_allowed2.h +@@ -32,5 +32,6 @@ + + #include "identity.h" + int pam_user_key_allowed2(struct passwd *, Key *, char *); ++int pam_user_key_command_allowed2(char *, char *, struct passwd *, Key *); + + #endif +diff --git a/pam_ssh_agent_auth-0.9.3/secure_filename.c b/pam_ssh_agent_auth-0.9.3/secure_filename.c +index c24cab2..d685599 100644 +--- a/pam_ssh_agent_auth-0.9.3/secure_filename.c ++++ b/pam_ssh_agent_auth-0.9.3/secure_filename.c +@@ -71,29 +71,38 @@ + * Returns 0 on success and -1 on failure + */ + int +-secure_filename(FILE *f, const char *file, struct passwd *pw, +- char *err, size_t errlen) ++pamsshagentauth_auth_secure_path(const char *name, struct stat *stp, ++ const char *pw_dir, uid_t uid, char *err, size_t errlen) + { +- uid_t uid = pw->pw_uid; + char buf[MAXPATHLEN], homedir[MAXPATHLEN]; + char *cp; + int comparehome = 0; + struct stat st; + +- verbose("secure_filename: checking for uid: %u", uid); ++ verbose("auth_secure_filename: checking for uid: %u", uid); + +- if (realpath(file, buf) == NULL) { +- snprintf(err, errlen, "realpath %s failed: %s", file, ++ /* if (realpath(pw->pw_dir, homedir) != NULL) */ ++ if (realpath(name, buf) == NULL) { ++ snprintf(err, errlen, "realpath %s failed: %s", name, + strerror(errno)); + return -1; + } +- if (realpath(pw->pw_dir, homedir) != NULL) ++ if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL) + comparehome = 1; + + /* check the open file to avoid races */ +- if (fstat(fileno(f), &st) < 0 || +- (st.st_uid != 0 && st.st_uid != uid) || +- (st.st_mode & 022) != 0) { ++ /* ++ * if (fstat(fileno(f), &st) < 0 || ++ * (st.st_uid != 0 && st.st_uid != uid) || ++ * (st.st_mode & 022) != 0) { ++ */ ++ if (!S_ISREG(stp->st_mode)) { ++ snprintf(err, errlen, "%s is not a regular file", buf); ++ return -1; ++ } ++ ++ if ((stp->st_uid != 0 && stp->st_uid != uid) || ++ (stp->st_mode & 022) != 0) { + snprintf(err, errlen, "bad ownership or modes for file %s", + buf); + return -1; +@@ -132,3 +141,25 @@ secure_filename(FILE *f, const char *file, struct passwd *pw, + return 0; + } + ++/* ++ * Version of secure_path() that accepts an open file descriptor to ++ * avoid races. ++ * ++ * Returns 0 on success and -1 on failure ++ */ ++int ++secure_filename(FILE *f, const char *file, struct passwd *pw, ++ char *err, size_t errlen) ++{ ++ struct stat st; ++ char buf[MAXPATHLEN] = { 0 }; ++ ++ /* check the open file to avoid races */ ++ if (fstat(fileno(f), &st) < 0) { ++ snprintf(err, errlen, "cannot stat file %s: %s", ++ buf, strerror(errno)); ++ return -1; ++ } ++ return pamsshagentauth_auth_secure_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen); ++} ++ +diff --git a/pam_ssh_agent_auth-0.9.3/secure_filename.h b/pam_ssh_agent_auth-0.9.3/secure_filename.h +index 198c13d..4c1a208 100644 +--- a/pam_ssh_agent_auth-0.9.3/secure_filename.h ++++ b/pam_ssh_agent_auth-0.9.3/secure_filename.h +@@ -28,5 +28,7 @@ + #define _SECURE_FILENAME_H + #include + #include ++struct stat; + int secure_filename(FILE *, const char *, struct passwd *, char *, size_t); ++int pamsshagentauth_auth_secure_path(const char *, struct stat *, const char *, uid_t, char *, size_t); + #endif +diff --git a/pam_ssh_agent_auth-0.9.3/userauth_pubkey_from_id.c b/pam_ssh_agent_auth-0.9.3/userauth_pubkey_from_id.c +index 163278b..31849f8 100644 +--- a/pam_ssh_agent_auth-0.9.3/userauth_pubkey_from_id.c ++++ b/pam_ssh_agent_auth-0.9.3/userauth_pubkey_from_id.c +@@ -48,11 +48,14 @@ + #include "identity.h" + #include "pam_user_authorized_keys.h" + +-extern u_char *session_id2; ++#define SSH2_MSG_USERAUTH_TRUST_REQUEST 54 ++ ++/* extern u_char *session_id2; + extern uint8_t session_id_len; ++ */ + + int +-userauth_pubkey_from_id(Identity * id) ++userauth_pubkey_from_id(const char *ruser, Identity * id, Buffer * session_id2) + { + Buffer b = { 0 }; + char *pkalg = NULL; +@@ -63,7 +66,7 @@ userauth_pubkey_from_id(Identity * id) + pkalg = (char *) key_ssh_name(id->key); + + /* first test if this key is even allowed */ +- if(! pam_user_key_allowed(id->key)) ++ if(! pam_user_key_allowed(ruser, id->key)) + goto user_auth_clean_exit; + + if(key_to_blob(id->key, &pkblob, &blen) == 0) +@@ -72,10 +75,10 @@ userauth_pubkey_from_id(Identity * id) + /* construct packet to sign and test */ + buffer_init(&b); + +- buffer_put_string(&b, session_id2, session_id_len); +- buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); +- buffer_put_cstring(&b, "root"); +- buffer_put_cstring(&b, "ssh-userauth"); ++ buffer_put_string(&b, session_id2->buf + session_id2->offset, session_id2->end - session_id2->offset); ++ buffer_put_char(&b, SSH2_MSG_USERAUTH_TRUST_REQUEST); ++ buffer_put_cstring(&b, ruser); ++ buffer_put_cstring(&b, "pam_ssh_agent_auth"); + buffer_put_cstring(&b, "publickey"); + buffer_put_char(&b, 1); + buffer_put_cstring(&b, pkalg); +@@ -89,8 +92,7 @@ userauth_pubkey_from_id(Identity * id) + authenticated = 1; + + user_auth_clean_exit: +- if(&b != NULL) +- buffer_free(&b); ++ buffer_free(&b); + if(sig != NULL) + free(sig); + if(pkblob != NULL) +diff --git a/pam_ssh_agent_auth-0.9.3/userauth_pubkey_from_id.h b/pam_ssh_agent_auth-0.9.3/userauth_pubkey_from_id.h +index 1e14231..7758808 100644 +--- a/pam_ssh_agent_auth-0.9.3/userauth_pubkey_from_id.h ++++ b/pam_ssh_agent_auth-0.9.3/userauth_pubkey_from_id.h +@@ -32,6 +32,6 @@ + #define _USERAUTH_PUBKEY_FROM_ID_H + + #include +-int userauth_pubkey_from_id(Identity *); ++int userauth_pubkey_from_id(const char *, Identity *, Buffer *); + + #endif +-- +2.5.0 + +--- openssh-6.6p1/pam_ssh_agent_auth-0.9.3/pam_user_authorized_keys.c.psaa-command 2016-04-20 09:31:32.164686370 +0200 ++++ openssh-6.6p1/pam_ssh_agent_auth-0.9.3/pam_user_authorized_keys.c 2016-04-20 09:35:49.778344576 +0200 +@@ -145,8 +145,12 @@ + int + pam_user_key_allowed(const char *ruser, Key * key) + { +- return pam_user_key_allowed2(getpwuid(authorized_keys_file_allowed_owner_uid), key, authorized_keys_file) +- || pam_user_key_allowed2(getpwuid(0), key, authorized_keys_file) ++ struct passwd *pw; ++ return ++ ((pw = getpwuid(authorized_keys_file_allowed_owner_uid)) && ++ pam_user_key_allowed2(pw, key, authorized_keys_file)) ++ || ((pw = getpwuid(0)) && ++ pam_user_key_allowed2(pw, key, authorized_keys_file)) + || pam_user_key_command_allowed2(authorized_keys_command, + authorized_keys_command_user, + getpwnam(ruser), key); diff --git a/SOURCES/sshd-keygen.service b/SOURCES/sshd-keygen.service index a27d4f6..77cffeb 100644 --- a/SOURCES/sshd-keygen.service +++ b/SOURCES/sshd-keygen.service @@ -1,8 +1,8 @@ [Unit] Description=OpenSSH Server Key Generation -ConditionPathExists=|!/etc/ssh/ssh_host_rsa_key -ConditionPathExists=|!/etc/ssh/ssh_host_ecdsa_key -ConditionPathExists=|!/etc/ssh/ssh_host_ed25519_key +ConditionFileNotEmpty=|!/etc/ssh/ssh_host_rsa_key +ConditionFileNotEmpty=|!/etc/ssh/ssh_host_ecdsa_key +ConditionFileNotEmpty=|!/etc/ssh/ssh_host_ed25519_key PartOf=sshd.service sshd.socket [Service] diff --git a/SOURCES/sshd.service b/SOURCES/sshd.service index eb87d32..089d4a7 100644 --- a/SOURCES/sshd.service +++ b/SOURCES/sshd.service @@ -5,8 +5,10 @@ After=network.target sshd-keygen.service Wants=sshd-keygen.service [Service] +Type=forking +PIDFile=/var/run/sshd.pid EnvironmentFile=/etc/sysconfig/sshd -ExecStart=/usr/sbin/sshd -D $OPTIONS +ExecStart=/usr/sbin/sshd $OPTIONS ExecReload=/bin/kill -HUP $MAINPID KillMode=process Restart=on-failure diff --git a/SPECS/openssh.spec b/SPECS/openssh.spec index d13eff8..3eaee3a 100644 --- a/SPECS/openssh.spec +++ b/SPECS/openssh.spec @@ -64,7 +64,7 @@ # Do not forget to bump pam_ssh_agent_auth release if you rewind the main package release to 1 %define openssh_ver 6.6.1p1 -%define openssh_rel 25 +%define openssh_rel 31 %define pam_ssh_agent_ver 0.9.3 %define pam_ssh_agent_rel 9 @@ -96,9 +96,6 @@ Patch0: openssh-5.9p1-wIm.patch Patch100: openssh-6.6.1p1-coverity.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1872 Patch101: openssh-6.6p1-fingerprint.patch -#https://bugzilla.mindrot.org/show_bug.cgi?id=1894 -#https://bugzilla.redhat.com/show_bug.cgi?id=735889 -Patch102: openssh-5.8p1-getaddrinfo.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1889 Patch103: openssh-5.8p1-packet.patch @@ -107,6 +104,8 @@ Patch200: openssh-6.6p1-audit.patch # https://bugzilla.redhat.com/show_bug.cgi?id=1171248 # record pfs= field in CRYPTO_SESSION audit event Patch201: openssh-6.6.1p1-audit-pfs.patch +# Do not write to one socket from more processes (#1310684) +Patch202: openssh-6.6p1-audit-race-condition.patch # --- pam_ssh-agent --- # make it build reusing the openssh sources @@ -117,6 +116,9 @@ Patch301: pam_ssh_agent_auth-0.9.2-seteuid.patch Patch302: pam_ssh_agent_auth-0.9.2-visibility.patch # don't use xfree (#1024965) Patch303: pam_ssh_agent_auth-0.9.3-no-xfree.patch +# don't use xfree (#1024965) +Patch304: pam_ssh_agent_auth-0.9.3-command.patch + #https://bugzilla.mindrot.org/show_bug.cgi?id=1641 (WONTFIX) Patch400: openssh-6.6p1-role-mls.patch #https://bugzilla.redhat.com/show_bug.cgi?id=781634 @@ -129,8 +131,6 @@ Patch502: openssh-6.6p1-keycat.patch #http6://bugzilla.mindrot.org/show_bug.cgi?id=1644 Patch601: openssh-6.6p1-allow-ip-opts.patch -#http://cvsweb.netbsd.org/cgi-bin/cvsweb.cgi/src/crypto/dist/ssh/Attic/sftp-glob.c.diff?r1=1.13&r2=1.13.12.1&f=h -Patch603: openssh-5.8p1-glob.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1893 Patch604: openssh-6.6p1-keyperm.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1925 @@ -153,8 +153,6 @@ Patch703: openssh-4.3p2-askpass-grab-info.patch # https://bugzilla.redhat.com/show_bug.cgi?id=205842 # drop? Patch704: openssh-5.9p1-edns.patch #? -Patch705: openssh-5.1p1-scp-manpage.patch -#? Patch706: openssh-6.6.1p1-localdomain.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1635 (WONTFIX) Patch707: openssh-6.6p1-redhat.patch @@ -178,6 +176,8 @@ Patch801: openssh-6.6p1-force_krb.patch # add new option GSSAPIEnablek5users and disable using ~/.k5users by default (#1169843) # CVE-2014-9278 Patch802: openssh-6.6p1-GSSAPIEnablek5users.patch +# Respect k5login_directory option in krk5.conf (#1328243) +Patch803: openssh-6.6p1-k5login_directory.patch Patch900: openssh-6.1p1-gssapi-canohost.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1780 Patch901: openssh-6.6p1-kuserok.patch @@ -250,6 +250,24 @@ Patch930: openssh-6.6p1-disable-roaming.patch Patch931: openssh-6.6p1-CVE-2016-3115.patch # CVE-2016-1908: possible fallback from untrusted X11 forwarding (#1298741) Patch932: openssh-6.6p1-fallback-X11-untrusted.patch +# CVE-2015-8325: privilege escalation via user's PAM environment and UseLogin=yes (#1328012) +Patch933: openssh-6.6p1-CVE-2015-8325.patch +# close ControlPersist background process stderr when not in debug mode (#1335540) +Patch934: openssh-6.6p1-ControlPersist-stderr.patch +# make s390 use /dev/ crypto devices -- ignore closefrom (#1318760) +Patch935: openssh-6.6p1-s390-closefrom.patch +# Default value and proper dump of AuthenticationMethods (#1237129) +Patch936: openssh-6.6p1-AuthenticationMethods.patch +# ssh-copy-id does not work with LogLevel=quiet (#1349556) +Patch937: openssh-6.6p1-ssh-copy-id-quiet.patch +# expose more information to PAM (#1312304) +Patch938: openssh-6.6p1-expose-auth-information.patch +# Move MAX_DISPLAYS to a configuration option (#1341302) +Patch939: openssh-6.6p1-x11-max-displays.patch +# Add a wildcard option to PermitOpen directive (#1344106) +Patch940: openssh-6.6p1-permitopen-any-host.patch +# Rework capabilities handling for SELinux confined users (#1357859) +Patch941: openssh-6.6p1-chroot-capabilities.patch License: BSD @@ -287,10 +305,12 @@ BuildRequires: libedit-devel ncurses-devel %endif %if %{WITH_SELINUX} +Conflicts: selinux-policy < 3.13.1-92 Requires: libselinux >= 1.27.7 BuildRequires: libselinux-devel >= 1.27.7 Requires: audit-libs >= 1.0.8 BuildRequires: audit-libs >= 1.0.8 +BuildRequires: libcap-ng-devel %endif BuildRequires: xauth @@ -407,7 +427,6 @@ The module is most useful for su and sudo service stacks. %endif %patch101 -p1 -b .fingerprint -# investigate %patch102 -p1 -b .getaddrinfo %patch103 -p1 -b .packet %if %{pam_ssh_agent} @@ -416,6 +435,7 @@ pushd pam_ssh_agent_auth-%{pam_ssh_agent_ver} %patch301 -p1 -b .psaa-seteuid %patch302 -p1 -b .psaa-visibility %patch303 -p1 -b .psaa-xfree +%patch304 -p2 -b .psaa-command # Remove duplicate headers rm -f $(cat %{SOURCE5}) popd @@ -432,7 +452,6 @@ popd %patch502 -p1 -b .keycat %patch601 -p1 -b .ip-opts -%patch603 -p1 -b .glob %patch604 -p1 -b .keyperm %patch606 -p1 -b .ipv6man %patch607 -p1 -b .sigpipe @@ -444,7 +463,6 @@ popd %patch703 -p1 -b .grab-info # investigate - https://bugzilla.redhat.com/show_bug.cgi?id=205842 # probably not needed anymore %patch704 -p1 -b .edns -# drop it %patch705 -p1 -b .manpage %patch706 -p1 -b .localdomain %patch707 -p1 -b .redhat %patch708 -p1 -b .entropy @@ -474,6 +492,7 @@ popd %patch918 -p1 -b .log-in-chroot %patch919 -p1 -b .mls-labels %patch802 -p1 -b .GSSAPIEnablek5users +%patch803 -p1 -b .k5login %patch920 -p1 -b .sshd-t %patch921 -p1 -b .sftp-force-mode %patch922 -p1 -b .term @@ -487,9 +506,19 @@ popd %patch930 -p1 -b .roaming %patch931 -p1 -b .xauth %patch932 -p1 -b .untrusted +%patch933 -p1 -b .uselogin +%patch934 -p1 -b .stderr +%patch935 -p1 -b .s390 +%patch936 -p1 -b .auth_meth +%patch937 -p1 -b .quiet +%patch938 -p1 -b .expose-auth +%patch939 -p1 -b .x11max +%patch940 -p1 -b .permitopen +%patch941 -p1 -b .chroot-cap %patch200 -p1 -b .audit %patch201 -p1 -b .audit-fps +%patch202 -p1 -b .audit-race %patch700 -p1 -b .fips %patch100 -p1 -b .coverity @@ -697,18 +726,6 @@ getent passwd sshd >/dev/null || \ %postun server %systemd_postun_with_restart sshd.service -%triggerun -n openssh-server -- openssh-server < 5.8p2-12 -/usr/bin/systemd-sysv-convert --save sshd >/dev/null 2>&1 || : -/bin/systemctl enable sshd.service >/dev/null 2>&1 -/sbin/chkconfig --del sshd >/dev/null 2>&1 || : -/bin/systemctl try-restart sshd.service >/dev/null 2>&1 || : - -%triggerun -n openssh-server -- openssh-server < 5.9p1-22 -/bin/systemctl --no-reload disable sshd-keygen.service >/dev/null 2>&1 || : - -%triggerpostun -n openssh-server-sysvinit -- openssh-server < 5.8p2-12 -/sbin/chkconfig --add sshd >/dev/null 2>&1 || : - %files %defattr(-,root,root) %{!?_licensedir:%global license %%doc} @@ -811,11 +828,44 @@ getent passwd sshd >/dev/null || \ %endif %changelog +* Tue Sep 06 2016 Jakub Jelen - 6.6.1p1-31 + 0.9.3-9 +- Do not depend on selinux-policy (#1373297) + +* Fri Jul 29 2016 Jakub Jelen - 6.6.1p1-30 + 0.9.3-9 +- Drop dependency on libcap-ng for ssh-keycat (#1357859) + +* Thu Jul 28 2016 Jakub Jelen - 6.6.1p1-29 + 0.9.3-9 +- Rework SELinux context handling with chroot using libcap-ng (#1357859) + +* Fri Jul 01 2016 Jakub Jelen - 6.6.1p1-28 + 0.9.3-9 +- SFTP force permission collision with umask (#1344614) +- Make closefrom() ignore FD's to /dev/ devices on s390 (#1318760) +- Create a default value for AuthenticationMethods any (#1237129) +- Fix ssh-copy-id with LogLevel=quiet (#1349556) +- Expose more information to PAM (#1312304) +- Move MAX_DISPLAYS to a configuration option (#1341302) +- Add a wildcard option to PermitOpen directive (host) (#1344106) + +* Tue May 31 2016 Jakub Jelen - 6.6.1p1-27 + 0.9.3-9 +- Coverity and RPMDiff build issues (#1334326) +- CVE-2015-8325: privilege escalation via user's PAM environment and UseLogin=yes (#1329191) +- Check for real location of .k5login file (#1328243) +- close ControlPersist background process stderr (#1335540) + +* Fri Apr 01 2016 Jakub Jelen 6.6.1p1-26 + 0.9.3-9 +- Drop glob patch for sftp client preventing listing many files (#1310303) +- Fix race condition between audit messages from different processes (#1310684) +- Make systemd service forking to properly report state (#1291172) +- Get rid of rpm triggers for openssh-5.x (#1312013) +- Generate the host keys when the key files are empty (#1266043) +- pam_ssh_agent_auth: authorized_keys_command option (#1317858) +- Don't use MD5 digest from pam_ssh_agent_auth in FIPS mode (#1317952) + * Wed Mar 16 2016 Jakub Jelen 6.6.1p1-25 + 0.9.3-9 - CVE-2016-1908: possible fallback from untrusted to trusted X11 forwarding (#1298741) * Tue Mar 15 2016 Jakub Jelen 6.6.1p1-24 + 0.9.3-9 -- CVE-2016-3115: missing sanitisation of input for X11 forwarding (#1317818) +- CVE-2016-3115: missing sanitisation of input for X11 forwarding (#1317819) * Wed Jan 13 2016 Jakub Jelen 6.6.1p1-23 + 0.9.3-9 - Disable undocumented feauture Roaming for good (#1298218)