From c54a8b0af7e7e9a846775fc178e02c522b2363a5 Mon Sep 17 00:00:00 2001 From: Jan F. Chadima Date: Oct 02 2009 13:50:30 +0000 Subject: Upgrade to new wersion 5.3p1 --- diff --git a/.cvsignore b/.cvsignore index 37aee5b..28fd036 100644 --- a/.cvsignore +++ b/.cvsignore @@ -1 +1 @@ -openssh-5.3p1.tar.gz +openssh-5.3p1-noacss.tar.bz2 diff --git a/openssh-3.8.1p1-krb5-config.patch b/openssh-3.8.1p1-krb5-config.patch deleted file mode 100644 index f284632..0000000 --- a/openssh-3.8.1p1-krb5-config.patch +++ /dev/null @@ -1,16 +0,0 @@ -Search the path for krb5-config if the prefix wasn't specified. ---- openssh-3.8p1/configure.ac 2004-02-26 21:17:12.000000000 -0500 -+++ openssh-3.8p1/configure.ac 2004-02-26 21:17:06.000000000 -0500 -@@ -2077,8 +2077,10 @@ - KRB5_MSG="yes" - - AC_MSG_CHECKING(for krb5-config) -- if test -x $KRB5ROOT/bin/krb5-config ; then -- KRB5CONF=$KRB5ROOT/bin/krb5-config -+ AC_PATH_PROG([KRB5CONF],[krb5-config], -+ [$KRB5ROOT/bin/krb5-config], -+ [$KRB5ROOT/bin:$PATH]) -+ if test -x $KRB5CONF ; then - AC_MSG_RESULT($KRB5CONF) - - AC_MSG_CHECKING(for gssapi support) diff --git a/openssh-4.7p1-audit.patch b/openssh-4.7p1-audit.patch deleted file mode 100644 index d561be0..0000000 --- a/openssh-4.7p1-audit.patch +++ /dev/null @@ -1,267 +0,0 @@ -diff -up openssh-5.2p1/auth.c.audit openssh-5.2p1/auth.c ---- openssh-5.2p1/auth.c.audit 2008-11-05 06:12:54.000000000 +0100 -+++ openssh-5.2p1/auth.c 2009-08-09 09:22:23.634850536 +0200 -@@ -287,6 +287,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)); -@@ -533,6 +539,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-5.2p1/config.h.in.audit openssh-5.2p1/config.h.in ---- openssh-5.2p1/config.h.in.audit 2009-02-23 01:18:12.000000000 +0100 -+++ openssh-5.2p1/config.h.in 2009-08-09 09:22:28.825939998 +0200 -@@ -1,5 +1,8 @@ - /* config.h.in. Generated from configure.ac by autoheader. */ - -+/* Define if building universal (internal helper macro) */ -+#undef AC_APPLE_UNIVERSAL_BUILD -+ - /* Define if you have a getaddrinfo that fails for the all-zeros IPv6 address - */ - #undef AIX_GETNAMEINFO_HACK -@@ -521,6 +524,9 @@ - /* Define to 1 if you have the header file. */ - #undef HAVE_LASTLOG_H - -+/* Define to 1 if you have the header file. */ -+#undef HAVE_LIBAUDIT_H -+ - /* Define to 1 if you have the `bsm' library (-lbsm). */ - #undef HAVE_LIBBSM - -@@ -560,6 +566,9 @@ - /* Define to 1 if you have the header file. */ - #undef HAVE_LIMITS_H - -+/* Define if you want Linux audit support. */ -+#undef HAVE_LINUX_AUDIT -+ - /* Define to 1 if you have the header file. */ - #undef HAVE_LINUX_IF_TUN_H - -@@ -756,6 +765,9 @@ - /* Define to 1 if you have the `setgroups' function. */ - #undef HAVE_SETGROUPS - -+/* Define to 1 if you have the `setkeycreatecon' function. */ -+#undef HAVE_SETKEYCREATECON -+ - /* Define to 1 if you have the `setlogin' function. */ - #undef HAVE_SETLOGIN - -@@ -1330,6 +1342,10 @@ - /* Prepend the address family to IP tunnel traffic */ - #undef SSH_TUN_PREPEND_AF - -+/* Define to your vendor patch level, if it has been modified from the -+ upstream source release. */ -+#undef SSH_VENDOR_PATCHLEVEL -+ - /* Define to 1 if you have the ANSI C header files. */ - #undef STDC_HEADERS - -@@ -1397,9 +1413,17 @@ - /* Define if you want SELinux support. */ - #undef WITH_SELINUX - --/* 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 -+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most -+ significant byte first (like Motorola and SPARC, unlike Intel). */ -+#if defined AC_APPLE_UNIVERSAL_BUILD -+# if defined __BIG_ENDIAN__ -+# define WORDS_BIGENDIAN 1 -+# endif -+#else -+# ifndef WORDS_BIGENDIAN -+# undef WORDS_BIGENDIAN -+# endif -+#endif - - /* Define if xauth is found in your path */ - #undef XAUTH_PATH -diff -up openssh-5.2p1/configure.ac.audit openssh-5.2p1/configure.ac ---- openssh-5.2p1/configure.ac.audit 2009-08-09 09:22:23.608877833 +0200 -+++ openssh-5.2p1/configure.ac 2009-08-09 09:22:23.646244409 +0200 -@@ -3342,6 +3342,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, -@@ -4170,6 +4182,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 -up openssh-5.2p1/loginrec.c.audit openssh-5.2p1/loginrec.c ---- openssh-5.2p1/loginrec.c.audit 2009-02-12 03:12:22.000000000 +0100 -+++ openssh-5.2p1/loginrec.c 2009-08-09 09:22:23.667199702 +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,87 @@ wtmpx_get_entry(struct logininfo *li) - } - #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[AUDIT_LOG_SIZE]; -+ 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 { -+ 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); -+ 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-5.2p1/loginrec.h.audit openssh-5.2p1/loginrec.h ---- openssh-5.2p1/loginrec.h.audit 2006-08-05 04:39:40.000000000 +0200 -+++ openssh-5.2p1/loginrec.h 2009-08-09 09:22:23.641175349 +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 --git a/openssh-5.1p1-mls.patch b/openssh-5.1p1-mls.patch deleted file mode 100644 index baf34ad..0000000 --- a/openssh-5.1p1-mls.patch +++ /dev/null @@ -1,445 +0,0 @@ -diff -up openssh-5.1p1/misc.c.mls openssh-5.1p1/misc.c ---- openssh-5.1p1/misc.c.mls 2008-06-13 06:48:59.000000000 +0200 -+++ openssh-5.1p1/misc.c 2008-07-23 18:53:37.000000000 +0200 -@@ -427,6 +427,7 @@ char * - colon(char *cp) - { - int flag = 0; -+ int start = 1; - - if (*cp == ':') /* Leading colon is part of file name. */ - return (0); -@@ -440,8 +441,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-5.1p1/session.c.mls openssh-5.1p1/session.c ---- openssh-5.1p1/session.c.mls 2008-06-16 15:29:18.000000000 +0200 -+++ openssh-5.1p1/session.c 2008-07-23 18:53:37.000000000 +0200 -@@ -1550,10 +1550,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-5.1p1/openbsd-compat/port-linux.c.mls openssh-5.1p1/openbsd-compat/port-linux.c ---- openssh-5.1p1/openbsd-compat/port-linux.c.mls 2008-07-23 18:53:37.000000000 +0200 -+++ openssh-5.1p1/openbsd-compat/port-linux.c 2008-07-23 18:53:37.000000000 +0200 -@@ -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 */ - 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,38 +239,63 @@ 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 - if (sename != NULL) -@@ -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,45 @@ 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); -+ } -+#ifdef HAVE_SETKEYCREATECON -+ else if (setkeycreatecon(user_ctx) < 0) { -+ error("%s: Failed to set SELinux keyring creation context %s for %s", -+ __func__, user_ctx, pwname); -+ } -+#endif -+ } -+ if (user_ctx == NULL) { -+ user_ctx = default_ctx; -+ } -+ if (r < 0 || user_ctx != default_ctx) { -+ /* audit just the case when user changed a role or there was -+ a failure */ -+ send_audit_message(r >= 0, default_ctx, user_ctx); -+ } -+ if (r < 0) { - switch (security_getenforce()) { - case -1: - fatal("%s: security_getenforce() failed", __func__); - case 0: -- error("%s: Failed to set SELinux execution " -- "context for %s", __func__, pwname); -+ error("%s: SELinux failure. Continuing in permissive mode.", -+ __func__); - break; - default: -- fatal("%s: Failed to set SELinux execution context " -- "for %s (in enforcing mode)", __func__, pwname); -+ fatal("%s: SELinux failure. Aborting connection.", -+ __func__); - } - } -- if (user_ctx != NULL) -+ if (user_ctx != NULL && user_ctx != default_ctx) - freecon(user_ctx); -+ if (default_ctx != NULL) -+ freecon(default_ctx); - - debug3("%s: done", __func__); - } -@@ -159,7 +380,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-5.1p1/configure.ac.mls openssh-5.1p1/configure.ac ---- openssh-5.1p1/configure.ac.mls 2008-07-23 18:53:37.000000000 +0200 -+++ openssh-5.1p1/configure.ac 2008-07-23 18:53:37.000000000 +0200 -@@ -3311,6 +3311,7 @@ AC_ARG_WITH(selinux, - SSHDLIBS="$SSHDLIBS $LIBSELINUX" - LIBS="$LIBS $LIBSELINUX" - AC_CHECK_FUNCS(getseuserbyname get_default_context_with_level) -+ AC_CHECK_FUNCS(setkeycreatecon) - LIBS="$save_LIBS" - fi ] - ) -diff -up openssh-5.1p1/sshd.c.mls openssh-5.1p1/sshd.c ---- openssh-5.1p1/sshd.c.mls 2008-07-23 18:53:37.000000000 +0200 -+++ openssh-5.1p1/sshd.c 2008-07-23 18:53:37.000000000 +0200 -@@ -1896,6 +1896,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-5.1p1-skip-initial.patch b/openssh-5.1p1-skip-initial.patch deleted file mode 100644 index be3204e..0000000 --- a/openssh-5.1p1-skip-initial.patch +++ /dev/null @@ -1,28 +0,0 @@ -Skip the initial empty-password check if permit_empty_passwd is disabled. This -doesn't change the timing profiles of the host because the additional condition -check which can short-circuit the call to pam_authenticate() has no dependency -on the identity of the user who is being authenticated. -diff -up openssh-5.1p1/auth1.c.skip-initial openssh-5.1p1/auth1.c ---- openssh-5.1p1/auth1.c.skip-initial 2008-07-09 12:54:05.000000000 +0200 -+++ openssh-5.1p1/auth1.c 2008-07-23 18:26:01.000000000 +0200 -@@ -244,7 +244,7 @@ do_authloop(Authctxt *authctxt) - authctxt->valid ? "" : "invalid user ", authctxt->user); - - /* If the user has no password, accept authentication immediately. */ -- if (options.password_authentication && -+ if (options.permit_empty_passwd && options.password_authentication && - #ifdef KRB5 - (!options.kerberos_authentication || options.kerberos_or_local_passwd) && - #endif -diff -up openssh-5.1p1/auth2-none.c.skip-initial openssh-5.1p1/auth2-none.c ---- openssh-5.1p1/auth2-none.c.skip-initial 2008-07-02 14:56:09.000000000 +0200 -+++ openssh-5.1p1/auth2-none.c 2008-07-23 18:26:01.000000000 +0200 -@@ -65,7 +65,7 @@ userauth_none(Authctxt *authctxt) - if (check_nt_auth(1, authctxt->pw) == 0) - return (0); - #endif -- if (options.password_authentication) -+ if (options.permit_empty_passwd && options.password_authentication) - return (PRIVSEP(auth_password(authctxt, ""))); - return (0); - } diff --git a/openssh-5.2p1-fips.patch b/openssh-5.2p1-fips.patch deleted file mode 100644 index 6e5b88c..0000000 --- a/openssh-5.2p1-fips.patch +++ /dev/null @@ -1,695 +0,0 @@ -diff -up openssh-5.2p1/auth2-pubkey.c.fips openssh-5.2p1/auth2-pubkey.c ---- openssh-5.2p1/auth2-pubkey.c.fips 2009-05-15 15:51:01.000000000 +0200 -+++ openssh-5.2p1/auth2-pubkey.c 2009-05-15 15:51:01.000000000 +0200 -@@ -33,6 +33,7 @@ - #include - #include - #include -+#include - - #include "xmalloc.h" - #include "ssh.h" -@@ -243,7 +244,7 @@ user_key_allowed2(struct passwd *pw, Key - found_key = 1; - debug("matching key found: file %s, line %lu", - file, linenum); -- fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); -+ fp = key_fingerprint(found, FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); - verbose("Found matching %s key: %s", - key_type(found), fp); - xfree(fp); -diff -up openssh-5.2p1/authfile.c.fips openssh-5.2p1/authfile.c ---- openssh-5.2p1/authfile.c.fips 2006-09-01 07:38:36.000000000 +0200 -+++ openssh-5.2p1/authfile.c 2009-05-15 16:08:34.000000000 +0200 -@@ -143,8 +143,14 @@ key_save_private_rsa1(Key *key, const ch - /* Allocate space for the private part of the key in the buffer. */ - cp = buffer_append_space(&encrypted, buffer_len(&buffer)); - -- cipher_set_key_string(&ciphercontext, cipher, passphrase, -- CIPHER_ENCRYPT); -+ if (cipher_set_key_string(&ciphercontext, cipher, passphrase, -+ CIPHER_ENCRYPT) < 0) { -+ error("cipher_set_key_string failed."); -+ buffer_free(&encrypted); -+ buffer_free(&buffer); -+ return 0; -+ } -+ - cipher_crypt(&ciphercontext, cp, - buffer_ptr(&buffer), buffer_len(&buffer)); - cipher_cleanup(&ciphercontext); -@@ -414,8 +420,14 @@ key_load_private_rsa1(int fd, const char - cp = buffer_append_space(&decrypted, buffer_len(&buffer)); - - /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ -- cipher_set_key_string(&ciphercontext, cipher, passphrase, -- CIPHER_DECRYPT); -+ if (cipher_set_key_string(&ciphercontext, cipher, passphrase, -+ CIPHER_DECRYPT) < 0) { -+ error("cipher_set_key_string failed."); -+ buffer_free(&decrypted); -+ buffer_free(&buffer); -+ goto fail; -+ } -+ - cipher_crypt(&ciphercontext, cp, - buffer_ptr(&buffer), buffer_len(&buffer)); - cipher_cleanup(&ciphercontext); -diff -up openssh-5.2p1/cipher.c.fips openssh-5.2p1/cipher.c ---- openssh-5.2p1/cipher.c.fips 2009-03-06 18:23:21.000000000 +0100 -+++ openssh-5.2p1/cipher.c 2009-05-15 16:14:16.000000000 +0200 -@@ -40,6 +40,7 @@ - #include - - #include -+#include - - #include - #include -@@ -93,6 +94,22 @@ struct Cipher { - { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, NULL } - }; - -+struct Cipher fips_ciphers[] = { -+ { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, EVP_enc_null }, -+ { "3des", SSH_CIPHER_3DES, 8, 16, 0, 1, evp_ssh1_3des }, -+ -+ { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 1, EVP_des_ede3_cbc }, -+ { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, 1, EVP_aes_128_cbc }, -+ { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, 1, EVP_aes_192_cbc }, -+ { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, 1, EVP_aes_256_cbc }, -+ { "rijndael-cbc@lysator.liu.se", -+ SSH_CIPHER_SSH2, 16, 32, 0, 1, EVP_aes_256_cbc }, -+ { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, evp_aes_128_ctr }, -+ { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, evp_aes_128_ctr }, -+ { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, evp_aes_128_ctr }, -+ { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, NULL } -+}; -+ - /*--*/ - - u_int -@@ -135,7 +152,7 @@ Cipher * - cipher_by_name(const char *name) - { - Cipher *c; -- for (c = ciphers; c->name != NULL; c++) -+ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) - if (strcmp(c->name, name) == 0) - return c; - return NULL; -@@ -145,7 +162,7 @@ Cipher * - cipher_by_number(int id) - { - Cipher *c; -- for (c = ciphers; c->name != NULL; c++) -+ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) - if (c->number == id) - return c; - return NULL; -@@ -189,7 +206,7 @@ cipher_number(const char *name) - Cipher *c; - if (name == NULL) - return -1; -- for (c = ciphers; c->name != NULL; c++) -+ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) - if (strcasecmp(c->name, name) == 0) - return c->number; - return -1; -@@ -296,14 +313,15 @@ cipher_cleanup(CipherContext *cc) - * passphrase and using the resulting 16 bytes as the key. - */ - --void -+int - cipher_set_key_string(CipherContext *cc, Cipher *cipher, - const char *passphrase, int do_encrypt) - { - MD5_CTX md; - u_char digest[16]; - -- MD5_Init(&md); -+ if (MD5_Init(&md) <= 0) -+ return -1; - MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase)); - MD5_Final(digest, &md); - -@@ -311,6 +329,7 @@ cipher_set_key_string(CipherContext *cc, - - memset(digest, 0, sizeof(digest)); - memset(&md, 0, sizeof(md)); -+ return 0; - } - - /* -diff -up openssh-5.2p1/cipher-ctr.c.fips openssh-5.2p1/cipher-ctr.c ---- openssh-5.2p1/cipher-ctr.c.fips 2007-06-14 15:21:33.000000000 +0200 -+++ openssh-5.2p1/cipher-ctr.c 2009-05-15 15:51:01.000000000 +0200 -@@ -140,7 +140,8 @@ evp_aes_128_ctr(void) - aes_ctr.do_cipher = ssh_aes_ctr; - #ifndef SSH_OLD_EVP - aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | -- EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV; -+ EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV | -+ EVP_CIPH_FLAG_FIPS; - #endif - return (&aes_ctr); - } -diff -up openssh-5.2p1/cipher.h.fips openssh-5.2p1/cipher.h ---- openssh-5.2p1/cipher.h.fips 2009-01-28 06:38:41.000000000 +0100 -+++ openssh-5.2p1/cipher.h 2009-05-15 15:51:01.000000000 +0200 -@@ -78,7 +78,7 @@ void cipher_init(CipherContext *, Ciphe - const u_char *, u_int, int); - void cipher_crypt(CipherContext *, u_char *, const u_char *, u_int); - void cipher_cleanup(CipherContext *); --void cipher_set_key_string(CipherContext *, Cipher *, const char *, int); -+int cipher_set_key_string(CipherContext *, Cipher *, const char *, int); - u_int cipher_blocksize(const Cipher *); - u_int cipher_keylen(const Cipher *); - u_int cipher_is_cbc(const Cipher *); -diff -up openssh-5.2p1/mac.c.fips openssh-5.2p1/mac.c ---- openssh-5.2p1/mac.c.fips 2008-06-13 02:58:50.000000000 +0200 -+++ openssh-5.2p1/mac.c 2009-05-15 15:51:01.000000000 +0200 -@@ -28,6 +28,7 @@ - #include - - #include -+#include - - #include - #include -@@ -47,14 +48,14 @@ - #define SSH_EVP 1 /* OpenSSL EVP-based MAC */ - #define SSH_UMAC 2 /* UMAC (not integrated with OpenSSL) */ - --struct { -+struct Macs { - char *name; - int type; - const EVP_MD * (*mdfunc)(void); - int truncatebits; /* truncate digest if != 0 */ - int key_len; /* just for UMAC */ - int len; /* just for UMAC */ --} macs[] = { -+} all_macs[] = { - { "hmac-sha1", SSH_EVP, EVP_sha1, 0, -1, -1 }, - { "hmac-sha1-96", SSH_EVP, EVP_sha1, 96, -1, -1 }, - { "hmac-md5", SSH_EVP, EVP_md5, 0, -1, -1 }, -@@ -65,9 +66,15 @@ struct { - { NULL, 0, NULL, 0, -1, -1 } - }; - -+struct Macs fips_macs[] = { -+ { "hmac-sha1", SSH_EVP, EVP_sha1, 0, -1, -1 }, -+ { NULL, 0, NULL, 0, -1, -1 } -+}; -+ - static void - mac_setup_by_id(Mac *mac, int which) - { -+ struct Macs *macs = FIPS_mode() ? fips_macs : all_macs; - int evp_len; - mac->type = macs[which].type; - if (mac->type == SSH_EVP) { -@@ -88,6 +95,7 @@ int - mac_setup(Mac *mac, char *name) - { - int i; -+ struct Macs *macs = FIPS_mode() ? fips_macs : all_macs; - - for (i = 0; macs[i].name; i++) { - if (strcmp(name, macs[i].name) == 0) { -diff -up openssh-5.2p1/Makefile.in.fips openssh-5.2p1/Makefile.in ---- openssh-5.2p1/Makefile.in.fips 2009-05-15 15:51:01.000000000 +0200 -+++ openssh-5.2p1/Makefile.in 2009-05-15 15:51:01.000000000 +0200 -@@ -134,28 +134,28 @@ libssh.a: $(LIBSSH_OBJS) - $(RANLIB) $@ - - ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS) -- $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -+ $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) - - sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS) -- $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) -+ $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) -lfipscheck $(LIBS) - - scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o - $(LD) -o $@ scp.o progressmeter.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) - - ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o -- $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -+ $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) - - ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o -- $(LD) -o $@ ssh-agent.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -+ $(LD) -o $@ ssh-agent.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) - - ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o -- $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -+ $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) - - ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o -- $(LD) -o $@ ssh-keysign.o readconf.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -+ $(LD) -o $@ ssh-keysign.o readconf.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) - - ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o -- $(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) -+ $(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS) - - sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o - $(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -diff -up openssh-5.2p1/myproposal.h.fips openssh-5.2p1/myproposal.h ---- openssh-5.2p1/myproposal.h.fips 2009-01-28 06:33:31.000000000 +0100 -+++ openssh-5.2p1/myproposal.h 2009-05-15 15:51:01.000000000 +0200 -@@ -53,7 +53,12 @@ - "hmac-sha1-96,hmac-md5-96" - #define KEX_DEFAULT_COMP "none,zlib@openssh.com,zlib" - #define KEX_DEFAULT_LANG "" -- -+#define KEX_FIPS_ENCRYPT \ -+ "aes128-ctr,aes192-ctr,aes256-ctr," \ -+ "aes128-cbc,3des-cbc," \ -+ "aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se" -+#define KEX_FIPS_MAC \ -+ "hmac-sha1" - - static char *myproposal[PROPOSAL_MAX] = { - KEX_DEFAULT_KEX, -diff -up openssh-5.2p1/nsskeys.c.fips openssh-5.2p1/nsskeys.c ---- openssh-5.2p1/nsskeys.c.fips 2009-05-15 15:51:01.000000000 +0200 -+++ openssh-5.2p1/nsskeys.c 2009-05-15 15:51:01.000000000 +0200 -@@ -183,8 +183,8 @@ nss_convert_pubkey(Key *k) - break; - } - -- p = key_fingerprint(k, SSH_FP_MD5, SSH_FP_HEX); -- debug("fingerprint %u %s", key_size(k), p); -+ p = key_fingerprint(k, SSH_FP_SHA1, SSH_FP_HEX); -+ debug("SHA1 fingerprint %u %s", key_size(k), p); - xfree(p); - - return 0; -diff -up openssh-5.2p1/openbsd-compat/bsd-arc4random.c.fips openssh-5.2p1/openbsd-compat/bsd-arc4random.c ---- openssh-5.2p1/openbsd-compat/bsd-arc4random.c.fips 2008-06-04 02:54:00.000000000 +0200 -+++ openssh-5.2p1/openbsd-compat/bsd-arc4random.c 2009-05-15 15:51:01.000000000 +0200 -@@ -39,6 +39,7 @@ - static int rc4_ready = 0; - static RC4_KEY rc4; - -+#if 0 - unsigned int - arc4random(void) - { -@@ -82,6 +83,32 @@ arc4random_stir(void) - - rc4_ready = REKEY_BYTES; - } -+#else -+unsigned int -+arc4random(void) -+{ -+ unsigned int r = 0; -+ void *rp = &r; -+ -+ if (!rc4_ready) { -+ arc4random_stir(); -+ } -+ RAND_bytes(rp, sizeof(r)); -+ -+ return(r); -+} -+ -+void -+arc4random_stir(void) -+{ -+ unsigned char rand_buf[SEED_SIZE]; -+ -+ if (RAND_bytes(rand_buf, sizeof(rand_buf)) <= 0) -+ fatal("Couldn't obtain random bytes (error %ld)", -+ ERR_get_error()); -+ rc4_ready = 1; -+} -+#endif - #endif /* !HAVE_ARC4RANDOM */ - - #ifndef ARC4RANDOM_BUF -diff -up openssh-5.2p1/ssh-add.c.fips openssh-5.2p1/ssh-add.c ---- openssh-5.2p1/ssh-add.c.fips 2009-05-15 15:51:01.000000000 +0200 -+++ openssh-5.2p1/ssh-add.c 2009-05-15 15:51:01.000000000 +0200 -@@ -42,6 +42,7 @@ - #include - - #include -+#include - #include "openbsd-compat/openssl-compat.h" - - #ifdef HAVE_LIBNSS -@@ -254,7 +255,7 @@ list_identities(AuthenticationConnection - key = ssh_get_next_identity(ac, &comment, version)) { - had_identities = 1; - if (do_fp) { -- fp = key_fingerprint(key, SSH_FP_MD5, -+ fp = key_fingerprint(key, FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5, - SSH_FP_HEX); - printf("%d %s %s (%s)\n", - key_size(key), fp, comment, key_type(key)); -diff -up openssh-5.2p1/ssh-agent.c.fips openssh-5.2p1/ssh-agent.c ---- openssh-5.2p1/ssh-agent.c.fips 2009-05-15 15:51:01.000000000 +0200 -+++ openssh-5.2p1/ssh-agent.c 2009-05-15 15:51:01.000000000 +0200 -@@ -51,6 +51,7 @@ - - #include - #include -+#include - #include "openbsd-compat/openssl-compat.h" - - #include -@@ -200,9 +201,9 @@ confirm_key(Identity *id) - char *p; - int ret = -1; - -- p = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX); -- if (ask_permission("Allow use of key %s?\nKey fingerprint %s.", -- id->comment, p)) -+ p = key_fingerprint(id->key, FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); -+ if (ask_permission("Allow use of key %s?\nKey %sfingerprint %s.", -+ id->comment, FIPS_mode() ? "SHA1 " : "", p)) - ret = 0; - xfree(p); - -diff -up openssh-5.2p1/ssh.c.fips openssh-5.2p1/ssh.c ---- openssh-5.2p1/ssh.c.fips 2009-05-15 15:51:01.000000000 +0200 -+++ openssh-5.2p1/ssh.c 2009-05-15 15:51:01.000000000 +0200 -@@ -71,6 +71,8 @@ - - #include - #include -+#include -+#include - #include "openbsd-compat/openssl-compat.h" - #include "openbsd-compat/sys-queue.h" - -@@ -220,6 +222,10 @@ main(int ac, char **av) - sanitise_stdfd(); - - __progname = ssh_get_progname(av[0]); -+ SSLeay_add_all_algorithms(); -+ if (FIPS_mode() && !FIPSCHECK_verify(NULL, NULL)) { -+ fatal("FIPS integrity verification test failed."); -+ } - init_rng(); - - /* -@@ -279,6 +285,9 @@ main(int ac, char **av) - "ACD:F:I:KL:MNO:PR:S:TVw:XYy")) != -1) { - switch (opt) { - case '1': -+ if (FIPS_mode()) { -+ fatal("Protocol 1 not allowed in the FIPS mode."); -+ } - options.protocol = SSH_PROTO_1; - break; - case '2': -@@ -550,7 +559,6 @@ main(int ac, char **av) - if (!host) - usage(); - -- SSLeay_add_all_algorithms(); - ERR_load_crypto_strings(); - - /* Initialize the command to execute on remote host. */ -@@ -635,6 +643,10 @@ main(int ac, char **av) - - seed_rng(); - -+ if (FIPS_mode()) { -+ logit("FIPS mode initialized"); -+ } -+ - if (options.user == NULL) - options.user = xstrdup(pw->pw_name); - -@@ -701,6 +713,12 @@ main(int ac, char **av) - - timeout_ms = options.connection_timeout * 1000; - -+ if (FIPS_mode()) { -+ options.protocol &= SSH_PROTO_2; -+ if (options.protocol == 0) -+ fatal("Protocol 2 disabled by configuration but required in the FIPS mode."); -+ } -+ - /* Open a connection to the remote host. */ - if (ssh_connect(host, &hostaddr, options.port, - options.address_family, options.connection_attempts, &timeout_ms, -diff -up openssh-5.2p1/sshconnect2.c.fips openssh-5.2p1/sshconnect2.c ---- openssh-5.2p1/sshconnect2.c.fips 2009-05-15 15:51:01.000000000 +0200 -+++ openssh-5.2p1/sshconnect2.c 2009-05-15 15:51:01.000000000 +0200 -@@ -44,6 +44,8 @@ - #include - #endif - -+#include -+ - #include "openbsd-compat/sys-queue.h" - - #include "xmalloc.h" -@@ -115,6 +117,10 @@ ssh_kex2(char *host, struct sockaddr *ho - if (options.ciphers != NULL) { - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; -+ } else if (FIPS_mode()) { -+ myproposal[PROPOSAL_ENC_ALGS_CTOS] = -+ myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_FIPS_ENCRYPT; -+ - } - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); -@@ -130,7 +136,11 @@ ssh_kex2(char *host, struct sockaddr *ho - if (options.macs != NULL) { - myproposal[PROPOSAL_MAC_ALGS_CTOS] = - myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; -+ } else if (FIPS_mode()) { -+ myproposal[PROPOSAL_MAC_ALGS_CTOS] = -+ myproposal[PROPOSAL_MAC_ALGS_STOC] = KEX_FIPS_MAC; - } -+ - if (options.hostkeyalgorithms != NULL) - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = - options.hostkeyalgorithms; -@@ -507,8 +517,8 @@ input_userauth_pk_ok(int type, u_int32_t - key->type, pktype); - goto done; - } -- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); -- debug2("input_userauth_pk_ok: fp %s", fp); -+ fp = key_fingerprint(key, SSH_FP_SHA1, SSH_FP_HEX); -+ debug2("input_userauth_pk_ok: SHA1 fp %s", fp); - xfree(fp); - - /* -diff -up openssh-5.2p1/sshconnect.c.fips openssh-5.2p1/sshconnect.c ---- openssh-5.2p1/sshconnect.c.fips 2009-05-15 15:51:01.000000000 +0200 -+++ openssh-5.2p1/sshconnect.c 2009-05-15 15:51:01.000000000 +0200 -@@ -40,6 +40,8 @@ - #include - #include - -+#include -+ - #include "xmalloc.h" - #include "key.h" - #include "hostfile.h" -@@ -761,6 +763,7 @@ check_host_key(char *hostname, struct so - goto fail; - } else if (options.strict_host_key_checking == 2) { - char msg1[1024], msg2[1024]; -+ int fips_on = FIPS_mode(); - - if (show_other_keys(host, host_key)) - snprintf(msg1, sizeof(msg1), -@@ -769,8 +772,8 @@ check_host_key(char *hostname, struct so - else - snprintf(msg1, sizeof(msg1), "."); - /* The default */ -- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); -- ra = key_fingerprint(host_key, SSH_FP_MD5, -+ fp = key_fingerprint(host_key, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); -+ ra = key_fingerprint(host_key, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, - SSH_FP_RANDOMART); - msg2[0] = '\0'; - if (options.verify_host_key_dns) { -@@ -786,10 +789,10 @@ check_host_key(char *hostname, struct so - snprintf(msg, sizeof(msg), - "The authenticity of host '%.200s (%s)' can't be " - "established%s\n" -- "%s key fingerprint is %s.%s%s\n%s" -+ "%s key %sfingerprint is %s.%s%s\n%s" - "Are you sure you want to continue connecting " - "(yes/no)? ", -- host, ip, msg1, type, fp, -+ host, ip, msg1, type, fips_on ? "SHA1 " : "", fp, - options.visual_host_key ? "\n" : "", - options.visual_host_key ? ra : "", - msg2); -@@ -1077,17 +1080,18 @@ show_key_from_file(const char *file, con - Key *found; - char *fp, *ra; - int line, ret; -+ int fips_on = FIPS_mode(); - - found = key_new(keytype); - if ((ret = lookup_key_in_hostfile_by_type(file, host, - keytype, found, &line))) { -- fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); -- ra = key_fingerprint(found, SSH_FP_MD5, SSH_FP_RANDOMART); -+ fp = key_fingerprint(found, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); -+ ra = key_fingerprint(found, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_RANDOMART); - logit("WARNING: %s key found for host %s\n" - "in %s:%d\n" -- "%s key fingerprint %s.\n%s\n", -+ "%s key %sfingerprint %s.\n%s\n", - key_type(found), host, file, line, -- key_type(found), fp, ra); -+ key_type(found), fips_on ? "SHA1 ":"", fp, ra); - xfree(ra); - xfree(fp); - } -@@ -1133,8 +1137,9 @@ warn_changed_key(Key *host_key) - { - char *fp; - const char *type = key_type(host_key); -+ int fips_on = FIPS_mode(); - -- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); -+ fp = key_fingerprint(host_key, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); - - error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); - error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @"); -@@ -1142,8 +1147,8 @@ warn_changed_key(Key *host_key) - error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!"); - error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!"); - error("It is also possible that the %s host key has just been changed.", type); -- error("The fingerprint for the %s key sent by the remote host is\n%s.", -- type, fp); -+ error("The %sfingerprint for the %s key sent by the remote host is\n%s.", -+ fips_on ? "SHA1 ":"", type, fp); - error("Please contact your system administrator."); - - xfree(fp); -diff -up openssh-5.2p1/sshd.c.fips openssh-5.2p1/sshd.c ---- openssh-5.2p1/sshd.c.fips 2009-05-15 15:51:01.000000000 +0200 -+++ openssh-5.2p1/sshd.c 2009-05-15 15:51:01.000000000 +0200 -@@ -76,6 +76,8 @@ - #include - #include - #include -+#include -+#include - #include "openbsd-compat/openssl-compat.h" - - #ifdef HAVE_SECUREWARE -@@ -1260,6 +1262,12 @@ main(int ac, char **av) - (void)set_auth_parameters(ac, av); - #endif - __progname = ssh_get_progname(av[0]); -+ -+ SSLeay_add_all_algorithms(); -+ if (FIPS_mode() && !FIPSCHECK_verify(NULL, NULL)) { -+ fatal("FIPS integrity verification test failed."); -+ } -+ - init_rng(); - - /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */ -@@ -1412,8 +1420,6 @@ main(int ac, char **av) - else - closefrom(REEXEC_DEVCRYPTO_RESERVED_FD); - -- SSLeay_add_all_algorithms(); -- - /* - * Force logging to stderr until we have loaded the private host - * key (unless started from inetd) -@@ -1531,6 +1537,10 @@ main(int ac, char **av) - debug("private host key: #%d type %d %s", i, key->type, - key_type(key)); - } -+ if ((options.protocol & SSH_PROTO_1) && FIPS_mode()) { -+ logit("Disabling protocol version 1. Not allowed in the FIPS mode."); -+ options.protocol &= ~SSH_PROTO_1; -+ } - if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) { - logit("Disabling protocol version 1. Could not load host key"); - options.protocol &= ~SSH_PROTO_1; -@@ -1655,6 +1665,10 @@ main(int ac, char **av) - /* Initialize the random number generator. */ - arc4random_stir(); - -+ if (FIPS_mode()) { -+ logit("FIPS mode initialized"); -+ } -+ - /* Chdir to the root directory so that the current disk can be - unmounted if desired. */ - chdir("/"); -@@ -2182,6 +2196,9 @@ do_ssh2_kex(void) - if (options.ciphers != NULL) { - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; -+ } else if (FIPS_mode()) { -+ myproposal[PROPOSAL_ENC_ALGS_CTOS] = -+ myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_FIPS_ENCRYPT; - } - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); -@@ -2191,6 +2208,9 @@ do_ssh2_kex(void) - if (options.macs != NULL) { - myproposal[PROPOSAL_MAC_ALGS_CTOS] = - myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; -+ } else if (FIPS_mode()) { -+ myproposal[PROPOSAL_MAC_ALGS_CTOS] = -+ myproposal[PROPOSAL_MAC_ALGS_STOC] = KEX_FIPS_MAC; - } - if (options.compression == COMP_NONE) { - myproposal[PROPOSAL_COMP_ALGS_CTOS] = -diff -up openssh-5.2p1/ssh-keygen.c.fips openssh-5.2p1/ssh-keygen.c ---- openssh-5.2p1/ssh-keygen.c.fips 2009-05-15 15:51:01.000000000 +0200 -+++ openssh-5.2p1/ssh-keygen.c 2009-05-15 15:51:01.000000000 +0200 -@@ -21,6 +21,7 @@ - - #include - #include -+#include - #include "openbsd-compat/openssl-compat.h" - - #include -@@ -537,7 +538,7 @@ do_fingerprint(struct passwd *pw) - enum fp_type fptype; - struct stat st; - -- fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5; -+ fptype = print_bubblebabble ? SSH_FP_SHA1 : FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5; - rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX; - - if (!have_identity) -@@ -1506,14 +1507,15 @@ passphrase_again: - fclose(f); - - if (!quiet) { -- char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX); -- char *ra = key_fingerprint(public, SSH_FP_MD5, -+ int fips_on = FIPS_mode(); -+ char *fp = key_fingerprint(public, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); -+ char *ra = key_fingerprint(public, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, - SSH_FP_RANDOMART); - printf("Your public key has been saved in %s.\n", - identity_file); -- printf("The key fingerprint is:\n"); -+ printf("The key %sfingerprint is:\n", fips_on ? "SHA1 " : ""); - printf("%s %s\n", fp, comment); -- printf("The key's randomart image is:\n"); -+ printf("The key's %srandomart image is:\n", fips_on ? "SHA1 " :""); - printf("%s\n", ra); - xfree(ra); - xfree(fp); diff --git a/openssh-5.2p1-nss-keys.patch b/openssh-5.2p1-nss-keys.patch deleted file mode 100644 index cf8bbea..0000000 --- a/openssh-5.2p1-nss-keys.patch +++ /dev/null @@ -1,1368 +0,0 @@ -diff -up openssh-5.2p1/authfd.c.nss-keys openssh-5.2p1/authfd.c ---- openssh-5.2p1/authfd.c.nss-keys 2006-09-01 07:38:36.000000000 +0200 -+++ openssh-5.2p1/authfd.c 2009-08-15 11:39:07.376618281 +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-5.2p1/authfd.h.nss-keys openssh-5.2p1/authfd.h ---- openssh-5.2p1/authfd.h.nss-keys 2006-08-05 04:39:39.000000000 +0200 -+++ openssh-5.2p1/authfd.h 2009-08-15 11:39:07.369353952 +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-5.2p1/configure.ac.nss-keys openssh-5.2p1/configure.ac ---- openssh-5.2p1/configure.ac.nss-keys 2009-08-15 11:39:07.161229467 +0200 -+++ openssh-5.2p1/configure.ac 2009-08-15 11:39:07.373539105 +0200 -@@ -3462,6 +3462,20 @@ AC_ARG_WITH(kerberos5, - ] - ) - -+# 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) -+ - # Looking for programs, paths and files - - PRIVSEP_PATH=/var/empty -@@ -4189,6 +4203,7 @@ echo " TCP Wrappers support - echo " MD5 password support: $MD5_MSG" - echo " libedit support: $LIBEDIT_MSG" - echo " Solaris process contract support: $SPC_MSG" -+echo " NSS support: $LIBNSS_MSG" - echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG" - echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG" - echo " BSD Auth support: $BSD_AUTH_MSG" -diff -up openssh-5.2p1/key.c.nss-keys openssh-5.2p1/key.c ---- openssh-5.2p1/key.c.nss-keys 2008-11-03 09:24:17.000000000 +0100 -+++ openssh-5.2p1/key.c 2009-08-15 11:39:07.363301772 +0200 -@@ -96,6 +96,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) - { -@@ -151,6 +199,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 != NULL && 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-5.2p1/key.h.nss-keys openssh-5.2p1/key.h ---- openssh-5.2p1/key.h.nss-keys 2008-06-12 20:40:35.000000000 +0200 -+++ openssh-5.2p1/key.h 2009-08-15 11:39:07.388333558 +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 { -@@ -48,16 +54,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-5.2p1/Makefile.in.nss-keys openssh-5.2p1/Makefile.in ---- openssh-5.2p1/Makefile.in.nss-keys 2008-11-05 06:20:46.000000000 +0100 -+++ openssh-5.2p1/Makefile.in 2009-08-15 11:39:07.387287237 +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 jpake.o schnorr.o -+ entropy.o scard-opensc.o gss-genr.o umac.o jpake.o schnorr.o nsskeys.o - - SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ - sshconnect.o sshconnect1.o sshconnect2.o mux.o -diff -up /dev/null openssh-5.2p1/nsskeys.c ---- /dev/null 2009-08-11 04:59:51.783705773 +0200 -+++ openssh-5.2p1/nsskeys.c 2009-08-15 11:39:07.381280271 +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 /dev/null openssh-5.2p1/nsskeys.h ---- /dev/null 2009-08-11 04:59:51.783705773 +0200 -+++ openssh-5.2p1/nsskeys.h 2009-08-15 11:39:07.385223433 +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-5.2p1/readconf.c.nss-keys openssh-5.2p1/readconf.c ---- openssh-5.2p1/readconf.c.nss-keys 2009-02-14 06:28:21.000000000 +0100 -+++ openssh-5.2p1/readconf.c 2009-08-15 11:39:07.397161060 +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, -@@ -210,6 +211,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 }, -@@ -612,6 +620,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: -@@ -1047,6 +1063,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 -up openssh-5.2p1/readconf.h.nss-keys openssh-5.2p1/readconf.h ---- openssh-5.2p1/readconf.h.nss-keys 2009-02-14 06:28:21.000000000 +0100 -+++ openssh-5.2p1/readconf.h 2009-08-15 11:39:07.377835083 +0200 -@@ -85,6 +85,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 openssh-5.2p1/ssh-add.c.nss-keys openssh-5.2p1/ssh-add.c ---- openssh-5.2p1/ssh-add.c.nss-keys 2008-02-28 09:13:52.000000000 +0100 -+++ openssh-5.2p1/ssh-add.c 2009-08-15 11:39:07.414164844 +0200 -@@ -44,6 +44,14 @@ - #include - #include "openbsd-compat/openssl-compat.h" - -+#ifdef HAVE_LIBNSS -+#include -+#include -+#include -+#include -+#include -+#endif -+ - #include - #include - #include -@@ -57,6 +65,7 @@ - #include "rsa.h" - #include "log.h" - #include "key.h" -+#include "nsskeys.h" - #include "buffer.h" - #include "authfd.h" - #include "authfile.h" -@@ -307,6 +316,128 @@ 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; -+ char **xkeyname = NULL; -+ -+ int count = 0; -+ int i; -+ -+ 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 ((count % 10) == 0) -+ xkeyname = xrealloc (xkeyname, count + 10, sizeof (char *)); -+ -+ xkeyname[count++] = keyname; -+ } -+ -+ PK11_Logout(slot); -+ -+ for (i = 0; i < count; i++) { -+ if (ssh_update_nss_key(ac, add, tokenname, xkeyname[i], -+ passcache?passcache:"", lifetime, confirm)) { -+ fprintf(stderr, "Key %s: %s:%s\n", -+ add?"added":"removed", tokenname, xkeyname[i]); -+ } else { -+ fprintf(stderr, "Could not %s key: %s:%s\n", -+ add?"add":"remove", tokenname, xkeyname[i]); -+ } -+ PORT_Free(xkeyname[i]); -+ } -+ -+ if (xkeyname != NULL) -+ free (xkeyname); -+ -+ if (passcache != NULL) { -+ memset(passcache, 0, strlen(passcache)); -+ xfree(passcache); -+ } -+ -+ SECKEY_DestroyPrivateKeyList(list); -+ -+ return count; -+} -+#endif -+ - static void - usage(void) - { -@@ -334,6 +465,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(); -@@ -351,7 +486,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': -@@ -373,6 +508,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; -@@ -387,6 +527,11 @@ main(int argc, char **argv) - goto done; - } - break; -+#ifdef HAVE_LIBNSS -+ case 'T': -+ token_id = optarg; -+ break; -+#endif - default: - usage(); - ret = 1; -@@ -400,6 +545,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-5.2p1/ssh-agent.c.nss-keys openssh-5.2p1/ssh-agent.c ---- openssh-5.2p1/ssh-agent.c.nss-keys 2008-07-04 15:10:49.000000000 +0200 -+++ openssh-5.2p1/ssh-agent.c 2009-08-15 11:39:07.368143486 +0200 -@@ -80,6 +80,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 -@@ -714,6 +718,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 -@@ -806,6 +918,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-5.2p1/ssh.c.nss-keys openssh-5.2p1/ssh.c ---- openssh-5.2p1/ssh.c.nss-keys 2009-02-14 06:28:21.000000000 +0100 -+++ openssh-5.2p1/ssh.c 2009-08-15 11:39:07.383383769 +0200 -@@ -104,6 +104,9 @@ - #ifdef SMARTCARD - #include "scard.h" - #endif -+#ifdef HAVE_LIBNSS -+#include "nsskeys.h" -+#endif - - extern char *__progname; - -@@ -1231,9 +1234,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) { -@@ -1256,6 +1261,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"); - pwname = xstrdup(pw->pw_name); -diff -up openssh-5.2p1/ssh-dss.c.nss-keys openssh-5.2p1/ssh-dss.c ---- openssh-5.2p1/ssh-dss.c.nss-keys 2006-11-07 13:14:42.000000000 +0100 -+++ openssh-5.2p1/ssh-dss.c 2009-08-15 11:39:07.365182193 +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-5.2p1/ssh-keygen.c.nss-keys openssh-5.2p1/ssh-keygen.c ---- openssh-5.2p1/ssh-keygen.c.nss-keys 2009-02-21 22:47:02.000000000 +0100 -+++ openssh-5.2p1/ssh-keygen.c 2009-08-15 11:39:07.395366022 +0200 -@@ -53,6 +53,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 -@@ -501,6 +506,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) - { -@@ -1083,7 +1108,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; - BIGNUM *start = NULL; -@@ -1116,7 +1142,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); -@@ -1156,6 +1182,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; -@@ -1187,10 +1217,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': -@@ -1299,6 +1329,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-5.2p1/ssh-rsa.c.nss-keys openssh-5.2p1/ssh-rsa.c ---- openssh-5.2p1/ssh-rsa.c.nss-keys 2006-09-01 07:38:37.000000000 +0200 -+++ openssh-5.2p1/ssh-rsa.c 2009-08-15 11:39:07.393249953 +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-5.2p1-pathmax.patch b/openssh-5.2p1-pathmax.patch deleted file mode 100644 index 5411589..0000000 --- a/openssh-5.2p1-pathmax.patch +++ /dev/null @@ -1,47 +0,0 @@ -diff -up openssh-5.2p1/ssh.c.pathmax openssh-5.2p1/ssh.c ---- openssh-5.2p1/ssh.c.pathmax 2009-07-08 14:23:19.000000000 +0200 -+++ openssh-5.2p1/ssh.c 2009-07-08 14:26:26.000000000 +0200 -@@ -49,6 +49,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -208,8 +209,8 @@ void muxserver_listen(void); - int - main(int ac, char **av) - { -- int i, opt, exit_status, use_syslog; -- char *p, *cp, *line, buf[256]; -+ int i, r, opt, exit_status, use_syslog; -+ char *p, *cp, *line, buf[MAXPATHLEN]; - struct stat st; - struct passwd *pw; - int dummy, timeout_ms; -@@ -624,9 +625,10 @@ main(int ac, char **av) - fatal("Can't open user config file %.100s: " - "%.100s", config, strerror(errno)); - } else { -- snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, -+ r = snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, - _PATH_SSH_USER_CONFFILE); -- (void)read_config_file(buf, host, &options, 1); -+ if (r > 0 && (size_t)r < sizeof(buf)) -+ (void)read_config_file(buf, host, &options, 1); - - /* Read systemwide configuration file after use config. */ - (void)read_config_file(_PATH_HOST_CONFIG_FILE, host, -@@ -787,9 +789,9 @@ main(int ac, char **av) - * Now that we are back to our own permissions, create ~/.ssh - * directory if it doesn't already exist. - */ -- snprintf(buf, sizeof buf, "%.100s%s%.100s", pw->pw_dir, -+ r = snprintf(buf, sizeof buf, "%s%s%s", pw->pw_dir, - strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR); -- if (stat(buf, &st) < 0) -+ if (r > 0 && (size_t)r < sizeof(buf) && stat(buf, &st) < 0) - if (mkdir(buf, 0700) < 0) - error("Could not create directory '%.200s'.", buf); - diff --git a/openssh-5.2p1-selabel.patch b/openssh-5.2p1-selabel.patch deleted file mode 100644 index 06ccffe..0000000 --- a/openssh-5.2p1-selabel.patch +++ /dev/null @@ -1,53 +0,0 @@ -diff -up openssh-5.2p1/contrib/ssh-copy-id.selabel openssh-5.2p1/contrib/ssh-copy-id ---- openssh-5.2p1/contrib/ssh-copy-id.selabel 2009-01-21 10:29:21.000000000 +0100 -+++ openssh-5.2p1/contrib/ssh-copy-id 2009-07-08 14:28:27.000000000 +0200 -@@ -38,7 +38,7 @@ if [ "$#" -lt 1 ] || [ "$1" = "-h" ] || - exit 1 - fi - --{ eval "$GET_ID" ; } | ssh $1 "umask 077; test -d .ssh || mkdir .ssh ; cat >> .ssh/authorized_keys" || exit 1 -+{ eval "$GET_ID" ; } | ssh $1 "umask 077; test -d .ssh || mkdir .ssh ; cat >> .ssh/authorized_keys; test -x /sbin/restorecon && /sbin/restorecon .ssh .ssh/authorized_keys" || exit 1 - - cat < - #include - #include -+#include - #include "openbsd-compat/openssl-compat.h" - #include "openbsd-compat/sys-queue.h" - -@@ -791,10 +792,15 @@ main(int ac, char **av) - */ - r = snprintf(buf, sizeof buf, "%s%s%s", pw->pw_dir, - strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR); -- if (r > 0 && (size_t)r < sizeof(buf) && stat(buf, &st) < 0) -+ if (r > 0 && (size_t)r < sizeof(buf) && stat(buf, &st) < 0) { -+ char *scon; -+ -+ matchpathcon(buf, 0700, &scon); -+ setfscreatecon(scon); - if (mkdir(buf, 0700) < 0) - error("Could not create directory '%.200s'.", buf); -- -+ setfscreatecon(NULL); -+ } - /* load options.identity_files */ - load_public_identity_files(); - diff --git a/openssh-5.3p1-fips.patch b/openssh-5.3p1-fips.patch new file mode 100644 index 0000000..01a715c --- /dev/null +++ b/openssh-5.3p1-fips.patch @@ -0,0 +1,695 @@ +diff -up openssh-5.3p1/auth2-pubkey.c.fips openssh-5.3p1/auth2-pubkey.c +--- openssh-5.3p1/auth2-pubkey.c.fips 2009-10-02 14:12:00.000000000 +0200 ++++ openssh-5.3p1/auth2-pubkey.c 2009-10-02 14:12:00.000000000 +0200 +@@ -33,6 +33,7 @@ + #include + #include + #include ++#include + + #include "xmalloc.h" + #include "ssh.h" +@@ -240,7 +241,7 @@ user_key_allowed2(struct passwd *pw, Key + found_key = 1; + debug("matching key found: file %s, line %lu", + file, linenum); +- fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); ++ fp = key_fingerprint(found, FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); + verbose("Found matching %s key: %s", + key_type(found), fp); + xfree(fp); +diff -up openssh-5.3p1/authfile.c.fips openssh-5.3p1/authfile.c +--- openssh-5.3p1/authfile.c.fips 2006-09-01 07:38:36.000000000 +0200 ++++ openssh-5.3p1/authfile.c 2009-10-02 14:12:00.000000000 +0200 +@@ -143,8 +143,14 @@ key_save_private_rsa1(Key *key, const ch + /* Allocate space for the private part of the key in the buffer. */ + cp = buffer_append_space(&encrypted, buffer_len(&buffer)); + +- cipher_set_key_string(&ciphercontext, cipher, passphrase, +- CIPHER_ENCRYPT); ++ if (cipher_set_key_string(&ciphercontext, cipher, passphrase, ++ CIPHER_ENCRYPT) < 0) { ++ error("cipher_set_key_string failed."); ++ buffer_free(&encrypted); ++ buffer_free(&buffer); ++ return 0; ++ } ++ + cipher_crypt(&ciphercontext, cp, + buffer_ptr(&buffer), buffer_len(&buffer)); + cipher_cleanup(&ciphercontext); +@@ -414,8 +420,14 @@ key_load_private_rsa1(int fd, const char + cp = buffer_append_space(&decrypted, buffer_len(&buffer)); + + /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ +- cipher_set_key_string(&ciphercontext, cipher, passphrase, +- CIPHER_DECRYPT); ++ if (cipher_set_key_string(&ciphercontext, cipher, passphrase, ++ CIPHER_DECRYPT) < 0) { ++ error("cipher_set_key_string failed."); ++ buffer_free(&decrypted); ++ buffer_free(&buffer); ++ goto fail; ++ } ++ + cipher_crypt(&ciphercontext, cp, + buffer_ptr(&buffer), buffer_len(&buffer)); + cipher_cleanup(&ciphercontext); +diff -up openssh-5.3p1/cipher.c.fips openssh-5.3p1/cipher.c +--- openssh-5.3p1/cipher.c.fips 2009-10-02 13:44:03.000000000 +0200 ++++ openssh-5.3p1/cipher.c 2009-10-02 14:12:00.000000000 +0200 +@@ -40,6 +40,7 @@ + #include + + #include ++#include + + #include + #include +@@ -93,6 +94,22 @@ struct Cipher { + { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, NULL } + }; + ++struct Cipher fips_ciphers[] = { ++ { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, EVP_enc_null }, ++ { "3des", SSH_CIPHER_3DES, 8, 16, 0, 1, evp_ssh1_3des }, ++ ++ { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 1, EVP_des_ede3_cbc }, ++ { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, 1, EVP_aes_128_cbc }, ++ { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, 1, EVP_aes_192_cbc }, ++ { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, 1, EVP_aes_256_cbc }, ++ { "rijndael-cbc@lysator.liu.se", ++ SSH_CIPHER_SSH2, 16, 32, 0, 1, EVP_aes_256_cbc }, ++ { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, evp_aes_128_ctr }, ++ { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, evp_aes_128_ctr }, ++ { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, evp_aes_128_ctr }, ++ { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, NULL } ++}; ++ + /*--*/ + + u_int +@@ -135,7 +152,7 @@ Cipher * + cipher_by_name(const char *name) + { + Cipher *c; +- for (c = ciphers; c->name != NULL; c++) ++ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) + if (strcmp(c->name, name) == 0) + return c; + return NULL; +@@ -145,7 +162,7 @@ Cipher * + cipher_by_number(int id) + { + Cipher *c; +- for (c = ciphers; c->name != NULL; c++) ++ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) + if (c->number == id) + return c; + return NULL; +@@ -189,7 +206,7 @@ cipher_number(const char *name) + Cipher *c; + if (name == NULL) + return -1; +- for (c = ciphers; c->name != NULL; c++) ++ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) + if (strcasecmp(c->name, name) == 0) + return c->number; + return -1; +@@ -296,14 +313,15 @@ cipher_cleanup(CipherContext *cc) + * passphrase and using the resulting 16 bytes as the key. + */ + +-void ++int + cipher_set_key_string(CipherContext *cc, Cipher *cipher, + const char *passphrase, int do_encrypt) + { + MD5_CTX md; + u_char digest[16]; + +- MD5_Init(&md); ++ if (MD5_Init(&md) <= 0) ++ return -1; + MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase)); + MD5_Final(digest, &md); + +@@ -311,6 +329,7 @@ cipher_set_key_string(CipherContext *cc, + + memset(digest, 0, sizeof(digest)); + memset(&md, 0, sizeof(md)); ++ return 0; + } + + /* +diff -up openssh-5.3p1/cipher-ctr.c.fips openssh-5.3p1/cipher-ctr.c +--- openssh-5.3p1/cipher-ctr.c.fips 2007-06-14 15:21:33.000000000 +0200 ++++ openssh-5.3p1/cipher-ctr.c 2009-10-02 14:12:00.000000000 +0200 +@@ -140,7 +140,8 @@ evp_aes_128_ctr(void) + aes_ctr.do_cipher = ssh_aes_ctr; + #ifndef SSH_OLD_EVP + aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | +- EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV; ++ EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV | ++ EVP_CIPH_FLAG_FIPS; + #endif + return (&aes_ctr); + } +diff -up openssh-5.3p1/cipher.h.fips openssh-5.3p1/cipher.h +--- openssh-5.3p1/cipher.h.fips 2009-01-28 06:38:41.000000000 +0100 ++++ openssh-5.3p1/cipher.h 2009-10-02 14:12:00.000000000 +0200 +@@ -78,7 +78,7 @@ void cipher_init(CipherContext *, Ciphe + const u_char *, u_int, int); + void cipher_crypt(CipherContext *, u_char *, const u_char *, u_int); + void cipher_cleanup(CipherContext *); +-void cipher_set_key_string(CipherContext *, Cipher *, const char *, int); ++int cipher_set_key_string(CipherContext *, Cipher *, const char *, int); + u_int cipher_blocksize(const Cipher *); + u_int cipher_keylen(const Cipher *); + u_int cipher_is_cbc(const Cipher *); +diff -up openssh-5.3p1/mac.c.fips openssh-5.3p1/mac.c +--- openssh-5.3p1/mac.c.fips 2008-06-13 02:58:50.000000000 +0200 ++++ openssh-5.3p1/mac.c 2009-10-02 14:12:00.000000000 +0200 +@@ -28,6 +28,7 @@ + #include + + #include ++#include + + #include + #include +@@ -47,14 +48,14 @@ + #define SSH_EVP 1 /* OpenSSL EVP-based MAC */ + #define SSH_UMAC 2 /* UMAC (not integrated with OpenSSL) */ + +-struct { ++struct Macs { + char *name; + int type; + const EVP_MD * (*mdfunc)(void); + int truncatebits; /* truncate digest if != 0 */ + int key_len; /* just for UMAC */ + int len; /* just for UMAC */ +-} macs[] = { ++} all_macs[] = { + { "hmac-sha1", SSH_EVP, EVP_sha1, 0, -1, -1 }, + { "hmac-sha1-96", SSH_EVP, EVP_sha1, 96, -1, -1 }, + { "hmac-md5", SSH_EVP, EVP_md5, 0, -1, -1 }, +@@ -65,9 +66,15 @@ struct { + { NULL, 0, NULL, 0, -1, -1 } + }; + ++struct Macs fips_macs[] = { ++ { "hmac-sha1", SSH_EVP, EVP_sha1, 0, -1, -1 }, ++ { NULL, 0, NULL, 0, -1, -1 } ++}; ++ + static void + mac_setup_by_id(Mac *mac, int which) + { ++ struct Macs *macs = FIPS_mode() ? fips_macs : all_macs; + int evp_len; + mac->type = macs[which].type; + if (mac->type == SSH_EVP) { +@@ -88,6 +95,7 @@ int + mac_setup(Mac *mac, char *name) + { + int i; ++ struct Macs *macs = FIPS_mode() ? fips_macs : all_macs; + + for (i = 0; macs[i].name; i++) { + if (strcmp(name, macs[i].name) == 0) { +diff -up openssh-5.3p1/Makefile.in.fips openssh-5.3p1/Makefile.in +--- openssh-5.3p1/Makefile.in.fips 2009-10-02 14:12:00.000000000 +0200 ++++ openssh-5.3p1/Makefile.in 2009-10-02 14:20:18.000000000 +0200 +@@ -136,28 +136,28 @@ libssh.a: $(LIBSSH_OBJS) + $(RANLIB) $@ + + ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS) +- $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ++ $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) + + sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS) +- $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) ++ $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(SSHDLIBS) $(LIBS) + + scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o + $(LD) -o $@ scp.o progressmeter.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) + + ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o +- $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ++ $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) + + ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o +- $(LD) -o $@ ssh-agent.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ++ $(LD) -o $@ ssh-agent.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) + + ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o +- $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ++ $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) + + ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o roaming_dummy.o +- $(LD) -o $@ ssh-keysign.o readconf.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ++ $(LD) -o $@ ssh-keysign.o readconf.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) + + ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o roaming_dummy.o +- $(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) ++ $(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS) + + sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o + $(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) +diff -up openssh-5.3p1/myproposal.h.fips openssh-5.3p1/myproposal.h +--- openssh-5.3p1/myproposal.h.fips 2009-01-28 06:33:31.000000000 +0100 ++++ openssh-5.3p1/myproposal.h 2009-10-02 14:12:00.000000000 +0200 +@@ -53,7 +53,12 @@ + "hmac-sha1-96,hmac-md5-96" + #define KEX_DEFAULT_COMP "none,zlib@openssh.com,zlib" + #define KEX_DEFAULT_LANG "" +- ++#define KEX_FIPS_ENCRYPT \ ++ "aes128-ctr,aes192-ctr,aes256-ctr," \ ++ "aes128-cbc,3des-cbc," \ ++ "aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se" ++#define KEX_FIPS_MAC \ ++ "hmac-sha1" + + static char *myproposal[PROPOSAL_MAX] = { + KEX_DEFAULT_KEX, +diff -up openssh-5.3p1/nsskeys.c.fips openssh-5.3p1/nsskeys.c +--- openssh-5.3p1/nsskeys.c.fips 2009-10-02 14:12:00.000000000 +0200 ++++ openssh-5.3p1/nsskeys.c 2009-10-02 14:12:00.000000000 +0200 +@@ -183,8 +183,8 @@ nss_convert_pubkey(Key *k) + break; + } + +- p = key_fingerprint(k, SSH_FP_MD5, SSH_FP_HEX); +- debug("fingerprint %u %s", key_size(k), p); ++ p = key_fingerprint(k, SSH_FP_SHA1, SSH_FP_HEX); ++ debug("SHA1 fingerprint %u %s", key_size(k), p); + xfree(p); + + return 0; +diff -up openssh-5.3p1/openbsd-compat/bsd-arc4random.c.fips openssh-5.3p1/openbsd-compat/bsd-arc4random.c +--- openssh-5.3p1/openbsd-compat/bsd-arc4random.c.fips 2008-06-04 02:54:00.000000000 +0200 ++++ openssh-5.3p1/openbsd-compat/bsd-arc4random.c 2009-10-02 14:12:00.000000000 +0200 +@@ -39,6 +39,7 @@ + static int rc4_ready = 0; + static RC4_KEY rc4; + ++#if 0 + unsigned int + arc4random(void) + { +@@ -82,6 +83,32 @@ arc4random_stir(void) + + rc4_ready = REKEY_BYTES; + } ++#else ++unsigned int ++arc4random(void) ++{ ++ unsigned int r = 0; ++ void *rp = &r; ++ ++ if (!rc4_ready) { ++ arc4random_stir(); ++ } ++ RAND_bytes(rp, sizeof(r)); ++ ++ return(r); ++} ++ ++void ++arc4random_stir(void) ++{ ++ unsigned char rand_buf[SEED_SIZE]; ++ ++ if (RAND_bytes(rand_buf, sizeof(rand_buf)) <= 0) ++ fatal("Couldn't obtain random bytes (error %ld)", ++ ERR_get_error()); ++ rc4_ready = 1; ++} ++#endif + #endif /* !HAVE_ARC4RANDOM */ + + #ifndef ARC4RANDOM_BUF +diff -up openssh-5.3p1/ssh-add.c.fips openssh-5.3p1/ssh-add.c +--- openssh-5.3p1/ssh-add.c.fips 2009-10-02 14:12:00.000000000 +0200 ++++ openssh-5.3p1/ssh-add.c 2009-10-02 14:12:00.000000000 +0200 +@@ -42,6 +42,7 @@ + #include + + #include ++#include + #include "openbsd-compat/openssl-compat.h" + + #ifdef HAVE_LIBNSS +@@ -254,7 +255,7 @@ list_identities(AuthenticationConnection + key = ssh_get_next_identity(ac, &comment, version)) { + had_identities = 1; + if (do_fp) { +- fp = key_fingerprint(key, SSH_FP_MD5, ++ fp = key_fingerprint(key, FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5, + SSH_FP_HEX); + printf("%d %s %s (%s)\n", + key_size(key), fp, comment, key_type(key)); +diff -up openssh-5.3p1/ssh-agent.c.fips openssh-5.3p1/ssh-agent.c +--- openssh-5.3p1/ssh-agent.c.fips 2009-10-02 14:12:00.000000000 +0200 ++++ openssh-5.3p1/ssh-agent.c 2009-10-02 14:12:00.000000000 +0200 +@@ -51,6 +51,7 @@ + + #include + #include ++#include + #include "openbsd-compat/openssl-compat.h" + + #include +@@ -200,9 +201,9 @@ confirm_key(Identity *id) + char *p; + int ret = -1; + +- p = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX); +- if (ask_permission("Allow use of key %s?\nKey fingerprint %s.", +- id->comment, p)) ++ p = key_fingerprint(id->key, FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); ++ if (ask_permission("Allow use of key %s?\nKey %sfingerprint %s.", ++ id->comment, FIPS_mode() ? "SHA1 " : "", p)) + ret = 0; + xfree(p); + +diff -up openssh-5.3p1/ssh.c.fips openssh-5.3p1/ssh.c +--- openssh-5.3p1/ssh.c.fips 2009-10-02 14:12:00.000000000 +0200 ++++ openssh-5.3p1/ssh.c 2009-10-02 14:12:00.000000000 +0200 +@@ -72,6 +72,8 @@ + + #include + #include ++#include ++#include + #include "openbsd-compat/openssl-compat.h" + #include "openbsd-compat/sys-queue.h" + +@@ -221,6 +223,10 @@ main(int ac, char **av) + sanitise_stdfd(); + + __progname = ssh_get_progname(av[0]); ++ SSLeay_add_all_algorithms(); ++ if (FIPS_mode() && !FIPSCHECK_verify(NULL, NULL)) { ++ fatal("FIPS integrity verification test failed."); ++ } + init_rng(); + + /* +@@ -281,6 +287,9 @@ main(int ac, char **av) + "ACD:F:I:KL:MNO:PR:S:TVw:XYy")) != -1) { + switch (opt) { + case '1': ++ if (FIPS_mode()) { ++ fatal("Protocol 1 not allowed in the FIPS mode."); ++ } + options.protocol = SSH_PROTO_1; + break; + case '2': +@@ -552,7 +561,6 @@ main(int ac, char **av) + if (!host) + usage(); + +- SSLeay_add_all_algorithms(); + ERR_load_crypto_strings(); + + /* Initialize the command to execute on remote host. */ +@@ -638,6 +646,10 @@ main(int ac, char **av) + + seed_rng(); + ++ if (FIPS_mode()) { ++ logit("FIPS mode initialized"); ++ } ++ + if (options.user == NULL) + options.user = xstrdup(pw->pw_name); + +@@ -704,6 +716,12 @@ main(int ac, char **av) + + timeout_ms = options.connection_timeout * 1000; + ++ if (FIPS_mode()) { ++ options.protocol &= SSH_PROTO_2; ++ if (options.protocol == 0) ++ fatal("Protocol 2 disabled by configuration but required in the FIPS mode."); ++ } ++ + /* Open a connection to the remote host. */ + if (ssh_connect(host, &hostaddr, options.port, + options.address_family, options.connection_attempts, &timeout_ms, +diff -up openssh-5.3p1/sshconnect2.c.fips openssh-5.3p1/sshconnect2.c +--- openssh-5.3p1/sshconnect2.c.fips 2009-10-02 14:12:00.000000000 +0200 ++++ openssh-5.3p1/sshconnect2.c 2009-10-02 14:12:00.000000000 +0200 +@@ -44,6 +44,8 @@ + #include + #endif + ++#include ++ + #include "openbsd-compat/sys-queue.h" + + #include "xmalloc.h" +@@ -116,6 +118,10 @@ ssh_kex2(char *host, struct sockaddr *ho + if (options.ciphers != NULL) { + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; ++ } else if (FIPS_mode()) { ++ myproposal[PROPOSAL_ENC_ALGS_CTOS] = ++ myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_FIPS_ENCRYPT; ++ + } + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); +@@ -131,7 +137,11 @@ ssh_kex2(char *host, struct sockaddr *ho + if (options.macs != NULL) { + myproposal[PROPOSAL_MAC_ALGS_CTOS] = + myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; ++ } else if (FIPS_mode()) { ++ myproposal[PROPOSAL_MAC_ALGS_CTOS] = ++ myproposal[PROPOSAL_MAC_ALGS_STOC] = KEX_FIPS_MAC; + } ++ + if (options.hostkeyalgorithms != NULL) + myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = + options.hostkeyalgorithms; +@@ -508,8 +518,8 @@ input_userauth_pk_ok(int type, u_int32_t + key->type, pktype); + goto done; + } +- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); +- debug2("input_userauth_pk_ok: fp %s", fp); ++ fp = key_fingerprint(key, SSH_FP_SHA1, SSH_FP_HEX); ++ debug2("input_userauth_pk_ok: SHA1 fp %s", fp); + xfree(fp); + + /* +diff -up openssh-5.3p1/sshconnect.c.fips openssh-5.3p1/sshconnect.c +--- openssh-5.3p1/sshconnect.c.fips 2009-10-02 14:12:00.000000000 +0200 ++++ openssh-5.3p1/sshconnect.c 2009-10-02 14:12:00.000000000 +0200 +@@ -40,6 +40,8 @@ + #include + #include + ++#include ++ + #include "xmalloc.h" + #include "key.h" + #include "hostfile.h" +@@ -763,6 +765,7 @@ check_host_key(char *hostname, struct so + goto fail; + } else if (options.strict_host_key_checking == 2) { + char msg1[1024], msg2[1024]; ++ int fips_on = FIPS_mode(); + + if (show_other_keys(host, host_key)) + snprintf(msg1, sizeof(msg1), +@@ -771,8 +774,8 @@ check_host_key(char *hostname, struct so + else + snprintf(msg1, sizeof(msg1), "."); + /* The default */ +- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); +- ra = key_fingerprint(host_key, SSH_FP_MD5, ++ fp = key_fingerprint(host_key, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); ++ ra = key_fingerprint(host_key, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, + SSH_FP_RANDOMART); + msg2[0] = '\0'; + if (options.verify_host_key_dns) { +@@ -788,10 +791,10 @@ check_host_key(char *hostname, struct so + snprintf(msg, sizeof(msg), + "The authenticity of host '%.200s (%s)' can't be " + "established%s\n" +- "%s key fingerprint is %s.%s%s\n%s" ++ "%s key %sfingerprint is %s.%s%s\n%s" + "Are you sure you want to continue connecting " + "(yes/no)? ", +- host, ip, msg1, type, fp, ++ host, ip, msg1, type, fips_on ? "SHA1 " : "", fp, + options.visual_host_key ? "\n" : "", + options.visual_host_key ? ra : "", + msg2); +@@ -1079,17 +1082,18 @@ show_key_from_file(const char *file, con + Key *found; + char *fp, *ra; + int line, ret; ++ int fips_on = FIPS_mode(); + + found = key_new(keytype); + if ((ret = lookup_key_in_hostfile_by_type(file, host, + keytype, found, &line))) { +- fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); +- ra = key_fingerprint(found, SSH_FP_MD5, SSH_FP_RANDOMART); ++ fp = key_fingerprint(found, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); ++ ra = key_fingerprint(found, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_RANDOMART); + logit("WARNING: %s key found for host %s\n" + "in %s:%d\n" +- "%s key fingerprint %s.\n%s\n", ++ "%s key %sfingerprint %s.\n%s\n", + key_type(found), host, file, line, +- key_type(found), fp, ra); ++ key_type(found), fips_on ? "SHA1 ":"", fp, ra); + xfree(ra); + xfree(fp); + } +@@ -1135,8 +1139,9 @@ warn_changed_key(Key *host_key) + { + char *fp; + const char *type = key_type(host_key); ++ int fips_on = FIPS_mode(); + +- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); ++ fp = key_fingerprint(host_key, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); + + error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); + error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @"); +@@ -1144,8 +1149,8 @@ warn_changed_key(Key *host_key) + error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!"); + error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!"); + error("It is also possible that the %s host key has just been changed.", type); +- error("The fingerprint for the %s key sent by the remote host is\n%s.", +- type, fp); ++ error("The %sfingerprint for the %s key sent by the remote host is\n%s.", ++ fips_on ? "SHA1 ":"", type, fp); + error("Please contact your system administrator."); + + xfree(fp); +diff -up openssh-5.3p1/sshd.c.fips openssh-5.3p1/sshd.c +--- openssh-5.3p1/sshd.c.fips 2009-10-02 14:12:00.000000000 +0200 ++++ openssh-5.3p1/sshd.c 2009-10-02 14:12:00.000000000 +0200 +@@ -76,6 +76,8 @@ + #include + #include + #include ++#include ++#include + #include "openbsd-compat/openssl-compat.h" + + #ifdef HAVE_SECUREWARE +@@ -1261,6 +1263,12 @@ main(int ac, char **av) + (void)set_auth_parameters(ac, av); + #endif + __progname = ssh_get_progname(av[0]); ++ ++ SSLeay_add_all_algorithms(); ++ if (FIPS_mode() && !FIPSCHECK_verify(NULL, NULL)) { ++ fatal("FIPS integrity verification test failed."); ++ } ++ + init_rng(); + + /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */ +@@ -1413,8 +1421,6 @@ main(int ac, char **av) + else + closefrom(REEXEC_DEVCRYPTO_RESERVED_FD); + +- SSLeay_add_all_algorithms(); +- + /* + * Force logging to stderr until we have loaded the private host + * key (unless started from inetd) +@@ -1532,6 +1538,10 @@ main(int ac, char **av) + debug("private host key: #%d type %d %s", i, key->type, + key_type(key)); + } ++ if ((options.protocol & SSH_PROTO_1) && FIPS_mode()) { ++ logit("Disabling protocol version 1. Not allowed in the FIPS mode."); ++ options.protocol &= ~SSH_PROTO_1; ++ } + if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) { + logit("Disabling protocol version 1. Could not load host key"); + options.protocol &= ~SSH_PROTO_1; +@@ -1656,6 +1666,10 @@ main(int ac, char **av) + /* Initialize the random number generator. */ + arc4random_stir(); + ++ if (FIPS_mode()) { ++ logit("FIPS mode initialized"); ++ } ++ + /* Chdir to the root directory so that the current disk can be + unmounted if desired. */ + chdir("/"); +@@ -2183,6 +2197,9 @@ do_ssh2_kex(void) + if (options.ciphers != NULL) { + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; ++ } else if (FIPS_mode()) { ++ myproposal[PROPOSAL_ENC_ALGS_CTOS] = ++ myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_FIPS_ENCRYPT; + } + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); +@@ -2192,6 +2209,9 @@ do_ssh2_kex(void) + if (options.macs != NULL) { + myproposal[PROPOSAL_MAC_ALGS_CTOS] = + myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; ++ } else if (FIPS_mode()) { ++ myproposal[PROPOSAL_MAC_ALGS_CTOS] = ++ myproposal[PROPOSAL_MAC_ALGS_STOC] = KEX_FIPS_MAC; + } + if (options.compression == COMP_NONE) { + myproposal[PROPOSAL_COMP_ALGS_CTOS] = +diff -up openssh-5.3p1/ssh-keygen.c.fips openssh-5.3p1/ssh-keygen.c +--- openssh-5.3p1/ssh-keygen.c.fips 2009-10-02 14:12:00.000000000 +0200 ++++ openssh-5.3p1/ssh-keygen.c 2009-10-02 14:12:00.000000000 +0200 +@@ -21,6 +21,7 @@ + + #include + #include ++#include + #include "openbsd-compat/openssl-compat.h" + + #include +@@ -537,7 +538,7 @@ do_fingerprint(struct passwd *pw) + enum fp_type fptype; + struct stat st; + +- fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5; ++ fptype = print_bubblebabble ? SSH_FP_SHA1 : FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5; + rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX; + + if (!have_identity) +@@ -1506,14 +1507,15 @@ passphrase_again: + fclose(f); + + if (!quiet) { +- char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX); +- char *ra = key_fingerprint(public, SSH_FP_MD5, ++ int fips_on = FIPS_mode(); ++ char *fp = key_fingerprint(public, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); ++ char *ra = key_fingerprint(public, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, + SSH_FP_RANDOMART); + printf("Your public key has been saved in %s.\n", + identity_file); +- printf("The key fingerprint is:\n"); ++ printf("The key %sfingerprint is:\n", fips_on ? "SHA1 " : ""); + printf("%s %s\n", fp, comment); +- printf("The key's randomart image is:\n"); ++ printf("The key's %srandomart image is:\n", fips_on ? "SHA1 " :""); + printf("%s\n", ra); + xfree(ra); + xfree(fp); diff --git a/openssh-5.3p1-mls.patch b/openssh-5.3p1-mls.patch new file mode 100644 index 0000000..451b7e8 --- /dev/null +++ b/openssh-5.3p1-mls.patch @@ -0,0 +1,445 @@ +diff -up openssh-5.3p1/configure.ac.mls openssh-5.3p1/configure.ac +--- openssh-5.3p1/configure.ac.mls 2009-10-02 14:04:31.000000000 +0200 ++++ openssh-5.3p1/configure.ac 2009-10-02 14:04:31.000000000 +0200 +@@ -3404,6 +3404,7 @@ AC_ARG_WITH(selinux, + SSHDLIBS="$SSHDLIBS $LIBSELINUX" + LIBS="$LIBS $LIBSELINUX" + AC_CHECK_FUNCS(getseuserbyname get_default_context_with_level) ++ AC_CHECK_FUNCS(setkeycreatecon) + LIBS="$save_LIBS" + fi ] + ) +diff -up openssh-5.3p1/misc.c.mls openssh-5.3p1/misc.c +--- openssh-5.3p1/misc.c.mls 2009-02-21 22:47:02.000000000 +0100 ++++ openssh-5.3p1/misc.c 2009-10-02 14:04:31.000000000 +0200 +@@ -423,6 +423,7 @@ char * + colon(char *cp) + { + int flag = 0; ++ int start = 1; + + if (*cp == ':') /* Leading colon is part of file name. */ + return (0); +@@ -436,8 +437,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-5.3p1/openbsd-compat/port-linux.c.mls openssh-5.3p1/openbsd-compat/port-linux.c +--- openssh-5.3p1/openbsd-compat/port-linux.c.mls 2009-10-02 14:04:31.000000000 +0200 ++++ openssh-5.3p1/openbsd-compat/port-linux.c 2009-10-02 14:04:31.000000000 +0200 +@@ -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 */ + 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,38 +239,63 @@ 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 + if (sename != NULL) +@@ -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,45 @@ 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); ++ } ++#ifdef HAVE_SETKEYCREATECON ++ else if (setkeycreatecon(user_ctx) < 0) { ++ error("%s: Failed to set SELinux keyring creation context %s for %s", ++ __func__, user_ctx, pwname); ++ } ++#endif ++ } ++ if (user_ctx == NULL) { ++ user_ctx = default_ctx; ++ } ++ if (r < 0 || user_ctx != default_ctx) { ++ /* audit just the case when user changed a role or there was ++ a failure */ ++ send_audit_message(r >= 0, default_ctx, user_ctx); ++ } ++ if (r < 0) { + switch (security_getenforce()) { + case -1: + fatal("%s: security_getenforce() failed", __func__); + case 0: +- error("%s: Failed to set SELinux execution " +- "context for %s", __func__, pwname); ++ error("%s: SELinux failure. Continuing in permissive mode.", ++ __func__); + break; + default: +- fatal("%s: Failed to set SELinux execution context " +- "for %s (in enforcing mode)", __func__, pwname); ++ fatal("%s: SELinux failure. Aborting connection.", ++ __func__); + } + } +- if (user_ctx != NULL) ++ if (user_ctx != NULL && user_ctx != default_ctx) + freecon(user_ctx); ++ if (default_ctx != NULL) ++ freecon(default_ctx); + + debug3("%s: done", __func__); + } +@@ -159,7 +380,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-5.3p1/session.c.mls openssh-5.3p1/session.c +--- openssh-5.3p1/session.c.mls 2009-08-20 08:20:50.000000000 +0200 ++++ openssh-5.3p1/session.c 2009-10-02 14:06:12.000000000 +0200 +@@ -1550,10 +1550,6 @@ do_setusercontext(struct passwd *pw) + + 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-5.3p1/sshd.c.mls openssh-5.3p1/sshd.c +--- openssh-5.3p1/sshd.c.mls 2009-10-02 14:04:31.000000000 +0200 ++++ openssh-5.3p1/sshd.c 2009-10-02 14:04:31.000000000 +0200 +@@ -1896,6 +1896,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-5.3p1-nss-keys.patch b/openssh-5.3p1-nss-keys.patch new file mode 100644 index 0000000..af12b97 --- /dev/null +++ b/openssh-5.3p1-nss-keys.patch @@ -0,0 +1,1368 @@ +diff -up openssh-5.3p1/authfd.c.nss-keys openssh-5.3p1/authfd.c +--- openssh-5.3p1/authfd.c.nss-keys 2006-09-01 07:38:36.000000000 +0200 ++++ openssh-5.3p1/authfd.c 2009-10-02 14:09:01.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-5.3p1/authfd.h.nss-keys openssh-5.3p1/authfd.h +--- openssh-5.3p1/authfd.h.nss-keys 2006-08-05 04:39:39.000000000 +0200 ++++ openssh-5.3p1/authfd.h 2009-10-02 14:09:01.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-5.3p1/configure.ac.nss-keys openssh-5.3p1/configure.ac +--- openssh-5.3p1/configure.ac.nss-keys 2009-10-02 14:09:01.000000000 +0200 ++++ openssh-5.3p1/configure.ac 2009-10-02 14:09:01.000000000 +0200 +@@ -3514,6 +3514,20 @@ AC_ARG_WITH(kerberos5, + ] + ) + ++# 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) ++ + # Looking for programs, paths and files + + PRIVSEP_PATH=/var/empty +@@ -4240,6 +4254,7 @@ echo " TCP Wrappers support + echo " MD5 password support: $MD5_MSG" + echo " libedit support: $LIBEDIT_MSG" + echo " Solaris process contract support: $SPC_MSG" ++echo " NSS support: $LIBNSS_MSG" + echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG" + echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG" + echo " BSD Auth support: $BSD_AUTH_MSG" +diff -up openssh-5.3p1/key.c.nss-keys openssh-5.3p1/key.c +--- openssh-5.3p1/key.c.nss-keys 2008-11-03 09:24:17.000000000 +0100 ++++ openssh-5.3p1/key.c 2009-10-02 14:09:01.000000000 +0200 +@@ -96,6 +96,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) + { +@@ -151,6 +199,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 != NULL && 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-5.3p1/key.h.nss-keys openssh-5.3p1/key.h +--- openssh-5.3p1/key.h.nss-keys 2008-06-12 20:40:35.000000000 +0200 ++++ openssh-5.3p1/key.h 2009-10-02 14:09:01.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 { +@@ -48,16 +54,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-5.3p1/Makefile.in.nss-keys openssh-5.3p1/Makefile.in +--- openssh-5.3p1/Makefile.in.nss-keys 2009-08-28 02:47:38.000000000 +0200 ++++ openssh-5.3p1/Makefile.in 2009-10-02 14:09:53.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 jpake.o schnorr.o ++ entropy.o scard-opensc.o gss-genr.o umac.o jpake.o schnorr.o nsskeys.o + + SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ + sshconnect.o sshconnect1.o sshconnect2.o mux.o \ +diff -up /dev/null openssh-5.3p1/nsskeys.c +--- /dev/null 2009-09-11 09:35:58.778798825 +0200 ++++ openssh-5.3p1/nsskeys.c 2009-10-02 14:09:01.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 /dev/null openssh-5.3p1/nsskeys.h +--- /dev/null 2009-09-11 09:35:58.778798825 +0200 ++++ openssh-5.3p1/nsskeys.h 2009-10-02 14:09:01.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-5.3p1/readconf.c.nss-keys openssh-5.3p1/readconf.c +--- openssh-5.3p1/readconf.c.nss-keys 2009-07-05 23:12:27.000000000 +0200 ++++ openssh-5.3p1/readconf.c 2009-10-02 14:09:01.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, +@@ -210,6 +211,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 }, +@@ -613,6 +621,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: +@@ -1052,6 +1068,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; +@@ -1183,6 +1201,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 -up openssh-5.3p1/readconf.h.nss-keys openssh-5.3p1/readconf.h +--- openssh-5.3p1/readconf.h.nss-keys 2009-07-05 23:12:27.000000000 +0200 ++++ openssh-5.3p1/readconf.h 2009-10-02 14:09:01.000000000 +0200 +@@ -85,6 +85,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 openssh-5.3p1/ssh-add.c.nss-keys openssh-5.3p1/ssh-add.c +--- openssh-5.3p1/ssh-add.c.nss-keys 2008-02-28 09:13:52.000000000 +0100 ++++ openssh-5.3p1/ssh-add.c 2009-10-02 14:09:01.000000000 +0200 +@@ -44,6 +44,14 @@ + #include + #include "openbsd-compat/openssl-compat.h" + ++#ifdef HAVE_LIBNSS ++#include ++#include ++#include ++#include ++#include ++#endif ++ + #include + #include + #include +@@ -57,6 +65,7 @@ + #include "rsa.h" + #include "log.h" + #include "key.h" ++#include "nsskeys.h" + #include "buffer.h" + #include "authfd.h" + #include "authfile.h" +@@ -307,6 +316,128 @@ 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; ++ char **xkeyname = NULL; ++ ++ int count = 0; ++ int i; ++ ++ 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 ((count % 10) == 0) ++ xkeyname = xrealloc (xkeyname, count + 10, sizeof (char *)); ++ ++ xkeyname[count++] = keyname; ++ } ++ ++ PK11_Logout(slot); ++ ++ for (i = 0; i < count; i++) { ++ if (ssh_update_nss_key(ac, add, tokenname, xkeyname[i], ++ passcache?passcache:"", lifetime, confirm)) { ++ fprintf(stderr, "Key %s: %s:%s\n", ++ add?"added":"removed", tokenname, xkeyname[i]); ++ } else { ++ fprintf(stderr, "Could not %s key: %s:%s\n", ++ add?"add":"remove", tokenname, xkeyname[i]); ++ } ++ PORT_Free(xkeyname[i]); ++ } ++ ++ if (xkeyname != NULL) ++ free (xkeyname); ++ ++ if (passcache != NULL) { ++ memset(passcache, 0, strlen(passcache)); ++ xfree(passcache); ++ } ++ ++ SECKEY_DestroyPrivateKeyList(list); ++ ++ return count; ++} ++#endif ++ + static void + usage(void) + { +@@ -334,6 +465,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(); +@@ -351,7 +486,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': +@@ -373,6 +508,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; +@@ -387,6 +527,11 @@ main(int argc, char **argv) + goto done; + } + break; ++#ifdef HAVE_LIBNSS ++ case 'T': ++ token_id = optarg; ++ break; ++#endif + default: + usage(); + ret = 1; +@@ -400,6 +545,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-5.3p1/ssh-agent.c.nss-keys openssh-5.3p1/ssh-agent.c +--- openssh-5.3p1/ssh-agent.c.nss-keys 2009-06-21 09:50:15.000000000 +0200 ++++ openssh-5.3p1/ssh-agent.c 2009-10-02 14:09:01.000000000 +0200 +@@ -80,6 +80,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 +@@ -714,6 +718,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 +@@ -806,6 +918,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-5.3p1/ssh.c.nss-keys openssh-5.3p1/ssh.c +--- openssh-5.3p1/ssh.c.nss-keys 2009-07-05 23:16:56.000000000 +0200 ++++ openssh-5.3p1/ssh.c 2009-10-02 14:09:01.000000000 +0200 +@@ -105,6 +105,9 @@ + #ifdef SMARTCARD + #include "scard.h" + #endif ++#ifdef HAVE_LIBNSS ++#include "nsskeys.h" ++#endif + + extern char *__progname; + +@@ -1234,9 +1237,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) { +@@ -1259,6 +1264,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"); + pwname = xstrdup(pw->pw_name); +diff -up openssh-5.3p1/ssh-dss.c.nss-keys openssh-5.3p1/ssh-dss.c +--- openssh-5.3p1/ssh-dss.c.nss-keys 2006-11-07 13:14:42.000000000 +0100 ++++ openssh-5.3p1/ssh-dss.c 2009-10-02 14:09:01.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-5.3p1/ssh-keygen.c.nss-keys openssh-5.3p1/ssh-keygen.c +--- openssh-5.3p1/ssh-keygen.c.nss-keys 2009-06-22 08:11:07.000000000 +0200 ++++ openssh-5.3p1/ssh-keygen.c 2009-10-02 14:09:01.000000000 +0200 +@@ -53,6 +53,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 +@@ -501,6 +506,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) + { +@@ -1083,7 +1108,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; + BIGNUM *start = NULL; +@@ -1116,7 +1142,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); +@@ -1156,6 +1182,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; +@@ -1187,10 +1217,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': +@@ -1299,6 +1329,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-5.3p1/ssh-rsa.c.nss-keys openssh-5.3p1/ssh-rsa.c +--- openssh-5.3p1/ssh-rsa.c.nss-keys 2006-09-01 07:38:37.000000000 +0200 ++++ openssh-5.3p1/ssh-rsa.c 2009-10-02 14:09:01.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-5.3p1-selabel.patch b/openssh-5.3p1-selabel.patch new file mode 100644 index 0000000..6e5d6bd --- /dev/null +++ b/openssh-5.3p1-selabel.patch @@ -0,0 +1,53 @@ +diff -up openssh-5.3p1/contrib/ssh-copy-id.selabel openssh-5.3p1/contrib/ssh-copy-id +--- openssh-5.3p1/contrib/ssh-copy-id.selabel 2009-01-21 10:29:21.000000000 +0100 ++++ openssh-5.3p1/contrib/ssh-copy-id 2009-10-02 14:21:54.000000000 +0200 +@@ -38,7 +38,7 @@ if [ "$#" -lt 1 ] || [ "$1" = "-h" ] || + exit 1 + fi + +-{ eval "$GET_ID" ; } | ssh $1 "umask 077; test -d .ssh || mkdir .ssh ; cat >> .ssh/authorized_keys" || exit 1 ++{ eval "$GET_ID" ; } | ssh $1 "umask 077; test -d .ssh || mkdir .ssh ; cat >> .ssh/authorized_keys; test -x /sbin/restorecon && /sbin/restorecon .ssh .ssh/authorized_keys" || exit 1 + + cat < + #include + #include ++#include + #include "openbsd-compat/openssl-compat.h" + #include "openbsd-compat/sys-queue.h" + +@@ -792,10 +793,15 @@ main(int ac, char **av) + */ + r = snprintf(buf, sizeof buf, "%s%s%s", pw->pw_dir, + strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR); +- if (r > 0 && (size_t)r < sizeof(buf) && stat(buf, &st) < 0) ++ if (r > 0 && (size_t)r < sizeof(buf) && stat(buf, &st) < 0) { ++ char *scon; ++ ++ matchpathcon(buf, 0700, &scon); ++ setfscreatecon(scon); + if (mkdir(buf, 0700) < 0) + error("Could not create directory '%.200s'.", buf); +- ++ setfscreatecon(NULL); ++ } + /* load options.identity_files */ + load_public_identity_files(); + diff --git a/openssh-5.3p1-skip-initial.patch b/openssh-5.3p1-skip-initial.patch new file mode 100644 index 0000000..d52962e --- /dev/null +++ b/openssh-5.3p1-skip-initial.patch @@ -0,0 +1,24 @@ +diff -up openssh-5.3p1/auth1.c.skip-initial openssh-5.3p1/auth1.c +--- openssh-5.3p1/auth1.c.skip-initial 2009-03-08 01:40:28.000000000 +0100 ++++ openssh-5.3p1/auth1.c 2009-10-02 13:55:00.000000000 +0200 +@@ -244,7 +244,7 @@ do_authloop(Authctxt *authctxt) + authctxt->valid ? "" : "invalid user ", authctxt->user); + + /* If the user has no password, accept authentication immediately. */ +- if (options.password_authentication && ++ if (options.permit_empty_passwd && options.password_authentication && + #ifdef KRB5 + (!options.kerberos_authentication || options.kerberos_or_local_passwd) && + #endif +diff -up openssh-5.3p1/auth2-none.c.skip-initial openssh-5.3p1/auth2-none.c +--- openssh-5.3p1/auth2-none.c.skip-initial 2009-03-08 01:40:28.000000000 +0100 ++++ openssh-5.3p1/auth2-none.c 2009-10-02 13:56:21.000000000 +0200 +@@ -61,7 +61,7 @@ userauth_none(Authctxt *authctxt) + { + none_enabled = 0; + packet_check_eom(); +- if (options.password_authentication) ++ if (options.permit_empty_passwd && options.password_authentication) + return (PRIVSEP(auth_password(authctxt, ""))); + return (0); + } diff --git a/openssh.spec b/openssh.spec index 2963f24..c76facd 100644 --- a/openssh.spec +++ b/openssh.spec @@ -63,7 +63,7 @@ Summary: An open source implementation of SSH protocol versions 1 and 2 Name: openssh Version: 5.3p1 -Release: 1%{?dist}%{?rescue_rel} +Release: 2%{?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.asc @@ -460,7 +460,7 @@ fi %endif %changelog -* Fri Oct 2 2009 Jan F. Chadima - 5.3p1-1 +* Fri Oct 2 2009 Jan F. Chadima - 5.3p1-2 - Upgrade to new wersion 5.3p1 * Tue Sep 29 2009 Jan F. Chadima - 5.2p1-29 diff --git a/sources b/sources index 40209a7..7d28e2e 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -13563dbf61f36ca9a1e4254260131041 openssh-5.3p1.tar.gz +89f85c1da83c24ca0b10c05344f7c93c openssh-5.3p1-noacss.tar.bz2