From c9833c96a49414065c7e0c0bafd276709bc83b62 Mon Sep 17 00:00:00 2001 From: Tomáš Mráz Date: Sep 06 2007 19:49:16 +0000 Subject: - upgrade to latest upstream - use libedit in sftp (#203009) - fixed audit log injection problem (CVE-2007-3102) --- diff --git a/.cvsignore b/.cvsignore index b99eac3..f41a76f 100644 --- a/.cvsignore +++ b/.cvsignore @@ -1 +1 @@ -openssh-4.5p1-noacss.tar.bz2 +openssh-4.7p1-noacss.tar.bz2 diff --git a/openssh-3.9p1-log-in-chroot.patch b/openssh-3.9p1-log-in-chroot.patch deleted file mode 100644 index 222487b..0000000 --- a/openssh-3.9p1-log-in-chroot.patch +++ /dev/null @@ -1,53 +0,0 @@ ---- openssh-3.9p1/log.h.log-chroot 2006-02-22 10:54:04.000000000 +0100 -+++ openssh-3.9p1/log.h 2006-02-22 10:53:29.000000000 +0100 -@@ -63,4 +63,6 @@ - - void do_log(LogLevel, const char *, va_list); - void cleanup_exit(int) __dead; -+ -+void open_log(void); - #endif ---- openssh-3.9p1/log.c.log-chroot 2006-02-22 13:29:48.000000000 +0100 -+++ openssh-3.9p1/log.c 2006-02-22 10:56:01.000000000 +0100 -@@ -48,6 +48,7 @@ - static int log_on_stderr = 1; - static int log_facility = LOG_AUTH; - static char *argv0; -+static int log_fd_keep; - - extern char *__progname; - -@@ -330,9 +331,20 @@ - syslog_r(pri, &sdata, "%.500s", fmtbuf); - closelog_r(&sdata); - #else -+ if (!log_fd_keep) { - openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility); -+ } - syslog(pri, "%.500s", fmtbuf); -+ if (!log_fd_keep) { - closelog(); -+ } - #endif - } - } -+ -+void -+open_log(void) -+{ -+ openlog(argv0 ? argv0 : __progname, LOG_PID|LOG_NDELAY, log_facility); -+ log_fd_keep = 1; -+} ---- openssh-3.9p1/sshd.c.log-chroot 2006-01-11 13:42:32.000000000 +0100 -+++ openssh-3.9p1/sshd.c 2006-02-22 18:58:24.000000000 +0100 -@@ -565,6 +565,10 @@ - memset(pw->pw_passwd, 0, strlen(pw->pw_passwd)); - endpwent(); - -+ /* Open the syslog permanently so the chrooted process still -+ can write to syslog. */ -+ open_log(); -+ - /* Change our root directory */ - if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1) - fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR, diff --git a/openssh-4.3p2-cve-2007-3102.patch b/openssh-4.3p2-cve-2007-3102.patch new file mode 100644 index 0000000..9237b62 --- /dev/null +++ b/openssh-4.3p2-cve-2007-3102.patch @@ -0,0 +1,62 @@ +--- openssh-4.3p2/loginrec.c.inject-fix 2007-06-20 21:18:00.000000000 +0200 ++++ openssh-4.3p2/loginrec.c 2007-07-13 15:25:35.000000000 +0200 +@@ -1389,11 +1389,44 @@ + #endif /* USE_WTMPX */ + + #ifdef HAVE_LINUX_AUDIT ++static void ++_audit_hexscape(const char *what, char *where, unsigned int size) ++{ ++ const char *ptr = what; ++ const char *hex = "0123456789ABCDEF"; ++ ++ while (*ptr) { ++ if (*ptr == '"' || *ptr < 0x21 || *ptr > 0x7E) { ++ unsigned int i; ++ ptr = what; ++ for (i = 0; *ptr && i+2 < size; i += 2) { ++ where[i] = hex[((unsigned)*ptr & 0xF0)>>4]; /* Upper nibble */ ++ where[i+1] = hex[(unsigned)*ptr & 0x0F]; /* Lower nibble */ ++ ptr++; ++ } ++ where[i] = '\0'; ++ return; ++ } ++ ptr++; ++ } ++ where[0] = '"'; ++ if ((unsigned)(ptr - what) < size - 3) ++ { ++ size = ptr - what + 3; ++ } ++ strncpy(where + 1, what, size - 3); ++ where[size-2] = '"'; ++ where[size-1] = '\0'; ++} ++ ++#define AUDIT_LOG_SIZE 128 ++#define AUDIT_ACCT_SIZE (AUDIT_LOG_SIZE - 8) ++ + int + linux_audit_record_event(int uid, const char *username, + const char *hostname, const char *ip, const char *ttyn, int success) + { +- char buf[64]; ++ char buf[AUDIT_LOG_SIZE]; + int audit_fd, rc; + + audit_fd = audit_open(); +@@ -1406,8 +1439,11 @@ + } + if (username == NULL) + snprintf(buf, sizeof(buf), "uid=%d", uid); +- else +- snprintf(buf, sizeof(buf), "acct=%s", username); ++ else { ++ char encoded[AUDIT_ACCT_SIZE]; ++ _audit_hexscape(username, encoded, sizeof(encoded)); ++ snprintf(buf, sizeof(buf), "acct=%s", encoded); ++ } + rc = audit_log_user_message(audit_fd, AUDIT_USER_LOGIN, + buf, hostname, ip, ttyn, success); + close(audit_fd); diff --git a/openssh-4.3p2-pam-session.patch b/openssh-4.3p2-pam-session.patch deleted file mode 100644 index 2772c81..0000000 --- a/openssh-4.3p2-pam-session.patch +++ /dev/null @@ -1,129 +0,0 @@ ---- openssh-4.3p2/auth-pam.c.pam-session 2006-11-27 17:39:08.000000000 +0100 -+++ openssh-4.3p2/auth-pam.c 2006-11-27 19:31:41.000000000 +0100 -@@ -563,15 +563,17 @@ - void - sshpam_cleanup(void) - { -- debug("PAM: cleanup"); -- if (sshpam_handle == NULL) -+ if (sshpam_handle == NULL || (use_privsep && !mm_is_monitor())) - return; -+ debug("PAM: cleanup"); - pam_set_item(sshpam_handle, PAM_CONV, (const void *)&null_conv); - if (sshpam_cred_established) { -+ debug("PAM: deleting credentials"); - pam_setcred(sshpam_handle, PAM_DELETE_CRED); - sshpam_cred_established = 0; - } - if (sshpam_session_open) { -+ debug("PAM: closing session"); - pam_close_session(sshpam_handle, PAM_SILENT); - sshpam_session_open = 0; - } ---- openssh-4.3p2/sshd.c.pam-session 2006-11-27 17:29:44.000000000 +0100 -+++ openssh-4.3p2/sshd.c 2006-11-28 21:21:52.000000000 +0100 -@@ -1745,7 +1745,21 @@ - audit_event(SSH_AUTH_SUCCESS); - #endif - -- /* -+#ifdef GSSAPI -+ if (options.gss_authentication) { -+ temporarily_use_uid(authctxt->pw); -+ ssh_gssapi_storecreds(); -+ restore_uid(); -+ } -+#endif -+#ifdef USE_PAM -+ if (options.use_pam) { -+ do_pam_setcred(1); -+ do_pam_session(); -+ } -+#endif -+ -+ /* - * In privilege separation, we fork another child and prepare - * file descriptor passing. - */ ---- openssh-4.3p2/monitor.c.pam-session 2006-11-27 17:29:44.000000000 +0100 -+++ openssh-4.3p2/monitor.c 2006-11-28 14:01:23.000000000 +0100 -@@ -1539,6 +1539,11 @@ - /* The child is terminating */ - session_destroy_all(&mm_session_close); - -+#ifdef USE_PAM -+ if (options.use_pam) -+ sshpam_cleanup(); -+#endif -+ - while (waitpid(pmonitor->m_pid, &status, 0) == -1) - if (errno != EINTR) - exit(1); ---- openssh-4.3p2/session.c.pam-session 2006-11-27 17:29:43.000000000 +0100 -+++ openssh-4.3p2/session.c 2006-11-28 21:17:56.000000000 +0100 -@@ -395,11 +395,6 @@ - - session_proctitle(s); - --#if defined(USE_PAM) -- if (options.use_pam && !use_privsep) -- do_pam_setcred(1); --#endif /* USE_PAM */ -- - /* Fork the child. */ - if ((pid = fork()) == 0) { - is_child = 1; -@@ -530,14 +525,6 @@ - ptyfd = s->ptyfd; - ttyfd = s->ttyfd; - --#if defined(USE_PAM) -- if (options.use_pam) { -- do_pam_set_tty(s->tty); -- if (!use_privsep) -- do_pam_setcred(1); -- } --#endif -- - /* Fork the child. */ - if ((pid = fork()) == 0) { - is_child = 1; -@@ -1266,16 +1253,8 @@ - # ifdef __bsdi__ - setpgid(0, 0); - # endif --#ifdef GSSAPI -- if (options.gss_authentication) { -- temporarily_use_uid(pw); -- ssh_gssapi_storecreds(); -- restore_uid(); -- } --#endif - # ifdef USE_PAM - if (options.use_pam) { -- do_pam_session(); - do_pam_setcred(0); - } - # endif /* USE_PAM */ -@@ -1303,13 +1282,6 @@ - exit(1); - } - endgrent(); --#ifdef GSSAPI -- if (options.gss_authentication) { -- temporarily_use_uid(pw); -- ssh_gssapi_storecreds(); -- restore_uid(); -- } --#endif - # ifdef USE_PAM - /* - * PAM credentials may take the form of supplementary groups. -@@ -1317,7 +1289,6 @@ - * Reestablish them here. - */ - if (options.use_pam) { -- do_pam_session(); - do_pam_setcred(0); - } - # endif /* USE_PAM */ diff --git a/openssh-4.5p1-audit.patch b/openssh-4.5p1-audit.patch deleted file mode 100644 index 9b148e4..0000000 --- a/openssh-4.5p1-audit.patch +++ /dev/null @@ -1,186 +0,0 @@ ---- openssh-4.5p1/loginrec.c.audit 2006-09-07 14:57:54.000000000 +0200 -+++ openssh-4.5p1/loginrec.c 2006-12-21 12:17:35.000000000 +0100 -@@ -175,6 +175,10 @@ - #include "auth.h" - #include "buffer.h" - -+#ifdef HAVE_LINUX_AUDIT -+# include -+#endif -+ - #ifdef HAVE_UTIL_H - # include - #endif -@@ -201,6 +205,9 @@ - int utmpx_write_entry(struct logininfo *li); - int wtmp_write_entry(struct logininfo *li); - int wtmpx_write_entry(struct logininfo *li); -+#ifdef HAVE_LINUX_AUDIT -+int linux_audit_write_entry(struct logininfo *li); -+#endif - int lastlog_write_entry(struct logininfo *li); - int syslogin_write_entry(struct logininfo *li); - -@@ -439,6 +446,10 @@ - - /* set the timestamp */ - login_set_current_time(li); -+#ifdef HAVE_LINUX_AUDIT -+ if (linux_audit_write_entry(li) == 0) -+ fatal("linux_audit_write_entry failed: %s", strerror(errno)); -+#endif - #ifdef USE_LOGIN - syslogin_write_entry(li); - #endif -@@ -1393,6 +1404,51 @@ - } - #endif /* USE_WTMPX */ - -+#ifdef HAVE_LINUX_AUDIT -+int -+linux_audit_record_event(int uid, const char *username, -+ const char *hostname, const char *ip, const char *ttyn, int success) -+{ -+ char buf[64]; -+ int audit_fd, rc; -+ -+ audit_fd = audit_open(); -+ if (audit_fd < 0) { -+ if (errno == EINVAL || errno == EPROTONOSUPPORT || -+ errno == EAFNOSUPPORT) -+ return 1; /* No audit support in kernel */ -+ else -+ return 0; /* Must prevent login */ -+ } -+ if (username == NULL) -+ snprintf(buf, sizeof(buf), "uid=%d", uid); -+ else -+ snprintf(buf, sizeof(buf), "acct=%s", username); -+ rc = audit_log_user_message(audit_fd, AUDIT_USER_LOGIN, -+ buf, hostname, ip, ttyn, success); -+ close(audit_fd); -+ if (rc >= 0) -+ return 1; -+ else -+ return 0; -+} -+ -+int -+linux_audit_write_entry(struct logininfo *li) -+{ -+ switch(li->type) { -+ case LTYPE_LOGIN: -+ return (linux_audit_record_event(li->uid, NULL, li->hostname, -+ NULL, li->line, 1)); -+ case LTYPE_LOGOUT: -+ return (1); /* We only care about logins */ -+ default: -+ logit("%s: invalid type field", __func__); -+ return (0); -+ } -+} -+#endif /* HAVE_LINUX_AUDIT */ -+ - /** - ** Low-level libutil login() functions - **/ ---- openssh-4.5p1/loginrec.h.audit 2006-08-05 04:39:40.000000000 +0200 -+++ openssh-4.5p1/loginrec.h 2006-12-21 12:17:35.000000000 +0100 -@@ -127,5 +127,9 @@ - char *line_abbrevname(char *dst, const char *src, int dstsize); - - void record_failed_login(const char *, const char *, const char *); -+#ifdef HAVE_LINUX_AUDIT -+int linux_audit_record_event(int uid, const char *username, -+ const char *hostname, const char *ip, const char *ttyn, int success); -+#endif /* HAVE_LINUX_AUDIT */ - - #endif /* _HAVE_LOGINREC_H_ */ ---- openssh-4.5p1/Makefile.in.audit 2006-10-23 23:44:47.000000000 +0200 -+++ openssh-4.5p1/Makefile.in 2006-12-21 12:19:39.000000000 +0100 -@@ -45,6 +45,7 @@ - CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@ - LIBS=@LIBS@ - LIBSELINUX=@LIBSELINUX@ -+LIBAUDIT=@LIBAUDIT@ - SSHDLIBS=@SSHDLIBS@ - LIBEDIT=@LIBEDIT@ - LIBPAM=@LIBPAM@ -@@ -139,7 +140,7 @@ - $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) - - sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS) -- $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBWRAP) $(LIBPAM) $(LIBSELINUX) $(SSHDLIBS) $(LIBS) -+ $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBWRAP) $(LIBPAM) $(LIBSELINUX) $(LIBAUDIT) $(SSHDLIBS) $(LIBS) - - scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o - $(LD) -o $@ scp.o progressmeter.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ---- openssh-4.5p1/config.h.in.audit 2006-11-07 14:07:01.000000000 +0100 -+++ openssh-4.5p1/config.h.in 2006-12-21 12:17:35.000000000 +0100 -@@ -1305,6 +1305,9 @@ - /* Define if you want SELinux support. */ - #undef WITH_SELINUX - -+/* Define if you want Linux audit support. */ -+#undef HAVE_LINUX_AUDIT -+ - /* Define to 1 if your processor stores words with the most significant byte - first (like Motorola and SPARC, unlike Intel and VAX). */ - #undef WORDS_BIGENDIAN ---- openssh-4.5p1/configure.ac.audit 2006-12-21 12:17:34.000000000 +0100 -+++ openssh-4.5p1/configure.ac 2006-12-21 12:17:35.000000000 +0100 -@@ -3161,6 +3161,20 @@ - ) - AC_SUBST(LIBSELINUX) - -+# Check whether user wants Linux audit support -+LINUX_AUDIT_MSG="no" -+LIBAUDIT="" -+AC_ARG_WITH(linux-audit, -+ [ --with-linux-audit Enable Linux audit support], -+ [ if test "x$withval" != "xno" ; then -+ AC_DEFINE(HAVE_LINUX_AUDIT,1,[Define if you want Linux audit support.]) -+ LINUX_AUDIT_MSG="yes" -+ AC_CHECK_HEADERS(libaudit.h) -+ LIBAUDIT="-laudit" -+ fi -+ ]) -+AC_SUBST(LIBAUDIT) -+ - # Check whether user wants Kerberos 5 support - KRB5_MSG="no" - AC_ARG_WITH(kerberos5, -@@ -3982,6 +3996,7 @@ - echo " OSF SIA support: $SIA_MSG" - echo " KerberosV support: $KRB5_MSG" - echo " SELinux support: $SELINUX_MSG" -+echo " Linux audit support: $LINUX_AUDIT_MSG" - echo " Smartcard support: $SCARD_MSG" - echo " S/KEY support: $SKEY_MSG" - echo " TCP Wrappers support: $TCPW_MSG" ---- openssh-4.5p1/auth.c.audit 2006-10-27 17:10:16.000000000 +0200 -+++ openssh-4.5p1/auth.c 2006-12-21 12:17:35.000000000 +0100 -@@ -286,6 +286,12 @@ - get_canonical_hostname(options.use_dns), "ssh", &loginmsg); - # endif - #endif -+#if HAVE_LINUX_AUDIT -+ if (authenticated == 0 && !authctxt->postponed) { -+ linux_audit_record_event(-1, authctxt->user, NULL, -+ get_remote_ipaddr(), "sshd", 0); -+ } -+#endif - #ifdef SSH_AUDIT_EVENTS - if (authenticated == 0 && !authctxt->postponed) - audit_event(audit_classify_auth(method)); -@@ -492,6 +498,10 @@ - record_failed_login(user, - get_canonical_hostname(options.use_dns), "ssh"); - #endif -+#ifdef HAVE_LINUX_AUDIT -+ linux_audit_record_event(-1, user, NULL, get_remote_ipaddr(), -+ "sshd", 0); -+#endif - #ifdef SSH_AUDIT_EVENTS - audit_event(SSH_INVALID_USER); - #endif /* SSH_AUDIT_EVENTS */ diff --git a/openssh-4.5p1-mls.patch b/openssh-4.5p1-mls.patch deleted file mode 100644 index b8d7752..0000000 --- a/openssh-4.5p1-mls.patch +++ /dev/null @@ -1,423 +0,0 @@ ---- openssh-4.5p1/openbsd-compat/port-linux.c.mls 2007-01-16 22:13:32.000000000 +0100 -+++ openssh-4.5p1/openbsd-compat/port-linux.c 2007-03-20 10:07:39.000000000 +0100 -@@ -33,12 +33,23 @@ - #include "key.h" - #include "hostfile.h" - #include "auth.h" -+#include "xmalloc.h" - - #include - #include -+#include - #include -+#include -+#include -+ -+#ifdef HAVE_LINUX_AUDIT -+#include -+#include -+#endif - - extern Authctxt *the_authctxt; -+extern int inetd_flag; -+extern int rexeced_flag; - - /* Wrapper around is_selinux_enabled() to log its return value once only */ - static int -@@ -54,17 +65,173 @@ - return (enabled); - } - -+/* Send audit message */ -+static int -+send_audit_message(int success, security_context_t default_context, -+ security_context_t selected_context) -+{ -+ int rc=0; -+#ifdef HAVE_LINUX_AUDIT -+ char *msg = NULL; -+ int audit_fd = audit_open(); -+ security_context_t default_raw=NULL; -+ security_context_t selected_raw=NULL; -+ rc = -1; -+ if (audit_fd < 0) { -+ if (errno == EINVAL || errno == EPROTONOSUPPORT || -+ errno == EAFNOSUPPORT) -+ return 0; /* No audit support in kernel */ -+ error("Error connecting to audit system."); -+ return rc; -+ } -+ if (selinux_trans_to_raw_context(default_context, &default_raw) < 0) { -+ error("Error translating default context."); -+ default_raw = NULL; -+ } -+ if (selinux_trans_to_raw_context(selected_context, &selected_raw) < 0) { -+ error("Error translating selected context."); -+ selected_raw = NULL; -+ } -+ if (asprintf(&msg, "sshd: default-context=%s selected-context=%s", -+ default_raw ? default_raw : (default_context ? default_context: "?"), -+ selected_context ? selected_raw : (selected_context ? selected_context :"?")) < 0) { -+ error("Error allocating memory."); -+ goto out; -+ } -+ if (audit_log_user_message(audit_fd, AUDIT_USER_ROLE_CHANGE, -+ msg, NULL, NULL, NULL, success) <= 0) { -+ error("Error sending audit message."); -+ goto out; -+ } -+ rc = 0; -+ out: -+ free(msg); -+ freecon(default_raw); -+ freecon(selected_raw); -+ close(audit_fd); -+#endif -+ return rc; -+} -+ -+static int -+mls_range_allowed(security_context_t src, security_context_t dst) -+{ -+ struct av_decision avd; -+ int retval; -+ unsigned int bit = CONTEXT__CONTAINS; -+ -+ debug("%s: src:%s dst:%s", __func__, src, dst); -+ retval = security_compute_av(src, dst, SECCLASS_CONTEXT, bit, &avd); -+ if (retval || ((bit & avd.allowed) != bit)) -+ return 0; -+ -+ return 1; -+} -+ -+static int -+get_user_context(const char *sename, const char *role, const char *lvl, -+ security_context_t *sc) { -+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL -+ if (lvl == NULL || lvl[0] == '\0' || get_default_context_with_level(sename, lvl, NULL, sc) != 0) { -+ /* User may have requested a level completely outside of his -+ allowed range. We get a context just for auditing as the -+ range check below will certainly fail for default context. */ -+#endif -+ if (get_default_context(sename, NULL, sc) != 0) { -+ *sc = NULL; -+ return -1; -+ } -+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL -+ } -+#endif -+ if (role != NULL && role[0]) { -+ context_t con; -+ char *type=NULL; -+ if (get_default_type(role, &type) != 0) { -+ error("get_default_type: failed to get default type for '%s'", -+ role); -+ goto out; -+ } -+ con = context_new(*sc); -+ if (!con) { -+ goto out; -+ } -+ context_role_set(con, role); -+ context_type_set(con, type); -+ freecon(*sc); -+ *sc = strdup(context_str(con)); -+ context_free(con); -+ if (!*sc) -+ return -1; -+ } -+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL -+ if (lvl != NULL && lvl[0]) { -+ /* verify that the requested range is obtained */ -+ context_t con; -+ security_context_t obtained_raw; -+ security_context_t requested_raw; -+ con = context_new(*sc); -+ if (!con) { -+ goto out; -+ } -+ context_range_set(con, lvl); -+ if (selinux_trans_to_raw_context(*sc, &obtained_raw) < 0) { -+ context_free(con); -+ goto out; -+ } -+ if (selinux_trans_to_raw_context(context_str(con), &requested_raw) < 0) { -+ freecon(obtained_raw); -+ context_free(con); -+ goto out; -+ } -+ -+ debug("get_user_context: obtained context '%s' requested context '%s'", -+ obtained_raw, requested_raw); -+ if (strcmp(obtained_raw, requested_raw)) { -+ /* set the context to the real requested one but fail */ -+ freecon(requested_raw); -+ freecon(obtained_raw); -+ freecon(*sc); -+ *sc = strdup(context_str(con)); -+ context_free(con); -+ return -1; -+ } -+ freecon(requested_raw); -+ freecon(obtained_raw); -+ context_free(con); -+ } -+#endif -+ return 0; -+ out: -+ freecon(*sc); -+ *sc = NULL; -+ return -1; -+} -+ - /* Return the default security context for the given username */ --static security_context_t --ssh_selinux_getctxbyname(char *pwname) -+static int -+ssh_selinux_getctxbyname(char *pwname, -+ security_context_t *default_sc, security_context_t *user_sc) - { -- security_context_t sc = NULL; - char *sename, *lvl; -+ const char *reqlvl = NULL; - char *role = NULL; -- int r = 0; -+ int r = -1; -+ context_t con = NULL; -+ -+ *default_sc = NULL; -+ *user_sc = NULL; -+ if (the_authctxt) { -+ if (the_authctxt->role != NULL) { -+ char *slash; -+ role = xstrdup(the_authctxt->role); -+ if ((slash = strchr(role, '/')) != NULL) { -+ *slash = '\0'; -+ reqlvl = slash + 1; -+ } -+ } -+ } - -- if (the_authctxt) -- role=the_authctxt->role; - #ifdef HAVE_GETSEUSERBYNAME - if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) { - sename = NULL; -@@ -72,37 +239,63 @@ - } - #else - sename = pwname; -- lvl = NULL; -+ lvl = ""; - #endif - - if (r == 0) { - #ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL -- if (role != NULL && role[0]) -- r = get_default_context_with_rolelevel(sename, role, lvl, NULL, &sc); -- else -- r = get_default_context_with_level(sename, lvl, NULL, &sc); -+ r = get_default_context_with_level(sename, lvl, NULL, default_sc); - #else -- if (role != NULL && role[0]) -- r = get_default_context_with_role(sename, role, NULL, &sc); -- else -- r = get_default_context(sename, NULL, &sc); -+ r = get_default_context(sename, NULL, default_sc); - #endif - } - -- if (r != 0) { -- switch (security_getenforce()) { -- case -1: -- fatal("%s: ssh_selinux_getctxbyname: " -- "security_getenforce() failed", __func__); -- case 0: -- error("%s: Failed to get default SELinux security " -- "context for %s", __func__, pwname); -- default: -- fatal("%s: Failed to get default SELinux security " -- "context for %s (in enforcing mode)", -- __func__, pwname); -+ if (r == 0) { -+ /* If launched from xinetd, we must use current level */ -+ if (inetd_flag && !rexeced_flag) { -+ security_context_t sshdsc=NULL; -+ -+ if (getcon_raw(&sshdsc) < 0) -+ fatal("failed to allocate security context"); -+ -+ if ((con=context_new(sshdsc)) == NULL) -+ fatal("failed to allocate selinux context"); -+ reqlvl = context_range_get(con); -+ freecon(sshdsc); -+ if (reqlvl !=NULL && lvl != NULL && strcmp(reqlvl, lvl) == 0) -+ /* we actually don't change level */ -+ reqlvl = ""; -+ -+ debug("%s: current connection level '%s'", __func__, reqlvl); -+ } -+ -+ if ((reqlvl != NULL && reqlvl[0]) || (role != NULL && role[0])) { -+ r = get_user_context(sename, role, reqlvl, user_sc); -+ -+ if (r == 0 && reqlvl != NULL && reqlvl[0]) { -+ security_context_t default_level_sc = *default_sc; -+ if (role != NULL && role[0]) { -+ if (get_user_context(sename, role, lvl, &default_level_sc) < 0) -+ default_level_sc = *default_sc; -+ } -+ /* verify that the requested range is contained in the user range */ -+ if (mls_range_allowed(default_level_sc, *user_sc)) { -+ logit("permit MLS level %s (user range %s)", reqlvl, lvl); -+ } else { -+ r = -1; -+ error("deny MLS level %s (user range %s)", reqlvl, lvl); -+ } -+ if (default_level_sc != *default_sc) -+ freecon(default_level_sc); -+ } -+ } else { -+ *user_sc = *default_sc; - } - } -+ if (r != 0) { -+ error("%s: Failed to get default SELinux security " -+ "context for %s", __func__, pwname); -+ } - - #ifdef HAVE_GETSEUSERBYNAME - if (sename != NULL) -@@ -110,14 +303,20 @@ - if (lvl != NULL) - xfree(lvl); - #endif -+ if (role != NULL) -+ xfree(role); -+ if (con) -+ context_free(con); - -- return (sc); -+ return (r); - } - - /* Set the execution context to the default for the specified user */ - void - ssh_selinux_setup_exec_context(char *pwname) - { -+ int r = 0; -+ security_context_t default_ctx = NULL; - security_context_t user_ctx = NULL; - - if (!ssh_selinux_enabled()) -@@ -125,21 +324,39 @@ - - debug3("%s: setting execution context", __func__); - -- user_ctx = ssh_selinux_getctxbyname(pwname); -- if (setexeccon(user_ctx) != 0) { -+ r = ssh_selinux_getctxbyname(pwname, &default_ctx, &user_ctx); -+ if (r >= 0) { -+ r = setexeccon(user_ctx); -+ if (r < 0) { -+ error("%s: Failed to set SELinux execution context %s for %s", -+ __func__, user_ctx, pwname); -+ } -+ } -+ if (user_ctx == NULL) { -+ user_ctx = default_ctx; -+ } -+ if (r < 0 || user_ctx != default_ctx) { -+ /* audit just the case when user changed a role or there was -+ a failure */ -+ send_audit_message(r >= 0, default_ctx, user_ctx); -+ } -+ if (r < 0) { - switch (security_getenforce()) { - case -1: - fatal("%s: security_getenforce() failed", __func__); - case 0: -- error("%s: Failed to set SELinux execution " -- "context for %s", __func__, pwname); -+ error("%s: SELinux failure. Continuing in permissive mode.", -+ __func__); -+ break; - default: -- fatal("%s: Failed to set SELinux execution context " -- "for %s (in enforcing mode)", __func__, pwname); -+ fatal("%s: SELinux failure. Aborting connection.", -+ __func__); - } - } -- if (user_ctx != NULL) -+ if (user_ctx != NULL && user_ctx != default_ctx) - freecon(user_ctx); -+ if (default_ctx != NULL) -+ freecon(default_ctx); - - debug3("%s: done", __func__); - } -@@ -157,7 +374,10 @@ - - debug3("%s: setting TTY context on %s", __func__, tty); - -- user_ctx = ssh_selinux_getctxbyname(pwname); -+ if (getexeccon(&user_ctx) < 0) { -+ error("%s: getexeccon: %s", __func__, strerror(errno)); -+ goto out; -+ } - - /* XXX: should these calls fatal() upon failure in enforcing mode? */ - ---- openssh-4.5p1/sshd.c.mls 2007-01-16 22:13:32.000000000 +0100 -+++ openssh-4.5p1/sshd.c 2007-01-16 22:13:32.000000000 +0100 -@@ -1833,6 +1833,9 @@ - restore_uid(); - } - #endif -+#ifdef WITH_SELINUX -+ ssh_selinux_setup_exec_context(authctxt->pw->pw_name); -+#endif - #ifdef USE_PAM - if (options.use_pam) { - do_pam_setcred(1); ---- openssh-4.5p1/misc.c.mls 2006-08-05 04:39:40.000000000 +0200 -+++ openssh-4.5p1/misc.c 2007-01-16 22:13:32.000000000 +0100 -@@ -418,6 +418,7 @@ - colon(char *cp) - { - int flag = 0; -+ int start = 1; - - if (*cp == ':') /* Leading colon is part of file name. */ - return (0); -@@ -431,8 +432,13 @@ - return (cp+1); - if (*cp == ':' && !flag) - return (cp); -- if (*cp == '/') -- return (0); -+ if (start) { -+ /* Slash on beginning or after dots only denotes file name. */ -+ if (*cp == '/') -+ return (0); -+ if (*cp != '.') -+ start = 0; -+ } - } - return (0); - } ---- openssh-4.5p1/session.c.mls 2007-01-16 22:13:32.000000000 +0100 -+++ openssh-4.5p1/session.c 2007-01-16 22:13:32.000000000 +0100 -@@ -1347,10 +1347,6 @@ - #endif - if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid) - fatal("Failed to set uids to %u.", (u_int) pw->pw_uid); -- --#ifdef WITH_SELINUX -- ssh_selinux_setup_exec_context(pw->pw_name); --#endif - } - - static void diff --git a/openssh-4.5p1-nss-keys.patch b/openssh-4.5p1-nss-keys.patch deleted file mode 100644 index 958290b..0000000 --- a/openssh-4.5p1-nss-keys.patch +++ /dev/null @@ -1,1409 +0,0 @@ -diff -urpN openssh-4.5p1/authfd.c openssh-4.5p1.nss/authfd.c ---- openssh-4.5p1/authfd.c 2006-09-01 07:38:36.000000000 +0200 -+++ openssh-4.5p1.nss/authfd.c 2007-05-23 15:01:55.000000000 +0200 -@@ -626,6 +626,45 @@ ssh_update_card(AuthenticationConnection - return decode_reply(type); - } - -+int -+ssh_update_nss_key(AuthenticationConnection *auth, int add, -+ const char *tokenname, const char *keyname, -+ const char *pass, u_int life, u_int confirm) -+{ -+ Buffer msg; -+ int type, constrained = (life || confirm); -+ -+ if (add) { -+ type = constrained ? -+ SSH_AGENTC_ADD_NSS_KEY_CONSTRAINED : -+ SSH_AGENTC_ADD_NSS_KEY; -+ } else -+ type = SSH_AGENTC_REMOVE_NSS_KEY; -+ -+ buffer_init(&msg); -+ buffer_put_char(&msg, type); -+ buffer_put_cstring(&msg, tokenname); -+ buffer_put_cstring(&msg, keyname); -+ buffer_put_cstring(&msg, pass); -+ -+ if (constrained) { -+ if (life != 0) { -+ buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_LIFETIME); -+ buffer_put_int(&msg, life); -+ } -+ if (confirm != 0) -+ buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_CONFIRM); -+ } -+ -+ if (ssh_request_reply(auth, &msg, &msg) == 0) { -+ buffer_free(&msg); -+ return 0; -+ } -+ type = buffer_get_char(&msg); -+ buffer_free(&msg); -+ return decode_reply(type); -+} -+ - /* - * Removes all identities from the agent. This call is not meant to be used - * by normal applications. -diff -urpN openssh-4.5p1/authfd.h openssh-4.5p1.nss/authfd.h ---- openssh-4.5p1/authfd.h 2006-08-05 04:39:39.000000000 +0200 -+++ openssh-4.5p1.nss/authfd.h 2007-05-17 11:47:39.000000000 +0200 -@@ -49,6 +49,12 @@ - #define SSH2_AGENTC_ADD_ID_CONSTRAINED 25 - #define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26 - -+/* nss */ -+#define SSH_AGENTC_ADD_NSS_KEY 30 -+#define SSH_AGENTC_REMOVE_NSS_KEY 31 -+#define SSH_AGENTC_ADD_NSS_KEY_CONSTRAINED 32 -+ -+ - #define SSH_AGENT_CONSTRAIN_LIFETIME 1 - #define SSH_AGENT_CONSTRAIN_CONFIRM 2 - -@@ -83,6 +89,8 @@ int ssh_remove_all_identities(Authentic - int ssh_lock_agent(AuthenticationConnection *, int, const char *); - int ssh_update_card(AuthenticationConnection *, int, const char *, - const char *, u_int, u_int); -+int ssh_update_nss_key(AuthenticationConnection *, int, const char *, -+ const char *, const char *, u_int, u_int); - - int - ssh_decrypt_challenge(AuthenticationConnection *, Key *, BIGNUM *, u_char[16], -diff -urpN openssh-4.5p1/configure.ac openssh-4.5p1.nss/configure.ac ---- openssh-4.5p1/configure.ac 2007-05-15 16:28:07.000000000 +0200 -+++ openssh-4.5p1.nss/configure.ac 2007-05-15 16:38:56.000000000 +0200 -@@ -3175,6 +3175,21 @@ AC_ARG_WITH(linux-audit, - ]) - AC_SUBST(LIBAUDIT) - -+# Check whether user wants NSS support -+LIBNSS_MSG="no" -+LIBNSS="" -+AC_ARG_WITH(nss, -+ [ --with-nss Enable NSS support], -+ [ if test "x$withval" != "xno" ; then -+ AC_DEFINE(HAVE_LIBNSS,1,[Define if you want NSS support.]) -+ LIBNSS_MSG="yes" -+ CPPFLAGS="$CPPFLAGS -I/usr/include/nss3 -I/usr/include/nspr4" -+ AC_CHECK_HEADERS(pk11pub.h) -+ LIBNSS="-lnss3" -+ fi -+ ]) -+AC_SUBST(LIBNSS) -+ - # Check whether user wants Kerberos 5 support - KRB5_MSG="no" - AC_ARG_WITH(kerberos5, -@@ -3997,6 +4012,7 @@ echo " OSF SIA support - echo " KerberosV support: $KRB5_MSG" - echo " SELinux support: $SELINUX_MSG" - echo " Linux audit support: $LINUX_AUDIT_MSG" -+echo " NSS support: $LIBNSS_MSG" - echo " Smartcard support: $SCARD_MSG" - echo " S/KEY support: $SKEY_MSG" - echo " TCP Wrappers support: $TCPW_MSG" -diff -urpN openssh-4.5p1/key.c openssh-4.5p1.nss/key.c ---- openssh-4.5p1/key.c 2006-11-07 13:14:42.000000000 +0100 -+++ openssh-4.5p1.nss/key.c 2007-06-20 14:30:11.000000000 +0200 -@@ -93,6 +93,54 @@ key_new(int type) - return k; - } - -+#ifdef HAVE_LIBNSS -+Key * -+key_new_nss(int type) -+{ -+ Key *k = key_new(type); -+ -+ k->nss = xcalloc(1, sizeof(*k->nss)); -+ k->flags = KEY_FLAG_EXT | KEY_FLAG_NSS; -+ -+ return k; -+} -+ -+Key * -+key_new_nss_copy(int type, const Key *c) -+{ -+ Key *k = key_new_nss(type); -+ -+ switch (k->type) { -+ case KEY_RSA: -+ if ((BN_copy(k->rsa->n, c->rsa->n) == NULL) || -+ (BN_copy(k->rsa->e, c->rsa->e) == NULL)) -+ fatal("key_new_nss_copy: BN_copy failed"); -+ break; -+ case KEY_DSA: -+ if ((BN_copy(k->dsa->p, c->rsa->p) == NULL) || -+ (BN_copy(k->dsa->q, c->dsa->q) == NULL) || -+ (BN_copy(k->dsa->g, c->dsa->g) == NULL) || -+ (BN_copy(k->dsa->pub_key, c->dsa->pub_key) == NULL)) -+ fatal("key_new_nss_copy: BN_copy failed"); -+ break; -+ } -+ -+ k->nss->privk = SECKEY_CopyPrivateKey(c->nss->privk); -+ if (k->nss->privk == NULL) -+ fatal("key_new_nss_copy: SECKEY_CopyPrivateKey failed"); -+ -+ k->nss->pubk = SECKEY_CopyPublicKey(c->nss->pubk); -+ if (k->nss->pubk == NULL) -+ fatal("key_new_nss_copy: SECKEY_CopyPublicKey failed"); -+ -+ if (c->nss->privk->wincx) -+ k->nss->privk->wincx = xstrdup(c->nss->privk->wincx); -+ -+ return k; -+} -+#endif -+ -+ - Key * - key_new_private(int type) - { -@@ -148,6 +196,19 @@ key_free(Key *k) - fatal("key_free: bad key type %d", k->type); - break; - } -+#ifdef HAVE_LIBNSS -+ if (k->flags & KEY_FLAG_NSS) { -+ if (k->nss->privk->wincx != NULL) { -+ memset(k->nss->privk->wincx, 0, -+ strlen(k->nss->privk->wincx)); -+ xfree(k->nss->privk->wincx); -+ k->nss->privk->wincx = NULL; -+ } -+ SECKEY_DestroyPrivateKey(k->nss->privk); -+ SECKEY_DestroyPublicKey(k->nss->pubk); -+ xfree(k->nss); -+ } -+#endif - xfree(k); - } - -diff -urpN openssh-4.5p1/key.h openssh-4.5p1.nss/key.h ---- openssh-4.5p1/key.h 2006-08-05 04:39:40.000000000 +0200 -+++ openssh-4.5p1.nss/key.h 2007-05-29 11:19:03.000000000 +0200 -@@ -29,11 +29,17 @@ - #include - #include - -+#ifdef HAVE_LIBNSS -+#include -+#include -+#endif -+ - typedef struct Key Key; - enum types { - KEY_RSA1, - KEY_RSA, - KEY_DSA, -+ KEY_NSS, - KEY_UNSPEC - }; - enum fp_type { -@@ -47,16 +53,30 @@ enum fp_rep { - - /* key is stored in external hardware */ - #define KEY_FLAG_EXT 0x0001 -+#define KEY_FLAG_NSS 0x0002 -+ -+#ifdef HAVE_LIBNSS -+typedef struct NSSKey NSSKey; -+struct NSSKey { -+ SECKEYPrivateKey *privk; -+ SECKEYPublicKey *pubk; -+}; -+#endif - - struct Key { - int type; - int flags; - RSA *rsa; - DSA *dsa; -+#ifdef HAVE_LIBNSS -+ NSSKey *nss; -+#endif - }; - - Key *key_new(int); - Key *key_new_private(int); -+Key *key_new_nss(int); -+Key *key_new_nss_copy(int, const Key *); - void key_free(Key *); - Key *key_demote(const Key *); - int key_equal(const Key *, const Key *); -diff -urpN openssh-4.5p1/Makefile.in openssh-4.5p1.nss/Makefile.in ---- openssh-4.5p1/Makefile.in 2007-05-15 16:28:07.000000000 +0200 -+++ openssh-4.5p1.nss/Makefile.in 2007-05-23 14:05:18.000000000 +0200 -@@ -43,7 +43,7 @@ CC=@CC@ - LD=@LD@ - CFLAGS=@CFLAGS@ - CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@ --LIBS=@LIBS@ -+LIBS=@LIBS@ @LIBNSS@ - LIBSELINUX=@LIBSELINUX@ - LIBAUDIT=@LIBAUDIT@ - SSHDLIBS=@SSHDLIBS@ -@@ -75,7 +75,7 @@ LIBSSH_OBJS=acss.o authfd.o authfile.o b - atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \ - monitor_fdpass.o rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o \ - kexgex.o kexdhc.o kexgexc.o scard.o msg.o progressmeter.o dns.o \ -- entropy.o scard-opensc.o gss-genr.o -+ entropy.o scard-opensc.o gss-genr.o nsskeys.o - - SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ - sshconnect.o sshconnect1.o sshconnect2.o -diff -urpN openssh-4.5p1/nsskeys.c openssh-4.5p1.nss/nsskeys.c ---- openssh-4.5p1/nsskeys.c 1970-01-01 01:00:00.000000000 +0100 -+++ openssh-4.5p1.nss/nsskeys.c 2007-06-20 17:57:11.000000000 +0200 -@@ -0,0 +1,327 @@ -+/* -+ * Copyright (c) 2001 Markus Friedl. All rights reserved. -+ * Copyright (c) 2007 Red Hat, Inc. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include "includes.h" -+#ifdef HAVE_LIBNSS -+ -+#include -+ -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "xmalloc.h" -+#include "key.h" -+#include "log.h" -+#include "misc.h" -+#include "nsskeys.h" -+#include "pathnames.h" -+ -+static char * -+password_cb(PK11SlotInfo *slot, PRBool retry, void *arg) -+{ -+ char *password = arg; -+ if (retry || password == NULL) -+ return NULL; -+ -+ return PL_strdup(password); -+} -+ -+int -+nss_init(PK11PasswordFunc pwfn) -+{ -+ char *dbpath; -+ char buf[MAXPATHLEN]; -+ -+ if (NSS_IsInitialized()) -+ return 0; -+ -+ if ((dbpath=getenv("NSS_DB_PATH")) == NULL) { -+ struct passwd *pw; -+ if ((pw = getpwuid(getuid())) == NULL || -+ pw->pw_dir == NULL) { -+ return -1; -+ } -+ snprintf(buf, sizeof(buf), "%s/%s", pw->pw_dir, -+ _PATH_SSH_USER_DIR); -+ dbpath = buf; -+ } -+ -+ if (NSS_Init(dbpath) != SECSuccess) -+ return -1; -+ -+ if (pwfn == NULL) { -+ pwfn = password_cb; -+ } -+ -+ PK11_SetPasswordFunc(pwfn); -+ -+ return 0; -+} -+ -+static Key * -+make_key_from_privkey(SECKEYPrivateKey *privk, char *password) -+{ -+ Key *k; -+ switch (SECKEY_GetPrivateKeyType(privk)) { -+ case rsaKey: -+ k = key_new_nss(KEY_RSA); -+ break; -+ case dsaKey: -+ k = key_new_nss(KEY_DSA); -+ break; -+ default: -+ return NULL; -+ } -+ k->nss->pubk = SECKEY_ConvertToPublicKey(privk); -+ if (k->nss->pubk != NULL) { -+ k->nss->privk = SECKEY_CopyPrivateKey(privk); -+ } -+ if (k->nss->privk != NULL) { -+ if (password != NULL) { -+ k->nss->privk->wincx = xstrdup(password); -+ } -+ return k; -+ } -+ key_free(k); -+ return NULL; -+} -+ -+static Key ** -+add_key_to_list(Key *k, Key **keys, size_t *i, size_t *allocated) -+{ -+ if (*allocated < *i + 2) { -+ *allocated += 16; -+ keys = xrealloc(keys, *allocated, sizeof(k)); -+ } -+ keys[*i] = k; -+ (*i)++; -+ keys[*i] = NULL; -+ return keys; -+} -+ -+static int -+nss_convert_pubkey(Key *k) -+{ -+ u_char *n; -+ unsigned int len; -+ char *p; -+ -+ switch (k->type) { -+ case KEY_RSA: -+ n = k->nss->pubk->u.rsa.modulus.data; -+ len = k->nss->pubk->u.rsa.modulus.len; -+ -+ if (BN_bin2bn(n, len, k->rsa->n) == NULL) { -+ fatal("nss_convert_pubkey: BN_bin2bn failed"); -+ } -+ -+ n = k->nss->pubk->u.rsa.publicExponent.data; -+ len = k->nss->pubk->u.rsa.publicExponent.len; -+ -+ if (BN_bin2bn(n, len, k->rsa->e) == NULL) { -+ fatal("nss_convert_pubkey: BN_bin2bn failed"); -+ } -+ break; -+ case KEY_DSA: -+ n = k->nss->pubk->u.dsa.params.prime.data; -+ len = k->nss->pubk->u.dsa.params.prime.len; -+ -+ if (BN_bin2bn(n, len, k->dsa->p) == NULL) { -+ fatal("nss_convert_pubkey: BN_bin2bn failed"); -+ } -+ -+ n = k->nss->pubk->u.dsa.params.subPrime.data; -+ len = k->nss->pubk->u.dsa.params.subPrime.len; -+ -+ if (BN_bin2bn(n, len, k->dsa->q) == NULL) { -+ fatal("nss_convert_pubkey: BN_bin2bn failed"); -+ } -+ -+ n = k->nss->pubk->u.dsa.params.base.data; -+ len = k->nss->pubk->u.dsa.params.base.len; -+ -+ if (BN_bin2bn(n, len, k->dsa->g) == NULL) { -+ fatal("nss_convert_pubkey: BN_bin2bn failed"); -+ } -+ -+ n = k->nss->pubk->u.dsa.publicValue.data; -+ len = k->nss->pubk->u.dsa.publicValue.len; -+ -+ if (BN_bin2bn(n, len, k->dsa->pub_key) == NULL) { -+ fatal("nss_convert_pubkey: BN_bin2bn failed"); -+ } -+ break; -+ } -+ -+ p = key_fingerprint(k, SSH_FP_MD5, SSH_FP_HEX); -+ debug("fingerprint %u %s", key_size(k), p); -+ xfree(p); -+ -+ return 0; -+} -+ -+static Key ** -+nss_find_privkeys(const char *tokenname, const char *keyname, -+ char *password) -+{ -+ Key *k = NULL; -+ Key **keys = NULL; -+ PK11SlotList *slots; -+ PK11SlotListElement *sle; -+ size_t allocated = 0; -+ size_t i = 0; -+ -+ if ((slots=PK11_FindSlotsByNames(NULL, NULL, tokenname, PR_TRUE)) == NULL) { -+ if (tokenname == NULL) { -+ debug("No NSS token found"); -+ } else { -+ debug("NSS token not found: %s", tokenname); -+ } -+ return NULL; -+ } -+ -+ for (sle = slots->head; sle; sle = sle->next) { -+ SECKEYPrivateKeyList *list; -+ SECKEYPrivateKeyListNode *node; -+ char *tmppass = password; -+ -+ if (PK11_NeedLogin(sle->slot)) { -+ if (password == NULL) { -+ char *prompt; -+ if (asprintf(&prompt, "Enter passphrase for token %s: ", -+ PK11_GetTokenName(sle->slot)) < 0) -+ fatal("password_cb: asprintf failed"); -+ tmppass = read_passphrase(prompt, RP_ALLOW_STDIN); -+ } -+ PK11_Authenticate(sle->slot, PR_TRUE, tmppass); -+ } -+ -+ debug("Looking for: %s:%s", tokenname, keyname); -+ list = PK11_ListPrivKeysInSlot(sle->slot, (char *)keyname, -+ tmppass); -+ if (list == NULL && keyname != NULL) { -+ char *fooname; -+ /* NSS bug workaround */ -+ if (asprintf(&fooname, "%s~", keyname) < 0) { -+ error("nss_find_privkey: asprintf failed"); -+ PK11_FreeSlotList(slots); -+ return NULL; -+ } -+ list = PK11_ListPrivKeysInSlot(sle->slot, fooname, -+ tmppass); -+ free(fooname); -+ } -+ if (list == NULL && keyname != NULL) { -+ CERTCertificate *cert; -+ SECKEYPrivateKey *privk; -+ cert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), -+ (char *)keyname); -+ if (cert == NULL) -+ goto cleanup; -+ privk = PK11_FindPrivateKeyFromCert(sle->slot, cert, tmppass); -+ CERT_DestroyCertificate(cert); -+ if (privk == NULL) -+ goto cleanup; -+ if ((k=make_key_from_privkey(privk, tmppass)) != NULL) { -+ nss_convert_pubkey(k); -+ keys = add_key_to_list(k, keys, &i, &allocated); -+ } -+ SECKEY_DestroyPrivateKey(privk); -+ } else { -+ if (list == NULL) -+ goto cleanup; -+ for (node=PRIVKEY_LIST_HEAD(list); !PRIVKEY_LIST_END(node, list); -+ node=PRIVKEY_LIST_NEXT(node)) -+ if ((k=make_key_from_privkey(node->key, tmppass)) != NULL) { -+ nss_convert_pubkey(k); -+ keys = add_key_to_list(k, keys, &i, &allocated); -+ } -+ SECKEY_DestroyPrivateKeyList(list); -+ } -+cleanup: -+ if (password == NULL && tmppass != NULL) { -+ memset(tmppass, 0, strlen(tmppass)); -+ xfree(tmppass); -+ } -+ } -+ PK11_FreeSlotList(slots); -+ -+ return keys; -+} -+ -+Key ** -+nss_get_keys(const char *tokenname, const char *keyname, -+ char *password) -+{ -+ Key **keys; -+ -+ if (nss_init(NULL) == -1) { -+ error("Failed to initialize NSS library"); -+ return NULL; -+ } -+ -+ keys = nss_find_privkeys(tokenname, keyname, password); -+ if (keys == NULL && keyname != NULL) { -+ error("Cannot find key in nss, token removed"); -+ return NULL; -+ } -+#if 0 -+ keys = xcalloc(3, sizeof(Key *)); -+ -+ if (k->type == KEY_RSA) { -+ n = key_new_nss_copy(KEY_RSA1, k); -+ -+ keys[0] = n; -+ keys[1] = k; -+ keys[2] = NULL; -+ } else { -+ keys[0] = k; -+ keys[1] = NULL; -+ } -+#endif -+ return keys; -+} -+ -+char * -+nss_get_key_label(Key *key) -+{ -+ char *label, *nickname; -+ -+ nickname = PK11_GetPrivateKeyNickname(key->nss->privk); -+ label = xstrdup(nickname); -+ PORT_Free(nickname); -+ -+ return label; -+} -+ -+#endif /* HAVE_LIBNSS */ -diff -urpN openssh-4.5p1/nsskeys.h openssh-4.5p1.nss/nsskeys.h ---- openssh-4.5p1/nsskeys.h 1970-01-01 01:00:00.000000000 +0100 -+++ openssh-4.5p1.nss/nsskeys.h 2007-05-29 11:40:18.000000000 +0200 -@@ -0,0 +1,39 @@ -+/* -+ * Copyright (c) 2001 Markus Friedl. All rights reserved. -+ * Copyright (c) 2007 Red Hat, Inc. 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 NSSKEYS_H -+#define NSSKEYS_H -+#ifdef HAVE_LIBNSS -+#include -+#include -+ -+int nss_init(PK11PasswordFunc); -+Key **nss_get_keys(const char *, const char *, char *); -+char *nss_get_key_label(Key *); -+/*void sc_close(void);*/ -+/*int sc_put_key(Key *, const char *);*/ -+ -+#endif -+#endif -diff -urpN openssh-4.5p1/readconf.c openssh-4.5p1.nss/readconf.c ---- openssh-4.5p1/readconf.c 2006-09-01 07:38:37.000000000 +0200 -+++ openssh-4.5p1.nss/readconf.c 2007-06-20 17:51:38.000000000 +0200 -@@ -124,6 +124,7 @@ typedef enum { - oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, - oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, - oHostKeyAlgorithms, oBindAddress, oSmartcardDevice, -+ oUseNSS, oNSSToken, - oClearAllForwardings, oNoHostAuthenticationForLocalhost, - oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, - oAddressFamily, oGssAuthentication, oGssDelegateCreds, -@@ -209,6 +210,13 @@ static struct { - #else - { "smartcarddevice", oUnsupported }, - #endif -+#ifdef HAVE_LIBNSS -+ { "usenss", oUseNSS }, -+ { "nsstoken", oNSSToken }, -+#else -+ { "usenss", oUnsupported }, -+ { "nsstoken", oNSSToken }, -+#endif - { "clearallforwardings", oClearAllForwardings }, - { "enablesshkeysign", oEnableSSHKeysign }, - { "verifyhostkeydns", oVerifyHostKeyDNS }, -@@ -601,6 +609,14 @@ parse_string: - charptr = &options->smartcard_device; - goto parse_string; - -+ case oUseNSS: -+ intptr = &options->use_nss; -+ goto parse_flag; -+ -+ case oNSSToken: -+ charptr = &options->nss_token; -+ goto parse_command; -+ - case oProxyCommand: - charptr = &options->proxy_command; - parse_command: -@@ -1049,6 +1065,8 @@ initialize_options(Options * options) - options->preferred_authentications = NULL; - options->bind_address = NULL; - options->smartcard_device = NULL; -+ options->use_nss = -1; -+ options->nss_token = NULL; - options->enable_ssh_keysign = - 1; - options->no_host_authentication_for_localhost = - 1; - options->identities_only = - 1; -@@ -1177,6 +1195,8 @@ fill_default_options(Options * options) - options->no_host_authentication_for_localhost = 0; - if (options->identities_only == -1) - options->identities_only = 0; -+ if (options->use_nss == -1) -+ options->use_nss = 0; - if (options->enable_ssh_keysign == -1) - options->enable_ssh_keysign = 0; - if (options->rekey_limit == -1) -diff -urpN openssh-4.5p1/readconf.h openssh-4.5p1.nss/readconf.h ---- openssh-4.5p1/readconf.h 2006-08-05 04:39:40.000000000 +0200 -+++ openssh-4.5p1.nss/readconf.h 2007-06-18 10:41:58.000000000 +0200 -@@ -84,6 +84,8 @@ typedef struct { - char *preferred_authentications; - char *bind_address; /* local socket address for connection to sshd */ - char *smartcard_device; /* Smartcard reader device */ -+ int use_nss; /* Use NSS library for keys */ -+ char *nss_token; /* Look for NSS keys on token */ - int verify_host_key_dns; /* Verify host key using DNS */ - - int num_identity_files; /* Number of files for RSA/DSA identities. */ -diff -urpN openssh-4.5p1/README.nss openssh-4.5p1.nss/README.nss ---- openssh-4.5p1/README.nss 1970-01-01 01:00:00.000000000 +0100 -+++ openssh-4.5p1.nss/README.nss 2007-06-20 18:28:28.000000000 +0200 -@@ -0,0 +1,36 @@ -+How to use NSS tokens with OpenSSH? -+ -+This version of OpenSSH contains experimental support for authentication using -+keys stored in tokens stored in NSS database. This for example includes any -+PKCS#11 tokens which are installed in your NSS database. -+ -+As the code is experimental and preliminary only SSH protocol 2 is supported. -+The NSS certificate and token databases are looked for in the ~/.ssh -+directory or in a directory specified by environment variable NSS_DB_PATH. -+ -+Common operations: -+ -+(1) tell the ssh client to use the NSS keys: -+ -+ $ ssh -o 'UseNSS yes' otherhost -+ -+ if you want to use a specific token: -+ -+ $ ssh -o 'UseNSS yes' -o 'NSS Token My PKCS11 Token' otherhost -+ -+(2) or tell the agent to use the NSS keys: -+ -+ $ ssh-add -n -+ -+ if you want to use a specific token: -+ -+ $ ssh-add -n -T 'My PKCS11 Token' -+ -+(3) extract the public key from token so it can be added to the -+server: -+ -+ $ ssh-keygen -n -+ -+ if you want to use a specific token and/or key: -+ -+ $ ssh-keygen -n -D 'My PKCS11 Token' 'My Key ID' -+ -+Tomas Mraz, Red Hat, Inc. -diff -urpN openssh-4.5p1/ssh-add.c openssh-4.5p1.nss/ssh-add.c ---- openssh-4.5p1/ssh-add.c 2006-09-01 07:38:37.000000000 +0200 -+++ openssh-4.5p1.nss/ssh-add.c 2007-05-29 18:26:08.000000000 +0200 -@@ -43,6 +43,14 @@ - - #include - -+#ifdef HAVE_LIBNSS -+#include -+#include -+#include -+#include -+#include -+#endif -+ - #include - #include - #include -@@ -56,6 +64,7 @@ - #include "rsa.h" - #include "log.h" - #include "key.h" -+#include "nsskeys.h" - #include "buffer.h" - #include "authfd.h" - #include "authfile.h" -@@ -306,6 +315,117 @@ do_file(AuthenticationConnection *ac, in - return 0; - } - -+#ifdef HAVE_LIBNSS -+static char * -+password_cb(PK11SlotInfo *slot, PRBool retry, void *arg) -+{ -+ char **passcache = arg; -+ char *password, *p2 = NULL; -+ char *prompt; -+ -+ if (retry) -+ return NULL; -+ -+ if (asprintf(&prompt, "Enter passphrase for token %s: ", -+ PK11_GetTokenName(slot)) < 0) -+ fatal("password_cb: asprintf failed"); -+ -+ password = read_passphrase(prompt, RP_ALLOW_STDIN); -+ -+ if (password != NULL && (p2=PL_strdup(password)) == NULL) { -+ memset(password, 0, strlen(password)); -+ fatal("password_cb: PL_strdup failed"); -+ } -+ -+ if (passcache != NULL) { -+ if (*passcache != NULL) { -+ memset(*passcache, 0, strlen(*passcache)); -+ xfree(*passcache); -+ } -+ *passcache = password; -+ } else { -+ memset(password, 0, strlen(password)); -+ xfree(password); -+ } -+ -+ return p2; -+} -+ -+static int -+add_slot_keys(AuthenticationConnection *ac, PK11SlotInfo *slot, int add) -+{ -+ SECKEYPrivateKeyList *list; -+ SECKEYPrivateKeyListNode *node; -+ char *passcache = NULL; -+ char *tokenname; -+ -+ int count = 0; -+ -+ if (PK11_NeedLogin(slot)) -+ PK11_Authenticate(slot, PR_TRUE, &passcache); -+ -+ if ((list=PK11_ListPrivKeysInSlot(slot, NULL, NULL)) == NULL) { -+ return 0; -+ } -+ -+ tokenname = PK11_GetTokenName(slot); -+ -+ for (node=PRIVKEY_LIST_HEAD(list); !PRIVKEY_LIST_END(node, list); -+ node=PRIVKEY_LIST_NEXT(node)) { -+ char *keyname; -+ SECKEYPublicKey *pub; -+ -+ keyname = PK11_GetPrivateKeyNickname(node->key); -+ if (keyname == NULL || *keyname == '\0') { -+ /* no nickname to refer to */ -+ CERTCertificate *cert; -+ char *kn; -+ cert = PK11_GetCertFromPrivateKey(node->key); -+ if (cert == NULL) -+ continue; -+ kn = strchr(cert->nickname, ':'); -+ if (kn == NULL) -+ kn = cert->nickname; -+ else -+ kn++; -+ keyname = PORT_Strdup(kn); -+ CERT_DestroyCertificate(cert); -+ if (keyname == NULL) -+ continue; -+ } -+ pub = SECKEY_ConvertToPublicKey(node->key); -+ if (pub == NULL) { -+ fprintf(stderr, "No public key for: %s:%s\n", -+ tokenname, keyname); -+ continue; /* not possible to obtain public key */ -+ } -+ SECKEY_DestroyPublicKey(pub); -+ -+ if (ssh_update_nss_key(ac, add, tokenname, keyname, -+ passcache?passcache:"", lifetime, confirm)) { -+ fprintf(stderr, "Key %s: %s:%s\n", -+ add?"added":"removed", tokenname, keyname); -+ count++; -+ } else { -+ fprintf(stderr, "Could not %s key: %s:%s\n", -+ add?"add":"remove", tokenname, keyname); -+ } -+ -+ PORT_Free(keyname); -+ count++; -+ } -+ -+ if (passcache != NULL) { -+ memset(passcache, 0, strlen(passcache)); -+ xfree(passcache); -+ } -+ -+ SECKEY_DestroyPrivateKeyList(list); -+ -+ return count; -+} -+#endif -+ - static void - usage(void) - { -@@ -333,6 +453,10 @@ main(int argc, char **argv) - AuthenticationConnection *ac = NULL; - char *sc_reader_id = NULL; - int i, ch, deleting = 0, ret = 0; -+#ifdef HAVE_LIBNSS -+ char *token_id = NULL; -+ int use_nss = 0; -+#endif - - /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ - sanitise_stdfd(); -@@ -350,7 +474,7 @@ main(int argc, char **argv) - "Could not open a connection to your authentication agent.\n"); - exit(2); - } -- while ((ch = getopt(argc, argv, "lLcdDxXe:s:t:")) != -1) { -+ while ((ch = getopt(argc, argv, "lLcdDnxXe:s:t:T:")) != -1) { - switch (ch) { - case 'l': - case 'L': -@@ -372,6 +496,11 @@ main(int argc, char **argv) - if (delete_all(ac) == -1) - ret = 1; - goto done; -+#ifdef HAVE_LIBNSS -+ case 'n': -+ use_nss = 1; -+ break; -+#endif - case 's': - sc_reader_id = optarg; - break; -@@ -386,6 +515,11 @@ main(int argc, char **argv) - goto done; - } - break; -+#ifdef HAVE_LIBNSS -+ case 'T': -+ token_id = optarg; -+ break; -+#endif - default: - usage(); - ret = 1; -@@ -399,6 +533,40 @@ main(int argc, char **argv) - ret = 1; - goto done; - } -+#ifdef HAVE_LIBNSS -+ if (use_nss) { -+ PK11SlotList *slots; -+ PK11SlotListElement *sle; -+ int count = 0; -+ if (nss_init(password_cb) == -1) { -+ fprintf(stderr, "Failed to initialize NSS library\n"); -+ ret = 1; -+ goto done; -+ } -+ -+ if ((slots=PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, -+ NULL)) == NULL) { -+ fprintf(stderr, "No tokens found\n"); -+ ret = 1; -+ goto nss_done; -+ } -+ -+ for (sle = slots->head; sle; sle = sle->next) { -+ int rv; -+ if ((rv=add_slot_keys(ac, sle->slot, !deleting)) == -1) { -+ ret = 1; -+ } -+ count += rv; -+ } -+ if (count == 0) { -+ ret = 1; -+ } -+nss_done: -+ NSS_Shutdown(); -+ clear_pass(); -+ goto done; -+ } -+#endif - if (argc == 0) { - char buf[MAXPATHLEN]; - struct passwd *pw; -diff -urpN openssh-4.5p1/ssh-agent.c openssh-4.5p1.nss/ssh-agent.c ---- openssh-4.5p1/ssh-agent.c 2006-10-23 19:01:16.000000000 +0200 -+++ openssh-4.5p1.nss/ssh-agent.c 2007-05-29 11:55:54.000000000 +0200 -@@ -79,6 +79,10 @@ - #include "scard.h" - #endif - -+#ifdef HAVE_LIBNSS -+#include "nsskeys.h" -+#endif -+ - #if defined(HAVE_SYS_PRCTL_H) - #include /* For prctl() and PR_SET_DUMPABLE */ - #endif -@@ -690,6 +694,114 @@ send: - } - #endif /* SMARTCARD */ - -+#ifdef HAVE_LIBNSS -+static void -+process_add_nss_key (SocketEntry *e) -+{ -+ char *tokenname = NULL, *keyname = NULL, *password = NULL; -+ int i, version, success = 0, death = 0, confirm = 0; -+ Key **keys, *k; -+ Identity *id; -+ Idtab *tab; -+ -+ tokenname = buffer_get_string(&e->request, NULL); -+ keyname = buffer_get_string(&e->request, NULL); -+ password = buffer_get_string(&e->request, NULL); -+ -+ while (buffer_len(&e->request)) { -+ switch (buffer_get_char(&e->request)) { -+ case SSH_AGENT_CONSTRAIN_LIFETIME: -+ death = time(NULL) + buffer_get_int(&e->request); -+ break; -+ case SSH_AGENT_CONSTRAIN_CONFIRM: -+ confirm = 1; -+ break; -+ default: -+ break; -+ } -+ } -+ if (lifetime && !death) -+ death = time(NULL) + lifetime; -+ -+ keys = nss_get_keys(tokenname, keyname, password); -+ /* password is owned by keys[0] now */ -+ xfree(tokenname); -+ xfree(keyname); -+ -+ if (keys == NULL) { -+ memset(password, 0, strlen(password)); -+ xfree(password); -+ error("nss_get_keys failed"); -+ goto send; -+ } -+ for (i = 0; keys[i] != NULL; i++) { -+ k = keys[i]; -+ version = k->type == KEY_RSA1 ? 1 : 2; -+ tab = idtab_lookup(version); -+ if (lookup_identity(k, version) == NULL) { -+ id = xmalloc(sizeof(Identity)); -+ id->key = k; -+ id->comment = nss_get_key_label(k); -+ id->death = death; -+ id->confirm = confirm; -+ TAILQ_INSERT_TAIL(&tab->idlist, id, next); -+ tab->nentries++; -+ success = 1; -+ } else { -+ key_free(k); -+ } -+ keys[i] = NULL; -+ } -+ xfree(keys); -+send: -+ buffer_put_int(&e->output, 1); -+ buffer_put_char(&e->output, -+ success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); -+} -+ -+static void -+process_remove_nss_key(SocketEntry *e) -+{ -+ char *tokenname = NULL, *keyname = NULL, *password = NULL; -+ int i, version, success = 0; -+ Key **keys, *k = NULL; -+ Identity *id; -+ Idtab *tab; -+ -+ tokenname = buffer_get_string(&e->request, NULL); -+ keyname = buffer_get_string(&e->request, NULL); -+ password = buffer_get_string(&e->request, NULL); -+ -+ keys = nss_get_keys(tokenname, keyname, password); -+ xfree(tokenname); -+ xfree(keyname); -+ xfree(password); -+ -+ if (keys == NULL || keys[0] == NULL) { -+ error("nss_get_keys failed"); -+ goto send; -+ } -+ for (i = 0; keys[i] != NULL; i++) { -+ k = keys[i]; -+ version = k->type == KEY_RSA1 ? 1 : 2; -+ if ((id = lookup_identity(k, version)) != NULL) { -+ tab = idtab_lookup(version); -+ TAILQ_REMOVE(&tab->idlist, id, next); -+ tab->nentries--; -+ free_identity(id); -+ success = 1; -+ } -+ key_free(k); -+ keys[i] = NULL; -+ } -+ xfree(keys); -+send: -+ buffer_put_int(&e->output, 1); -+ buffer_put_char(&e->output, -+ success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); -+} -+#endif /* HAVE_LIBNSS */ -+ - /* dispatch incoming messages */ - - static void -@@ -785,6 +897,15 @@ process_message(SocketEntry *e) - process_remove_smartcard_key(e); - break; - #endif /* SMARTCARD */ -+#ifdef HAVE_LIBNSS -+ case SSH_AGENTC_ADD_NSS_KEY: -+ case SSH_AGENTC_ADD_NSS_KEY_CONSTRAINED: -+ process_add_nss_key(e); -+ break; -+ case SSH_AGENTC_REMOVE_NSS_KEY: -+ process_remove_nss_key(e); -+ break; -+#endif /* SMARTCARD */ - default: - /* Unknown message. Respond with failure. */ - error("Unknown message %d", type); -diff -urpN openssh-4.5p1/ssh.c openssh-4.5p1.nss/ssh.c ---- openssh-4.5p1/ssh.c 2006-10-23 19:01:16.000000000 +0200 -+++ openssh-4.5p1.nss/ssh.c 2007-06-20 15:45:40.000000000 +0200 -@@ -104,6 +104,9 @@ - #ifdef SMARTCARD - #include "scard.h" - #endif -+#ifdef HAVE_LIBNSS -+#include "nsskeys.h" -+#endif - - extern char *__progname; - -@@ -1227,9 +1230,11 @@ load_public_identity_files(void) - int i = 0; - Key *public; - struct passwd *pw; --#ifdef SMARTCARD -+#if defined(SMARTCARD) || defined(HAVE_LIBNSS) - Key **keys; -+#endif - -+#ifdef SMARTCARD - if (options.smartcard_device != NULL && - options.num_identity_files < SSH_MAX_IDENTITY_FILES && - (keys = sc_get_keys(options.smartcard_device, NULL)) != NULL) { -@@ -1250,6 +1255,27 @@ load_public_identity_files(void) - xfree(keys); - } - #endif /* SMARTCARD */ -+#ifdef HAVE_LIBNSS -+ if (options.use_nss && -+ options.num_identity_files < SSH_MAX_IDENTITY_FILES && -+ (keys = nss_get_keys(options.nss_token, NULL, NULL)) != NULL) { -+ int count; -+ for (count = 0; keys[count] != NULL; count++) { -+ memmove(&options.identity_files[1], &options.identity_files[0], -+ sizeof(char *) * (SSH_MAX_IDENTITY_FILES - 1)); -+ memmove(&options.identity_keys[1], &options.identity_keys[0], -+ sizeof(Key *) * (SSH_MAX_IDENTITY_FILES - 1)); -+ options.num_identity_files++; -+ options.identity_keys[0] = keys[count]; -+ options.identity_files[0] = nss_get_key_label(keys[count]); -+ } -+ if (options.num_identity_files > SSH_MAX_IDENTITY_FILES) -+ options.num_identity_files = SSH_MAX_IDENTITY_FILES; -+ i += count; -+ xfree(keys); -+ } -+#endif /* HAVE_LIBNSS */ -+ - if ((pw = getpwuid(original_real_uid)) == NULL) - fatal("load_public_identity_files: getpwuid failed"); - if (gethostname(thishost, sizeof(thishost)) == -1) -diff -urpN openssh-4.5p1/ssh-dss.c openssh-4.5p1.nss/ssh-dss.c ---- openssh-4.5p1/ssh-dss.c 2006-11-07 13:14:42.000000000 +0100 -+++ openssh-4.5p1.nss/ssh-dss.c 2007-05-25 15:45:19.000000000 +0200 -@@ -39,6 +39,10 @@ - #include "log.h" - #include "key.h" - -+#ifdef HAVE_LIBNSS -+#include -+#endif -+ - #define INTBLOB_LEN 20 - #define SIGBLOB_LEN (2*INTBLOB_LEN) - -@@ -57,6 +61,34 @@ ssh_dss_sign(const Key *key, u_char **si - error("ssh_dss_sign: no DSA key"); - return -1; - } -+#ifdef HAVE_LIBNSS -+ if (key->flags & KEY_FLAG_NSS) { -+ SECItem sigitem; -+ SECItem *rawsig; -+ -+ memset(&sigitem, 0, sizeof(sigitem)); -+ if (SEC_SignData(&sigitem, (u_char *)data, datalen, key->nss->privk, -+ SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) != SECSuccess) { -+ error("ssh_dss_sign: sign failed"); -+ return -1; -+ } -+ -+ if ((rawsig=DSAU_DecodeDerSig(&sigitem)) == NULL) { -+ error("ssh_dss_sign: der decode failed"); -+ SECITEM_ZfreeItem(&sigitem, PR_FALSE); -+ return -1; -+ } -+ SECITEM_ZfreeItem(&sigitem, PR_FALSE); -+ if (rawsig->len != SIGBLOB_LEN) { -+ error("ssh_dss_sign: unsupported signature length %d", -+ rawsig->len); -+ SECITEM_ZfreeItem(rawsig, PR_TRUE); -+ return -1; -+ } -+ memcpy(sigblob, rawsig->data, SIGBLOB_LEN); -+ SECITEM_ZfreeItem(rawsig, PR_TRUE); -+ } else { -+#endif - EVP_DigestInit(&md, evp_md); - EVP_DigestUpdate(&md, data, datalen); - EVP_DigestFinal(&md, digest, &dlen); -@@ -80,7 +112,9 @@ ssh_dss_sign(const Key *key, u_char **si - BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen); - BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen); - DSA_SIG_free(sig); -- -+#ifdef HAVE_LIBNSS -+ } -+#endif - if (datafellows & SSH_BUG_SIGBLOB) { - if (lenp != NULL) - *lenp = SIGBLOB_LEN; -diff -urpN openssh-4.5p1/ssh-keygen.c openssh-4.5p1.nss/ssh-keygen.c ---- openssh-4.5p1/ssh-keygen.c 2006-11-07 13:14:42.000000000 +0100 -+++ openssh-4.5p1.nss/ssh-keygen.c 2007-06-20 18:24:40.000000000 +0200 -@@ -52,6 +52,11 @@ - #include "scard.h" - #endif - -+#ifdef HAVE_LIBNSS -+#include -+#include "nsskeys.h" -+#endif -+ - /* Number of bits in the RSA/DSA key. This value can be set on the command line. */ - #define DEFAULT_BITS 2048 - #define DEFAULT_BITS_DSA 1024 -@@ -500,6 +505,26 @@ do_download(struct passwd *pw, const cha - } - #endif /* SMARTCARD */ - -+#ifdef HAVE_LIBNSS -+static void -+do_nss_download(struct passwd *pw, const char *tokenname, const char *keyname) -+{ -+ Key **keys = NULL; -+ int i; -+ -+ keys = nss_get_keys(tokenname, keyname, NULL); -+ if (keys == NULL) -+ fatal("cannot find public key in NSS"); -+ for (i = 0; keys[i]; i++) { -+ key_write(keys[i], stdout); -+ key_free(keys[i]); -+ fprintf(stdout, "\n"); -+ } -+ xfree(keys); -+ exit(0); -+} -+#endif /* HAVE_LIBNSS */ -+ - static void - do_fingerprint(struct passwd *pw) - { -@@ -1057,7 +1082,8 @@ main(int ac, char **av) - Key *private, *public; - struct passwd *pw; - struct stat st; -- int opt, type, fd, download = 0; -+ int opt, type, fd, download = 1; -+ int use_nss = 0; - u_int32_t memory = 0, generator_wanted = 0, trials = 100; - int do_gen_candidates = 0, do_screen_candidates = 0; - int log_level = SYSLOG_LEVEL_INFO; -@@ -1091,7 +1117,7 @@ main(int ac, char **av) - } - - while ((opt = getopt(ac, av, -- "degiqpclBHvxXyF:b:f:t:U:D:P:N:C:r:g:R:T:G:M:S:a:W:")) != -1) { -+ "degiqpclnBHvxXyF:b:f:t:U:D:P:N:C:r:g:R:T:G:M:S:a:W:")) != -1) { - switch (opt) { - case 'b': - bits = (u_int32_t)strtonum(optarg, 768, 32768, &errstr); -@@ -1131,6 +1157,10 @@ main(int ac, char **av) - case 'g': - print_generic = 1; - break; -+ case 'n': -+ use_nss = 1; -+ download = 1; -+ break; - case 'P': - identity_passphrase = optarg; - break; -@@ -1162,10 +1192,10 @@ main(int ac, char **av) - case 't': - key_type_name = optarg; - break; -- case 'D': -- download = 1; -- /*FALLTHROUGH*/ - case 'U': -+ download = 0; -+ /*FALLTHROUGH*/ -+ case 'D': - reader_id = optarg; - break; - case 'v': -@@ -1270,6 +1300,17 @@ main(int ac, char **av) - exit(0); - } - } -+ -+ if (use_nss) { -+#ifdef HAVE_LIBNSS -+ if (download) -+ do_nss_download(pw, reader_id, identity_file); -+ else -+ fatal("no support for NSS key upload."); -+#else -+ fatal("no support for NSS keys."); -+#endif -+ } - if (reader_id != NULL) { - #ifdef SMARTCARD - if (download) -diff -urpN openssh-4.5p1/ssh-rsa.c openssh-4.5p1.nss/ssh-rsa.c ---- openssh-4.5p1/ssh-rsa.c 2006-09-01 07:38:37.000000000 +0200 -+++ openssh-4.5p1.nss/ssh-rsa.c 2007-05-25 15:44:57.000000000 +0200 -@@ -32,6 +32,10 @@ - #include "compat.h" - #include "ssh.h" - -+#ifdef HAVE_LIBNSS -+#include -+#endif -+ - static int openssh_RSA_verify(int, u_char *, u_int, u_char *, u_int, RSA *); - - /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ -@@ -50,6 +54,38 @@ ssh_rsa_sign(const Key *key, u_char **si - error("ssh_rsa_sign: no RSA key"); - return -1; - } -+ -+ slen = RSA_size(key->rsa); -+ sig = xmalloc(slen); -+ -+#ifdef HAVE_LIBNSS -+ if (key->flags & KEY_FLAG_NSS) { -+ SECItem sigitem; -+ SECOidTag alg; -+ -+ memset(&sigitem, 0, sizeof(sigitem)); -+ alg = (datafellows & SSH_BUG_RSASIGMD5) ? -+ SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION : -+ SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; -+ -+ if (SEC_SignData(&sigitem, (u_char *)data, datalen, key->nss->privk, -+ alg) != SECSuccess) { -+ error("ssh_rsa_sign: sign failed"); -+ return -1; -+ } -+ if (sigitem.len > slen) { -+ error("ssh_rsa_sign: slen %u slen2 %u", slen, sigitem.len); -+ xfree(sig); -+ SECITEM_ZfreeItem(&sigitem, PR_FALSE); -+ return -1; -+ } -+ if (sigitem.len < slen) { -+ memset(sig, 0, slen - sigitem.len); -+ } -+ memcpy(sig+slen-sigitem.len, sigitem.data, sigitem.len); -+ SECITEM_ZfreeItem(&sigitem, PR_FALSE); -+ } else { -+#endif - nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1; - if ((evp_md = EVP_get_digestbynid(nid)) == NULL) { - error("ssh_rsa_sign: EVP_get_digestbynid %d failed", nid); -@@ -59,9 +95,6 @@ ssh_rsa_sign(const Key *key, u_char **si - EVP_DigestUpdate(&md, data, datalen); - EVP_DigestFinal(&md, digest, &dlen); - -- slen = RSA_size(key->rsa); -- sig = xmalloc(slen); -- - ok = RSA_sign(nid, digest, dlen, sig, &len, key->rsa); - memset(digest, 'd', sizeof(digest)); - -@@ -83,6 +116,9 @@ ssh_rsa_sign(const Key *key, u_char **si - xfree(sig); - return -1; - } -+#ifdef HAVE_LIBNSS -+ } -+#endif - /* encode signature */ - buffer_init(&b); - buffer_put_cstring(&b, "ssh-rsa"); diff --git a/openssh-4.5p1-redhat.patch b/openssh-4.5p1-redhat.patch deleted file mode 100644 index 2d10fa6..0000000 --- a/openssh-4.5p1-redhat.patch +++ /dev/null @@ -1,99 +0,0 @@ ---- openssh-4.5p1/sshd_config.0.redhat 2006-11-07 14:07:28.000000000 +0100 -+++ openssh-4.5p1/sshd_config.0 2006-12-20 22:04:16.000000000 +0100 -@@ -430,9 +430,9 @@ - - SyslogFacility - Gives the facility code that is used when logging messages from -- sshd(8). The possible values are: DAEMON, USER, AUTH, LOCAL0, -- LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The de- -- fault is AUTH. -+ sshd(8). The possible values are: DAEMON, USER, AUTH, AUTHPRIV, -+ LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. -+ The default is AUTH. - - TCPKeepAlive - Specifies whether the system should send TCP keepalive messages ---- openssh-4.5p1/sshd_config.redhat 2006-07-24 06:06:47.000000000 +0200 -+++ openssh-4.5p1/sshd_config 2006-12-20 21:59:15.000000000 +0100 -@@ -12,6 +12,7 @@ - - #Port 22 - #Protocol 2,1 -+Protocol 2 - #AddressFamily any - #ListenAddress 0.0.0.0 - #ListenAddress :: -@@ -29,6 +30,7 @@ - # Logging - # obsoletes QuietMode and FascistLogging - #SyslogFacility AUTH -+SyslogFacility AUTHPRIV - #LogLevel INFO - - # Authentication: -@@ -55,9 +57,11 @@ - # To disable tunneled clear text passwords, change to no here! - #PasswordAuthentication yes - #PermitEmptyPasswords no -+PasswordAuthentication yes - - # Change to no to disable s/key passwords - #ChallengeResponseAuthentication yes -+ChallengeResponseAuthentication no - - # Kerberos options - #KerberosAuthentication no -@@ -67,7 +71,9 @@ - - # GSSAPI options - #GSSAPIAuthentication no -+GSSAPIAuthentication yes - #GSSAPICleanupCredentials yes -+GSSAPICleanupCredentials yes - - # Set this to 'yes' to enable PAM authentication, account processing, - # and session processing. If this is enabled, PAM authentication will -@@ -79,10 +85,16 @@ - # PAM authentication, then enable this but set PasswordAuthentication - # and ChallengeResponseAuthentication to 'no'. - #UsePAM no -+UsePAM yes - -+# Accept locale-related environment variables -+AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES -+AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT -+AcceptEnv LC_IDENTIFICATION LC_ALL - #AllowTcpForwarding yes - #GatewayPorts no - #X11Forwarding no -+X11Forwarding yes - #X11DisplayOffset 10 - #X11UseLocalhost yes - #PrintMotd yes ---- openssh-4.5p1/ssh_config.redhat 2006-06-13 05:01:10.000000000 +0200 -+++ openssh-4.5p1/ssh_config 2006-12-20 21:59:15.000000000 +0100 -@@ -42,3 +42,13 @@ - # Tunnel no - # TunnelDevice any:any - # PermitLocalCommand no -+Host * -+ GSSAPIAuthentication yes -+# If this option is set to yes then remote X11 clients will have full access -+# to the original X11 display. As virtually no X11 client supports the untrusted -+# mode correctly we set this to yes. -+ ForwardX11Trusted yes -+# Send locale-related environment variables -+ SendEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES -+ SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT -+ SendEnv LC_IDENTIFICATION LC_ALL ---- openssh-4.5p1/sshd_config.5.redhat 2006-08-30 03:06:34.000000000 +0200 -+++ openssh-4.5p1/sshd_config.5 2006-12-20 22:05:18.000000000 +0100 -@@ -740,7 +740,7 @@ - .It Cm SyslogFacility - Gives the facility code that is used when logging messages from - .Xr sshd 8 . --The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2, -+The possible values are: DAEMON, USER, AUTH, AUTHPRIV, LOCAL0, LOCAL1, LOCAL2, - LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. - The default is AUTH. - .It Cm TCPKeepAlive diff --git a/openssh-4.5p1-selinux.patch b/openssh-4.5p1-selinux.patch deleted file mode 100644 index 3eac2d4..0000000 --- a/openssh-4.5p1-selinux.patch +++ /dev/null @@ -1,255 +0,0 @@ ---- openssh-4.5p1/auth.h.selinux 2006-08-18 16:32:46.000000000 +0200 -+++ openssh-4.5p1/auth.h 2006-12-20 22:10:48.000000000 +0100 -@@ -58,6 +58,7 @@ - char *service; - struct passwd *pw; /* set if 'valid' */ - char *style; -+ char *role; - void *kbdintctxt; - #ifdef BSD_AUTH - auth_session_t *as; ---- openssh-4.5p1/auth1.c.selinux 2006-12-20 22:10:35.000000000 +0100 -+++ openssh-4.5p1/auth1.c 2006-12-20 22:10:48.000000000 +0100 -@@ -388,7 +388,7 @@ - do_authentication(Authctxt *authctxt) - { - u_int ulen; -- char *user, *style = NULL; -+ char *user, *style = NULL, *role=NULL; - - /* Get the name of the user that we wish to log in as. */ - packet_read_expect(SSH_CMSG_USER); -@@ -397,11 +397,19 @@ - user = packet_get_string(&ulen); - packet_check_eom(); - -+ if ((role = strchr(user, '/')) != NULL) -+ *role++ = '\0'; -+ - if ((style = strchr(user, ':')) != NULL) - *style++ = '\0'; -+ else -+ if (role && (style = strchr(role, ':')) != NULL) -+ *style++ = '\0'; -+ - - authctxt->user = user; - authctxt->style = style; -+ authctxt->role = role; - - /* Verify that the user is a valid user. */ - if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL) ---- openssh-4.5p1/monitor.c.selinux 2006-11-07 13:16:08.000000000 +0100 -+++ openssh-4.5p1/monitor.c 2006-12-20 22:10:48.000000000 +0100 -@@ -133,6 +133,7 @@ - int mm_answer_pwnamallow(int, Buffer *); - int mm_answer_auth2_read_banner(int, Buffer *); - int mm_answer_authserv(int, Buffer *); -+int mm_answer_authrole(int, Buffer *); - int mm_answer_authpassword(int, Buffer *); - int mm_answer_bsdauthquery(int, Buffer *); - int mm_answer_bsdauthrespond(int, Buffer *); -@@ -204,6 +205,7 @@ - {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, - {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, - {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, -+ {MONITOR_REQ_AUTHROLE, MON_ONCE, mm_answer_authrole}, - {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner}, - {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, - #ifdef USE_PAM -@@ -653,6 +655,7 @@ - else { - /* Allow service/style information on the auth context */ - monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1); -+ monitor_permit(mon_dispatch, MONITOR_REQ_AUTHROLE, 1); - monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1); - } - -@@ -698,6 +701,23 @@ - } - - int -+mm_answer_authrole(int sock, Buffer *m) -+{ -+ monitor_permit_authentications(1); -+ -+ authctxt->role = buffer_get_string(m, NULL); -+ debug3("%s: role=%s", -+ __func__, authctxt->role); -+ -+ if (strlen(authctxt->role) == 0) { -+ xfree(authctxt->role); -+ authctxt->role = NULL; -+ } -+ -+ return (0); -+} -+ -+int - mm_answer_authpassword(int sock, Buffer *m) - { - static int call_count; ---- openssh-4.5p1/openbsd-compat/port-linux.c.selinux 2006-09-01 07:38:41.000000000 +0200 -+++ openssh-4.5p1/openbsd-compat/port-linux.c 2006-12-21 12:15:59.000000000 +0100 -@@ -30,11 +30,16 @@ - #ifdef WITH_SELINUX - #include "log.h" - #include "port-linux.h" -+#include "key.h" -+#include "hostfile.h" -+#include "auth.h" - - #include - #include - #include - -+extern Authctxt *the_authctxt; -+ - /* Wrapper around is_selinux_enabled() to log its return value once only */ - static int - ssh_selinux_enabled(void) -@@ -53,23 +58,36 @@ - static security_context_t - ssh_selinux_getctxbyname(char *pwname) - { -- security_context_t sc; -- char *sename = NULL, *lvl = NULL; -- int r; -+ security_context_t sc = NULL; -+ char *sename, *lvl; -+ char *role = NULL; -+ int r = 0; - -+ if (the_authctxt) -+ role=the_authctxt->role; - #ifdef HAVE_GETSEUSERBYNAME -- if (getseuserbyname(pwname, &sename, &lvl) != 0) -- return NULL; -+ if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) { -+ sename = NULL; -+ lvl = NULL; -+ } - #else - sename = pwname; - lvl = NULL; - #endif - -+ if (r == 0) { - #ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL -- r = get_default_context_with_level(sename, lvl, NULL, &sc); -+ if (role != NULL && role[0]) -+ r = get_default_context_with_rolelevel(sename, role, lvl, NULL, &sc); -+ else -+ r = get_default_context_with_level(sename, lvl, NULL, &sc); - #else -- r = get_default_context(sename, NULL, &sc); -+ if (role != NULL && role[0]) -+ r = get_default_context_with_role(sename, role, NULL, &sc); -+ else -+ r = get_default_context(sename, NULL, &sc); - #endif -+ } - - if (r != 0) { - switch (security_getenforce()) { ---- openssh-4.5p1/configure.ac.selinux 2006-12-20 22:10:35.000000000 +0100 -+++ openssh-4.5p1/configure.ac 2006-12-21 11:18:48.000000000 +0100 -@@ -3137,8 +3137,16 @@ - SELINUX_MSG="no" - LIBSELINUX="" - AC_ARG_WITH(selinux, -- [ --with-selinux Enable SELinux support], -+ [ --with-selinux[[=LIBSELINUX-PATH]] Enable SELinux support], - [ if test "x$withval" != "xno" ; then -+ if test "x$withval" != "xyes"; then -+ CPPFLAGS="$CPPFLAGS -I${withval}/include" -+ if test -n "${need_dash_r}"; then -+ LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}" -+ else -+ LDFLAGS="-L${withval}/lib ${LDFLAGS}" -+ fi -+ fi - AC_DEFINE(WITH_SELINUX,1,[Define if you want SELinux support.]) - SELINUX_MSG="yes" - AC_CHECK_HEADER([selinux/selinux.h], , ---- openssh-4.5p1/auth2.c.selinux 2006-08-05 04:39:39.000000000 +0200 -+++ openssh-4.5p1/auth2.c 2006-12-20 22:10:48.000000000 +0100 -@@ -145,7 +145,7 @@ - { - Authctxt *authctxt = ctxt; - Authmethod *m = NULL; -- char *user, *service, *method, *style = NULL; -+ char *user, *service, *method, *style = NULL, *role = NULL; - int authenticated = 0; - - if (authctxt == NULL) -@@ -157,6 +157,9 @@ - debug("userauth-request for user %s service %s method %s", user, service, method); - debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); - -+ if ((role = strchr(user, '/')) != NULL) -+ *role++ = 0; -+ - if ((style = strchr(user, ':')) != NULL) - *style++ = 0; - -@@ -182,8 +185,11 @@ - use_privsep ? " [net]" : ""); - authctxt->service = xstrdup(service); - authctxt->style = style ? xstrdup(style) : NULL; -- if (use_privsep) -+ authctxt->role = role ? xstrdup(role) : NULL; -+ if (use_privsep) { - mm_inform_authserv(service, style); -+ mm_inform_authrole(role); -+ } - } else if (strcmp(user, authctxt->user) != 0 || - strcmp(service, authctxt->service) != 0) { - packet_disconnect("Change of username or service not allowed: " ---- openssh-4.5p1/monitor_wrap.h.selinux 2006-08-05 04:39:40.000000000 +0200 -+++ openssh-4.5p1/monitor_wrap.h 2006-12-20 22:10:48.000000000 +0100 -@@ -41,6 +41,7 @@ - DH *mm_choose_dh(int, int, int); - int mm_key_sign(Key *, u_char **, u_int *, u_char *, u_int); - void mm_inform_authserv(char *, char *); -+void mm_inform_authrole(char *); - struct passwd *mm_getpwnamallow(const char *); - char *mm_auth2_read_banner(void); - int mm_auth_password(struct Authctxt *, char *); ---- openssh-4.5p1/monitor_wrap.c.selinux 2006-09-01 07:38:37.000000000 +0200 -+++ openssh-4.5p1/monitor_wrap.c 2006-12-20 22:10:48.000000000 +0100 -@@ -282,6 +282,23 @@ - buffer_free(&m); - } - -+/* Inform the privileged process about role */ -+ -+void -+mm_inform_authrole(char *role) -+{ -+ Buffer m; -+ -+ debug3("%s entering", __func__); -+ -+ buffer_init(&m); -+ buffer_put_cstring(&m, role ? role : ""); -+ -+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHROLE, &m); -+ -+ buffer_free(&m); -+} -+ - /* Do the password authentication */ - int - mm_auth_password(Authctxt *authctxt, char *password) ---- openssh-4.5p1/monitor.h.selinux 2006-03-26 05:30:02.000000000 +0200 -+++ openssh-4.5p1/monitor.h 2006-12-20 22:10:35.000000000 +0100 -@@ -30,7 +30,7 @@ - - enum monitor_reqtype { - MONITOR_REQ_MODULI, MONITOR_ANS_MODULI, -- MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV, -+ MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV,MONITOR_REQ_AUTHROLE, - MONITOR_REQ_SIGN, MONITOR_ANS_SIGN, - MONITOR_REQ_PWNAM, MONITOR_ANS_PWNAM, - MONITOR_REQ_AUTH2_READ_BANNER, MONITOR_ANS_AUTH2_READ_BANNER, diff --git a/openssh-4.5p1-sftp-drain-acks.patch b/openssh-4.5p1-sftp-drain-acks.patch deleted file mode 100644 index 4e1d3d5..0000000 --- a/openssh-4.5p1-sftp-drain-acks.patch +++ /dev/null @@ -1,70 +0,0 @@ -diff -up openssh-4.5p1/sftp-client.c.drain-acks openssh-4.5p1/sftp-client.c ---- openssh-4.5p1/sftp-client.c.drain-acks 2006-10-23 19:03:02.000000000 +0200 -+++ openssh-4.5p1/sftp-client.c 2007-08-07 17:46:16.000000000 +0200 -@@ -992,7 +992,8 @@ int - do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, - int pflag) - { -- int local_fd, status; -+ int local_fd; -+ int status = SSH2_FX_OK; - u_int handle_len, id, type; - u_int64_t offset; - char *handle, *data; -@@ -1074,7 +1075,7 @@ do_upload(struct sftp_conn *conn, char * - * Simulate an EOF on interrupt, allowing ACKs from the - * server to drain. - */ -- if (interrupted) -+ if (interrupted || status != SSH2_FX_OK) - len = 0; - else do - len = read(local_fd, data, conn->transfer_buflen); -@@ -1131,17 +1132,6 @@ do_upload(struct sftp_conn *conn, char * - fatal("Can't find request for ID %u", r_id); - TAILQ_REMOVE(&acks, ack, tq); - -- if (status != SSH2_FX_OK) { -- error("Couldn't write to remote file \"%s\": %s", -- remote_path, fx2txt(status)); -- if (showprogress) -- stop_progress_meter(); -- do_close(conn, handle, handle_len); -- close(local_fd); -- xfree(data); -- xfree(ack); -- goto done; -- } - debug3("In write loop, ack for %u %u bytes at %llu", - ack->id, ack->len, (unsigned long long)ack->offset); - ++ackid; -@@ -1153,21 +1143,25 @@ do_upload(struct sftp_conn *conn, char * - stop_progress_meter(); - xfree(data); - -+ if (status != SSH2_FX_OK) { -+ error("Couldn't write to remote file \"%s\": %s", -+ remote_path, fx2txt(status)); -+ status = -1; -+ } -+ - if (close(local_fd) == -1) { - error("Couldn't close local file \"%s\": %s", local_path, - strerror(errno)); -- do_close(conn, handle, handle_len); - status = -1; -- goto done; - } - - /* Override umask and utimes if asked */ - if (pflag) - do_fsetstat(conn, handle, handle_len, &a); - -- status = do_close(conn, handle, handle_len); -+ if (do_close(conn, handle, handle_len) != SSH2_FX_OK) -+ status = -1; - --done: - xfree(handle); - buffer_free(&msg); - return(status); diff --git a/openssh-4.5p1-vendor.patch b/openssh-4.5p1-vendor.patch deleted file mode 100644 index e06008a..0000000 --- a/openssh-4.5p1-vendor.patch +++ /dev/null @@ -1,143 +0,0 @@ ---- openssh-4.5p1/servconf.h.vendor 2006-08-18 16:23:15.000000000 +0200 -+++ openssh-4.5p1/servconf.h 2006-12-20 22:06:27.000000000 +0100 -@@ -120,6 +120,7 @@ - int max_startups; - int max_authtries; - char *banner; /* SSH-2 banner message */ -+ int show_patchlevel; /* Show vendor patch level to clients */ - int use_dns; - int client_alive_interval; /* - * poke the client this often to ---- openssh-4.5p1/sshd_config.vendor 2006-12-20 22:06:27.000000000 +0100 -+++ openssh-4.5p1/sshd_config 2006-12-20 22:06:27.000000000 +0100 -@@ -106,6 +106,7 @@ - #Compression delayed - #ClientAliveInterval 0 - #ClientAliveCountMax 3 -+#ShowPatchLevel no - #UseDNS yes - #PidFile /var/run/sshd.pid - #MaxStartups 10 ---- openssh-4.5p1/sshd.c.vendor 2006-11-07 13:14:42.000000000 +0100 -+++ openssh-4.5p1/sshd.c 2006-12-20 22:06:27.000000000 +0100 -@@ -418,7 +418,8 @@ - major = PROTOCOL_MAJOR_1; - minor = PROTOCOL_MINOR_1; - } -- snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", major, minor, SSH_VERSION); -+ snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", major, minor, -+ (options.show_patchlevel == 1) ? SSH_VENDOR_PATCHLEVEL : SSH_VERSION); - server_version_string = xstrdup(buf); - - /* Send our protocol version identification. */ -@@ -1429,7 +1430,8 @@ - exit(1); - } - -- debug("sshd version %.100s", SSH_RELEASE); -+ debug("sshd version %.100s", -+ (options.show_patchlevel == 1) ? SSH_VENDOR_PATCHLEVEL : SSH_RELEASE); - - /* Store privilege separation user for later use if required. */ - if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) { ---- openssh-4.5p1/configure.ac.vendor 2006-12-20 22:06:27.000000000 +0100 -+++ openssh-4.5p1/configure.ac 2006-12-20 22:06:27.000000000 +0100 -@@ -3729,6 +3729,12 @@ - fi - ] - ) -+AC_ARG_ENABLE(vendor-patchlevel, -+ [ --enable-vendor-patchlevel=TAG specify a vendor patch level], -+ [AC_DEFINE_UNQUOTED(SSH_VENDOR_PATCHLEVEL,[SSH_RELEASE "-" "$enableval"],[Define to your vendor patch level, if it has been modified from the upstream source release.]) -+ SSH_VENDOR_PATCHLEVEL="$enableval"], -+ [AC_DEFINE(SSH_VENDOR_PATCHLEVEL,SSH_RELEASE,[Define to your vendor patch level, if it has been modified from the upstream source release.]) -+ SSH_VENDOR_PATCHLEVEL=none]) - - dnl lastlog, [uw]tmpx? detection - dnl NOTE: set the paths in the platform section to avoid the -@@ -3978,6 +3984,7 @@ - echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG" - echo " BSD Auth support: $BSD_AUTH_MSG" - echo " Random number source: $RAND_MSG" -+echo " Vendor patch level: $SSH_VENDOR_PATCHLEVEL" - if test ! -z "$USE_RAND_HELPER" ; then - echo " ssh-rand-helper collects from: $RAND_HELPER_MSG" - fi ---- openssh-4.5p1/sshd_config.0.vendor 2006-12-20 22:06:27.000000000 +0100 -+++ openssh-4.5p1/sshd_config.0 2006-12-20 22:06:27.000000000 +0100 -@@ -413,6 +413,11 @@ - Defines the number of bits in the ephemeral protocol version 1 - server key. The minimum value is 512, and the default is 768. - -+ ShowPatchLevel -+ Specifies whether sshd will display the specific patch level of -+ the binary in the server identification string. The patch level -+ is set at compile-time. The default is M-bM-^@M-^\noM-bM-^@M-^]. -+ - StrictModes - Specifies whether sshd(8) should check file modes and ownership - of the user's files and home directory before accepting login. ---- openssh-4.5p1/servconf.c.vendor 2006-08-18 16:23:15.000000000 +0200 -+++ openssh-4.5p1/servconf.c 2006-12-20 22:08:41.000000000 +0100 -@@ -113,6 +113,7 @@ - options->max_startups = -1; - options->max_authtries = -1; - options->banner = NULL; -+ options->show_patchlevel = -1; - options->use_dns = -1; - options->client_alive_interval = -1; - options->client_alive_count_max = -1; -@@ -250,6 +251,9 @@ - if (options->permit_tun == -1) - options->permit_tun = SSH_TUNMODE_NO; - -+ if (options->show_patchlevel == -1) -+ options->show_patchlevel = 0; -+ - /* Turn privilege separation on by default */ - if (use_privsep == -1) - use_privsep = 1; -@@ -293,6 +297,7 @@ - sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, - sMatch, sPermitOpen, sForceCommand, - sUsePrivilegeSeparation, -+ sShowPatchLevel, - sDeprecated, sUnsupported - } ServerOpCodes; - -@@ -390,6 +395,7 @@ - { "maxstartups", sMaxStartups, SSHCFG_GLOBAL }, - { "maxauthtries", sMaxAuthTries, SSHCFG_GLOBAL }, - { "banner", sBanner, SSHCFG_GLOBAL }, -+ { "showpatchlevel", sShowPatchLevel, SSHCFG_GLOBAL }, - { "usedns", sUseDNS, SSHCFG_GLOBAL }, - { "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL }, - { "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL }, -@@ -1006,6 +1012,10 @@ - intptr = &use_privsep; - goto parse_flag; - -+ case sShowPatchLevel: -+ intptr = &options->show_patchlevel; -+ goto parse_flag; -+ - case sAllowUsers: - while ((arg = strdelim(&cp)) && *arg != '\0') { - if (options->num_allow_users >= MAX_ALLOW_USERS) ---- openssh-4.5p1/sshd_config.5.vendor 2006-12-20 22:06:27.000000000 +0100 -+++ openssh-4.5p1/sshd_config.5 2006-12-20 22:06:27.000000000 +0100 -@@ -717,6 +717,14 @@ - .It Cm ServerKeyBits - Defines the number of bits in the ephemeral protocol version 1 server key. - The minimum value is 512, and the default is 768. -+.It Cm ShowPatchLevel -+Specifies whether -+.Nm sshd -+will display the patch level of the binary in the identification string. -+The patch level is set at compile-time. -+The default is -+.Dq no . -+This option applies to protocol version 1 only. - .It Cm StrictModes - Specifies whether - .Xr sshd 8 diff --git a/openssh-4.7p1-audit.patch b/openssh-4.7p1-audit.patch new file mode 100644 index 0000000..2c925ef --- /dev/null +++ b/openssh-4.7p1-audit.patch @@ -0,0 +1,170 @@ +diff -up openssh-4.7p1/auth.c.audit openssh-4.7p1/auth.c +--- openssh-4.7p1/auth.c.audit 2007-03-26 18:35:28.000000000 +0200 ++++ openssh-4.7p1/auth.c 2007-09-06 17:07:44.000000000 +0200 +@@ -286,6 +286,12 @@ auth_log(Authctxt *authctxt, int authent + get_canonical_hostname(options.use_dns), "ssh", &loginmsg); + # endif + #endif ++#if HAVE_LINUX_AUDIT ++ if (authenticated == 0 && !authctxt->postponed) { ++ linux_audit_record_event(-1, authctxt->user, NULL, ++ get_remote_ipaddr(), "sshd", 0); ++ } ++#endif + #ifdef SSH_AUDIT_EVENTS + if (authenticated == 0 && !authctxt->postponed) + audit_event(audit_classify_auth(method)); +@@ -492,6 +498,10 @@ getpwnamallow(const char *user) + record_failed_login(user, + get_canonical_hostname(options.use_dns), "ssh"); + #endif ++#ifdef HAVE_LINUX_AUDIT ++ linux_audit_record_event(-1, user, NULL, get_remote_ipaddr(), ++ "sshd", 0); ++#endif + #ifdef SSH_AUDIT_EVENTS + audit_event(SSH_INVALID_USER); + #endif /* SSH_AUDIT_EVENTS */ +diff -up openssh-4.7p1/loginrec.c.audit openssh-4.7p1/loginrec.c +--- openssh-4.7p1/loginrec.c.audit 2007-04-29 04:10:58.000000000 +0200 ++++ openssh-4.7p1/loginrec.c 2007-09-06 17:07:44.000000000 +0200 +@@ -176,6 +176,10 @@ + #include "auth.h" + #include "buffer.h" + ++#ifdef HAVE_LINUX_AUDIT ++# include ++#endif ++ + #ifdef HAVE_UTIL_H + # include + #endif +@@ -202,6 +206,9 @@ int utmp_write_entry(struct logininfo *l + int utmpx_write_entry(struct logininfo *li); + int wtmp_write_entry(struct logininfo *li); + int wtmpx_write_entry(struct logininfo *li); ++#ifdef HAVE_LINUX_AUDIT ++int linux_audit_write_entry(struct logininfo *li); ++#endif + int lastlog_write_entry(struct logininfo *li); + int syslogin_write_entry(struct logininfo *li); + +@@ -440,6 +447,10 @@ login_write(struct logininfo *li) + + /* set the timestamp */ + login_set_current_time(li); ++#ifdef HAVE_LINUX_AUDIT ++ if (linux_audit_write_entry(li) == 0) ++ fatal("linux_audit_write_entry failed: %s", strerror(errno)); ++#endif + #ifdef USE_LOGIN + syslogin_write_entry(li); + #endif +@@ -1394,6 +1405,51 @@ wtmpx_get_entry(struct logininfo *li) + } + #endif /* USE_WTMPX */ + ++#ifdef HAVE_LINUX_AUDIT ++int ++linux_audit_record_event(int uid, const char *username, ++ const char *hostname, const char *ip, const char *ttyn, int success) ++{ ++ char buf[64]; ++ int audit_fd, rc; ++ ++ audit_fd = audit_open(); ++ if (audit_fd < 0) { ++ if (errno == EINVAL || errno == EPROTONOSUPPORT || ++ errno == EAFNOSUPPORT) ++ return 1; /* No audit support in kernel */ ++ else ++ return 0; /* Must prevent login */ ++ } ++ if (username == NULL) ++ snprintf(buf, sizeof(buf), "uid=%d", uid); ++ else ++ snprintf(buf, sizeof(buf), "acct=%s", username); ++ rc = audit_log_user_message(audit_fd, AUDIT_USER_LOGIN, ++ buf, hostname, ip, ttyn, success); ++ close(audit_fd); ++ if (rc >= 0) ++ return 1; ++ else ++ return 0; ++} ++ ++int ++linux_audit_write_entry(struct logininfo *li) ++{ ++ switch(li->type) { ++ case LTYPE_LOGIN: ++ return (linux_audit_record_event(li->uid, NULL, li->hostname, ++ NULL, li->line, 1)); ++ case LTYPE_LOGOUT: ++ return (1); /* We only care about logins */ ++ default: ++ logit("%s: invalid type field", __func__); ++ return (0); ++ } ++} ++#endif /* HAVE_LINUX_AUDIT */ ++ + /** + ** Low-level libutil login() functions + **/ +diff -up openssh-4.7p1/config.h.in.audit openssh-4.7p1/config.h.in +--- openssh-4.7p1/config.h.in.audit 2007-09-04 08:50:04.000000000 +0200 ++++ openssh-4.7p1/config.h.in 2007-09-06 17:07:44.000000000 +0200 +@@ -1334,6 +1334,9 @@ + /* Define if you want SELinux support. */ + #undef WITH_SELINUX + ++/* Define if you want Linux audit support. */ ++#undef HAVE_LINUX_AUDIT ++ + /* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ + #undef WORDS_BIGENDIAN +diff -up openssh-4.7p1/loginrec.h.audit openssh-4.7p1/loginrec.h +--- openssh-4.7p1/loginrec.h.audit 2006-08-05 04:39:40.000000000 +0200 ++++ openssh-4.7p1/loginrec.h 2007-09-06 17:07:44.000000000 +0200 +@@ -127,5 +127,9 @@ char *line_stripname(char *dst, const ch + char *line_abbrevname(char *dst, const char *src, int dstsize); + + void record_failed_login(const char *, const char *, const char *); ++#ifdef HAVE_LINUX_AUDIT ++int linux_audit_record_event(int uid, const char *username, ++ const char *hostname, const char *ip, const char *ttyn, int success); ++#endif /* HAVE_LINUX_AUDIT */ + + #endif /* _HAVE_LOGINREC_H_ */ +diff -up openssh-4.7p1/configure.ac.audit openssh-4.7p1/configure.ac +--- openssh-4.7p1/configure.ac.audit 2007-09-06 17:07:44.000000000 +0200 ++++ openssh-4.7p1/configure.ac 2007-09-06 17:15:23.000000000 +0200 +@@ -3216,6 +3216,18 @@ AC_ARG_WITH(selinux, + fi ] + ) + ++# Check whether user wants Linux audit support ++LINUX_AUDIT_MSG="no" ++AC_ARG_WITH(linux-audit, ++ [ --with-linux-audit Enable Linux audit support], ++ [ if test "x$withval" != "xno" ; then ++ AC_DEFINE(HAVE_LINUX_AUDIT,1,[Define if you want Linux audit support.]) ++ LINUX_AUDIT_MSG="yes" ++ AC_CHECK_HEADERS(libaudit.h) ++ SSHDLIBS="$SSHDLIBS -laudit" ++ fi ] ++) ++ + # Check whether user wants Kerberos 5 support + KRB5_MSG="no" + AC_ARG_WITH(kerberos5, +@@ -4037,6 +4049,7 @@ echo " PAM support + echo " OSF SIA support: $SIA_MSG" + echo " KerberosV support: $KRB5_MSG" + echo " SELinux support: $SELINUX_MSG" ++echo " Linux audit support: $LINUX_AUDIT_MSG" + echo " Smartcard support: $SCARD_MSG" + echo " S/KEY support: $SKEY_MSG" + echo " TCP Wrappers support: $TCPW_MSG" diff --git a/openssh-4.7p1-log-in-chroot.patch b/openssh-4.7p1-log-in-chroot.patch new file mode 100644 index 0000000..e510f58 --- /dev/null +++ b/openssh-4.7p1-log-in-chroot.patch @@ -0,0 +1,57 @@ +diff -up openssh-4.7p1/sshd.c.log-chroot openssh-4.7p1/sshd.c +--- openssh-4.7p1/sshd.c.log-chroot 2007-09-06 17:24:13.000000000 +0200 ++++ openssh-4.7p1/sshd.c 2007-09-06 17:24:13.000000000 +0200 +@@ -596,6 +596,10 @@ privsep_preauth_child(void) + /* Demote the private keys to public keys. */ + demote_sensitive_data(); + ++ /* Open the syslog permanently so the chrooted process still ++ can write to syslog. */ ++ open_log(); ++ + /* Change our root directory */ + if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1) + fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR, +diff -up openssh-4.7p1/log.c.log-chroot openssh-4.7p1/log.c +--- openssh-4.7p1/log.c.log-chroot 2007-05-20 07:08:16.000000000 +0200 ++++ openssh-4.7p1/log.c 2007-09-06 17:29:34.000000000 +0200 +@@ -56,6 +56,7 @@ static LogLevel log_level = SYSLOG_LEVEL + static int log_on_stderr = 1; + static int log_facility = LOG_AUTH; + static char *argv0; ++static int log_fd_keep; + + extern char *__progname; + +@@ -370,10 +371,21 @@ do_log(LogLevel level, const char *fmt, + syslog_r(pri, &sdata, "%.500s", fmtbuf); + closelog_r(&sdata); + #else ++ if (!log_fd_keep) { + openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility); ++ } + syslog(pri, "%.500s", fmtbuf); ++ if (!log_fd_keep) { + closelog(); ++ } + #endif + } + errno = saved_errno; + } ++ ++void ++open_log(void) ++{ ++ openlog(argv0 ? argv0 : __progname, LOG_PID|LOG_NDELAY, log_facility); ++ log_fd_keep = 1; ++} +diff -up openssh-4.7p1/log.h.log-chroot openssh-4.7p1/log.h +--- openssh-4.7p1/log.h.log-chroot 2006-08-18 16:32:21.000000000 +0200 ++++ openssh-4.7p1/log.h 2007-09-06 17:24:13.000000000 +0200 +@@ -62,4 +62,6 @@ void debug3(const char *, ...) __att + + void do_log(LogLevel, const char *, va_list); + void cleanup_exit(int) __dead; ++ ++void open_log(void); + #endif diff --git a/openssh-4.7p1-mls.patch b/openssh-4.7p1-mls.patch new file mode 100644 index 0000000..286fd0f --- /dev/null +++ b/openssh-4.7p1-mls.patch @@ -0,0 +1,433 @@ +diff -up openssh-4.7p1/misc.c.mls openssh-4.7p1/misc.c +--- openssh-4.7p1/misc.c.mls 2007-01-05 06:24:48.000000000 +0100 ++++ openssh-4.7p1/misc.c 2007-09-06 17:39:28.000000000 +0200 +@@ -418,6 +418,7 @@ char * + colon(char *cp) + { + int flag = 0; ++ int start = 1; + + if (*cp == ':') /* Leading colon is part of file name. */ + return (0); +@@ -431,8 +432,13 @@ colon(char *cp) + return (cp+1); + if (*cp == ':' && !flag) + return (cp); +- if (*cp == '/') +- return (0); ++ if (start) { ++ /* Slash on beginning or after dots only denotes file name. */ ++ if (*cp == '/') ++ return (0); ++ if (*cp != '.') ++ start = 0; ++ } + } + return (0); + } +diff -up openssh-4.7p1/session.c.mls openssh-4.7p1/session.c +--- openssh-4.7p1/session.c.mls 2007-09-06 17:39:28.000000000 +0200 ++++ openssh-4.7p1/session.c 2007-09-06 17:39:28.000000000 +0200 +@@ -1347,10 +1347,6 @@ do_setusercontext(struct passwd *pw) + #endif + if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid) + fatal("Failed to set uids to %u.", (u_int) pw->pw_uid); +- +-#ifdef WITH_SELINUX +- ssh_selinux_setup_exec_context(pw->pw_name); +-#endif + } + + static void +diff -up openssh-4.7p1/openbsd-compat/port-linux.c.mls openssh-4.7p1/openbsd-compat/port-linux.c +--- openssh-4.7p1/openbsd-compat/port-linux.c.mls 2007-09-06 17:39:28.000000000 +0200 ++++ openssh-4.7p1/openbsd-compat/port-linux.c 2007-08-07 17:38:18.000000000 +0200 +@@ -1,4 +1,4 @@ +-/* $Id: port-linux.c,v 1.4 2007/06/27 22:48:03 djm Exp $ */ ++/* $Id: port-linux.c,v 1.3 2006/09/01 05:38:41 djm Exp $ */ + + /* + * Copyright (c) 2005 Daniel Walsh +@@ -33,12 +33,23 @@ + #include "key.h" + #include "hostfile.h" + #include "auth.h" ++#include "xmalloc.h" + + #include + #include ++#include + #include ++#include ++#include ++ ++#ifdef HAVE_LINUX_AUDIT ++#include ++#include ++#endif + + extern Authctxt *the_authctxt; ++extern int inetd_flag; ++extern int rexeced_flag; + + /* Wrapper around is_selinux_enabled() to log its return value once only */ + static int +@@ -54,17 +65,173 @@ ssh_selinux_enabled(void) + return (enabled); + } + ++/* Send audit message */ ++static int ++send_audit_message(int success, security_context_t default_context, ++ security_context_t selected_context) ++{ ++ int rc=0; ++#ifdef HAVE_LINUX_AUDIT ++ char *msg = NULL; ++ int audit_fd = audit_open(); ++ security_context_t default_raw=NULL; ++ security_context_t selected_raw=NULL; ++ rc = -1; ++ if (audit_fd < 0) { ++ if (errno == EINVAL || errno == EPROTONOSUPPORT || ++ errno == EAFNOSUPPORT) ++ return 0; /* No audit support in kernel */ ++ error("Error connecting to audit system."); ++ return rc; ++ } ++ if (selinux_trans_to_raw_context(default_context, &default_raw) < 0) { ++ error("Error translating default context."); ++ default_raw = NULL; ++ } ++ if (selinux_trans_to_raw_context(selected_context, &selected_raw) < 0) { ++ error("Error translating selected context."); ++ selected_raw = NULL; ++ } ++ if (asprintf(&msg, "sshd: default-context=%s selected-context=%s", ++ default_raw ? default_raw : (default_context ? default_context: "?"), ++ selected_context ? selected_raw : (selected_context ? selected_context :"?")) < 0) { ++ error("Error allocating memory."); ++ goto out; ++ } ++ if (audit_log_user_message(audit_fd, AUDIT_USER_ROLE_CHANGE, ++ msg, NULL, NULL, NULL, success) <= 0) { ++ error("Error sending audit message."); ++ goto out; ++ } ++ rc = 0; ++ out: ++ free(msg); ++ freecon(default_raw); ++ freecon(selected_raw); ++ close(audit_fd); ++#endif ++ return rc; ++} ++ ++static int ++mls_range_allowed(security_context_t src, security_context_t dst) ++{ ++ struct av_decision avd; ++ int retval; ++ unsigned int bit = CONTEXT__CONTAINS; ++ ++ debug("%s: src:%s dst:%s", __func__, src, dst); ++ retval = security_compute_av(src, dst, SECCLASS_CONTEXT, bit, &avd); ++ if (retval || ((bit & avd.allowed) != bit)) ++ return 0; ++ ++ return 1; ++} ++ ++static int ++get_user_context(const char *sename, const char *role, const char *lvl, ++ security_context_t *sc) { ++#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL ++ if (lvl == NULL || lvl[0] == '\0' || get_default_context_with_level(sename, lvl, NULL, sc) != 0) { ++ /* User may have requested a level completely outside of his ++ allowed range. We get a context just for auditing as the ++ range check below will certainly fail for default context. */ ++#endif ++ if (get_default_context(sename, NULL, sc) != 0) { ++ *sc = NULL; ++ return -1; ++ } ++#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL ++ } ++#endif ++ if (role != NULL && role[0]) { ++ context_t con; ++ char *type=NULL; ++ if (get_default_type(role, &type) != 0) { ++ error("get_default_type: failed to get default type for '%s'", ++ role); ++ goto out; ++ } ++ con = context_new(*sc); ++ if (!con) { ++ goto out; ++ } ++ context_role_set(con, role); ++ context_type_set(con, type); ++ freecon(*sc); ++ *sc = strdup(context_str(con)); ++ context_free(con); ++ if (!*sc) ++ return -1; ++ } ++#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL ++ if (lvl != NULL && lvl[0]) { ++ /* verify that the requested range is obtained */ ++ context_t con; ++ security_context_t obtained_raw; ++ security_context_t requested_raw; ++ con = context_new(*sc); ++ if (!con) { ++ goto out; ++ } ++ context_range_set(con, lvl); ++ if (selinux_trans_to_raw_context(*sc, &obtained_raw) < 0) { ++ context_free(con); ++ goto out; ++ } ++ if (selinux_trans_to_raw_context(context_str(con), &requested_raw) < 0) { ++ freecon(obtained_raw); ++ context_free(con); ++ goto out; ++ } ++ ++ debug("get_user_context: obtained context '%s' requested context '%s'", ++ obtained_raw, requested_raw); ++ if (strcmp(obtained_raw, requested_raw)) { ++ /* set the context to the real requested one but fail */ ++ freecon(requested_raw); ++ freecon(obtained_raw); ++ freecon(*sc); ++ *sc = strdup(context_str(con)); ++ context_free(con); ++ return -1; ++ } ++ freecon(requested_raw); ++ freecon(obtained_raw); ++ context_free(con); ++ } ++#endif ++ return 0; ++ out: ++ freecon(*sc); ++ *sc = NULL; ++ return -1; ++} ++ + /* Return the default security context for the given username */ +-static security_context_t +-ssh_selinux_getctxbyname(char *pwname) ++static int ++ssh_selinux_getctxbyname(char *pwname, ++ security_context_t *default_sc, security_context_t *user_sc) + { +- security_context_t sc = NULL; + char *sename, *lvl; ++ const char *reqlvl = NULL; + char *role = NULL; +- int r = 0; ++ int r = -1; ++ context_t con = NULL; ++ ++ *default_sc = NULL; ++ *user_sc = NULL; ++ if (the_authctxt) { ++ if (the_authctxt->role != NULL) { ++ char *slash; ++ role = xstrdup(the_authctxt->role); ++ if ((slash = strchr(role, '/')) != NULL) { ++ *slash = '\0'; ++ reqlvl = slash + 1; ++ } ++ } ++ } + +- if (the_authctxt) +- role=the_authctxt->role; + #ifdef HAVE_GETSEUSERBYNAME + if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) { + sename = NULL; +@@ -72,37 +239,62 @@ ssh_selinux_getctxbyname(char *pwname) + } + #else + sename = pwname; +- lvl = NULL; ++ lvl = ""; + #endif + + if (r == 0) { + #ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL +- if (role != NULL && role[0]) +- r = get_default_context_with_rolelevel(sename, role, lvl, NULL, &sc); +- else +- r = get_default_context_with_level(sename, lvl, NULL, &sc); ++ r = get_default_context_with_level(sename, lvl, NULL, default_sc); + #else +- if (role != NULL && role[0]) +- r = get_default_context_with_role(sename, role, NULL, &sc); +- else +- r = get_default_context(sename, NULL, &sc); ++ r = get_default_context(sename, NULL, default_sc); + #endif + } + +- if (r != 0) { +- switch (security_getenforce()) { +- case -1: +- fatal("%s: ssh_selinux_getctxbyname: " +- "security_getenforce() failed", __func__); +- case 0: +- error("%s: Failed to get default SELinux security " +- "context for %s", __func__, pwname); +- break; +- default: +- fatal("%s: Failed to get default SELinux security " +- "context for %s (in enforcing mode)", +- __func__, pwname); ++ if (r == 0) { ++ /* If launched from xinetd, we must use current level */ ++ if (inetd_flag && !rexeced_flag) { ++ security_context_t sshdsc=NULL; ++ ++ if (getcon_raw(&sshdsc) < 0) ++ fatal("failed to allocate security context"); ++ ++ if ((con=context_new(sshdsc)) == NULL) ++ fatal("failed to allocate selinux context"); ++ reqlvl = context_range_get(con); ++ freecon(sshdsc); ++ if (reqlvl !=NULL && lvl != NULL && strcmp(reqlvl, lvl) == 0) ++ /* we actually don't change level */ ++ reqlvl = ""; ++ ++ debug("%s: current connection level '%s'", __func__, reqlvl); + } ++ ++ if ((reqlvl != NULL && reqlvl[0]) || (role != NULL && role[0])) { ++ r = get_user_context(sename, role, reqlvl, user_sc); ++ ++ if (r == 0 && reqlvl != NULL && reqlvl[0]) { ++ security_context_t default_level_sc = *default_sc; ++ if (role != NULL && role[0]) { ++ if (get_user_context(sename, role, lvl, &default_level_sc) < 0) ++ default_level_sc = *default_sc; ++ } ++ /* verify that the requested range is contained in the user range */ ++ if (mls_range_allowed(default_level_sc, *user_sc)) { ++ logit("permit MLS level %s (user range %s)", reqlvl, lvl); ++ } else { ++ r = -1; ++ error("deny MLS level %s (user range %s)", reqlvl, lvl); ++ } ++ if (default_level_sc != *default_sc) ++ freecon(default_level_sc); ++ } ++ } else { ++ *user_sc = *default_sc; ++ } ++ } ++ if (r != 0) { ++ error("%s: Failed to get default SELinux security " ++ "context for %s", __func__, pwname); + } + + #ifdef HAVE_GETSEUSERBYNAME +@@ -111,14 +303,20 @@ ssh_selinux_getctxbyname(char *pwname) + if (lvl != NULL) + xfree(lvl); + #endif ++ if (role != NULL) ++ xfree(role); ++ if (con) ++ context_free(con); + +- return (sc); ++ return (r); + } + + /* Set the execution context to the default for the specified user */ + void + ssh_selinux_setup_exec_context(char *pwname) + { ++ int r = 0; ++ security_context_t default_ctx = NULL; + security_context_t user_ctx = NULL; + + if (!ssh_selinux_enabled()) +@@ -126,22 +324,39 @@ ssh_selinux_setup_exec_context(char *pwn + + debug3("%s: setting execution context", __func__); + +- user_ctx = ssh_selinux_getctxbyname(pwname); +- if (setexeccon(user_ctx) != 0) { ++ r = ssh_selinux_getctxbyname(pwname, &default_ctx, &user_ctx); ++ if (r >= 0) { ++ r = setexeccon(user_ctx); ++ if (r < 0) { ++ error("%s: Failed to set SELinux execution context %s for %s", ++ __func__, user_ctx, pwname); ++ } ++ } ++ if (user_ctx == NULL) { ++ user_ctx = default_ctx; ++ } ++ if (r < 0 || user_ctx != default_ctx) { ++ /* audit just the case when user changed a role or there was ++ a failure */ ++ send_audit_message(r >= 0, default_ctx, user_ctx); ++ } ++ if (r < 0) { + switch (security_getenforce()) { + case -1: + fatal("%s: security_getenforce() failed", __func__); + case 0: +- error("%s: Failed to set SELinux execution " +- "context for %s", __func__, pwname); ++ error("%s: SELinux failure. Continuing in permissive mode.", ++ __func__); + break; + default: +- fatal("%s: Failed to set SELinux execution context " +- "for %s (in enforcing mode)", __func__, pwname); ++ fatal("%s: SELinux failure. Aborting connection.", ++ __func__); + } + } +- if (user_ctx != NULL) ++ if (user_ctx != NULL && user_ctx != default_ctx) + freecon(user_ctx); ++ if (default_ctx != NULL) ++ freecon(default_ctx); + + debug3("%s: done", __func__); + } +@@ -159,7 +374,10 @@ ssh_selinux_setup_pty(char *pwname, cons + + debug3("%s: setting TTY context on %s", __func__, tty); + +- user_ctx = ssh_selinux_getctxbyname(pwname); ++ if (getexeccon(&user_ctx) < 0) { ++ error("%s: getexeccon: %s", __func__, strerror(errno)); ++ goto out; ++ } + + /* XXX: should these calls fatal() upon failure in enforcing mode? */ + +diff -up openssh-4.7p1/sshd.c.mls openssh-4.7p1/sshd.c +--- openssh-4.7p1/sshd.c.mls 2007-09-06 17:39:28.000000000 +0200 ++++ openssh-4.7p1/sshd.c 2007-09-06 17:39:28.000000000 +0200 +@@ -1838,6 +1838,9 @@ main(int ac, char **av) + restore_uid(); + } + #endif ++#ifdef WITH_SELINUX ++ ssh_selinux_setup_exec_context(authctxt->pw->pw_name); ++#endif + #ifdef USE_PAM + if (options.use_pam) { + do_pam_setcred(1); diff --git a/openssh-4.7p1-nss-keys.patch b/openssh-4.7p1-nss-keys.patch new file mode 100644 index 0000000..51ae678 --- /dev/null +++ b/openssh-4.7p1-nss-keys.patch @@ -0,0 +1,1397 @@ +diff -up openssh-4.7p1/key.c.nss-keys openssh-4.7p1/key.c +--- openssh-4.7p1/key.c.nss-keys 2007-08-08 06:28:26.000000000 +0200 ++++ openssh-4.7p1/key.c 2007-09-06 17:43:59.000000000 +0200 +@@ -93,6 +93,54 @@ key_new(int type) + return k; + } + ++#ifdef HAVE_LIBNSS ++Key * ++key_new_nss(int type) ++{ ++ Key *k = key_new(type); ++ ++ k->nss = xcalloc(1, sizeof(*k->nss)); ++ k->flags = KEY_FLAG_EXT | KEY_FLAG_NSS; ++ ++ return k; ++} ++ ++Key * ++key_new_nss_copy(int type, const Key *c) ++{ ++ Key *k = key_new_nss(type); ++ ++ switch (k->type) { ++ case KEY_RSA: ++ if ((BN_copy(k->rsa->n, c->rsa->n) == NULL) || ++ (BN_copy(k->rsa->e, c->rsa->e) == NULL)) ++ fatal("key_new_nss_copy: BN_copy failed"); ++ break; ++ case KEY_DSA: ++ if ((BN_copy(k->dsa->p, c->rsa->p) == NULL) || ++ (BN_copy(k->dsa->q, c->dsa->q) == NULL) || ++ (BN_copy(k->dsa->g, c->dsa->g) == NULL) || ++ (BN_copy(k->dsa->pub_key, c->dsa->pub_key) == NULL)) ++ fatal("key_new_nss_copy: BN_copy failed"); ++ break; ++ } ++ ++ k->nss->privk = SECKEY_CopyPrivateKey(c->nss->privk); ++ if (k->nss->privk == NULL) ++ fatal("key_new_nss_copy: SECKEY_CopyPrivateKey failed"); ++ ++ k->nss->pubk = SECKEY_CopyPublicKey(c->nss->pubk); ++ if (k->nss->pubk == NULL) ++ fatal("key_new_nss_copy: SECKEY_CopyPublicKey failed"); ++ ++ if (c->nss->privk->wincx) ++ k->nss->privk->wincx = xstrdup(c->nss->privk->wincx); ++ ++ return k; ++} ++#endif ++ ++ + Key * + key_new_private(int type) + { +@@ -148,6 +196,19 @@ key_free(Key *k) + fatal("key_free: bad key type %d", k->type); + break; + } ++#ifdef HAVE_LIBNSS ++ if (k->flags & KEY_FLAG_NSS) { ++ if (k->nss->privk->wincx != NULL) { ++ memset(k->nss->privk->wincx, 0, ++ strlen(k->nss->privk->wincx)); ++ xfree(k->nss->privk->wincx); ++ k->nss->privk->wincx = NULL; ++ } ++ SECKEY_DestroyPrivateKey(k->nss->privk); ++ SECKEY_DestroyPublicKey(k->nss->pubk); ++ xfree(k->nss); ++ } ++#endif + xfree(k); + } + +diff -up openssh-4.7p1/ssh-dss.c.nss-keys openssh-4.7p1/ssh-dss.c +--- openssh-4.7p1/ssh-dss.c.nss-keys 2006-11-07 13:14:42.000000000 +0100 ++++ openssh-4.7p1/ssh-dss.c 2007-09-06 17:43:59.000000000 +0200 +@@ -39,6 +39,10 @@ + #include "log.h" + #include "key.h" + ++#ifdef HAVE_LIBNSS ++#include ++#endif ++ + #define INTBLOB_LEN 20 + #define SIGBLOB_LEN (2*INTBLOB_LEN) + +@@ -57,6 +61,34 @@ ssh_dss_sign(const Key *key, u_char **si + error("ssh_dss_sign: no DSA key"); + return -1; + } ++#ifdef HAVE_LIBNSS ++ if (key->flags & KEY_FLAG_NSS) { ++ SECItem sigitem; ++ SECItem *rawsig; ++ ++ memset(&sigitem, 0, sizeof(sigitem)); ++ if (SEC_SignData(&sigitem, (u_char *)data, datalen, key->nss->privk, ++ SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) != SECSuccess) { ++ error("ssh_dss_sign: sign failed"); ++ return -1; ++ } ++ ++ if ((rawsig=DSAU_DecodeDerSig(&sigitem)) == NULL) { ++ error("ssh_dss_sign: der decode failed"); ++ SECITEM_ZfreeItem(&sigitem, PR_FALSE); ++ return -1; ++ } ++ SECITEM_ZfreeItem(&sigitem, PR_FALSE); ++ if (rawsig->len != SIGBLOB_LEN) { ++ error("ssh_dss_sign: unsupported signature length %d", ++ rawsig->len); ++ SECITEM_ZfreeItem(rawsig, PR_TRUE); ++ return -1; ++ } ++ memcpy(sigblob, rawsig->data, SIGBLOB_LEN); ++ SECITEM_ZfreeItem(rawsig, PR_TRUE); ++ } else { ++#endif + EVP_DigestInit(&md, evp_md); + EVP_DigestUpdate(&md, data, datalen); + EVP_DigestFinal(&md, digest, &dlen); +@@ -80,7 +112,9 @@ ssh_dss_sign(const Key *key, u_char **si + BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen); + BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen); + DSA_SIG_free(sig); +- ++#ifdef HAVE_LIBNSS ++ } ++#endif + if (datafellows & SSH_BUG_SIGBLOB) { + if (lenp != NULL) + *lenp = SIGBLOB_LEN; +diff -up openssh-4.7p1/ssh-agent.c.nss-keys openssh-4.7p1/ssh-agent.c +--- openssh-4.7p1/ssh-agent.c.nss-keys 2007-03-21 10:45:07.000000000 +0100 ++++ openssh-4.7p1/ssh-agent.c 2007-09-06 17:43:59.000000000 +0200 +@@ -79,6 +79,10 @@ + #include "scard.h" + #endif + ++#ifdef HAVE_LIBNSS ++#include "nsskeys.h" ++#endif ++ + #if defined(HAVE_SYS_PRCTL_H) + #include /* For prctl() and PR_SET_DUMPABLE */ + #endif +@@ -701,6 +705,114 @@ send: + } + #endif /* SMARTCARD */ + ++#ifdef HAVE_LIBNSS ++static void ++process_add_nss_key (SocketEntry *e) ++{ ++ char *tokenname = NULL, *keyname = NULL, *password = NULL; ++ int i, version, success = 0, death = 0, confirm = 0; ++ Key **keys, *k; ++ Identity *id; ++ Idtab *tab; ++ ++ tokenname = buffer_get_string(&e->request, NULL); ++ keyname = buffer_get_string(&e->request, NULL); ++ password = buffer_get_string(&e->request, NULL); ++ ++ while (buffer_len(&e->request)) { ++ switch (buffer_get_char(&e->request)) { ++ case SSH_AGENT_CONSTRAIN_LIFETIME: ++ death = time(NULL) + buffer_get_int(&e->request); ++ break; ++ case SSH_AGENT_CONSTRAIN_CONFIRM: ++ confirm = 1; ++ break; ++ default: ++ break; ++ } ++ } ++ if (lifetime && !death) ++ death = time(NULL) + lifetime; ++ ++ keys = nss_get_keys(tokenname, keyname, password); ++ /* password is owned by keys[0] now */ ++ xfree(tokenname); ++ xfree(keyname); ++ ++ if (keys == NULL) { ++ memset(password, 0, strlen(password)); ++ xfree(password); ++ error("nss_get_keys failed"); ++ goto send; ++ } ++ for (i = 0; keys[i] != NULL; i++) { ++ k = keys[i]; ++ version = k->type == KEY_RSA1 ? 1 : 2; ++ tab = idtab_lookup(version); ++ if (lookup_identity(k, version) == NULL) { ++ id = xmalloc(sizeof(Identity)); ++ id->key = k; ++ id->comment = nss_get_key_label(k); ++ id->death = death; ++ id->confirm = confirm; ++ TAILQ_INSERT_TAIL(&tab->idlist, id, next); ++ tab->nentries++; ++ success = 1; ++ } else { ++ key_free(k); ++ } ++ keys[i] = NULL; ++ } ++ xfree(keys); ++send: ++ buffer_put_int(&e->output, 1); ++ buffer_put_char(&e->output, ++ success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); ++} ++ ++static void ++process_remove_nss_key(SocketEntry *e) ++{ ++ char *tokenname = NULL, *keyname = NULL, *password = NULL; ++ int i, version, success = 0; ++ Key **keys, *k = NULL; ++ Identity *id; ++ Idtab *tab; ++ ++ tokenname = buffer_get_string(&e->request, NULL); ++ keyname = buffer_get_string(&e->request, NULL); ++ password = buffer_get_string(&e->request, NULL); ++ ++ keys = nss_get_keys(tokenname, keyname, password); ++ xfree(tokenname); ++ xfree(keyname); ++ xfree(password); ++ ++ if (keys == NULL || keys[0] == NULL) { ++ error("nss_get_keys failed"); ++ goto send; ++ } ++ for (i = 0; keys[i] != NULL; i++) { ++ k = keys[i]; ++ version = k->type == KEY_RSA1 ? 1 : 2; ++ if ((id = lookup_identity(k, version)) != NULL) { ++ tab = idtab_lookup(version); ++ TAILQ_REMOVE(&tab->idlist, id, next); ++ tab->nentries--; ++ free_identity(id); ++ success = 1; ++ } ++ key_free(k); ++ keys[i] = NULL; ++ } ++ xfree(keys); ++send: ++ buffer_put_int(&e->output, 1); ++ buffer_put_char(&e->output, ++ success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); ++} ++#endif /* HAVE_LIBNSS */ ++ + /* dispatch incoming messages */ + + static void +@@ -793,6 +905,15 @@ process_message(SocketEntry *e) + process_remove_smartcard_key(e); + break; + #endif /* SMARTCARD */ ++#ifdef HAVE_LIBNSS ++ case SSH_AGENTC_ADD_NSS_KEY: ++ case SSH_AGENTC_ADD_NSS_KEY_CONSTRAINED: ++ process_add_nss_key(e); ++ break; ++ case SSH_AGENTC_REMOVE_NSS_KEY: ++ process_remove_nss_key(e); ++ break; ++#endif /* SMARTCARD */ + default: + /* Unknown message. Respond with failure. */ + error("Unknown message %d", type); +diff -up openssh-4.7p1/authfd.h.nss-keys openssh-4.7p1/authfd.h +--- openssh-4.7p1/authfd.h.nss-keys 2006-08-05 04:39:39.000000000 +0200 ++++ openssh-4.7p1/authfd.h 2007-09-06 17:43:59.000000000 +0200 +@@ -49,6 +49,12 @@ + #define SSH2_AGENTC_ADD_ID_CONSTRAINED 25 + #define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26 + ++/* nss */ ++#define SSH_AGENTC_ADD_NSS_KEY 30 ++#define SSH_AGENTC_REMOVE_NSS_KEY 31 ++#define SSH_AGENTC_ADD_NSS_KEY_CONSTRAINED 32 ++ ++ + #define SSH_AGENT_CONSTRAIN_LIFETIME 1 + #define SSH_AGENT_CONSTRAIN_CONFIRM 2 + +@@ -83,6 +89,8 @@ int ssh_remove_all_identities(Authentic + int ssh_lock_agent(AuthenticationConnection *, int, const char *); + int ssh_update_card(AuthenticationConnection *, int, const char *, + const char *, u_int, u_int); ++int ssh_update_nss_key(AuthenticationConnection *, int, const char *, ++ const char *, const char *, u_int, u_int); + + int + ssh_decrypt_challenge(AuthenticationConnection *, Key *, BIGNUM *, u_char[16], +diff -up openssh-4.7p1/configure.ac.nss-keys openssh-4.7p1/configure.ac +--- openssh-4.7p1/configure.ac.nss-keys 2007-09-06 17:43:59.000000000 +0200 ++++ openssh-4.7p1/configure.ac 2007-09-06 17:51:48.000000000 +0200 +@@ -3228,6 +3228,20 @@ AC_ARG_WITH(linux-audit, + fi ] + ) + ++# Check whether user wants NSS support ++LIBNSS_MSG="no" ++AC_ARG_WITH(nss, ++ [ --with-nss Enable NSS support], ++ [ if test "x$withval" != "xno" ; then ++ AC_DEFINE(HAVE_LIBNSS,1,[Define if you want NSS support.]) ++ LIBNSS_MSG="yes" ++ CPPFLAGS="$CPPFLAGS -I/usr/include/nss3 -I/usr/include/nspr4" ++ AC_CHECK_HEADERS(pk11pub.h) ++ LIBS="$LIBS -lnss3" ++ fi ++ ]) ++AC_SUBST(LIBNSS) ++ + # Check whether user wants Kerberos 5 support + KRB5_MSG="no" + AC_ARG_WITH(kerberos5, +@@ -4050,6 +4064,7 @@ echo " OSF SIA support + echo " KerberosV support: $KRB5_MSG" + echo " SELinux support: $SELINUX_MSG" + echo " Linux audit support: $LINUX_AUDIT_MSG" ++echo " NSS support: $LIBNSS_MSG" + echo " Smartcard support: $SCARD_MSG" + echo " S/KEY support: $SKEY_MSG" + echo " TCP Wrappers support: $TCPW_MSG" +diff -up /dev/null openssh-4.7p1/README.nss +--- /dev/null 2007-09-04 17:17:14.474470098 +0200 ++++ openssh-4.7p1/README.nss 2007-09-06 17:43:59.000000000 +0200 +@@ -0,0 +1,36 @@ ++How to use NSS tokens with OpenSSH? ++ ++This version of OpenSSH contains experimental support for authentication using ++keys stored in tokens stored in NSS database. This for example includes any ++PKCS#11 tokens which are installed in your NSS database. ++ ++As the code is experimental and preliminary only SSH protocol 2 is supported. ++The NSS certificate and token databases are looked for in the ~/.ssh ++directory or in a directory specified by environment variable NSS_DB_PATH. ++ ++Common operations: ++ ++(1) tell the ssh client to use the NSS keys: ++ ++ $ ssh -o 'UseNSS yes' otherhost ++ ++ if you want to use a specific token: ++ ++ $ ssh -o 'UseNSS yes' -o 'NSS Token My PKCS11 Token' otherhost ++ ++(2) or tell the agent to use the NSS keys: ++ ++ $ ssh-add -n ++ ++ if you want to use a specific token: ++ ++ $ ssh-add -n -T 'My PKCS11 Token' ++ ++(3) extract the public key from token so it can be added to the ++server: ++ ++ $ ssh-keygen -n ++ ++ if you want to use a specific token and/or key: ++ ++ $ ssh-keygen -n -D 'My PKCS11 Token' 'My Key ID' +diff -up openssh-4.7p1/authfd.c.nss-keys openssh-4.7p1/authfd.c +--- openssh-4.7p1/authfd.c.nss-keys 2006-09-01 07:38:36.000000000 +0200 ++++ openssh-4.7p1/authfd.c 2007-09-06 17:43:59.000000000 +0200 +@@ -626,6 +626,45 @@ ssh_update_card(AuthenticationConnection + return decode_reply(type); + } + ++int ++ssh_update_nss_key(AuthenticationConnection *auth, int add, ++ const char *tokenname, const char *keyname, ++ const char *pass, u_int life, u_int confirm) ++{ ++ Buffer msg; ++ int type, constrained = (life || confirm); ++ ++ if (add) { ++ type = constrained ? ++ SSH_AGENTC_ADD_NSS_KEY_CONSTRAINED : ++ SSH_AGENTC_ADD_NSS_KEY; ++ } else ++ type = SSH_AGENTC_REMOVE_NSS_KEY; ++ ++ buffer_init(&msg); ++ buffer_put_char(&msg, type); ++ buffer_put_cstring(&msg, tokenname); ++ buffer_put_cstring(&msg, keyname); ++ buffer_put_cstring(&msg, pass); ++ ++ if (constrained) { ++ if (life != 0) { ++ buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_LIFETIME); ++ buffer_put_int(&msg, life); ++ } ++ if (confirm != 0) ++ buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_CONFIRM); ++ } ++ ++ if (ssh_request_reply(auth, &msg, &msg) == 0) { ++ buffer_free(&msg); ++ return 0; ++ } ++ type = buffer_get_char(&msg); ++ buffer_free(&msg); ++ return decode_reply(type); ++} ++ + /* + * Removes all identities from the agent. This call is not meant to be used + * by normal applications. +diff -up openssh-4.7p1/readconf.h.nss-keys openssh-4.7p1/readconf.h +--- openssh-4.7p1/readconf.h.nss-keys 2006-08-05 04:39:40.000000000 +0200 ++++ openssh-4.7p1/readconf.h 2007-09-06 17:43:59.000000000 +0200 +@@ -84,6 +84,8 @@ typedef struct { + char *preferred_authentications; + char *bind_address; /* local socket address for connection to sshd */ + char *smartcard_device; /* Smartcard reader device */ ++ int use_nss; /* Use NSS library for keys */ ++ char *nss_token; /* Look for NSS keys on token */ + int verify_host_key_dns; /* Verify host key using DNS */ + + int num_identity_files; /* Number of files for RSA/DSA identities. */ +diff -up /dev/null openssh-4.7p1/nsskeys.c +--- /dev/null 2007-09-04 17:17:14.474470098 +0200 ++++ openssh-4.7p1/nsskeys.c 2007-09-06 17:43:59.000000000 +0200 +@@ -0,0 +1,327 @@ ++/* ++ * Copyright (c) 2001 Markus Friedl. All rights reserved. ++ * Copyright (c) 2007 Red Hat, Inc. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include "includes.h" ++#ifdef HAVE_LIBNSS ++ ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "xmalloc.h" ++#include "key.h" ++#include "log.h" ++#include "misc.h" ++#include "nsskeys.h" ++#include "pathnames.h" ++ ++static char * ++password_cb(PK11SlotInfo *slot, PRBool retry, void *arg) ++{ ++ char *password = arg; ++ if (retry || password == NULL) ++ return NULL; ++ ++ return PL_strdup(password); ++} ++ ++int ++nss_init(PK11PasswordFunc pwfn) ++{ ++ char *dbpath; ++ char buf[MAXPATHLEN]; ++ ++ if (NSS_IsInitialized()) ++ return 0; ++ ++ if ((dbpath=getenv("NSS_DB_PATH")) == NULL) { ++ struct passwd *pw; ++ if ((pw = getpwuid(getuid())) == NULL || ++ pw->pw_dir == NULL) { ++ return -1; ++ } ++ snprintf(buf, sizeof(buf), "%s/%s", pw->pw_dir, ++ _PATH_SSH_USER_DIR); ++ dbpath = buf; ++ } ++ ++ if (NSS_Init(dbpath) != SECSuccess) ++ return -1; ++ ++ if (pwfn == NULL) { ++ pwfn = password_cb; ++ } ++ ++ PK11_SetPasswordFunc(pwfn); ++ ++ return 0; ++} ++ ++static Key * ++make_key_from_privkey(SECKEYPrivateKey *privk, char *password) ++{ ++ Key *k; ++ switch (SECKEY_GetPrivateKeyType(privk)) { ++ case rsaKey: ++ k = key_new_nss(KEY_RSA); ++ break; ++ case dsaKey: ++ k = key_new_nss(KEY_DSA); ++ break; ++ default: ++ return NULL; ++ } ++ k->nss->pubk = SECKEY_ConvertToPublicKey(privk); ++ if (k->nss->pubk != NULL) { ++ k->nss->privk = SECKEY_CopyPrivateKey(privk); ++ } ++ if (k->nss->privk != NULL) { ++ if (password != NULL) { ++ k->nss->privk->wincx = xstrdup(password); ++ } ++ return k; ++ } ++ key_free(k); ++ return NULL; ++} ++ ++static Key ** ++add_key_to_list(Key *k, Key **keys, size_t *i, size_t *allocated) ++{ ++ if (*allocated < *i + 2) { ++ *allocated += 16; ++ keys = xrealloc(keys, *allocated, sizeof(k)); ++ } ++ keys[*i] = k; ++ (*i)++; ++ keys[*i] = NULL; ++ return keys; ++} ++ ++static int ++nss_convert_pubkey(Key *k) ++{ ++ u_char *n; ++ unsigned int len; ++ char *p; ++ ++ switch (k->type) { ++ case KEY_RSA: ++ n = k->nss->pubk->u.rsa.modulus.data; ++ len = k->nss->pubk->u.rsa.modulus.len; ++ ++ if (BN_bin2bn(n, len, k->rsa->n) == NULL) { ++ fatal("nss_convert_pubkey: BN_bin2bn failed"); ++ } ++ ++ n = k->nss->pubk->u.rsa.publicExponent.data; ++ len = k->nss->pubk->u.rsa.publicExponent.len; ++ ++ if (BN_bin2bn(n, len, k->rsa->e) == NULL) { ++ fatal("nss_convert_pubkey: BN_bin2bn failed"); ++ } ++ break; ++ case KEY_DSA: ++ n = k->nss->pubk->u.dsa.params.prime.data; ++ len = k->nss->pubk->u.dsa.params.prime.len; ++ ++ if (BN_bin2bn(n, len, k->dsa->p) == NULL) { ++ fatal("nss_convert_pubkey: BN_bin2bn failed"); ++ } ++ ++ n = k->nss->pubk->u.dsa.params.subPrime.data; ++ len = k->nss->pubk->u.dsa.params.subPrime.len; ++ ++ if (BN_bin2bn(n, len, k->dsa->q) == NULL) { ++ fatal("nss_convert_pubkey: BN_bin2bn failed"); ++ } ++ ++ n = k->nss->pubk->u.dsa.params.base.data; ++ len = k->nss->pubk->u.dsa.params.base.len; ++ ++ if (BN_bin2bn(n, len, k->dsa->g) == NULL) { ++ fatal("nss_convert_pubkey: BN_bin2bn failed"); ++ } ++ ++ n = k->nss->pubk->u.dsa.publicValue.data; ++ len = k->nss->pubk->u.dsa.publicValue.len; ++ ++ if (BN_bin2bn(n, len, k->dsa->pub_key) == NULL) { ++ fatal("nss_convert_pubkey: BN_bin2bn failed"); ++ } ++ break; ++ } ++ ++ p = key_fingerprint(k, SSH_FP_MD5, SSH_FP_HEX); ++ debug("fingerprint %u %s", key_size(k), p); ++ xfree(p); ++ ++ return 0; ++} ++ ++static Key ** ++nss_find_privkeys(const char *tokenname, const char *keyname, ++ char *password) ++{ ++ Key *k = NULL; ++ Key **keys = NULL; ++ PK11SlotList *slots; ++ PK11SlotListElement *sle; ++ size_t allocated = 0; ++ size_t i = 0; ++ ++ if ((slots=PK11_FindSlotsByNames(NULL, NULL, tokenname, PR_TRUE)) == NULL) { ++ if (tokenname == NULL) { ++ debug("No NSS token found"); ++ } else { ++ debug("NSS token not found: %s", tokenname); ++ } ++ return NULL; ++ } ++ ++ for (sle = slots->head; sle; sle = sle->next) { ++ SECKEYPrivateKeyList *list; ++ SECKEYPrivateKeyListNode *node; ++ char *tmppass = password; ++ ++ if (PK11_NeedLogin(sle->slot)) { ++ if (password == NULL) { ++ char *prompt; ++ if (asprintf(&prompt, "Enter passphrase for token %s: ", ++ PK11_GetTokenName(sle->slot)) < 0) ++ fatal("password_cb: asprintf failed"); ++ tmppass = read_passphrase(prompt, RP_ALLOW_STDIN); ++ } ++ PK11_Authenticate(sle->slot, PR_TRUE, tmppass); ++ } ++ ++ debug("Looking for: %s:%s", tokenname, keyname); ++ list = PK11_ListPrivKeysInSlot(sle->slot, (char *)keyname, ++ tmppass); ++ if (list == NULL && keyname != NULL) { ++ char *fooname; ++ /* NSS bug workaround */ ++ if (asprintf(&fooname, "%s~", keyname) < 0) { ++ error("nss_find_privkey: asprintf failed"); ++ PK11_FreeSlotList(slots); ++ return NULL; ++ } ++ list = PK11_ListPrivKeysInSlot(sle->slot, fooname, ++ tmppass); ++ free(fooname); ++ } ++ if (list == NULL && keyname != NULL) { ++ CERTCertificate *cert; ++ SECKEYPrivateKey *privk; ++ cert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), ++ (char *)keyname); ++ if (cert == NULL) ++ goto cleanup; ++ privk = PK11_FindPrivateKeyFromCert(sle->slot, cert, tmppass); ++ CERT_DestroyCertificate(cert); ++ if (privk == NULL) ++ goto cleanup; ++ if ((k=make_key_from_privkey(privk, tmppass)) != NULL) { ++ nss_convert_pubkey(k); ++ keys = add_key_to_list(k, keys, &i, &allocated); ++ } ++ SECKEY_DestroyPrivateKey(privk); ++ } else { ++ if (list == NULL) ++ goto cleanup; ++ for (node=PRIVKEY_LIST_HEAD(list); !PRIVKEY_LIST_END(node, list); ++ node=PRIVKEY_LIST_NEXT(node)) ++ if ((k=make_key_from_privkey(node->key, tmppass)) != NULL) { ++ nss_convert_pubkey(k); ++ keys = add_key_to_list(k, keys, &i, &allocated); ++ } ++ SECKEY_DestroyPrivateKeyList(list); ++ } ++cleanup: ++ if (password == NULL && tmppass != NULL) { ++ memset(tmppass, 0, strlen(tmppass)); ++ xfree(tmppass); ++ } ++ } ++ PK11_FreeSlotList(slots); ++ ++ return keys; ++} ++ ++Key ** ++nss_get_keys(const char *tokenname, const char *keyname, ++ char *password) ++{ ++ Key **keys; ++ ++ if (nss_init(NULL) == -1) { ++ error("Failed to initialize NSS library"); ++ return NULL; ++ } ++ ++ keys = nss_find_privkeys(tokenname, keyname, password); ++ if (keys == NULL && keyname != NULL) { ++ error("Cannot find key in nss, token removed"); ++ return NULL; ++ } ++#if 0 ++ keys = xcalloc(3, sizeof(Key *)); ++ ++ if (k->type == KEY_RSA) { ++ n = key_new_nss_copy(KEY_RSA1, k); ++ ++ keys[0] = n; ++ keys[1] = k; ++ keys[2] = NULL; ++ } else { ++ keys[0] = k; ++ keys[1] = NULL; ++ } ++#endif ++ return keys; ++} ++ ++char * ++nss_get_key_label(Key *key) ++{ ++ char *label, *nickname; ++ ++ nickname = PK11_GetPrivateKeyNickname(key->nss->privk); ++ label = xstrdup(nickname); ++ PORT_Free(nickname); ++ ++ return label; ++} ++ ++#endif /* HAVE_LIBNSS */ +diff -up openssh-4.7p1/ssh.c.nss-keys openssh-4.7p1/ssh.c +--- openssh-4.7p1/ssh.c.nss-keys 2007-08-08 06:32:41.000000000 +0200 ++++ openssh-4.7p1/ssh.c 2007-09-06 17:43:59.000000000 +0200 +@@ -104,6 +104,9 @@ + #ifdef SMARTCARD + #include "scard.h" + #endif ++#ifdef HAVE_LIBNSS ++#include "nsskeys.h" ++#endif + + extern char *__progname; + +@@ -1217,9 +1220,11 @@ load_public_identity_files(void) + int i = 0; + Key *public; + struct passwd *pw; +-#ifdef SMARTCARD ++#if defined(SMARTCARD) || defined(HAVE_LIBNSS) + Key **keys; ++#endif + ++#ifdef SMARTCARD + if (options.smartcard_device != NULL && + options.num_identity_files < SSH_MAX_IDENTITY_FILES && + (keys = sc_get_keys(options.smartcard_device, NULL)) != NULL) { +@@ -1240,6 +1245,27 @@ load_public_identity_files(void) + xfree(keys); + } + #endif /* SMARTCARD */ ++#ifdef HAVE_LIBNSS ++ if (options.use_nss && ++ options.num_identity_files < SSH_MAX_IDENTITY_FILES && ++ (keys = nss_get_keys(options.nss_token, NULL, NULL)) != NULL) { ++ int count; ++ for (count = 0; keys[count] != NULL; count++) { ++ memmove(&options.identity_files[1], &options.identity_files[0], ++ sizeof(char *) * (SSH_MAX_IDENTITY_FILES - 1)); ++ memmove(&options.identity_keys[1], &options.identity_keys[0], ++ sizeof(Key *) * (SSH_MAX_IDENTITY_FILES - 1)); ++ options.num_identity_files++; ++ options.identity_keys[0] = keys[count]; ++ options.identity_files[0] = nss_get_key_label(keys[count]); ++ } ++ if (options.num_identity_files > SSH_MAX_IDENTITY_FILES) ++ options.num_identity_files = SSH_MAX_IDENTITY_FILES; ++ i += count; ++ xfree(keys); ++ } ++#endif /* HAVE_LIBNSS */ ++ + if ((pw = getpwuid(original_real_uid)) == NULL) + fatal("load_public_identity_files: getpwuid failed"); + if (gethostname(thishost, sizeof(thishost)) == -1) +diff -up /dev/null openssh-4.7p1/nsskeys.h +--- /dev/null 2007-09-04 17:17:14.474470098 +0200 ++++ openssh-4.7p1/nsskeys.h 2007-09-06 17:43:59.000000000 +0200 +@@ -0,0 +1,39 @@ ++/* ++ * Copyright (c) 2001 Markus Friedl. All rights reserved. ++ * Copyright (c) 2007 Red Hat, Inc. 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 NSSKEYS_H ++#define NSSKEYS_H ++#ifdef HAVE_LIBNSS ++#include ++#include ++ ++int nss_init(PK11PasswordFunc); ++Key **nss_get_keys(const char *, const char *, char *); ++char *nss_get_key_label(Key *); ++/*void sc_close(void);*/ ++/*int sc_put_key(Key *, const char *);*/ ++ ++#endif ++#endif +diff -up openssh-4.7p1/Makefile.in.nss-keys openssh-4.7p1/Makefile.in +--- openssh-4.7p1/Makefile.in.nss-keys 2007-06-11 06:01:42.000000000 +0200 ++++ openssh-4.7p1/Makefile.in 2007-09-06 17:53:14.000000000 +0200 +@@ -71,7 +71,7 @@ LIBSSH_OBJS=acss.o authfd.o authfile.o b + atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \ + monitor_fdpass.o rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o \ + kexgex.o kexdhc.o kexgexc.o scard.o msg.o progressmeter.o dns.o \ +- entropy.o scard-opensc.o gss-genr.o umac.o ++ entropy.o scard-opensc.o gss-genr.o umac.o nsskeys.o + + SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ + sshconnect.o sshconnect1.o sshconnect2.o +diff -up openssh-4.7p1/key.h.nss-keys openssh-4.7p1/key.h +--- openssh-4.7p1/key.h.nss-keys 2006-08-05 04:39:40.000000000 +0200 ++++ openssh-4.7p1/key.h 2007-09-06 17:43:59.000000000 +0200 +@@ -29,11 +29,17 @@ + #include + #include + ++#ifdef HAVE_LIBNSS ++#include ++#include ++#endif ++ + typedef struct Key Key; + enum types { + KEY_RSA1, + KEY_RSA, + KEY_DSA, ++ KEY_NSS, + KEY_UNSPEC + }; + enum fp_type { +@@ -47,16 +53,30 @@ enum fp_rep { + + /* key is stored in external hardware */ + #define KEY_FLAG_EXT 0x0001 ++#define KEY_FLAG_NSS 0x0002 ++ ++#ifdef HAVE_LIBNSS ++typedef struct NSSKey NSSKey; ++struct NSSKey { ++ SECKEYPrivateKey *privk; ++ SECKEYPublicKey *pubk; ++}; ++#endif + + struct Key { + int type; + int flags; + RSA *rsa; + DSA *dsa; ++#ifdef HAVE_LIBNSS ++ NSSKey *nss; ++#endif + }; + + Key *key_new(int); + Key *key_new_private(int); ++Key *key_new_nss(int); ++Key *key_new_nss_copy(int, const Key *); + void key_free(Key *); + Key *key_demote(const Key *); + int key_equal(const Key *, const Key *); +diff -up openssh-4.7p1/ssh-add.c.nss-keys openssh-4.7p1/ssh-add.c +--- openssh-4.7p1/ssh-add.c.nss-keys 2006-09-01 07:38:37.000000000 +0200 ++++ openssh-4.7p1/ssh-add.c 2007-09-06 17:43:59.000000000 +0200 +@@ -43,6 +43,14 @@ + + #include + ++#ifdef HAVE_LIBNSS ++#include ++#include ++#include ++#include ++#include ++#endif ++ + #include + #include + #include +@@ -56,6 +64,7 @@ + #include "rsa.h" + #include "log.h" + #include "key.h" ++#include "nsskeys.h" + #include "buffer.h" + #include "authfd.h" + #include "authfile.h" +@@ -306,6 +315,117 @@ do_file(AuthenticationConnection *ac, in + return 0; + } + ++#ifdef HAVE_LIBNSS ++static char * ++password_cb(PK11SlotInfo *slot, PRBool retry, void *arg) ++{ ++ char **passcache = arg; ++ char *password, *p2 = NULL; ++ char *prompt; ++ ++ if (retry) ++ return NULL; ++ ++ if (asprintf(&prompt, "Enter passphrase for token %s: ", ++ PK11_GetTokenName(slot)) < 0) ++ fatal("password_cb: asprintf failed"); ++ ++ password = read_passphrase(prompt, RP_ALLOW_STDIN); ++ ++ if (password != NULL && (p2=PL_strdup(password)) == NULL) { ++ memset(password, 0, strlen(password)); ++ fatal("password_cb: PL_strdup failed"); ++ } ++ ++ if (passcache != NULL) { ++ if (*passcache != NULL) { ++ memset(*passcache, 0, strlen(*passcache)); ++ xfree(*passcache); ++ } ++ *passcache = password; ++ } else { ++ memset(password, 0, strlen(password)); ++ xfree(password); ++ } ++ ++ return p2; ++} ++ ++static int ++add_slot_keys(AuthenticationConnection *ac, PK11SlotInfo *slot, int add) ++{ ++ SECKEYPrivateKeyList *list; ++ SECKEYPrivateKeyListNode *node; ++ char *passcache = NULL; ++ char *tokenname; ++ ++ int count = 0; ++ ++ if (PK11_NeedLogin(slot)) ++ PK11_Authenticate(slot, PR_TRUE, &passcache); ++ ++ if ((list=PK11_ListPrivKeysInSlot(slot, NULL, NULL)) == NULL) { ++ return 0; ++ } ++ ++ tokenname = PK11_GetTokenName(slot); ++ ++ for (node=PRIVKEY_LIST_HEAD(list); !PRIVKEY_LIST_END(node, list); ++ node=PRIVKEY_LIST_NEXT(node)) { ++ char *keyname; ++ SECKEYPublicKey *pub; ++ ++ keyname = PK11_GetPrivateKeyNickname(node->key); ++ if (keyname == NULL || *keyname == '\0') { ++ /* no nickname to refer to */ ++ CERTCertificate *cert; ++ char *kn; ++ cert = PK11_GetCertFromPrivateKey(node->key); ++ if (cert == NULL) ++ continue; ++ kn = strchr(cert->nickname, ':'); ++ if (kn == NULL) ++ kn = cert->nickname; ++ else ++ kn++; ++ keyname = PORT_Strdup(kn); ++ CERT_DestroyCertificate(cert); ++ if (keyname == NULL) ++ continue; ++ } ++ pub = SECKEY_ConvertToPublicKey(node->key); ++ if (pub == NULL) { ++ fprintf(stderr, "No public key for: %s:%s\n", ++ tokenname, keyname); ++ continue; /* not possible to obtain public key */ ++ } ++ SECKEY_DestroyPublicKey(pub); ++ ++ if (ssh_update_nss_key(ac, add, tokenname, keyname, ++ passcache?passcache:"", lifetime, confirm)) { ++ fprintf(stderr, "Key %s: %s:%s\n", ++ add?"added":"removed", tokenname, keyname); ++ count++; ++ } else { ++ fprintf(stderr, "Could not %s key: %s:%s\n", ++ add?"add":"remove", tokenname, keyname); ++ } ++ ++ PORT_Free(keyname); ++ count++; ++ } ++ ++ if (passcache != NULL) { ++ memset(passcache, 0, strlen(passcache)); ++ xfree(passcache); ++ } ++ ++ SECKEY_DestroyPrivateKeyList(list); ++ ++ return count; ++} ++#endif ++ + static void + usage(void) + { +@@ -333,6 +453,10 @@ main(int argc, char **argv) + AuthenticationConnection *ac = NULL; + char *sc_reader_id = NULL; + int i, ch, deleting = 0, ret = 0; ++#ifdef HAVE_LIBNSS ++ char *token_id = NULL; ++ int use_nss = 0; ++#endif + + /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ + sanitise_stdfd(); +@@ -350,7 +474,7 @@ main(int argc, char **argv) + "Could not open a connection to your authentication agent.\n"); + exit(2); + } +- while ((ch = getopt(argc, argv, "lLcdDxXe:s:t:")) != -1) { ++ while ((ch = getopt(argc, argv, "lLcdDnxXe:s:t:T:")) != -1) { + switch (ch) { + case 'l': + case 'L': +@@ -372,6 +496,11 @@ main(int argc, char **argv) + if (delete_all(ac) == -1) + ret = 1; + goto done; ++#ifdef HAVE_LIBNSS ++ case 'n': ++ use_nss = 1; ++ break; ++#endif + case 's': + sc_reader_id = optarg; + break; +@@ -386,6 +515,11 @@ main(int argc, char **argv) + goto done; + } + break; ++#ifdef HAVE_LIBNSS ++ case 'T': ++ token_id = optarg; ++ break; ++#endif + default: + usage(); + ret = 1; +@@ -399,6 +533,40 @@ main(int argc, char **argv) + ret = 1; + goto done; + } ++#ifdef HAVE_LIBNSS ++ if (use_nss) { ++ PK11SlotList *slots; ++ PK11SlotListElement *sle; ++ int count = 0; ++ if (nss_init(password_cb) == -1) { ++ fprintf(stderr, "Failed to initialize NSS library\n"); ++ ret = 1; ++ goto done; ++ } ++ ++ if ((slots=PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, ++ NULL)) == NULL) { ++ fprintf(stderr, "No tokens found\n"); ++ ret = 1; ++ goto nss_done; ++ } ++ ++ for (sle = slots->head; sle; sle = sle->next) { ++ int rv; ++ if ((rv=add_slot_keys(ac, sle->slot, !deleting)) == -1) { ++ ret = 1; ++ } ++ count += rv; ++ } ++ if (count == 0) { ++ ret = 1; ++ } ++nss_done: ++ NSS_Shutdown(); ++ clear_pass(); ++ goto done; ++ } ++#endif + if (argc == 0) { + char buf[MAXPATHLEN]; + struct passwd *pw; +diff -up openssh-4.7p1/ssh-rsa.c.nss-keys openssh-4.7p1/ssh-rsa.c +--- openssh-4.7p1/ssh-rsa.c.nss-keys 2006-09-01 07:38:37.000000000 +0200 ++++ openssh-4.7p1/ssh-rsa.c 2007-09-06 17:43:59.000000000 +0200 +@@ -32,6 +32,10 @@ + #include "compat.h" + #include "ssh.h" + ++#ifdef HAVE_LIBNSS ++#include ++#endif ++ + static int openssh_RSA_verify(int, u_char *, u_int, u_char *, u_int, RSA *); + + /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ +@@ -50,6 +54,38 @@ ssh_rsa_sign(const Key *key, u_char **si + error("ssh_rsa_sign: no RSA key"); + return -1; + } ++ ++ slen = RSA_size(key->rsa); ++ sig = xmalloc(slen); ++ ++#ifdef HAVE_LIBNSS ++ if (key->flags & KEY_FLAG_NSS) { ++ SECItem sigitem; ++ SECOidTag alg; ++ ++ memset(&sigitem, 0, sizeof(sigitem)); ++ alg = (datafellows & SSH_BUG_RSASIGMD5) ? ++ SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION : ++ SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; ++ ++ if (SEC_SignData(&sigitem, (u_char *)data, datalen, key->nss->privk, ++ alg) != SECSuccess) { ++ error("ssh_rsa_sign: sign failed"); ++ return -1; ++ } ++ if (sigitem.len > slen) { ++ error("ssh_rsa_sign: slen %u slen2 %u", slen, sigitem.len); ++ xfree(sig); ++ SECITEM_ZfreeItem(&sigitem, PR_FALSE); ++ return -1; ++ } ++ if (sigitem.len < slen) { ++ memset(sig, 0, slen - sigitem.len); ++ } ++ memcpy(sig+slen-sigitem.len, sigitem.data, sigitem.len); ++ SECITEM_ZfreeItem(&sigitem, PR_FALSE); ++ } else { ++#endif + nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1; + if ((evp_md = EVP_get_digestbynid(nid)) == NULL) { + error("ssh_rsa_sign: EVP_get_digestbynid %d failed", nid); +@@ -59,9 +95,6 @@ ssh_rsa_sign(const Key *key, u_char **si + EVP_DigestUpdate(&md, data, datalen); + EVP_DigestFinal(&md, digest, &dlen); + +- slen = RSA_size(key->rsa); +- sig = xmalloc(slen); +- + ok = RSA_sign(nid, digest, dlen, sig, &len, key->rsa); + memset(digest, 'd', sizeof(digest)); + +@@ -83,6 +116,9 @@ ssh_rsa_sign(const Key *key, u_char **si + xfree(sig); + return -1; + } ++#ifdef HAVE_LIBNSS ++ } ++#endif + /* encode signature */ + buffer_init(&b); + buffer_put_cstring(&b, "ssh-rsa"); +diff -up openssh-4.7p1/ssh-keygen.c.nss-keys openssh-4.7p1/ssh-keygen.c +--- openssh-4.7p1/ssh-keygen.c.nss-keys 2007-02-19 12:10:25.000000000 +0100 ++++ openssh-4.7p1/ssh-keygen.c 2007-09-06 17:48:08.000000000 +0200 +@@ -52,6 +52,11 @@ + #include "scard.h" + #endif + ++#ifdef HAVE_LIBNSS ++#include ++#include "nsskeys.h" ++#endif ++ + /* Number of bits in the RSA/DSA key. This value can be set on the command line. */ + #define DEFAULT_BITS 2048 + #define DEFAULT_BITS_DSA 1024 +@@ -499,6 +504,26 @@ do_download(struct passwd *pw, const cha + } + #endif /* SMARTCARD */ + ++#ifdef HAVE_LIBNSS ++static void ++do_nss_download(struct passwd *pw, const char *tokenname, const char *keyname) ++{ ++ Key **keys = NULL; ++ int i; ++ ++ keys = nss_get_keys(tokenname, keyname, NULL); ++ if (keys == NULL) ++ fatal("cannot find public key in NSS"); ++ for (i = 0; keys[i]; i++) { ++ key_write(keys[i], stdout); ++ key_free(keys[i]); ++ fprintf(stdout, "\n"); ++ } ++ xfree(keys); ++ exit(0); ++} ++#endif /* HAVE_LIBNSS */ ++ + static void + do_fingerprint(struct passwd *pw) + { +@@ -1056,7 +1081,8 @@ main(int argc, char **argv) + Key *private, *public; + struct passwd *pw; + struct stat st; +- int opt, type, fd, download = 0; ++ int opt, type, fd, download = 1; ++ int use_nss = 0; + u_int32_t memory = 0, generator_wanted = 0, trials = 100; + int do_gen_candidates = 0, do_screen_candidates = 0; + int log_level = SYSLOG_LEVEL_INFO; +@@ -1090,7 +1116,7 @@ main(int argc, char **argv) + } + + while ((opt = getopt(argc, argv, +- "degiqpclBHvxXyF:b:f:t:U:D:P:N:C:r:g:R:T:G:M:S:a:W:")) != -1) { ++ "degiqpclnBHvxXyF:b:f:t:U:D:P:N:C:r:g:R:T:G:M:S:a:W:")) != -1) { + switch (opt) { + case 'b': + bits = (u_int32_t)strtonum(optarg, 768, 32768, &errstr); +@@ -1130,6 +1156,10 @@ main(int argc, char **argv) + case 'g': + print_generic = 1; + break; ++ case 'n': ++ use_nss = 1; ++ download = 1; ++ break; + case 'P': + identity_passphrase = optarg; + break; +@@ -1161,10 +1191,10 @@ main(int argc, char **argv) + case 't': + key_type_name = optarg; + break; +- case 'D': +- download = 1; +- /*FALLTHROUGH*/ + case 'U': ++ download = 0; ++ /*FALLTHROUGH*/ ++ case 'D': + reader_id = optarg; + break; + case 'v': +@@ -1269,6 +1299,17 @@ main(int argc, char **argv) + exit(0); + } + } ++ ++ if (use_nss) { ++#ifdef HAVE_LIBNSS ++ if (download) ++ do_nss_download(pw, reader_id, identity_file); ++ else ++ fatal("no support for NSS key upload."); ++#else ++ fatal("no support for NSS keys."); ++#endif ++ } + if (reader_id != NULL) { + #ifdef SMARTCARD + if (download) +diff -up openssh-4.7p1/readconf.c.nss-keys openssh-4.7p1/readconf.c +--- openssh-4.7p1/readconf.c.nss-keys 2007-03-21 10:46:03.000000000 +0100 ++++ openssh-4.7p1/readconf.c 2007-09-06 17:43:59.000000000 +0200 +@@ -124,6 +124,7 @@ typedef enum { + oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, + oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, + oHostKeyAlgorithms, oBindAddress, oSmartcardDevice, ++ oUseNSS, oNSSToken, + oClearAllForwardings, oNoHostAuthenticationForLocalhost, + oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, + oAddressFamily, oGssAuthentication, oGssDelegateCreds, +@@ -209,6 +210,13 @@ static struct { + #else + { "smartcarddevice", oUnsupported }, + #endif ++#ifdef HAVE_LIBNSS ++ { "usenss", oUseNSS }, ++ { "nsstoken", oNSSToken }, ++#else ++ { "usenss", oUnsupported }, ++ { "nsstoken", oNSSToken }, ++#endif + { "clearallforwardings", oClearAllForwardings }, + { "enablesshkeysign", oEnableSSHKeysign }, + { "verifyhostkeydns", oVerifyHostKeyDNS }, +@@ -601,6 +609,14 @@ parse_string: + charptr = &options->smartcard_device; + goto parse_string; + ++ case oUseNSS: ++ intptr = &options->use_nss; ++ goto parse_flag; ++ ++ case oNSSToken: ++ charptr = &options->nss_token; ++ goto parse_command; ++ + case oProxyCommand: + charptr = &options->proxy_command; + parse_command: +@@ -1049,6 +1065,8 @@ initialize_options(Options * options) + options->preferred_authentications = NULL; + options->bind_address = NULL; + options->smartcard_device = NULL; ++ options->use_nss = -1; ++ options->nss_token = NULL; + options->enable_ssh_keysign = - 1; + options->no_host_authentication_for_localhost = - 1; + options->identities_only = - 1; +@@ -1177,6 +1195,8 @@ fill_default_options(Options * options) + options->no_host_authentication_for_localhost = 0; + if (options->identities_only == -1) + options->identities_only = 0; ++ if (options->use_nss == -1) ++ options->use_nss = 0; + if (options->enable_ssh_keysign == -1) + options->enable_ssh_keysign = 0; + if (options->rekey_limit == -1) diff --git a/openssh-4.7p1-pam-session.patch b/openssh-4.7p1-pam-session.patch new file mode 100644 index 0000000..8c1c791 --- /dev/null +++ b/openssh-4.7p1-pam-session.patch @@ -0,0 +1,137 @@ +diff -up openssh-4.7p1/session.c.pam-session openssh-4.7p1/session.c +--- openssh-4.7p1/session.c.pam-session 2007-08-16 15:28:04.000000000 +0200 ++++ openssh-4.7p1/session.c 2007-09-06 17:37:46.000000000 +0200 +@@ -422,11 +422,6 @@ do_exec_no_pty(Session *s, const char *c + + session_proctitle(s); + +-#if defined(USE_PAM) +- if (options.use_pam && !use_privsep) +- do_pam_setcred(1); +-#endif /* USE_PAM */ +- + /* Fork the child. */ + if ((pid = fork()) == 0) { + is_child = 1; +@@ -557,14 +552,6 @@ do_exec_pty(Session *s, const char *comm + ptyfd = s->ptyfd; + ttyfd = s->ttyfd; + +-#if defined(USE_PAM) +- if (options.use_pam) { +- do_pam_set_tty(s->tty); +- if (!use_privsep) +- do_pam_setcred(1); +- } +-#endif +- + /* Fork the child. */ + if ((pid = fork()) == 0) { + is_child = 1; +@@ -1300,17 +1287,9 @@ do_setusercontext(struct passwd *pw) + # ifdef __bsdi__ + setpgid(0, 0); + # endif +-#ifdef GSSAPI +- if (options.gss_authentication) { +- temporarily_use_uid(pw); +- ssh_gssapi_storecreds(); +- restore_uid(); +- } +-#endif + # ifdef USE_PAM + if (options.use_pam) { +- do_pam_session(); +- do_pam_setcred(use_privsep); ++ do_pam_setcred(0); + } + # endif /* USE_PAM */ + if (setusercontext(lc, pw, pw->pw_uid, +@@ -1337,13 +1316,6 @@ do_setusercontext(struct passwd *pw) + exit(1); + } + endgrent(); +-#ifdef GSSAPI +- if (options.gss_authentication) { +- temporarily_use_uid(pw); +- ssh_gssapi_storecreds(); +- restore_uid(); +- } +-#endif + # ifdef USE_PAM + /* + * PAM credentials may take the form of supplementary groups. +@@ -1351,8 +1323,7 @@ do_setusercontext(struct passwd *pw) + * Reestablish them here. + */ + if (options.use_pam) { +- do_pam_session(); +- do_pam_setcred(use_privsep); ++ do_pam_setcred(0); + } + # endif /* USE_PAM */ + # if defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) +diff -up openssh-4.7p1/sshd.c.pam-session openssh-4.7p1/sshd.c +--- openssh-4.7p1/sshd.c.pam-session 2007-09-06 17:37:46.000000000 +0200 ++++ openssh-4.7p1/sshd.c 2007-09-06 17:37:46.000000000 +0200 +@@ -1831,7 +1831,21 @@ main(int ac, char **av) + audit_event(SSH_AUTH_SUCCESS); + #endif + +- /* ++#ifdef GSSAPI ++ if (options.gss_authentication) { ++ temporarily_use_uid(authctxt->pw); ++ ssh_gssapi_storecreds(); ++ restore_uid(); ++ } ++#endif ++#ifdef USE_PAM ++ if (options.use_pam) { ++ do_pam_setcred(1); ++ do_pam_session(); ++ } ++#endif ++ ++ /* + * In privilege separation, we fork another child and prepare + * file descriptor passing. + */ +diff -up openssh-4.7p1/monitor.c.pam-session openssh-4.7p1/monitor.c +--- openssh-4.7p1/monitor.c.pam-session 2007-09-06 17:37:46.000000000 +0200 ++++ openssh-4.7p1/monitor.c 2007-09-06 17:37:46.000000000 +0200 +@@ -1566,6 +1566,11 @@ mm_answer_term(int sock, Buffer *req) + /* The child is terminating */ + session_destroy_all(&mm_session_close); + ++#ifdef USE_PAM ++ if (options.use_pam) ++ sshpam_cleanup(); ++#endif ++ + while (waitpid(pmonitor->m_pid, &status, 0) == -1) + if (errno != EINTR) + exit(1); +diff -up openssh-4.7p1/auth-pam.c.pam-session openssh-4.7p1/auth-pam.c +--- openssh-4.7p1/auth-pam.c.pam-session 2007-08-10 06:32:34.000000000 +0200 ++++ openssh-4.7p1/auth-pam.c 2007-09-06 17:37:46.000000000 +0200 +@@ -598,15 +598,17 @@ static struct pam_conv store_conv = { ss + void + sshpam_cleanup(void) + { +- debug("PAM: cleanup"); +- if (sshpam_handle == NULL) ++ if (sshpam_handle == NULL || (use_privsep && !mm_is_monitor())) + return; ++ debug("PAM: cleanup"); + pam_set_item(sshpam_handle, PAM_CONV, (const void *)&null_conv); + if (sshpam_cred_established) { ++ debug("PAM: deleting credentials"); + pam_setcred(sshpam_handle, PAM_DELETE_CRED); + sshpam_cred_established = 0; + } + if (sshpam_session_open) { ++ debug("PAM: closing session"); + pam_close_session(sshpam_handle, PAM_SILENT); + sshpam_session_open = 0; + } diff --git a/openssh-4.7p1-redhat.patch b/openssh-4.7p1-redhat.patch new file mode 100644 index 0000000..eb4b3dd --- /dev/null +++ b/openssh-4.7p1-redhat.patch @@ -0,0 +1,95 @@ +diff -up openssh-4.7p1/sshd_config.redhat openssh-4.7p1/sshd_config +--- openssh-4.7p1/sshd_config.redhat 2007-03-21 10:42:25.000000000 +0100 ++++ openssh-4.7p1/sshd_config 2007-09-06 16:23:58.000000000 +0200 +@@ -33,6 +33,7 @@ Protocol 2 + # Logging + # obsoletes QuietMode and FascistLogging + #SyslogFacility AUTH ++SyslogFacility AUTHPRIV + #LogLevel INFO + + # Authentication: +@@ -59,9 +60,11 @@ Protocol 2 + # To disable tunneled clear text passwords, change to no here! + #PasswordAuthentication yes + #PermitEmptyPasswords no ++PasswordAuthentication yes + + # Change to no to disable s/key passwords + #ChallengeResponseAuthentication yes ++ChallengeResponseAuthentication no + + # Kerberos options + #KerberosAuthentication no +@@ -71,7 +74,9 @@ Protocol 2 + + # GSSAPI options + #GSSAPIAuthentication no ++GSSAPIAuthentication yes + #GSSAPICleanupCredentials yes ++GSSAPICleanupCredentials yes + + # Set this to 'yes' to enable PAM authentication, account processing, + # and session processing. If this is enabled, PAM authentication will +@@ -83,10 +88,16 @@ Protocol 2 + # PAM authentication, then enable this but set PasswordAuthentication + # and ChallengeResponseAuthentication to 'no'. + #UsePAM no ++UsePAM yes + ++# Accept locale-related environment variables ++AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES ++AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT ++AcceptEnv LC_IDENTIFICATION LC_ALL + #AllowTcpForwarding yes + #GatewayPorts no + #X11Forwarding no ++X11Forwarding yes + #X11DisplayOffset 10 + #X11UseLocalhost yes + #PrintMotd yes +diff -up openssh-4.7p1/ssh_config.redhat openssh-4.7p1/ssh_config +--- openssh-4.7p1/ssh_config.redhat 2007-06-11 06:04:42.000000000 +0200 ++++ openssh-4.7p1/ssh_config 2007-09-06 16:21:49.000000000 +0200 +@@ -43,3 +43,13 @@ + # Tunnel no + # TunnelDevice any:any + # PermitLocalCommand no ++Host * ++ GSSAPIAuthentication yes ++# If this option is set to yes then remote X11 clients will have full access ++# to the original X11 display. As virtually no X11 client supports the untrusted ++# mode correctly we set this to yes. ++ ForwardX11Trusted yes ++# Send locale-related environment variables ++ SendEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES ++ SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT ++ SendEnv LC_IDENTIFICATION LC_ALL +diff -up openssh-4.7p1/sshd_config.0.redhat openssh-4.7p1/sshd_config.0 +--- openssh-4.7p1/sshd_config.0.redhat 2007-09-04 08:50:11.000000000 +0200 ++++ openssh-4.7p1/sshd_config.0 2007-09-06 16:21:49.000000000 +0200 +@@ -435,9 +435,9 @@ DESCRIPTION + + SyslogFacility + Gives the facility code that is used when logging messages from +- sshd(8). The possible values are: DAEMON, USER, AUTH, LOCAL0, +- LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The de- +- fault is AUTH. ++ sshd(8). The possible values are: DAEMON, USER, AUTH, AUTHPRIV, ++ LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. ++ The default is AUTH. + + TCPKeepAlive + Specifies whether the system should send TCP keepalive messages +diff -up openssh-4.7p1/sshd_config.5.redhat openssh-4.7p1/sshd_config.5 +--- openssh-4.7p1/sshd_config.5.redhat 2007-06-11 06:07:13.000000000 +0200 ++++ openssh-4.7p1/sshd_config.5 2007-09-06 16:21:49.000000000 +0200 +@@ -748,7 +748,7 @@ Note that this option applies to protoco + .It Cm SyslogFacility + Gives the facility code that is used when logging messages from + .Xr sshd 8 . +-The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2, ++The possible values are: DAEMON, USER, AUTH, AUTHPRIV, LOCAL0, LOCAL1, LOCAL2, + LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. + The default is AUTH. + .It Cm TCPKeepAlive diff --git a/openssh-4.7p1-selinux.patch b/openssh-4.7p1-selinux.patch new file mode 100644 index 0000000..4346660 --- /dev/null +++ b/openssh-4.7p1-selinux.patch @@ -0,0 +1,254 @@ +diff -up openssh-4.7p1/configure.ac.selinux openssh-4.7p1/configure.ac +--- openssh-4.7p1/configure.ac.selinux 2007-09-06 19:46:32.000000000 +0200 ++++ openssh-4.7p1/configure.ac 2007-09-06 19:52:23.000000000 +0200 +@@ -3211,6 +3211,7 @@ AC_ARG_WITH(selinux, + AC_CHECK_LIB(selinux, setexeccon, [ LIBSELINUX="-lselinux" ], + AC_MSG_ERROR(SELinux support requires libselinux library)) + SSHDLIBS="$SSHDLIBS $LIBSELINUX" ++ LIBS="$LIBS $LIBSELINUX" + AC_CHECK_FUNCS(getseuserbyname get_default_context_with_level) + LIBS="$save_LIBS" + fi ] +diff -up openssh-4.7p1/auth1.c.selinux openssh-4.7p1/auth1.c +--- openssh-4.7p1/auth1.c.selinux 2007-09-06 19:46:32.000000000 +0200 ++++ openssh-4.7p1/auth1.c 2007-09-06 19:46:32.000000000 +0200 +@@ -388,7 +388,7 @@ void + do_authentication(Authctxt *authctxt) + { + u_int ulen; +- char *user, *style = NULL; ++ char *user, *style = NULL, *role=NULL; + + /* Get the name of the user that we wish to log in as. */ + packet_read_expect(SSH_CMSG_USER); +@@ -397,11 +397,19 @@ do_authentication(Authctxt *authctxt) + user = packet_get_string(&ulen); + packet_check_eom(); + ++ if ((role = strchr(user, '/')) != NULL) ++ *role++ = '\0'; ++ + if ((style = strchr(user, ':')) != NULL) + *style++ = '\0'; ++ else ++ if (role && (style = strchr(role, ':')) != NULL) ++ *style++ = '\0'; ++ + + authctxt->user = user; + authctxt->style = style; ++ authctxt->role = role; + + /* Verify that the user is a valid user. */ + if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL) +diff -up openssh-4.7p1/monitor_wrap.h.selinux openssh-4.7p1/monitor_wrap.h +--- openssh-4.7p1/monitor_wrap.h.selinux 2006-08-05 04:39:40.000000000 +0200 ++++ openssh-4.7p1/monitor_wrap.h 2007-09-06 19:46:32.000000000 +0200 +@@ -41,6 +41,7 @@ int mm_is_monitor(void); + DH *mm_choose_dh(int, int, int); + int mm_key_sign(Key *, u_char **, u_int *, u_char *, u_int); + void mm_inform_authserv(char *, char *); ++void mm_inform_authrole(char *); + struct passwd *mm_getpwnamallow(const char *); + char *mm_auth2_read_banner(void); + int mm_auth_password(struct Authctxt *, char *); +diff -up openssh-4.7p1/monitor.h.selinux openssh-4.7p1/monitor.h +--- openssh-4.7p1/monitor.h.selinux 2006-03-26 05:30:02.000000000 +0200 ++++ openssh-4.7p1/monitor.h 2007-09-06 19:46:32.000000000 +0200 +@@ -30,7 +30,7 @@ + + enum monitor_reqtype { + MONITOR_REQ_MODULI, MONITOR_ANS_MODULI, +- MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV, ++ MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV,MONITOR_REQ_AUTHROLE, + MONITOR_REQ_SIGN, MONITOR_ANS_SIGN, + MONITOR_REQ_PWNAM, MONITOR_ANS_PWNAM, + MONITOR_REQ_AUTH2_READ_BANNER, MONITOR_ANS_AUTH2_READ_BANNER, +diff -up openssh-4.7p1/monitor_wrap.c.selinux openssh-4.7p1/monitor_wrap.c +--- openssh-4.7p1/monitor_wrap.c.selinux 2007-06-11 06:01:42.000000000 +0200 ++++ openssh-4.7p1/monitor_wrap.c 2007-09-06 19:46:32.000000000 +0200 +@@ -294,6 +294,23 @@ mm_inform_authserv(char *service, char * + buffer_free(&m); + } + ++/* Inform the privileged process about role */ ++ ++void ++mm_inform_authrole(char *role) ++{ ++ Buffer m; ++ ++ debug3("%s entering", __func__); ++ ++ buffer_init(&m); ++ buffer_put_cstring(&m, role ? role : ""); ++ ++ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHROLE, &m); ++ ++ buffer_free(&m); ++} ++ + /* Do the password authentication */ + int + mm_auth_password(Authctxt *authctxt, char *password) +diff -up openssh-4.7p1/openbsd-compat/port-linux.c.selinux openssh-4.7p1/openbsd-compat/port-linux.c +--- openssh-4.7p1/openbsd-compat/port-linux.c.selinux 2007-06-28 00:48:03.000000000 +0200 ++++ openssh-4.7p1/openbsd-compat/port-linux.c 2007-09-06 19:46:32.000000000 +0200 +@@ -30,11 +30,16 @@ + #ifdef WITH_SELINUX + #include "log.h" + #include "port-linux.h" ++#include "key.h" ++#include "hostfile.h" ++#include "auth.h" + + #include + #include + #include + ++extern Authctxt *the_authctxt; ++ + /* Wrapper around is_selinux_enabled() to log its return value once only */ + static int + ssh_selinux_enabled(void) +@@ -53,23 +58,36 @@ ssh_selinux_enabled(void) + static security_context_t + ssh_selinux_getctxbyname(char *pwname) + { +- security_context_t sc; +- char *sename = NULL, *lvl = NULL; +- int r; ++ security_context_t sc = NULL; ++ char *sename, *lvl; ++ char *role = NULL; ++ int r = 0; + ++ if (the_authctxt) ++ role=the_authctxt->role; + #ifdef HAVE_GETSEUSERBYNAME +- if (getseuserbyname(pwname, &sename, &lvl) != 0) +- return NULL; ++ if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) { ++ sename = NULL; ++ lvl = NULL; ++ } + #else + sename = pwname; + lvl = NULL; + #endif + ++ if (r == 0) { + #ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL +- r = get_default_context_with_level(sename, lvl, NULL, &sc); ++ if (role != NULL && role[0]) ++ r = get_default_context_with_rolelevel(sename, role, lvl, NULL, &sc); ++ else ++ r = get_default_context_with_level(sename, lvl, NULL, &sc); + #else +- r = get_default_context(sename, NULL, &sc); ++ if (role != NULL && role[0]) ++ r = get_default_context_with_role(sename, role, NULL, &sc); ++ else ++ r = get_default_context(sename, NULL, &sc); + #endif ++ } + + if (r != 0) { + switch (security_getenforce()) { +diff -up openssh-4.7p1/auth.h.selinux openssh-4.7p1/auth.h +--- openssh-4.7p1/auth.h.selinux 2006-08-18 16:32:46.000000000 +0200 ++++ openssh-4.7p1/auth.h 2007-09-06 19:46:32.000000000 +0200 +@@ -58,6 +58,7 @@ struct Authctxt { + char *service; + struct passwd *pw; /* set if 'valid' */ + char *style; ++ char *role; + void *kbdintctxt; + #ifdef BSD_AUTH + auth_session_t *as; +diff -up openssh-4.7p1/auth2.c.selinux openssh-4.7p1/auth2.c +--- openssh-4.7p1/auth2.c.selinux 2007-05-20 06:58:41.000000000 +0200 ++++ openssh-4.7p1/auth2.c 2007-09-06 19:46:32.000000000 +0200 +@@ -141,7 +141,7 @@ input_userauth_request(int type, u_int32 + { + Authctxt *authctxt = ctxt; + Authmethod *m = NULL; +- char *user, *service, *method, *style = NULL; ++ char *user, *service, *method, *style = NULL, *role = NULL; + int authenticated = 0; + + if (authctxt == NULL) +@@ -153,6 +153,9 @@ input_userauth_request(int type, u_int32 + debug("userauth-request for user %s service %s method %s", user, service, method); + debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); + ++ if ((role = strchr(user, '/')) != NULL) ++ *role++ = 0; ++ + if ((style = strchr(user, ':')) != NULL) + *style++ = 0; + +@@ -178,8 +181,11 @@ input_userauth_request(int type, u_int32 + use_privsep ? " [net]" : ""); + authctxt->service = xstrdup(service); + authctxt->style = style ? xstrdup(style) : NULL; +- if (use_privsep) ++ authctxt->role = role ? xstrdup(role) : NULL; ++ if (use_privsep) { + mm_inform_authserv(service, style); ++ mm_inform_authrole(role); ++ } + } else if (strcmp(user, authctxt->user) != 0 || + strcmp(service, authctxt->service) != 0) { + packet_disconnect("Change of username or service not allowed: " +diff -up openssh-4.7p1/monitor.c.selinux openssh-4.7p1/monitor.c +--- openssh-4.7p1/monitor.c.selinux 2007-05-20 07:10:16.000000000 +0200 ++++ openssh-4.7p1/monitor.c 2007-09-06 19:46:32.000000000 +0200 +@@ -133,6 +133,7 @@ int mm_answer_sign(int, Buffer *); + int mm_answer_pwnamallow(int, Buffer *); + int mm_answer_auth2_read_banner(int, Buffer *); + int mm_answer_authserv(int, Buffer *); ++int mm_answer_authrole(int, Buffer *); + int mm_answer_authpassword(int, Buffer *); + int mm_answer_bsdauthquery(int, Buffer *); + int mm_answer_bsdauthrespond(int, Buffer *); +@@ -204,6 +205,7 @@ struct mon_table mon_dispatch_proto20[] + {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, + {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, + {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, ++ {MONITOR_REQ_AUTHROLE, MON_ONCE, mm_answer_authrole}, + {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner}, + {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, + #ifdef USE_PAM +@@ -657,6 +659,7 @@ mm_answer_pwnamallow(int sock, Buffer *m + else { + /* Allow service/style information on the auth context */ + monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1); ++ monitor_permit(mon_dispatch, MONITOR_REQ_AUTHROLE, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1); + } + +@@ -702,6 +705,23 @@ mm_answer_authserv(int sock, Buffer *m) + } + + int ++mm_answer_authrole(int sock, Buffer *m) ++{ ++ monitor_permit_authentications(1); ++ ++ authctxt->role = buffer_get_string(m, NULL); ++ debug3("%s: role=%s", ++ __func__, authctxt->role); ++ ++ if (strlen(authctxt->role) == 0) { ++ xfree(authctxt->role); ++ authctxt->role = NULL; ++ } ++ ++ return (0); ++} ++ ++int + mm_answer_authpassword(int sock, Buffer *m) + { + static int call_count; diff --git a/openssh-4.7p1-sftp-drain-acks.patch b/openssh-4.7p1-sftp-drain-acks.patch new file mode 100644 index 0000000..0664aa9 --- /dev/null +++ b/openssh-4.7p1-sftp-drain-acks.patch @@ -0,0 +1,71 @@ +diff -up openssh-4.7p1/sftp-client.c.drain-acks openssh-4.7p1/sftp-client.c +--- openssh-4.7p1/sftp-client.c.drain-acks 2007-02-19 12:13:39.000000000 +0100 ++++ openssh-4.7p1/sftp-client.c 2007-09-06 17:54:41.000000000 +0200 +@@ -992,7 +992,8 @@ int + do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, + int pflag) + { +- int local_fd, status; ++ int local_fd; ++ int status = SSH2_FX_OK; + u_int handle_len, id, type; + u_int64_t offset; + char *handle, *data; +@@ -1074,7 +1075,7 @@ do_upload(struct sftp_conn *conn, char * + * Simulate an EOF on interrupt, allowing ACKs from the + * server to drain. + */ +- if (interrupted) ++ if (interrupted || status != SSH2_FX_OK) + len = 0; + else do + len = read(local_fd, data, conn->transfer_buflen); +@@ -1131,18 +1132,6 @@ do_upload(struct sftp_conn *conn, char * + fatal("Can't find request for ID %u", r_id); + TAILQ_REMOVE(&acks, ack, tq); + +- if (status != SSH2_FX_OK) { +- error("Couldn't write to remote file \"%s\": %s", +- remote_path, fx2txt(status)); +- if (showprogress) +- stop_progress_meter(); +- do_close(conn, handle, handle_len); +- close(local_fd); +- xfree(data); +- xfree(ack); +- status = -1; +- goto done; +- } + debug3("In write loop, ack for %u %u bytes at %llu", + ack->id, ack->len, (unsigned long long)ack->offset); + ++ackid; +@@ -1154,21 +1143,25 @@ do_upload(struct sftp_conn *conn, char * + stop_progress_meter(); + xfree(data); + ++ if (status != SSH2_FX_OK) { ++ error("Couldn't write to remote file \"%s\": %s", ++ remote_path, fx2txt(status)); ++ status = -1; ++ } ++ + if (close(local_fd) == -1) { + error("Couldn't close local file \"%s\": %s", local_path, + strerror(errno)); +- do_close(conn, handle, handle_len); + status = -1; +- goto done; + } + + /* Override umask and utimes if asked */ + if (pflag) + do_fsetstat(conn, handle, handle_len, &a); + +- status = do_close(conn, handle, handle_len); ++ if (do_close(conn, handle, handle_len) != SSH2_FX_OK) ++ status = -1; + +-done: + xfree(handle); + buffer_free(&msg); + return(status); diff --git a/openssh-4.7p1-vendor.patch b/openssh-4.7p1-vendor.patch new file mode 100644 index 0000000..eff213a --- /dev/null +++ b/openssh-4.7p1-vendor.patch @@ -0,0 +1,150 @@ +diff -up openssh-4.7p1/configure.ac.vendor openssh-4.7p1/configure.ac +--- openssh-4.7p1/configure.ac.vendor 2007-09-06 16:27:47.000000000 +0200 ++++ openssh-4.7p1/configure.ac 2007-09-06 16:27:47.000000000 +0200 +@@ -3792,6 +3792,12 @@ AC_ARG_WITH(lastlog, + fi + ] + ) ++AC_ARG_ENABLE(vendor-patchlevel, ++ [ --enable-vendor-patchlevel=TAG specify a vendor patch level], ++ [AC_DEFINE_UNQUOTED(SSH_VENDOR_PATCHLEVEL,[SSH_RELEASE "-" "$enableval"],[Define to your vendor patch level, if it has been modified from the upstream source release.]) ++ SSH_VENDOR_PATCHLEVEL="$enableval"], ++ [AC_DEFINE(SSH_VENDOR_PATCHLEVEL,SSH_RELEASE,[Define to your vendor patch level, if it has been modified from the upstream source release.]) ++ SSH_VENDOR_PATCHLEVEL=none]) + + dnl lastlog, [uw]tmpx? detection + dnl NOTE: set the paths in the platform section to avoid the +@@ -4041,6 +4047,7 @@ echo " IP address in \$DISPLAY hac + echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG" + echo " BSD Auth support: $BSD_AUTH_MSG" + echo " Random number source: $RAND_MSG" ++echo " Vendor patch level: $SSH_VENDOR_PATCHLEVEL" + if test ! -z "$USE_RAND_HELPER" ; then + echo " ssh-rand-helper collects from: $RAND_HELPER_MSG" + fi +diff -up openssh-4.7p1/sshd_config.5.vendor openssh-4.7p1/sshd_config.5 +--- openssh-4.7p1/sshd_config.5.vendor 2007-09-06 16:27:47.000000000 +0200 ++++ openssh-4.7p1/sshd_config.5 2007-09-06 16:27:47.000000000 +0200 +@@ -725,6 +725,14 @@ This option applies to protocol version + .It Cm ServerKeyBits + Defines the number of bits in the ephemeral protocol version 1 server key. + The minimum value is 512, and the default is 768. ++.It Cm ShowPatchLevel ++Specifies whether ++.Nm sshd ++will display the patch level of the binary in the identification string. ++The patch level is set at compile-time. ++The default is ++.Dq no . ++This option applies to protocol version 1 only. + .It Cm StrictModes + Specifies whether + .Xr sshd 8 +diff -up openssh-4.7p1/servconf.h.vendor openssh-4.7p1/servconf.h +--- openssh-4.7p1/servconf.h.vendor 2007-02-19 12:25:38.000000000 +0100 ++++ openssh-4.7p1/servconf.h 2007-09-06 16:27:47.000000000 +0200 +@@ -120,6 +120,7 @@ typedef struct { + int max_startups; + int max_authtries; + char *banner; /* SSH-2 banner message */ ++ int show_patchlevel; /* Show vendor patch level to clients */ + int use_dns; + int client_alive_interval; /* + * poke the client this often to +diff -up openssh-4.7p1/servconf.c.vendor openssh-4.7p1/servconf.c +--- openssh-4.7p1/servconf.c.vendor 2007-05-20 07:03:16.000000000 +0200 ++++ openssh-4.7p1/servconf.c 2007-09-06 16:29:11.000000000 +0200 +@@ -113,6 +113,7 @@ initialize_server_options(ServerOptions + options->max_startups = -1; + options->max_authtries = -1; + options->banner = NULL; ++ options->show_patchlevel = -1; + options->use_dns = -1; + options->client_alive_interval = -1; + options->client_alive_count_max = -1; +@@ -250,6 +251,9 @@ fill_default_server_options(ServerOption + if (options->permit_tun == -1) + options->permit_tun = SSH_TUNMODE_NO; + ++ if (options->show_patchlevel == -1) ++ options->show_patchlevel = 0; ++ + /* Turn privilege separation on by default */ + if (use_privsep == -1) + use_privsep = 1; +@@ -293,6 +297,7 @@ typedef enum { + sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, + sMatch, sPermitOpen, sForceCommand, + sUsePrivilegeSeparation, ++ sShowPatchLevel, + sDeprecated, sUnsupported + } ServerOpCodes; + +@@ -390,6 +395,7 @@ static struct { + { "maxstartups", sMaxStartups, SSHCFG_GLOBAL }, + { "maxauthtries", sMaxAuthTries, SSHCFG_GLOBAL }, + { "banner", sBanner, SSHCFG_ALL }, ++ { "showpatchlevel", sShowPatchLevel, SSHCFG_GLOBAL }, + { "usedns", sUseDNS, SSHCFG_GLOBAL }, + { "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL }, + { "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL }, +@@ -1005,6 +1011,10 @@ parse_flag: + intptr = &use_privsep; + goto parse_flag; + ++ case sShowPatchLevel: ++ intptr = &options->show_patchlevel; ++ goto parse_flag; ++ + case sAllowUsers: + while ((arg = strdelim(&cp)) && *arg != '\0') { + if (options->num_allow_users >= MAX_ALLOW_USERS) +diff -up openssh-4.7p1/sshd_config.0.vendor openssh-4.7p1/sshd_config.0 +--- openssh-4.7p1/sshd_config.0.vendor 2007-09-06 16:27:47.000000000 +0200 ++++ openssh-4.7p1/sshd_config.0 2007-09-06 16:27:47.000000000 +0200 +@@ -418,6 +418,11 @@ DESCRIPTION + Defines the number of bits in the ephemeral protocol version 1 + server key. The minimum value is 512, and the default is 768. + ++ ShowPatchLevel ++ Specifies whether sshd will display the specific patch level of ++ the binary in the server identification string. The patch level ++ is set at compile-time. The default is M-bM-^@M-^\noM-bM-^@M-^]. ++ + StrictModes + Specifies whether sshd(8) should check file modes and ownership + of the user's files and home directory before accepting login. +diff -up openssh-4.7p1/sshd_config.vendor openssh-4.7p1/sshd_config +--- openssh-4.7p1/sshd_config.vendor 2007-09-06 16:27:47.000000000 +0200 ++++ openssh-4.7p1/sshd_config 2007-09-06 16:27:47.000000000 +0200 +@@ -109,6 +109,7 @@ X11Forwarding yes + #Compression delayed + #ClientAliveInterval 0 + #ClientAliveCountMax 3 ++#ShowPatchLevel no + #UseDNS yes + #PidFile /var/run/sshd.pid + #MaxStartups 10 +diff -up openssh-4.7p1/sshd.c.vendor openssh-4.7p1/sshd.c +--- openssh-4.7p1/sshd.c.vendor 2007-06-05 10:22:32.000000000 +0200 ++++ openssh-4.7p1/sshd.c 2007-09-06 16:27:47.000000000 +0200 +@@ -419,7 +419,8 @@ sshd_exchange_identification(int sock_in + major = PROTOCOL_MAJOR_1; + minor = PROTOCOL_MINOR_1; + } +- snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", major, minor, SSH_VERSION); ++ snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", major, minor, ++ (options.show_patchlevel == 1) ? SSH_VENDOR_PATCHLEVEL : SSH_VERSION); + server_version_string = xstrdup(buf); + + /* Send our protocol version identification. */ +@@ -1434,7 +1435,8 @@ main(int ac, char **av) + exit(1); + } + +- debug("sshd version %.100s", SSH_RELEASE); ++ debug("sshd version %.100s", ++ (options.show_patchlevel == 1) ? SSH_VENDOR_PATCHLEVEL : SSH_RELEASE); + + /* Store privilege separation user for later use if required. */ + if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) { diff --git a/openssh.spec b/openssh.spec index 1e94952..7367829 100644 --- a/openssh.spec +++ b/openssh.spec @@ -1,10 +1,5 @@ +# Do we want SELinux & Audit %define WITH_SELINUX 1 -%if %{WITH_SELINUX} -# Audit patch applicable only over SELinux patch -%define WITH_AUDIT 1 -%else -%define WITH_AUDIT 0 -%endif # OpenSSH privilege separation requires a user & group ID %define sshd_uid 74 @@ -28,6 +23,9 @@ # Do we want kerberos5 support (1=yes 0=no) %define kerberos5 1 +# Do we want libedit support +%define libedit 1 + # Do we want NSS tokens support %define nss 1 @@ -59,42 +57,44 @@ # Turn off some stuff for resuce builds %if %{rescue} %define kerberos5 0 +%define libedit 0 %endif Summary: The OpenSSH implementation of SSH protocol versions 1 and 2 Name: openssh -Version: 4.5p1 -Release: 8%{?dist}%{?rescue_rel} +Version: 4.7p1 +Release: 1%{?dist}%{?rescue_rel} URL: http://www.openssh.com/portable.html #Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz -#Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.sig +#Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc # This package differs from the upstream OpenSSH tarball in that # the ACSS cipher is removed by running openssh-nukeacss.sh in # the unpacked source directory. Source0: openssh-%{version}-noacss.tar.bz2 Source1: openssh-nukeacss.sh -Patch0: openssh-4.5p1-redhat.patch +Patch0: openssh-4.7p1-redhat.patch Patch2: openssh-3.8.1p1-skip-initial.patch Patch3: openssh-3.8.1p1-krb5-config.patch -Patch4: openssh-4.5p1-vendor.patch +Patch4: openssh-4.7p1-vendor.patch Patch5: openssh-4.3p2-initscript.patch -Patch12: openssh-4.5p1-selinux.patch -Patch16: openssh-4.5p1-audit.patch +Patch10: openssh-4.7p1-pam-session.patch +Patch12: openssh-4.7p1-selinux.patch +Patch13: openssh-4.7p1-mls.patch +Patch16: openssh-4.7p1-audit.patch +Patch17: openssh-4.3p2-cve-2007-3102.patch Patch22: openssh-3.9p1-askpass-keep-above.patch Patch24: openssh-4.3p1-fromto-remote.patch Patch26: openssh-4.2p1-pam-no-stack.patch -Patch27: openssh-3.9p1-log-in-chroot.patch +Patch27: openssh-4.7p1-log-in-chroot.patch Patch30: openssh-4.0p1-exit-deadlock.patch Patch31: openssh-3.9p1-skip-used.patch Patch35: openssh-4.2p1-askpass-progress.patch Patch38: openssh-4.3p2-askpass-grab-info.patch Patch39: openssh-4.3p2-no-v6only.patch Patch44: openssh-4.3p2-allow-ip-opts.patch -Patch48: openssh-4.3p2-pam-session.patch Patch49: openssh-4.3p2-gssapi-canohost.patch -Patch50: openssh-4.5p1-mls.patch -Patch51: openssh-4.5p1-nss-keys.patch -Patch52: openssh-4.5p1-sftp-drain-acks.patch +Patch51: openssh-4.7p1-nss-keys.patch +Patch52: openssh-4.7p1-sftp-drain-acks.patch License: BSD Group: Applications/Internet BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) @@ -126,6 +126,10 @@ BuildRequires: tcp_wrappers-devel BuildRequires: krb5-devel %endif +%if %{libedit} +BuildRequires: libedit-devel +%endif + %if %{nss} BuildRequires: nss-devel %endif @@ -133,9 +137,6 @@ BuildRequires: nss-devel %if %{WITH_SELINUX} Requires: libselinux >= 1.27.7 BuildRequires: libselinux-devel >= 1.27.7 -%endif - -%if %{WITH_AUDIT} Requires: audit-libs >= 1.0.8 BuildRequires: audit-libs >= 1.0.8 %endif @@ -204,13 +205,14 @@ an X11 passphrase dialog for OpenSSH. %patch4 -p1 -b .vendor %patch5 -p1 -b .initscript +%patch10 -p1 -b .pam-session + %if %{WITH_SELINUX} #SELinux %patch12 -p1 -b .selinux -%endif - -%if %{WITH_AUDIT} +%patch13 -p1 -b .mls %patch16 -p1 -b .audit +%patch17 -p1 -b .inject-fix %endif %patch22 -p1 -b .keep-above @@ -223,9 +225,7 @@ an X11 passphrase dialog for OpenSSH. %patch38 -p1 -b .grab-info %patch39 -p1 -b .no-v6only %patch44 -p1 -b .ip-opts -%patch48 -p1 -b .pam-sesssion %patch49 -p1 -b .canohost -%patch50 -p1 -b .mls %patch51 -p1 -b .nss-keys %patch52 -p1 -b .drain-acks @@ -282,15 +282,17 @@ fi --with-pam \ %endif %if %{WITH_SELINUX} - --with-selinux \ -%endif -%if %{WITH_AUDIT} - --with-linux-audit \ + --with-selinux --with-linux-audit \ %endif %if %{kerberos5} - --with-kerberos5${krb5_prefix:+=${krb5_prefix}} + --with-kerberos5${krb5_prefix:+=${krb5_prefix}} \ %else - --without-kerberos5 + --without-kerberos5 \ +%endif +%if %{libedit} + --with-libedit +%else + --without-libedit %endif %if %{static_libcrypto} @@ -478,6 +480,11 @@ fi %endif %changelog +* Thu Sep 6 2007 Tomas Mraz - 4.7p1-1 +- upgrade to latest upstream +- use libedit in sftp (#203009) +- fixed audit log injection problem (CVE-2007-3102) + * Thu Aug 9 2007 Tomas Mraz - 4.5p1-8 - fix sftp client problems on write error (#247802) - allow disabling autocreation of server keys (#235466) diff --git a/sources b/sources index 6315519..16f424a 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -9ef9bf019945105f2ac1760c95c9b339 openssh-4.5p1-noacss.tar.bz2 +21634329a8f1cd0e7a7974ade7280bdc openssh-4.7p1-noacss.tar.bz2