rpms/openssh/devel openssh-4.3p2-cve-2007-3102.patch, NONE, 1.1 openssh-4.7p1-audit.patch, NONE, 1.1 openssh-4.7p1-log-in-chroot.patch, NONE, 1.1 openssh-4.7p1-mls.patch, NONE, 1.1 openssh-4.7p1-nss-keys.patch, NONE, 1.1 openssh-4.7p1-pam-session.patch, NONE, 1.1 openssh-4.7p1-redhat.patch, NONE, 1.1 openssh-4.7p1-selinux.patch, NONE, 1.1 openssh-4.7p1-sftp-drain-acks.patch, NONE, 1.1 openssh-4.7p1-vendor.patch, NONE, 1.1 .cvsignore, 1.19, 1.20 openssh.spec, 1.112, 1.113 sources, 1.19, 1.20 openssh-3.9p1-log-in-chroot.patch, 1.1, NONE openssh-4.3p2-pam-session.patch, 1.3, NONE openssh-4.5p1-audit.patch, 1.1, NONE openssh-4.5p1-mls.patch, 1.5, NONE openssh-4.5p1-nss-keys.patch, 1.3, NONE openssh-4.5p1-redhat.patch, 1.1, NONE openssh-4.5p1-selinux.patch, 1.2, NONE openssh-4.5p1-sftp-drain-acks.patch, 1.1, NONE openssh-4.5p1-vendor.patch, 1.1, NONE

Tomas Mraz (tmraz) fedora-extras-commits at redhat.com
Thu Sep 6 19:49:49 UTC 2007


Author: tmraz

Update of /cvs/pkgs/rpms/openssh/devel
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv8741

Modified Files:
	.cvsignore openssh.spec sources 
Added Files:
	openssh-4.3p2-cve-2007-3102.patch openssh-4.7p1-audit.patch 
	openssh-4.7p1-log-in-chroot.patch openssh-4.7p1-mls.patch 
	openssh-4.7p1-nss-keys.patch openssh-4.7p1-pam-session.patch 
	openssh-4.7p1-redhat.patch openssh-4.7p1-selinux.patch 
	openssh-4.7p1-sftp-drain-acks.patch openssh-4.7p1-vendor.patch 
Removed Files:
	openssh-3.9p1-log-in-chroot.patch 
	openssh-4.3p2-pam-session.patch openssh-4.5p1-audit.patch 
	openssh-4.5p1-mls.patch openssh-4.5p1-nss-keys.patch 
	openssh-4.5p1-redhat.patch openssh-4.5p1-selinux.patch 
	openssh-4.5p1-sftp-drain-acks.patch openssh-4.5p1-vendor.patch 
Log Message:
* Thu Sep  6 2007 Tomas Mraz <tmraz at redhat.com> - 4.7p1-1
- upgrade to latest upstream
- use libedit in sftp (#203009)
- fixed audit log injection problem (CVE-2007-3102)


openssh-4.3p2-cve-2007-3102.patch:

--- NEW FILE openssh-4.3p2-cve-2007-3102.patch ---
--- openssh-4.3p2/loginrec.c.inject-fix	2007-06-20 21:18:00.000000000 +0200
+++ openssh-4.3p2/loginrec.c	2007-07-13 15:25:35.000000000 +0200
@@ -1389,11 +1389,44 @@
 #endif /* USE_WTMPX */
 
 #ifdef HAVE_LINUX_AUDIT
+static void
+_audit_hexscape(const char *what, char *where, unsigned int size)
+{
+	const char *ptr = what;
+	const char *hex = "0123456789ABCDEF";
+
+	while (*ptr) {
+		if (*ptr == '"' || *ptr < 0x21 || *ptr > 0x7E) {
+			unsigned int i;
+			ptr = what;
+			for (i = 0; *ptr && i+2 < size; i += 2) {
+				where[i] = hex[((unsigned)*ptr & 0xF0)>>4]; /* Upper nibble */
+				where[i+1] = hex[(unsigned)*ptr & 0x0F];   /* Lower nibble */
+				ptr++;
+			}
+			where[i] = '\0';
+			return;
+		}
+		ptr++;
+	}
+	where[0] = '"';
+	if ((unsigned)(ptr - what) < size - 3)
+	{
+		size = ptr - what + 3;
+	}
+	strncpy(where + 1, what, size - 3);
+	where[size-2] = '"';
+	where[size-1] = '\0';
+}
+
+#define AUDIT_LOG_SIZE 128
+#define AUDIT_ACCT_SIZE (AUDIT_LOG_SIZE - 8)
+
 int
 linux_audit_record_event(int uid, const char *username,
 	const char *hostname, const char *ip, const char *ttyn, int success)
 {
-	char buf[64];
+	char buf[AUDIT_LOG_SIZE];
 	int audit_fd, rc;
 
 	audit_fd = audit_open();
@@ -1406,8 +1439,11 @@
 	}
 	if (username == NULL)
 		snprintf(buf, sizeof(buf), "uid=%d", uid);
-	else
-		snprintf(buf, sizeof(buf), "acct=%s", username);
+	else {
+		char encoded[AUDIT_ACCT_SIZE];
+		_audit_hexscape(username, encoded, sizeof(encoded));
+		snprintf(buf, sizeof(buf), "acct=%s", encoded);
+	}
 	rc = audit_log_user_message(audit_fd, AUDIT_USER_LOGIN,
 		buf, hostname, ip, ttyn, success);
 	close(audit_fd);

openssh-4.7p1-audit.patch:

--- NEW FILE openssh-4.7p1-audit.patch ---
diff -up openssh-4.7p1/auth.c.audit openssh-4.7p1/auth.c
--- openssh-4.7p1/auth.c.audit	2007-03-26 18:35:28.000000000 +0200
+++ openssh-4.7p1/auth.c	2007-09-06 17:07:44.000000000 +0200
@@ -286,6 +286,12 @@ auth_log(Authctxt *authctxt, int authent
 		    get_canonical_hostname(options.use_dns), "ssh", &loginmsg);
 # endif
 #endif
+#if HAVE_LINUX_AUDIT
+	if (authenticated == 0 && !authctxt->postponed) {
+		linux_audit_record_event(-1, authctxt->user, NULL,
+			get_remote_ipaddr(), "sshd", 0);
+	}
+#endif
 #ifdef SSH_AUDIT_EVENTS
 	if (authenticated == 0 && !authctxt->postponed)
 		audit_event(audit_classify_auth(method));
@@ -492,6 +498,10 @@ getpwnamallow(const char *user)
 		record_failed_login(user,
 		    get_canonical_hostname(options.use_dns), "ssh");
 #endif
+#ifdef HAVE_LINUX_AUDIT
+		linux_audit_record_event(-1, user, NULL, get_remote_ipaddr(),
+			"sshd", 0);
+#endif
 #ifdef SSH_AUDIT_EVENTS
 		audit_event(SSH_INVALID_USER);
 #endif /* SSH_AUDIT_EVENTS */
diff -up openssh-4.7p1/loginrec.c.audit openssh-4.7p1/loginrec.c
--- openssh-4.7p1/loginrec.c.audit	2007-04-29 04:10:58.000000000 +0200
+++ openssh-4.7p1/loginrec.c	2007-09-06 17:07:44.000000000 +0200
@@ -176,6 +176,10 @@
 #include "auth.h"
 #include "buffer.h"
 
+#ifdef HAVE_LINUX_AUDIT
+# include <libaudit.h>
+#endif
+
 #ifdef HAVE_UTIL_H
 # include <util.h>
 #endif
@@ -202,6 +206,9 @@ int utmp_write_entry(struct logininfo *l
 int utmpx_write_entry(struct logininfo *li);
 int wtmp_write_entry(struct logininfo *li);
 int wtmpx_write_entry(struct logininfo *li);
+#ifdef HAVE_LINUX_AUDIT
+int linux_audit_write_entry(struct logininfo *li);
+#endif
 int lastlog_write_entry(struct logininfo *li);
 int syslogin_write_entry(struct logininfo *li);
 
@@ -440,6 +447,10 @@ login_write(struct logininfo *li)
 
 	/* set the timestamp */
 	login_set_current_time(li);
+#ifdef HAVE_LINUX_AUDIT
+	if (linux_audit_write_entry(li) == 0)
+		fatal("linux_audit_write_entry failed: %s", strerror(errno));
+#endif
 #ifdef USE_LOGIN
 	syslogin_write_entry(li);
 #endif
@@ -1394,6 +1405,51 @@ wtmpx_get_entry(struct logininfo *li)
 }
 #endif /* USE_WTMPX */
 
+#ifdef HAVE_LINUX_AUDIT
+int
+linux_audit_record_event(int uid, const char *username,
+	const char *hostname, const char *ip, const char *ttyn, int success)
+{
+	char buf[64];
+	int audit_fd, rc;
+
+	audit_fd = audit_open();
+	if (audit_fd < 0) {
+	 	if (errno == EINVAL || errno == EPROTONOSUPPORT ||
+					errno == EAFNOSUPPORT)
+			return 1; /* No audit support in kernel */
+		else
+			return 0; /* Must prevent login */
+	}
+	if (username == NULL)
+		snprintf(buf, sizeof(buf), "uid=%d", uid);
+	else
+		snprintf(buf, sizeof(buf), "acct=%s", username);
+	rc = audit_log_user_message(audit_fd, AUDIT_USER_LOGIN,
+		buf, hostname, ip, ttyn, success);
+	close(audit_fd);
+	if (rc >= 0)
+		return 1;
+	else
+		return 0;
+}
+
+int
+linux_audit_write_entry(struct logininfo *li)
+{
+	switch(li->type) {
+	case LTYPE_LOGIN:
+		return (linux_audit_record_event(li->uid, NULL, li->hostname,
+			NULL, li->line, 1));
+	case LTYPE_LOGOUT:
+		return (1);	/* We only care about logins */
+	default:
+		logit("%s: invalid type field", __func__);
+		return (0);
+	}
+}
+#endif /* HAVE_LINUX_AUDIT */
+
 /**
  ** Low-level libutil login() functions
  **/
diff -up openssh-4.7p1/config.h.in.audit openssh-4.7p1/config.h.in
--- openssh-4.7p1/config.h.in.audit	2007-09-04 08:50:04.000000000 +0200
+++ openssh-4.7p1/config.h.in	2007-09-06 17:07:44.000000000 +0200
@@ -1334,6 +1334,9 @@
 /* Define if you want SELinux support. */
 #undef WITH_SELINUX
 
+/* Define if you want Linux audit support. */
+#undef HAVE_LINUX_AUDIT
+
 /* Define to 1 if your processor stores words with the most significant byte
    first (like Motorola and SPARC, unlike Intel and VAX). */
 #undef WORDS_BIGENDIAN
diff -up openssh-4.7p1/loginrec.h.audit openssh-4.7p1/loginrec.h
--- openssh-4.7p1/loginrec.h.audit	2006-08-05 04:39:40.000000000 +0200
+++ openssh-4.7p1/loginrec.h	2007-09-06 17:07:44.000000000 +0200
@@ -127,5 +127,9 @@ char *line_stripname(char *dst, const ch
 char *line_abbrevname(char *dst, const char *src, int dstsize);
 
 void record_failed_login(const char *, const char *, const char *);
+#ifdef HAVE_LINUX_AUDIT
+int linux_audit_record_event(int uid, const char *username,
+	const char *hostname, const char *ip, const char *ttyn, int success);
+#endif /* HAVE_LINUX_AUDIT */
 
 #endif /* _HAVE_LOGINREC_H_ */
diff -up openssh-4.7p1/configure.ac.audit openssh-4.7p1/configure.ac
--- openssh-4.7p1/configure.ac.audit	2007-09-06 17:07:44.000000000 +0200
+++ openssh-4.7p1/configure.ac	2007-09-06 17:15:23.000000000 +0200
@@ -3216,6 +3216,18 @@ AC_ARG_WITH(selinux,
 	fi ]
 )
 
+# Check whether user wants Linux audit support
+LINUX_AUDIT_MSG="no"
+AC_ARG_WITH(linux-audit,
+	[  --with-linux-audit   Enable Linux audit support],
+	[ if test "x$withval" != "xno" ; then
+		AC_DEFINE(HAVE_LINUX_AUDIT,1,[Define if you want Linux audit support.])
+		LINUX_AUDIT_MSG="yes"
+		AC_CHECK_HEADERS(libaudit.h)
+		SSHDLIBS="$SSHDLIBS -laudit"
+	fi ]
+)
+
 # Check whether user wants Kerberos 5 support
 KRB5_MSG="no"
 AC_ARG_WITH(kerberos5,
@@ -4037,6 +4049,7 @@ echo "                       PAM support
 echo "                   OSF SIA support: $SIA_MSG"
 echo "                 KerberosV support: $KRB5_MSG"
 echo "                   SELinux support: $SELINUX_MSG"
+echo "               Linux audit support: $LINUX_AUDIT_MSG"
 echo "                 Smartcard support: $SCARD_MSG"
 echo "                     S/KEY support: $SKEY_MSG"
 echo "              TCP Wrappers support: $TCPW_MSG"

openssh-4.7p1-log-in-chroot.patch:

--- NEW FILE openssh-4.7p1-log-in-chroot.patch ---
diff -up openssh-4.7p1/sshd.c.log-chroot openssh-4.7p1/sshd.c
--- openssh-4.7p1/sshd.c.log-chroot	2007-09-06 17:24:13.000000000 +0200
+++ openssh-4.7p1/sshd.c	2007-09-06 17:24:13.000000000 +0200
@@ -596,6 +596,10 @@ privsep_preauth_child(void)
 	/* Demote the private keys to public keys. */
 	demote_sensitive_data();
 
+	/* Open the syslog permanently so the chrooted process still
+	   can write to syslog. */
+	open_log();
+	
 	/* Change our root directory */
 	if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1)
 		fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR,
diff -up openssh-4.7p1/log.c.log-chroot openssh-4.7p1/log.c
--- openssh-4.7p1/log.c.log-chroot	2007-05-20 07:08:16.000000000 +0200
+++ openssh-4.7p1/log.c	2007-09-06 17:29:34.000000000 +0200
@@ -56,6 +56,7 @@ static LogLevel log_level = SYSLOG_LEVEL
 static int log_on_stderr = 1;
 static int log_facility = LOG_AUTH;
 static char *argv0;
+static int log_fd_keep;
 
 extern char *__progname;
 
@@ -370,10 +371,21 @@ do_log(LogLevel level, const char *fmt, 
 		syslog_r(pri, &sdata, "%.500s", fmtbuf);
 		closelog_r(&sdata);
 #else
+	    if (!log_fd_keep) {
 		openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility);
+	    }
 		syslog(pri, "%.500s", fmtbuf);
+	    if (!log_fd_keep) {
 		closelog();
+	    }
 #endif
 	}
 	errno = saved_errno;
 }
+
+void
+open_log(void)
+{
+	openlog(argv0 ? argv0 : __progname, LOG_PID|LOG_NDELAY, log_facility);
+	log_fd_keep = 1;
+}
diff -up openssh-4.7p1/log.h.log-chroot openssh-4.7p1/log.h
--- openssh-4.7p1/log.h.log-chroot	2006-08-18 16:32:21.000000000 +0200
+++ openssh-4.7p1/log.h	2007-09-06 17:24:13.000000000 +0200
@@ -62,4 +62,6 @@ void     debug3(const char *, ...) __att
 
 void	 do_log(LogLevel, const char *, va_list);
 void	 cleanup_exit(int) __dead;
+
+void     open_log(void);
 #endif

openssh-4.7p1-mls.patch:

--- NEW FILE openssh-4.7p1-mls.patch ---
diff -up openssh-4.7p1/misc.c.mls openssh-4.7p1/misc.c
--- openssh-4.7p1/misc.c.mls	2007-01-05 06:24:48.000000000 +0100
+++ openssh-4.7p1/misc.c	2007-09-06 17:39:28.000000000 +0200
@@ -418,6 +418,7 @@ char *
 colon(char *cp)
 {
 	int flag = 0;
+	int start = 1;
 
 	if (*cp == ':')		/* Leading colon is part of file name. */
 		return (0);
@@ -431,8 +432,13 @@ colon(char *cp)
 			return (cp+1);
 		if (*cp == ':' && !flag)
 			return (cp);
-		if (*cp == '/')
-			return (0);
+		if (start) {
+		/* Slash on beginning or after dots only denotes file name. */
+			if (*cp == '/')
+				return (0);
+			if (*cp != '.')
+				start = 0;
+		}
 	}
 	return (0);
 }
diff -up openssh-4.7p1/session.c.mls openssh-4.7p1/session.c
--- openssh-4.7p1/session.c.mls	2007-09-06 17:39:28.000000000 +0200
+++ openssh-4.7p1/session.c	2007-09-06 17:39:28.000000000 +0200
@@ -1347,10 +1347,6 @@ do_setusercontext(struct passwd *pw)
 #endif
 	if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
 		fatal("Failed to set uids to %u.", (u_int) pw->pw_uid);
-
-#ifdef WITH_SELINUX
-	ssh_selinux_setup_exec_context(pw->pw_name);
-#endif
 }
 
 static void
diff -up openssh-4.7p1/openbsd-compat/port-linux.c.mls openssh-4.7p1/openbsd-compat/port-linux.c
--- openssh-4.7p1/openbsd-compat/port-linux.c.mls	2007-09-06 17:39:28.000000000 +0200
+++ openssh-4.7p1/openbsd-compat/port-linux.c	2007-08-07 17:38:18.000000000 +0200
@@ -1,4 +1,4 @@
-/* $Id: port-linux.c,v 1.4 2007/06/27 22:48:03 djm Exp $ */
+/* $Id: port-linux.c,v 1.3 2006/09/01 05:38:41 djm Exp $ */
 
 /*
  * Copyright (c) 2005 Daniel Walsh <dwalsh at redhat.com>
@@ -33,12 +33,23 @@
 #include "key.h"
 #include "hostfile.h"
 #include "auth.h"
+#include "xmalloc.h"
 
 #include <selinux/selinux.h>
 #include <selinux/flask.h>
+#include <selinux/context.h>
 #include <selinux/get_context_list.h>
+#include <selinux/get_default_type.h>
+#include <selinux/av_permissions.h>
+
+#ifdef HAVE_LINUX_AUDIT
+#include <libaudit.h>
+#include <unistd.h>
+#endif
 
 extern Authctxt *the_authctxt;
+extern int inetd_flag;
+extern int rexeced_flag;
 
 /* Wrapper around is_selinux_enabled() to log its return value once only */
 static int
@@ -54,17 +65,173 @@ ssh_selinux_enabled(void)
 	return (enabled);
 }
 
+/* Send audit message */
+static int
+send_audit_message(int success, security_context_t default_context,
+		       security_context_t selected_context)
+{
+	int rc=0;
+#ifdef HAVE_LINUX_AUDIT
+	char *msg = NULL;
+	int audit_fd = audit_open();
+	security_context_t default_raw=NULL;
+	security_context_t selected_raw=NULL;
+	rc = -1;
+	if (audit_fd < 0) {
+		if (errno == EINVAL || errno == EPROTONOSUPPORT ||
+                                        errno == EAFNOSUPPORT)
+                        return 0; /* No audit support in kernel */
+		error("Error connecting to audit system.");
+		return rc;
+	}
+	if (selinux_trans_to_raw_context(default_context, &default_raw) < 0) {
+		error("Error translating default context.");
+		default_raw = NULL;
+	}
+	if (selinux_trans_to_raw_context(selected_context, &selected_raw) < 0) {
+		error("Error translating selected context.");
+		selected_raw = NULL;
+	}
+	if (asprintf(&msg, "sshd: default-context=%s selected-context=%s",
+		     default_raw ? default_raw : (default_context ? default_context: "?"),
+		     selected_context ? selected_raw : (selected_context ? selected_context :"?")) < 0) {
+		error("Error allocating memory.");
+		goto out;
+	}
+	if (audit_log_user_message(audit_fd, AUDIT_USER_ROLE_CHANGE,
+				   msg, NULL, NULL, NULL, success) <= 0) {
+		error("Error sending audit message.");
+		goto out;
+	}
+	rc = 0;
+      out:
+	free(msg);
+	freecon(default_raw);
+	freecon(selected_raw);
+	close(audit_fd);
+#endif
+	return rc;
+}
+
+static int
+mls_range_allowed(security_context_t src, security_context_t dst)
+{
+	struct av_decision avd;
+	int retval;
+	unsigned int bit = CONTEXT__CONTAINS;
+
+	debug("%s: src:%s dst:%s", __func__, src, dst);
+	retval = security_compute_av(src, dst, SECCLASS_CONTEXT, bit, &avd);
+	if (retval || ((bit & avd.allowed) != bit))
+		return 0;
+
+	return 1;
+}
+
+static int
+get_user_context(const char *sename, const char *role, const char *lvl,
+	security_context_t *sc) {
+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
+	if (lvl == NULL || lvl[0] == '\0' || get_default_context_with_level(sename, lvl, NULL, sc) != 0) {
+	        /* User may have requested a level completely outside of his 
+	           allowed range. We get a context just for auditing as the
+	           range check below will certainly fail for default context. */
+#endif
+		if (get_default_context(sename, NULL, sc) != 0) {
+			*sc = NULL;
+			return -1;
+		}
+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
+	}
+#endif
+	if (role != NULL && role[0]) {
+		context_t con;
+		char *type=NULL;
+		if (get_default_type(role, &type) != 0) {
+			error("get_default_type: failed to get default type for '%s'",
+				role);
+			goto out;
+		}
+		con = context_new(*sc);
+		if (!con) {
+			goto out;
+		}
+		context_role_set(con, role);
+		context_type_set(con, type);
+		freecon(*sc);
+		*sc = strdup(context_str(con));
+		context_free(con);
+		if (!*sc) 
+			return -1;
+	}
+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
+	if (lvl != NULL && lvl[0]) {
+		/* verify that the requested range is obtained */
+		context_t con;
+		security_context_t obtained_raw;
+		security_context_t requested_raw;
+		con = context_new(*sc);
+		if (!con) {
+			goto out;
+		}
+		context_range_set(con, lvl);
+		if (selinux_trans_to_raw_context(*sc, &obtained_raw) < 0) {
+			context_free(con);
+			goto out;
+		}
+		if (selinux_trans_to_raw_context(context_str(con), &requested_raw) < 0) {
+			freecon(obtained_raw);
+			context_free(con);
+			goto out;
+		}
+
+		debug("get_user_context: obtained context '%s' requested context '%s'",
+			obtained_raw, requested_raw);
+		if (strcmp(obtained_raw, requested_raw)) {
+			/* set the context to the real requested one but fail */
+			freecon(requested_raw);
+			freecon(obtained_raw);
+			freecon(*sc);
+			*sc = strdup(context_str(con));
+			context_free(con);
+			return -1;
+		}
+		freecon(requested_raw);
+		freecon(obtained_raw);
+		context_free(con);
+	}
+#endif
+	return 0;
+      out:
+        freecon(*sc);
+        *sc = NULL;
+        return -1;
+}
+
 /* Return the default security context for the given username */
-static security_context_t
-ssh_selinux_getctxbyname(char *pwname)
+static int
+ssh_selinux_getctxbyname(char *pwname,
+	security_context_t *default_sc, security_context_t *user_sc)
 {
-	security_context_t sc = NULL;
 	char *sename, *lvl;
+	const char *reqlvl = NULL;
 	char *role = NULL;
-	int r = 0;
+	int r = -1;
+	context_t con = NULL;
+
+	*default_sc = NULL;
+	*user_sc = NULL;
+	if (the_authctxt) {
+		if (the_authctxt->role != NULL) {
+			char *slash;
+			role = xstrdup(the_authctxt->role);
+			if ((slash = strchr(role, '/')) != NULL) {
+				*slash = '\0';
+				reqlvl = slash + 1;
+			}
+		}
+	}
 
-	if (the_authctxt) 
-		role=the_authctxt->role;
 #ifdef HAVE_GETSEUSERBYNAME
 	if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) {
 		sename = NULL;
@@ -72,37 +239,62 @@ ssh_selinux_getctxbyname(char *pwname)
 	}
 #else
 	sename = pwname;
-	lvl = NULL;
+	lvl = "";
 #endif
 
 	if (r == 0) {
 #ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
-		if (role != NULL && role[0])
-			r = get_default_context_with_rolelevel(sename, role, lvl, NULL, &sc);
-		else
-			r = get_default_context_with_level(sename, lvl, NULL, &sc);
+		r = get_default_context_with_level(sename, lvl, NULL, default_sc);
 #else
-		if (role != NULL && role[0])
-			r = get_default_context_with_role(sename, role, NULL, &sc);
-		else
-			r = get_default_context(sename, NULL, &sc);
+		r = get_default_context(sename, NULL, default_sc);
 #endif
 	}
 
-	if (r != 0) {
-		switch (security_getenforce()) {
-		case -1:
-			fatal("%s: ssh_selinux_getctxbyname: "
-			    "security_getenforce() failed", __func__);
-		case 0:
-			error("%s: Failed to get default SELinux security "
-			    "context for %s", __func__, pwname);
-			break;
-		default:
-			fatal("%s: Failed to get default SELinux security "
-			    "context for %s (in enforcing mode)",
-			    __func__, pwname);
+	if (r == 0) {
+		/* If launched from xinetd, we must use current level */
+		if (inetd_flag && !rexeced_flag) {
+			security_context_t sshdsc=NULL;
+
+			if (getcon_raw(&sshdsc) < 0)
+				fatal("failed to allocate security context");
+
+			if ((con=context_new(sshdsc)) == NULL)
+				fatal("failed to allocate selinux context");
+			reqlvl = context_range_get(con);
+			freecon(sshdsc);
+			if (reqlvl !=NULL && lvl != NULL && strcmp(reqlvl, lvl) == 0)
+			    /* we actually don't change level */
+			    reqlvl = "";
+
+			debug("%s: current connection level '%s'", __func__, reqlvl);
 		}
+		
+		if ((reqlvl != NULL && reqlvl[0]) || (role != NULL && role[0])) {
+			r = get_user_context(sename, role, reqlvl, user_sc);
+		
+			if (r == 0 && reqlvl != NULL && reqlvl[0]) {
+				security_context_t default_level_sc = *default_sc;
+				if (role != NULL && role[0]) {
+					if (get_user_context(sename, role, lvl, &default_level_sc) < 0)
+						default_level_sc = *default_sc;
+				}
+				/* verify that the requested range is contained in the user range */
+				if (mls_range_allowed(default_level_sc, *user_sc)) {
+					logit("permit MLS level %s (user range %s)", reqlvl, lvl);
+				} else {
+					r = -1;
+					error("deny MLS level %s (user range %s)", reqlvl, lvl);
+				}
+				if (default_level_sc != *default_sc)
+					freecon(default_level_sc);
+			}
+		} else {
+			*user_sc = *default_sc;
+		}
+	}
+	if (r != 0) {
+		error("%s: Failed to get default SELinux security "
+		    "context for %s", __func__, pwname);
 	}
 
 #ifdef HAVE_GETSEUSERBYNAME
@@ -111,14 +303,20 @@ ssh_selinux_getctxbyname(char *pwname)
 	if (lvl != NULL)
 		xfree(lvl);
 #endif
+	if (role != NULL)
+		xfree(role);
+	if (con)
+		context_free(con);
 
-	return (sc);
+	return (r);
 }
 
 /* Set the execution context to the default for the specified user */
 void
 ssh_selinux_setup_exec_context(char *pwname)
 {
+	int r = 0;
+	security_context_t default_ctx = NULL;
 	security_context_t user_ctx = NULL;
 
 	if (!ssh_selinux_enabled())
@@ -126,22 +324,39 @@ ssh_selinux_setup_exec_context(char *pwn
 
 	debug3("%s: setting execution context", __func__);
 
-	user_ctx = ssh_selinux_getctxbyname(pwname);
-	if (setexeccon(user_ctx) != 0) {
+	r = ssh_selinux_getctxbyname(pwname, &default_ctx, &user_ctx);
+	if (r >= 0) {
+		r = setexeccon(user_ctx);
+		if (r < 0) {
+			error("%s: Failed to set SELinux execution context %s for %s",
+			    __func__, user_ctx, pwname);
+		}
+	}
+	if (user_ctx == NULL) {
+		user_ctx = default_ctx;
+	}
+	if (r < 0 || user_ctx != default_ctx) {
+		/* audit just the case when user changed a role or there was
+		   a failure */
+		send_audit_message(r >= 0, default_ctx, user_ctx);
+	}
+	if (r < 0) {
 		switch (security_getenforce()) {
 		case -1:
 			fatal("%s: security_getenforce() failed", __func__);
 		case 0:
-			error("%s: Failed to set SELinux execution "
-			    "context for %s", __func__, pwname);
+			error("%s: SELinux failure. Continuing in permissive mode.",
+			    __func__);
 			break;
 		default:
-			fatal("%s: Failed to set SELinux execution context "
-			    "for %s (in enforcing mode)", __func__, pwname);
+			fatal("%s: SELinux failure. Aborting connection.",
+			    __func__);
 		}
 	}
-	if (user_ctx != NULL)
+	if (user_ctx != NULL && user_ctx != default_ctx)
 		freecon(user_ctx);
+	if (default_ctx != NULL)
+		freecon(default_ctx);
 
 	debug3("%s: done", __func__);
 }
@@ -159,7 +374,10 @@ ssh_selinux_setup_pty(char *pwname, cons
 
 	debug3("%s: setting TTY context on %s", __func__, tty);
 
-	user_ctx = ssh_selinux_getctxbyname(pwname);
+	if (getexeccon(&user_ctx) < 0) {
+		error("%s: getexeccon: %s", __func__, strerror(errno));
+		goto out;
+	}
 
 	/* XXX: should these calls fatal() upon failure in enforcing mode? */
 
diff -up openssh-4.7p1/sshd.c.mls openssh-4.7p1/sshd.c
--- openssh-4.7p1/sshd.c.mls	2007-09-06 17:39:28.000000000 +0200
+++ openssh-4.7p1/sshd.c	2007-09-06 17:39:28.000000000 +0200
@@ -1838,6 +1838,9 @@ main(int ac, char **av)
 		restore_uid();
 	}
 #endif
+#ifdef WITH_SELINUX
+	ssh_selinux_setup_exec_context(authctxt->pw->pw_name);
+#endif
 #ifdef USE_PAM
 	if (options.use_pam) {
 		do_pam_setcred(1);

openssh-4.7p1-nss-keys.patch:

--- NEW FILE openssh-4.7p1-nss-keys.patch ---
diff -up openssh-4.7p1/key.c.nss-keys openssh-4.7p1/key.c
--- openssh-4.7p1/key.c.nss-keys	2007-08-08 06:28:26.000000000 +0200
+++ openssh-4.7p1/key.c	2007-09-06 17:43:59.000000000 +0200
@@ -93,6 +93,54 @@ key_new(int type)
 	return k;
 }
 
+#ifdef HAVE_LIBNSS
+Key *
+key_new_nss(int type)
+{
+	Key *k = key_new(type);
+
+	k->nss = xcalloc(1, sizeof(*k->nss));
+	k->flags = KEY_FLAG_EXT | KEY_FLAG_NSS;
+
+	return k;
+}
+
+Key *
+key_new_nss_copy(int type, const Key *c)
+{
+	Key *k = key_new_nss(type);
+
+	switch (k->type) {
+		case KEY_RSA:
+			if ((BN_copy(k->rsa->n, c->rsa->n) == NULL) ||
+				(BN_copy(k->rsa->e, c->rsa->e) == NULL))
+				fatal("key_new_nss_copy: BN_copy failed");
+			break;
+		case KEY_DSA:
+			if ((BN_copy(k->dsa->p, c->rsa->p) == NULL) ||
+				(BN_copy(k->dsa->q, c->dsa->q) == NULL) ||
+				(BN_copy(k->dsa->g, c->dsa->g) == NULL) ||
+				(BN_copy(k->dsa->pub_key, c->dsa->pub_key) == NULL))
+				fatal("key_new_nss_copy: BN_copy failed");
+			break;
+	}
+		
+	k->nss->privk = SECKEY_CopyPrivateKey(c->nss->privk);
+	if (k->nss->privk == NULL)
+		fatal("key_new_nss_copy: SECKEY_CopyPrivateKey failed");
+
+	k->nss->pubk = SECKEY_CopyPublicKey(c->nss->pubk);
+	if (k->nss->pubk == NULL)
+		fatal("key_new_nss_copy: SECKEY_CopyPublicKey failed");
+	
+	if (c->nss->privk->wincx)
+		k->nss->privk->wincx = xstrdup(c->nss->privk->wincx);
+
+	return k;
+}
+#endif
+
+
 Key *
 key_new_private(int type)
 {
@@ -148,6 +196,19 @@ key_free(Key *k)
 		fatal("key_free: bad key type %d", k->type);
 		break;
 	}
+#ifdef HAVE_LIBNSS
+	if (k->flags & KEY_FLAG_NSS) {
+		if (k->nss->privk->wincx != NULL) {
+			memset(k->nss->privk->wincx, 0,
+				strlen(k->nss->privk->wincx));
+			xfree(k->nss->privk->wincx);
+			k->nss->privk->wincx = NULL;
+		}
+		SECKEY_DestroyPrivateKey(k->nss->privk);
+		SECKEY_DestroyPublicKey(k->nss->pubk);
+		xfree(k->nss);
+	}
+#endif
 	xfree(k);
 }
 
diff -up openssh-4.7p1/ssh-dss.c.nss-keys openssh-4.7p1/ssh-dss.c
--- openssh-4.7p1/ssh-dss.c.nss-keys	2006-11-07 13:14:42.000000000 +0100
+++ openssh-4.7p1/ssh-dss.c	2007-09-06 17:43:59.000000000 +0200
@@ -39,6 +39,10 @@
 #include "log.h"
 #include "key.h"
 
+#ifdef HAVE_LIBNSS
+#include <cryptohi.h>
+#endif
+
 #define INTBLOB_LEN	20
 #define SIGBLOB_LEN	(2*INTBLOB_LEN)
 
@@ -57,6 +61,34 @@ ssh_dss_sign(const Key *key, u_char **si
 		error("ssh_dss_sign: no DSA key");
 		return -1;
 	}
+#ifdef HAVE_LIBNSS
+	if (key->flags & KEY_FLAG_NSS) {
+		SECItem sigitem;
+		SECItem *rawsig;
+
+		memset(&sigitem, 0, sizeof(sigitem));
+		if (SEC_SignData(&sigitem, (u_char *)data, datalen, key->nss->privk,
+			SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) != SECSuccess) {
+			error("ssh_dss_sign: sign failed");
+			return -1;
+		}
+		
+		if ((rawsig=DSAU_DecodeDerSig(&sigitem)) == NULL) {
+			error("ssh_dss_sign: der decode failed");
+			SECITEM_ZfreeItem(&sigitem, PR_FALSE);
+			return -1;
+		}
+		SECITEM_ZfreeItem(&sigitem, PR_FALSE);
+		if (rawsig->len != SIGBLOB_LEN) {
+			error("ssh_dss_sign: unsupported signature length %d",
+				rawsig->len);
+			SECITEM_ZfreeItem(rawsig, PR_TRUE);
+			return -1;
+		}
+		memcpy(sigblob, rawsig->data, SIGBLOB_LEN);
+		SECITEM_ZfreeItem(rawsig, PR_TRUE);
+	} else {
+#endif
 	EVP_DigestInit(&md, evp_md);
 	EVP_DigestUpdate(&md, data, datalen);
 	EVP_DigestFinal(&md, digest, &dlen);
@@ -80,7 +112,9 @@ ssh_dss_sign(const Key *key, u_char **si
 	BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen);
 	BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen);
 	DSA_SIG_free(sig);
-
+#ifdef HAVE_LIBNSS
+	}
+#endif
 	if (datafellows & SSH_BUG_SIGBLOB) {
 		if (lenp != NULL)
 			*lenp = SIGBLOB_LEN;
diff -up openssh-4.7p1/ssh-agent.c.nss-keys openssh-4.7p1/ssh-agent.c
--- openssh-4.7p1/ssh-agent.c.nss-keys	2007-03-21 10:45:07.000000000 +0100
+++ openssh-4.7p1/ssh-agent.c	2007-09-06 17:43:59.000000000 +0200
@@ -79,6 +79,10 @@
 #include "scard.h"
 #endif
 
+#ifdef HAVE_LIBNSS
+#include "nsskeys.h"
+#endif
+
 #if defined(HAVE_SYS_PRCTL_H)
 #include <sys/prctl.h>	/* For prctl() and PR_SET_DUMPABLE */
 #endif
@@ -701,6 +705,114 @@ send:
 }
 #endif /* SMARTCARD */
 
+#ifdef HAVE_LIBNSS
+static void
+process_add_nss_key (SocketEntry *e)
+{
+	char *tokenname = NULL, *keyname = NULL, *password = NULL;
+	int i, version, success = 0, death = 0, confirm = 0;
+	Key **keys, *k;
+	Identity *id;
+	Idtab *tab;
+
+	tokenname = buffer_get_string(&e->request, NULL);
+	keyname = buffer_get_string(&e->request, NULL);
+	password = buffer_get_string(&e->request, NULL);
+
+	while (buffer_len(&e->request)) {
+		switch (buffer_get_char(&e->request)) {
+		case SSH_AGENT_CONSTRAIN_LIFETIME:
+			death = time(NULL) + buffer_get_int(&e->request);
+			break;
+		case SSH_AGENT_CONSTRAIN_CONFIRM:
+			confirm = 1;
+			break;
+		default:
+			break;
+		}
+	}
+	if (lifetime && !death)
+		death = time(NULL) + lifetime;
+
+	keys = nss_get_keys(tokenname, keyname, password);
+	/* password is owned by keys[0] now */
+	xfree(tokenname);
+	xfree(keyname);
+
+	if (keys == NULL) {
+		memset(password, 0, strlen(password));
+		xfree(password);
+		error("nss_get_keys failed");
+		goto send;
+	}
+	for (i = 0; keys[i] != NULL; i++) {
+		k = keys[i];
+		version = k->type == KEY_RSA1 ? 1 : 2;
+		tab = idtab_lookup(version);
+		if (lookup_identity(k, version) == NULL) {
+			id = xmalloc(sizeof(Identity));
+			id->key = k;
+			id->comment = nss_get_key_label(k);
+			id->death = death;
+			id->confirm = confirm;
+			TAILQ_INSERT_TAIL(&tab->idlist, id, next);
+			tab->nentries++;
+			success = 1;
+		} else {
+			key_free(k);
+		}
+		keys[i] = NULL;
+	}
+	xfree(keys);
+send:
+	buffer_put_int(&e->output, 1);
+	buffer_put_char(&e->output,
+	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
+}
+
+static void
+process_remove_nss_key(SocketEntry *e)
+{
+	char *tokenname = NULL, *keyname = NULL, *password = NULL;
+	int i, version, success = 0;
+	Key **keys, *k = NULL;
+	Identity *id;
+	Idtab *tab;
+
+	tokenname = buffer_get_string(&e->request, NULL);
+	keyname = buffer_get_string(&e->request, NULL);
+	password = buffer_get_string(&e->request, NULL);
+
+	keys = nss_get_keys(tokenname, keyname, password);
+	xfree(tokenname);
+	xfree(keyname);
+	xfree(password);
+
+	if (keys == NULL || keys[0] == NULL) {
+		error("nss_get_keys failed");
+		goto send;
+	}
+	for (i = 0; keys[i] != NULL; i++) {
+		k = keys[i];
+		version = k->type == KEY_RSA1 ? 1 : 2;
+		if ((id = lookup_identity(k, version)) != NULL) {
+			tab = idtab_lookup(version);
+			TAILQ_REMOVE(&tab->idlist, id, next);
+			tab->nentries--;
+			free_identity(id);
+			success = 1;
+		}
+		key_free(k);
+		keys[i] = NULL;
+	}
+	xfree(keys);
+send:
+	buffer_put_int(&e->output, 1);
+	buffer_put_char(&e->output,
+	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
+}
+#endif /* HAVE_LIBNSS */
+
 /* dispatch incoming messages */
 
 static void
@@ -793,6 +905,15 @@ process_message(SocketEntry *e)
 		process_remove_smartcard_key(e);
 		break;
 #endif /* SMARTCARD */
+#ifdef HAVE_LIBNSS
+	case SSH_AGENTC_ADD_NSS_KEY:
+	case SSH_AGENTC_ADD_NSS_KEY_CONSTRAINED:
+		process_add_nss_key(e);
+		break;
+	case SSH_AGENTC_REMOVE_NSS_KEY:
+		process_remove_nss_key(e);
+		break;
+#endif /* SMARTCARD */
 	default:
 		/* Unknown message.  Respond with failure. */
 		error("Unknown message %d", type);
diff -up openssh-4.7p1/authfd.h.nss-keys openssh-4.7p1/authfd.h
--- openssh-4.7p1/authfd.h.nss-keys	2006-08-05 04:39:39.000000000 +0200
+++ openssh-4.7p1/authfd.h	2007-09-06 17:43:59.000000000 +0200
@@ -49,6 +49,12 @@
 #define SSH2_AGENTC_ADD_ID_CONSTRAINED		25
 #define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26
 
+/* nss */
+#define SSH_AGENTC_ADD_NSS_KEY			30
+#define SSH_AGENTC_REMOVE_NSS_KEY		31
+#define SSH_AGENTC_ADD_NSS_KEY_CONSTRAINED	32
+
+
 #define	SSH_AGENT_CONSTRAIN_LIFETIME		1
 #define	SSH_AGENT_CONSTRAIN_CONFIRM		2
 
@@ -83,6 +89,8 @@ int	 ssh_remove_all_identities(Authentic
 int	 ssh_lock_agent(AuthenticationConnection *, int, const char *);
 int	 ssh_update_card(AuthenticationConnection *, int, const char *,
     const char *, u_int, u_int);
+int	 ssh_update_nss_key(AuthenticationConnection *, int, const char *,
+    const char *, const char *, u_int, u_int);
 
 int
 ssh_decrypt_challenge(AuthenticationConnection *, Key *, BIGNUM *, u_char[16],
diff -up openssh-4.7p1/configure.ac.nss-keys openssh-4.7p1/configure.ac
--- openssh-4.7p1/configure.ac.nss-keys	2007-09-06 17:43:59.000000000 +0200
+++ openssh-4.7p1/configure.ac	2007-09-06 17:51:48.000000000 +0200
@@ -3228,6 +3228,20 @@ AC_ARG_WITH(linux-audit,
 	fi ]
 )
 
+# Check whether user wants NSS support
+LIBNSS_MSG="no"
+AC_ARG_WITH(nss,
+	[  --with-nss   Enable NSS support],
+	[ if test "x$withval" != "xno" ; then
+		AC_DEFINE(HAVE_LIBNSS,1,[Define if you want NSS support.])
+		LIBNSS_MSG="yes"
+		CPPFLAGS="$CPPFLAGS -I/usr/include/nss3 -I/usr/include/nspr4"
+		AC_CHECK_HEADERS(pk11pub.h)
+		LIBS="$LIBS -lnss3"
+	fi
+	])
+AC_SUBST(LIBNSS)
+
 # Check whether user wants Kerberos 5 support
 KRB5_MSG="no"
 AC_ARG_WITH(kerberos5,
@@ -4050,6 +4064,7 @@ echo "                   OSF SIA support
 echo "                 KerberosV support: $KRB5_MSG"
 echo "                   SELinux support: $SELINUX_MSG"
 echo "               Linux audit support: $LINUX_AUDIT_MSG"
+echo "                       NSS support: $LIBNSS_MSG"
 echo "                 Smartcard support: $SCARD_MSG"
 echo "                     S/KEY support: $SKEY_MSG"
 echo "              TCP Wrappers support: $TCPW_MSG"
diff -up /dev/null openssh-4.7p1/README.nss
--- /dev/null	2007-09-04 17:17:14.474470098 +0200
+++ openssh-4.7p1/README.nss	2007-09-06 17:43:59.000000000 +0200
@@ -0,0 +1,36 @@
+How to use NSS tokens with OpenSSH?
+
+This version of OpenSSH contains experimental support for authentication using
+keys stored in tokens stored in NSS database. This for example includes any
+PKCS#11 tokens which are installed in your NSS database.
+
+As the code is experimental and preliminary only SSH protocol 2 is supported.
+The NSS certificate and token databases are looked for in the ~/.ssh
+directory or in a directory specified by environment variable NSS_DB_PATH.
+
+Common operations:
+
+(1) tell the ssh client to use the NSS keys:
+
+	$ ssh -o 'UseNSS yes' otherhost
+	
+	if you want to use a specific token:
+	
+	$ ssh -o 'UseNSS yes' -o 'NSS Token My PKCS11 Token' otherhost
+
+(2) or tell the agent to use the NSS keys:
+
+	$ ssh-add -n
+	
+	if you want to use a specific token:
+	
+	$ ssh-add -n -T 'My PKCS11 Token'
+
+(3) extract the public key from token so it can be added to the
+server:
+
+	$ ssh-keygen -n
+	
+	if you want to use a specific token and/or key:
+	
+	$ ssh-keygen -n -D 'My PKCS11 Token' 'My Key ID'
diff -up openssh-4.7p1/authfd.c.nss-keys openssh-4.7p1/authfd.c
--- openssh-4.7p1/authfd.c.nss-keys	2006-09-01 07:38:36.000000000 +0200
+++ openssh-4.7p1/authfd.c	2007-09-06 17:43:59.000000000 +0200
@@ -626,6 +626,45 @@ ssh_update_card(AuthenticationConnection
 	return decode_reply(type);
 }
 
+int
+ssh_update_nss_key(AuthenticationConnection *auth, int add,
+    const char *tokenname, const char *keyname,
+    const char *pass, u_int life, u_int confirm)
+{
+	Buffer msg;
+	int type, constrained = (life || confirm);
+
+	if (add) {
+		type = constrained ?
+		    SSH_AGENTC_ADD_NSS_KEY_CONSTRAINED :
+		    SSH_AGENTC_ADD_NSS_KEY;
+	} else
+		type = SSH_AGENTC_REMOVE_NSS_KEY;
+
+	buffer_init(&msg);
+	buffer_put_char(&msg, type);
+	buffer_put_cstring(&msg, tokenname);
+	buffer_put_cstring(&msg, keyname);
+	buffer_put_cstring(&msg, pass);
+
+	if (constrained) {
+		if (life != 0) {
+			buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_LIFETIME);
+			buffer_put_int(&msg, life);
+		}
+		if (confirm != 0)
+			buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_CONFIRM);
+	}
+
+	if (ssh_request_reply(auth, &msg, &msg) == 0) {
+		buffer_free(&msg);
+		return 0;
+	}
+	type = buffer_get_char(&msg);
+	buffer_free(&msg);
+	return decode_reply(type);
+}
+
 /*
  * Removes all identities from the agent.  This call is not meant to be used
  * by normal applications.
diff -up openssh-4.7p1/readconf.h.nss-keys openssh-4.7p1/readconf.h
--- openssh-4.7p1/readconf.h.nss-keys	2006-08-05 04:39:40.000000000 +0200
+++ openssh-4.7p1/readconf.h	2007-09-06 17:43:59.000000000 +0200
@@ -84,6 +84,8 @@ typedef struct {
 	char   *preferred_authentications;
 	char   *bind_address;	/* local socket address for connection to sshd */
 	char   *smartcard_device; /* Smartcard reader device */
+	int     use_nss;        /* Use NSS library for keys */
+	char   *nss_token;      /* Look for NSS keys on token */
 	int	verify_host_key_dns;	/* Verify host key using DNS */
 
 	int     num_identity_files;	/* Number of files for RSA/DSA identities. */
diff -up /dev/null openssh-4.7p1/nsskeys.c
--- /dev/null	2007-09-04 17:17:14.474470098 +0200
+++ openssh-4.7p1/nsskeys.c	2007-09-06 17:43:59.000000000 +0200
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2001 Markus Friedl.  All rights reserved.
+ * Copyright (c) 2007 Red Hat, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+#ifdef HAVE_LIBNSS
+
+#include <sys/types.h>
+
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <openssl/evp.h>
+
+#include <nss.h>
+#include <keyhi.h>
+#include <pk11pub.h>
+#include <cert.h>
+
+#include "xmalloc.h"
+#include "key.h"
+#include "log.h"
+#include "misc.h"
+#include "nsskeys.h"
+#include "pathnames.h"
+
+static char *
+password_cb(PK11SlotInfo *slot, PRBool retry, void *arg)
+{
+	char *password = arg;
+	if (retry || password == NULL)
+		return NULL;
+	
+	return PL_strdup(password);
+}
+
+int
+nss_init(PK11PasswordFunc pwfn)
+{
+	char *dbpath;
+	char buf[MAXPATHLEN];
+
+	if (NSS_IsInitialized())
+		return 0;
+
+	if ((dbpath=getenv("NSS_DB_PATH")) == NULL) {
+		struct passwd *pw;
+		if ((pw = getpwuid(getuid())) == NULL ||
+			pw->pw_dir == NULL) {
+			return -1;
+		}
+		snprintf(buf, sizeof(buf), "%s/%s", pw->pw_dir,
+			    _PATH_SSH_USER_DIR);
+		dbpath = buf;
+	}
+
+	if (NSS_Init(dbpath) != SECSuccess)
+		return -1;
+
+	if (pwfn == NULL) {
+		pwfn = password_cb;
+	}
+
+	PK11_SetPasswordFunc(pwfn);
+	
+	return 0;
+}
+
+static Key *
+make_key_from_privkey(SECKEYPrivateKey *privk, char *password)
+{
+	Key *k;
+	switch (SECKEY_GetPrivateKeyType(privk)) {
+		case rsaKey:
+			k = key_new_nss(KEY_RSA);
+			break;
+		case dsaKey:
+			k = key_new_nss(KEY_DSA);
+			break;
+		default:
+			return NULL;
+	}
+	k->nss->pubk = SECKEY_ConvertToPublicKey(privk);
+	if (k->nss->pubk != NULL) {
+		k->nss->privk = SECKEY_CopyPrivateKey(privk);
+	}
+	if (k->nss->privk != NULL) {
+		if (password != NULL) {
+			k->nss->privk->wincx = xstrdup(password);
+		}
+		return k;
+	}
+	key_free(k);
+	return NULL;
+}
+
+static Key **
+add_key_to_list(Key *k, Key **keys, size_t *i, size_t *allocated)
+{
+	if (*allocated < *i + 2) {
+		*allocated += 16;
+		keys = xrealloc(keys, *allocated, sizeof(k));
+	}
+	keys[*i] = k;
+	(*i)++;
+	keys[*i] = NULL;
+	return keys;
+}
+
+static int
+nss_convert_pubkey(Key *k)
+{
+	u_char *n;
+	unsigned int len;
+	char *p;
+
+	switch (k->type) {
+		case KEY_RSA:
+			n = k->nss->pubk->u.rsa.modulus.data;
+			len = k->nss->pubk->u.rsa.modulus.len;
+
+			if (BN_bin2bn(n, len, k->rsa->n) == NULL) {
+				fatal("nss_convert_pubkey: BN_bin2bn failed");
+			}
+
+			n = k->nss->pubk->u.rsa.publicExponent.data;
+			len = k->nss->pubk->u.rsa.publicExponent.len;
+
+			if (BN_bin2bn(n, len, k->rsa->e) == NULL) {
+				fatal("nss_convert_pubkey: BN_bin2bn failed");
+			}
+			break;
+		case KEY_DSA:
+			n = k->nss->pubk->u.dsa.params.prime.data;
+			len = k->nss->pubk->u.dsa.params.prime.len;
+
+			if (BN_bin2bn(n, len, k->dsa->p) == NULL) {
+				fatal("nss_convert_pubkey: BN_bin2bn failed");
+			}
+
+			n = k->nss->pubk->u.dsa.params.subPrime.data;
+			len = k->nss->pubk->u.dsa.params.subPrime.len;
+
+			if (BN_bin2bn(n, len, k->dsa->q) == NULL) {
+				fatal("nss_convert_pubkey: BN_bin2bn failed");
+			}
+
+			n = k->nss->pubk->u.dsa.params.base.data;
+			len = k->nss->pubk->u.dsa.params.base.len;
+
+			if (BN_bin2bn(n, len, k->dsa->g) == NULL) {
+				fatal("nss_convert_pubkey: BN_bin2bn failed");
+			}
+
+			n = k->nss->pubk->u.dsa.publicValue.data;
+			len = k->nss->pubk->u.dsa.publicValue.len;
+
+			if (BN_bin2bn(n, len, k->dsa->pub_key) == NULL) {
+				fatal("nss_convert_pubkey: BN_bin2bn failed");
+			}
+			break;
+	}
+
+	p = key_fingerprint(k, SSH_FP_MD5, SSH_FP_HEX);
+	debug("fingerprint %u %s", key_size(k), p);
+	xfree(p);
+
+	return 0;
+}
+
+static Key **
+nss_find_privkeys(const char *tokenname, const char *keyname,
+    char *password)
+{
+	Key *k = NULL;
+	Key **keys = NULL;
+	PK11SlotList *slots;
+	PK11SlotListElement *sle;
+	size_t allocated = 0;
+	size_t i = 0;
+
+	if ((slots=PK11_FindSlotsByNames(NULL, NULL, tokenname, PR_TRUE)) == NULL) {
+		if (tokenname == NULL) {
+			debug("No NSS token found");
+		} else {
+			debug("NSS token not found: %s", tokenname);
+		}
+		return NULL;
+	}
+	
+	for (sle = slots->head; sle; sle = sle->next) {
+		SECKEYPrivateKeyList *list;
+		SECKEYPrivateKeyListNode *node;
+		char *tmppass = password;
+				
+		if (PK11_NeedLogin(sle->slot)) {
+			if (password == NULL) {
+				char *prompt;
+				if (asprintf(&prompt, "Enter passphrase for token %s: ",
+					PK11_GetTokenName(sle->slot)) < 0)
+					fatal("password_cb: asprintf failed");
+				tmppass = read_passphrase(prompt, RP_ALLOW_STDIN);
+			}
+			PK11_Authenticate(sle->slot, PR_TRUE, tmppass);
+		}
+
+		debug("Looking for: %s:%s", tokenname, keyname);
+		list = PK11_ListPrivKeysInSlot(sle->slot, (char *)keyname,
+			tmppass);
+		if (list == NULL && keyname != NULL) {
+			char *fooname;
+			/* NSS bug workaround */
+			if (asprintf(&fooname, "%s~", keyname) < 0) {
+				error("nss_find_privkey: asprintf failed");
+				PK11_FreeSlotList(slots);
+				return NULL;
+			}
+			list = PK11_ListPrivKeysInSlot(sle->slot, fooname,
+			tmppass);
+			free(fooname);
+		}
+		if (list == NULL && keyname != NULL) {
+			CERTCertificate *cert;
+			SECKEYPrivateKey *privk;
+			cert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(),
+				(char *)keyname);
+			if (cert == NULL)
+				goto cleanup;
+			privk = PK11_FindPrivateKeyFromCert(sle->slot, cert, tmppass);
+			CERT_DestroyCertificate(cert);
+			if (privk == NULL)
+				goto cleanup;
+			if ((k=make_key_from_privkey(privk, tmppass)) != NULL) {
+				nss_convert_pubkey(k);
+				keys = add_key_to_list(k, keys, &i, &allocated);
+			}
+			SECKEY_DestroyPrivateKey(privk);
+		} else {
+			if (list == NULL)
+				goto cleanup;
+			for (node=PRIVKEY_LIST_HEAD(list); !PRIVKEY_LIST_END(node, list);
+				node=PRIVKEY_LIST_NEXT(node))
+				if ((k=make_key_from_privkey(node->key, tmppass)) != NULL) {
+					nss_convert_pubkey(k);
+					keys = add_key_to_list(k, keys, &i, &allocated);
+				}
+			SECKEY_DestroyPrivateKeyList(list);
+		}
+cleanup:
+		if (password == NULL && tmppass != NULL) {
+			memset(tmppass, 0, strlen(tmppass));
+			xfree(tmppass);
+		}
+	}
+	PK11_FreeSlotList(slots);
+
+	return keys;
+}
+
+Key **
+nss_get_keys(const char *tokenname, const char *keyname,
+    char *password)
+{
+	Key **keys;
+
+	if (nss_init(NULL) == -1) {
+		error("Failed to initialize NSS library");
+		return NULL;
+	}
+
+	keys = nss_find_privkeys(tokenname, keyname, password);
+	if (keys == NULL && keyname != NULL) {
+		error("Cannot find key in nss, token removed");
+		return NULL;
+	}
+#if 0
+	keys = xcalloc(3, sizeof(Key *));
+
+	if (k->type == KEY_RSA) {
+		n = key_new_nss_copy(KEY_RSA1, k);
+
+		keys[0] = n;
+		keys[1] = k;
+		keys[2] = NULL;
+	} else {
+		keys[0] = k;
+		keys[1] = NULL;
+	}
+#endif
+	return keys;
+}
+
+char *
+nss_get_key_label(Key *key)
+{
+	char *label, *nickname;
+	
+	nickname = PK11_GetPrivateKeyNickname(key->nss->privk);
+	label = xstrdup(nickname);
+	PORT_Free(nickname);
+
+	return label;
+}
+
+#endif /* HAVE_LIBNSS */
diff -up openssh-4.7p1/ssh.c.nss-keys openssh-4.7p1/ssh.c
--- openssh-4.7p1/ssh.c.nss-keys	2007-08-08 06:32:41.000000000 +0200
+++ openssh-4.7p1/ssh.c	2007-09-06 17:43:59.000000000 +0200
@@ -104,6 +104,9 @@
 #ifdef SMARTCARD
 #include "scard.h"
 #endif
+#ifdef HAVE_LIBNSS
+#include "nsskeys.h"
+#endif
 
 extern char *__progname;
 
@@ -1217,9 +1220,11 @@ load_public_identity_files(void)
 	int i = 0;
 	Key *public;
 	struct passwd *pw;
-#ifdef SMARTCARD
+#if defined(SMARTCARD) || defined(HAVE_LIBNSS)
 	Key **keys;
+#endif
 
+#ifdef SMARTCARD
 	if (options.smartcard_device != NULL &&
 	    options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
 	    (keys = sc_get_keys(options.smartcard_device, NULL)) != NULL) {
@@ -1240,6 +1245,27 @@ load_public_identity_files(void)
 		xfree(keys);
 	}
 #endif /* SMARTCARD */
+#ifdef HAVE_LIBNSS
+	if (options.use_nss &&
+	    options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
+	    (keys = nss_get_keys(options.nss_token, NULL, NULL)) != NULL) {
+		int count;
+		for (count = 0; keys[count] != NULL; count++) {
+			memmove(&options.identity_files[1], &options.identity_files[0],
+			    sizeof(char *) * (SSH_MAX_IDENTITY_FILES - 1));
+			memmove(&options.identity_keys[1], &options.identity_keys[0],
+			    sizeof(Key *) * (SSH_MAX_IDENTITY_FILES - 1));
+			options.num_identity_files++;
+			options.identity_keys[0] = keys[count];
+			options.identity_files[0] = nss_get_key_label(keys[count]);
+		}
+		if (options.num_identity_files > SSH_MAX_IDENTITY_FILES)
+			options.num_identity_files = SSH_MAX_IDENTITY_FILES;
+		i += count;
+		xfree(keys);
+	}
+#endif /* HAVE_LIBNSS */
+
 	if ((pw = getpwuid(original_real_uid)) == NULL)
 		fatal("load_public_identity_files: getpwuid failed");
 	if (gethostname(thishost, sizeof(thishost)) == -1)
diff -up /dev/null openssh-4.7p1/nsskeys.h
--- /dev/null	2007-09-04 17:17:14.474470098 +0200
+++ openssh-4.7p1/nsskeys.h	2007-09-06 17:43:59.000000000 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2001 Markus Friedl.  All rights reserved.
+ * Copyright (c) 2007 Red Hat, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef NSSKEYS_H
+#define NSSKEYS_H
+#ifdef HAVE_LIBNSS
+#include <pk11func.h>
+#include <prtypes.h>
+
+int	nss_init(PK11PasswordFunc);
+Key	**nss_get_keys(const char *, const char *, char *);
+char	*nss_get_key_label(Key *);
+/*void	 sc_close(void);*/
+/*int	 sc_put_key(Key *, const char *);*/
+
+#endif
+#endif
diff -up openssh-4.7p1/Makefile.in.nss-keys openssh-4.7p1/Makefile.in
--- openssh-4.7p1/Makefile.in.nss-keys	2007-06-11 06:01:42.000000000 +0200
+++ openssh-4.7p1/Makefile.in	2007-09-06 17:53:14.000000000 +0200
@@ -71,7 +71,7 @@ LIBSSH_OBJS=acss.o authfd.o authfile.o b
 	atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \
 	monitor_fdpass.o rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o \
 	kexgex.o kexdhc.o kexgexc.o scard.o msg.o progressmeter.o dns.o \
-	entropy.o scard-opensc.o gss-genr.o umac.o
+	entropy.o scard-opensc.o gss-genr.o umac.o nsskeys.o
 
 SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
 	sshconnect.o sshconnect1.o sshconnect2.o
diff -up openssh-4.7p1/key.h.nss-keys openssh-4.7p1/key.h
--- openssh-4.7p1/key.h.nss-keys	2006-08-05 04:39:40.000000000 +0200
+++ openssh-4.7p1/key.h	2007-09-06 17:43:59.000000000 +0200
@@ -29,11 +29,17 @@
 #include <openssl/rsa.h>
 #include <openssl/dsa.h>
 
+#ifdef HAVE_LIBNSS
+#include <nss.h>
+#include <keyhi.h>
+#endif
+
 typedef struct Key Key;
 enum types {
 	KEY_RSA1,
 	KEY_RSA,
 	KEY_DSA,
+	KEY_NSS,
 	KEY_UNSPEC
 };
 enum fp_type {
@@ -47,16 +53,30 @@ enum fp_rep {
 
 /* key is stored in external hardware */
 #define KEY_FLAG_EXT		0x0001
+#define KEY_FLAG_NSS		0x0002
+
+#ifdef HAVE_LIBNSS
+typedef struct NSSKey NSSKey;
+struct NSSKey {
+	SECKEYPrivateKey *privk;
+	SECKEYPublicKey *pubk;
+};
+#endif
 
 struct Key {
 	int	 type;
 	int	 flags;
 	RSA	*rsa;
 	DSA	*dsa;
+#ifdef HAVE_LIBNSS
+	NSSKey  *nss;
+#endif
 };
 
 Key		*key_new(int);
 Key		*key_new_private(int);
+Key 		*key_new_nss(int);
+Key		*key_new_nss_copy(int, const Key *);
 void		 key_free(Key *);
 Key		*key_demote(const Key *);
 int		 key_equal(const Key *, const Key *);
diff -up openssh-4.7p1/ssh-add.c.nss-keys openssh-4.7p1/ssh-add.c
--- openssh-4.7p1/ssh-add.c.nss-keys	2006-09-01 07:38:37.000000000 +0200
+++ openssh-4.7p1/ssh-add.c	2007-09-06 17:43:59.000000000 +0200
@@ -43,6 +43,14 @@
 
 #include <openssl/evp.h>
 
+#ifdef HAVE_LIBNSS
+#include <nss.h>
+#include <secmod.h>
+#include <pk11pub.h>
+#include <keyhi.h>
+#include <cert.h>
+#endif
+
 #include <fcntl.h>
 #include <pwd.h>
 #include <stdarg.h>
@@ -56,6 +64,7 @@
 #include "rsa.h"
 #include "log.h"
 #include "key.h"
+#include "nsskeys.h"
 #include "buffer.h"
 #include "authfd.h"
 #include "authfile.h"
@@ -306,6 +315,117 @@ do_file(AuthenticationConnection *ac, in
 	return 0;
 }
 
+#ifdef HAVE_LIBNSS
+static char *
+password_cb(PK11SlotInfo *slot, PRBool retry, void *arg)
+{
+	char **passcache = arg;
+	char *password, *p2 = NULL;
+	char *prompt;
+	
+	if (retry)
+		return NULL;
+	
+	if (asprintf(&prompt, "Enter passphrase for token %s: ",
+		PK11_GetTokenName(slot)) < 0)
+		fatal("password_cb: asprintf failed");
+
+	password = read_passphrase(prompt, RP_ALLOW_STDIN);
+	
+	if (password != NULL && (p2=PL_strdup(password)) == NULL) {
+		memset(password, 0, strlen(password));
+		fatal("password_cb: PL_strdup failed");
+	}
+
+	if (passcache != NULL) {
+		if (*passcache != NULL) {
+			memset(*passcache, 0, strlen(*passcache));
+			xfree(*passcache);
+		}
+		*passcache = password;
+	} else {
+		memset(password, 0, strlen(password));
+		xfree(password);
+	}
+	
+	return p2;
+}
+
+static int
+add_slot_keys(AuthenticationConnection *ac, PK11SlotInfo *slot, int add)
+{
+	SECKEYPrivateKeyList *list;
+	SECKEYPrivateKeyListNode *node;
+	char *passcache = NULL;
+	char *tokenname;
+	
+	int count = 0;
+	
+	if (PK11_NeedLogin(slot))
+		PK11_Authenticate(slot, PR_TRUE, &passcache);
+		
+	if ((list=PK11_ListPrivKeysInSlot(slot, NULL, NULL)) == NULL) {
+		return 0;
+	}
+	
+	tokenname = PK11_GetTokenName(slot);
+	
+	for (node=PRIVKEY_LIST_HEAD(list); !PRIVKEY_LIST_END(node, list);
+		node=PRIVKEY_LIST_NEXT(node)) {
+		char *keyname;
+		SECKEYPublicKey *pub;
+		
+		keyname = PK11_GetPrivateKeyNickname(node->key);
+		if (keyname == NULL || *keyname == '\0') {
+			/* no nickname to refer to */
+			CERTCertificate *cert;
+			char *kn;
+			cert = PK11_GetCertFromPrivateKey(node->key);
+			if (cert == NULL)
+				continue;
+			kn = strchr(cert->nickname, ':');
+			if (kn == NULL)
+				kn = cert->nickname;
+			else
+				kn++;
+			keyname = PORT_Strdup(kn);
+			CERT_DestroyCertificate(cert);
+			if (keyname == NULL)
+				continue;
+		}
+		pub = SECKEY_ConvertToPublicKey(node->key);
+		if (pub == NULL) {
+			fprintf(stderr, "No public key for: %s:%s\n",
+				tokenname, keyname);
+			continue; /* not possible to obtain public key */
+		}
+		SECKEY_DestroyPublicKey(pub);
+		
+		if (ssh_update_nss_key(ac, add, tokenname, keyname,
+			passcache?passcache:"",	lifetime, confirm)) {
+			fprintf(stderr, "Key %s: %s:%s\n",
+				add?"added":"removed", tokenname, keyname);
+			count++;
+		} else {
+			fprintf(stderr, "Could not %s key: %s:%s\n",
+				add?"add":"remove", tokenname, keyname);
+		}
+		
+		PORT_Free(keyname);
+		count++;
+	}
+
+	if (passcache != NULL) {
+		memset(passcache, 0, strlen(passcache));
+		xfree(passcache);
+	}
+	
+	SECKEY_DestroyPrivateKeyList(list);
+	
+	return count;
+}
+#endif
+
 static void
 usage(void)
 {
@@ -333,6 +453,10 @@ main(int argc, char **argv)
 	AuthenticationConnection *ac = NULL;
 	char *sc_reader_id = NULL;
 	int i, ch, deleting = 0, ret = 0;
+#ifdef HAVE_LIBNSS
+	char *token_id = NULL;
+	int use_nss = 0;
+#endif
 
 	/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
 	sanitise_stdfd();
@@ -350,7 +474,7 @@ main(int argc, char **argv)
 		    "Could not open a connection to your authentication agent.\n");
 		exit(2);
 	}
-	while ((ch = getopt(argc, argv, "lLcdDxXe:s:t:")) != -1) {
+	while ((ch = getopt(argc, argv, "lLcdDnxXe:s:t:T:")) != -1) {
 		switch (ch) {
 		case 'l':
 		case 'L':
@@ -372,6 +496,11 @@ main(int argc, char **argv)
 			if (delete_all(ac) == -1)
 				ret = 1;
 			goto done;
+#ifdef HAVE_LIBNSS
+		case 'n':
+			use_nss = 1;
+			break;
+#endif
 		case 's':
 			sc_reader_id = optarg;
 			break;
@@ -386,6 +515,11 @@ main(int argc, char **argv)
 				goto done;
 			}
 			break;
+#ifdef HAVE_LIBNSS
+		case 'T':
+			token_id = optarg;
+			break;
+#endif
 		default:
 			usage();
 			ret = 1;
@@ -399,6 +533,40 @@ main(int argc, char **argv)
 			ret = 1;
 		goto done;
 	}
+#ifdef HAVE_LIBNSS
+	if (use_nss) {
+		PK11SlotList *slots;
+		PK11SlotListElement *sle;
+		int count = 0;
+		if (nss_init(password_cb) == -1) {
+			fprintf(stderr, "Failed to initialize NSS library\n");
+			ret = 1;
+			goto done;
+		}
+		
+		if ((slots=PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE,
+			NULL)) == NULL) {
+			fprintf(stderr, "No tokens found\n");
+			ret = 1;
+			goto nss_done;
+		}
+
+		for (sle = slots->head; sle; sle = sle->next) {
+			int rv;
+			if ((rv=add_slot_keys(ac, sle->slot, !deleting)) == -1) {
+				ret = 1;
+			}
+			count += rv;
+		}
+		if (count == 0) {
+			ret = 1;
+		}
+nss_done:		
+		NSS_Shutdown();
+		clear_pass();
+		goto done;
+	}
+#endif
 	if (argc == 0) {
 		char buf[MAXPATHLEN];
 		struct passwd *pw;
diff -up openssh-4.7p1/ssh-rsa.c.nss-keys openssh-4.7p1/ssh-rsa.c
--- openssh-4.7p1/ssh-rsa.c.nss-keys	2006-09-01 07:38:37.000000000 +0200
+++ openssh-4.7p1/ssh-rsa.c	2007-09-06 17:43:59.000000000 +0200
@@ -32,6 +32,10 @@
 #include "compat.h"
 #include "ssh.h"
 
+#ifdef HAVE_LIBNSS
+#include <cryptohi.h>
+#endif
+
 static int openssh_RSA_verify(int, u_char *, u_int, u_char *, u_int, RSA *);
 
 /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */
@@ -50,6 +54,38 @@ ssh_rsa_sign(const Key *key, u_char **si
 		error("ssh_rsa_sign: no RSA key");
 		return -1;
 	}
+
+	slen = RSA_size(key->rsa);
+	sig = xmalloc(slen);
+
+#ifdef HAVE_LIBNSS
+	if (key->flags & KEY_FLAG_NSS) {
+		SECItem sigitem;
+		SECOidTag alg;
+
+		memset(&sigitem, 0, sizeof(sigitem));
+		alg = (datafellows & SSH_BUG_RSASIGMD5) ?
+			SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION :
+			SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
+
+		if (SEC_SignData(&sigitem, (u_char *)data, datalen, key->nss->privk,
+			alg) != SECSuccess) {
+			error("ssh_rsa_sign: sign failed");
+			return -1;
+		}
+		if (sigitem.len > slen) {
+			error("ssh_rsa_sign: slen %u slen2 %u", slen, sigitem.len);
+			xfree(sig);
+			SECITEM_ZfreeItem(&sigitem, PR_FALSE);
+			return -1;
+		}
+		if (sigitem.len < slen) {
+			memset(sig, 0, slen - sigitem.len);
+		}
+		memcpy(sig+slen-sigitem.len, sigitem.data, sigitem.len);
+		SECITEM_ZfreeItem(&sigitem, PR_FALSE);
+	} else {
+#endif
 	nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1;
 	if ((evp_md = EVP_get_digestbynid(nid)) == NULL) {
 		error("ssh_rsa_sign: EVP_get_digestbynid %d failed", nid);
@@ -59,9 +95,6 @@ ssh_rsa_sign(const Key *key, u_char **si
 	EVP_DigestUpdate(&md, data, datalen);
 	EVP_DigestFinal(&md, digest, &dlen);
 
-	slen = RSA_size(key->rsa);
-	sig = xmalloc(slen);
-
 	ok = RSA_sign(nid, digest, dlen, sig, &len, key->rsa);
 	memset(digest, 'd', sizeof(digest));
 
@@ -83,6 +116,9 @@ ssh_rsa_sign(const Key *key, u_char **si
 		xfree(sig);
 		return -1;
 	}
+#ifdef HAVE_LIBNSS
+	}
+#endif
 	/* encode signature */
 	buffer_init(&b);
 	buffer_put_cstring(&b, "ssh-rsa");
diff -up openssh-4.7p1/ssh-keygen.c.nss-keys openssh-4.7p1/ssh-keygen.c
--- openssh-4.7p1/ssh-keygen.c.nss-keys	2007-02-19 12:10:25.000000000 +0100
+++ openssh-4.7p1/ssh-keygen.c	2007-09-06 17:48:08.000000000 +0200
@@ -52,6 +52,11 @@
 #include "scard.h"
 #endif
 
+#ifdef HAVE_LIBNSS
+#include <nss.h>
+#include "nsskeys.h"
+#endif
+
 /* Number of bits in the RSA/DSA key.  This value can be set on the command line. */
 #define DEFAULT_BITS		2048
 #define DEFAULT_BITS_DSA	1024
@@ -499,6 +504,26 @@ do_download(struct passwd *pw, const cha
 }
 #endif /* SMARTCARD */
 
+#ifdef HAVE_LIBNSS
+static void
+do_nss_download(struct passwd *pw, const char *tokenname, const char *keyname)
+{
+	Key **keys = NULL;
+	int i;
+	
+	keys = nss_get_keys(tokenname, keyname, NULL);
+	if (keys == NULL)
+		fatal("cannot find public key in NSS");
+	for (i = 0; keys[i]; i++) {
+		key_write(keys[i], stdout);
+		key_free(keys[i]);
+		fprintf(stdout, "\n");
+	}
+	xfree(keys);
+	exit(0);
+}
+#endif /* HAVE_LIBNSS */
+
 static void
 do_fingerprint(struct passwd *pw)
 {
@@ -1056,7 +1081,8 @@ main(int argc, char **argv)
 	Key *private, *public;
 	struct passwd *pw;
 	struct stat st;
-	int opt, type, fd, download = 0;
+	int opt, type, fd, download = 1;
+	int use_nss = 0;
 	u_int32_t memory = 0, generator_wanted = 0, trials = 100;
 	int do_gen_candidates = 0, do_screen_candidates = 0;
 	int log_level = SYSLOG_LEVEL_INFO;
@@ -1090,7 +1116,7 @@ main(int argc, char **argv)
 	}
 
 	while ((opt = getopt(argc, argv,
-	    "degiqpclBHvxXyF:b:f:t:U:D:P:N:C:r:g:R:T:G:M:S:a:W:")) != -1) {
+	    "degiqpclnBHvxXyF:b:f:t:U:D:P:N:C:r:g:R:T:G:M:S:a:W:")) != -1) {
 		switch (opt) {
 		case 'b':
 			bits = (u_int32_t)strtonum(optarg, 768, 32768, &errstr);
@@ -1130,6 +1156,10 @@ main(int argc, char **argv)
 		case 'g':
 			print_generic = 1;
 			break;
+		case 'n':
+			use_nss = 1;
+			download = 1;
+			break;
 		case 'P':
 			identity_passphrase = optarg;
 			break;
@@ -1161,10 +1191,10 @@ main(int argc, char **argv)
 		case 't':
 			key_type_name = optarg;
 			break;
-		case 'D':
-			download = 1;
-			/*FALLTHROUGH*/
 		case 'U':
+			download = 0;
+			/*FALLTHROUGH*/
+		case 'D':
 			reader_id = optarg;
 			break;
 		case 'v':
@@ -1269,6 +1299,17 @@ main(int argc, char **argv)
 			exit(0);
 		}
 	}
+
+	if (use_nss) {
+#ifdef HAVE_LIBNSS
+		if (download)
+			do_nss_download(pw, reader_id, identity_file);
+		else
+			fatal("no support for NSS key upload.");
+#else
+		fatal("no support for NSS keys.");
+#endif
+	}
 	if (reader_id != NULL) {
 #ifdef SMARTCARD
 		if (download)
diff -up openssh-4.7p1/readconf.c.nss-keys openssh-4.7p1/readconf.c
--- openssh-4.7p1/readconf.c.nss-keys	2007-03-21 10:46:03.000000000 +0100
+++ openssh-4.7p1/readconf.c	2007-09-06 17:43:59.000000000 +0200
@@ -124,6 +124,7 @@ typedef enum {
 	oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
 	oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
 	oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
+	oUseNSS, oNSSToken,
 	oClearAllForwardings, oNoHostAuthenticationForLocalhost,
 	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
 	oAddressFamily, oGssAuthentication, oGssDelegateCreds,
@@ -209,6 +210,13 @@ static struct {
 #else
 	{ "smartcarddevice", oUnsupported },
 #endif
+#ifdef HAVE_LIBNSS
+	{ "usenss", oUseNSS },
+	{ "nsstoken", oNSSToken },
+#else
+	{ "usenss", oUnsupported },
+	{ "nsstoken", oNSSToken },
+#endif
 	{ "clearallforwardings", oClearAllForwardings },
 	{ "enablesshkeysign", oEnableSSHKeysign },
 	{ "verifyhostkeydns", oVerifyHostKeyDNS },
@@ -601,6 +609,14 @@ parse_string:
 		charptr = &options->smartcard_device;
 		goto parse_string;
 
+	case oUseNSS:
+		intptr = &options->use_nss;
+		goto parse_flag;
+
+	case oNSSToken:
+		charptr = &options->nss_token;
+		goto parse_command;
+
 	case oProxyCommand:
 		charptr = &options->proxy_command;
 parse_command:
@@ -1049,6 +1065,8 @@ initialize_options(Options * options)
 	options->preferred_authentications = NULL;
 	options->bind_address = NULL;
 	options->smartcard_device = NULL;
+	options->use_nss = -1;
+	options->nss_token = NULL;
 	options->enable_ssh_keysign = - 1;
 	options->no_host_authentication_for_localhost = - 1;
 	options->identities_only = - 1;
@@ -1177,6 +1195,8 @@ fill_default_options(Options * options)
 		options->no_host_authentication_for_localhost = 0;
 	if (options->identities_only == -1)
 		options->identities_only = 0;
+	if (options->use_nss == -1)
+		options->use_nss = 0;
 	if (options->enable_ssh_keysign == -1)
 		options->enable_ssh_keysign = 0;
 	if (options->rekey_limit == -1)

openssh-4.7p1-pam-session.patch:

--- NEW FILE openssh-4.7p1-pam-session.patch ---
diff -up openssh-4.7p1/session.c.pam-session openssh-4.7p1/session.c
--- openssh-4.7p1/session.c.pam-session	2007-08-16 15:28:04.000000000 +0200
+++ openssh-4.7p1/session.c	2007-09-06 17:37:46.000000000 +0200
@@ -422,11 +422,6 @@ do_exec_no_pty(Session *s, const char *c
 
 	session_proctitle(s);
 
-#if defined(USE_PAM)
-	if (options.use_pam && !use_privsep)
-		do_pam_setcred(1);
-#endif /* USE_PAM */
-
 	/* Fork the child. */
 	if ((pid = fork()) == 0) {
 		is_child = 1;
@@ -557,14 +552,6 @@ do_exec_pty(Session *s, const char *comm
 	ptyfd = s->ptyfd;
 	ttyfd = s->ttyfd;
 
-#if defined(USE_PAM)
-	if (options.use_pam) {
-		do_pam_set_tty(s->tty);
-		if (!use_privsep)
-			do_pam_setcred(1);
-	}
-#endif
-
 	/* Fork the child. */
 	if ((pid = fork()) == 0) {
 		is_child = 1;
@@ -1300,17 +1287,9 @@ do_setusercontext(struct passwd *pw)
 # ifdef __bsdi__
 		setpgid(0, 0);
 # endif
-#ifdef GSSAPI
-		if (options.gss_authentication) {
-			temporarily_use_uid(pw);
-			ssh_gssapi_storecreds();
-			restore_uid();
-		}
-#endif
 # ifdef USE_PAM
 		if (options.use_pam) {
-			do_pam_session();
-			do_pam_setcred(use_privsep);
+			do_pam_setcred(0);
 		}
 # endif /* USE_PAM */
 		if (setusercontext(lc, pw, pw->pw_uid,
@@ -1337,13 +1316,6 @@ do_setusercontext(struct passwd *pw)
 			exit(1);
 		}
 		endgrent();
-#ifdef GSSAPI
-		if (options.gss_authentication) {
-			temporarily_use_uid(pw);
-			ssh_gssapi_storecreds();
-			restore_uid();
-		}
-#endif
 # ifdef USE_PAM
 		/*
 		 * PAM credentials may take the form of supplementary groups.
@@ -1351,8 +1323,7 @@ do_setusercontext(struct passwd *pw)
 		 * Reestablish them here.
 		 */
 		if (options.use_pam) {
-			do_pam_session();
-			do_pam_setcred(use_privsep);
+			do_pam_setcred(0);
 		}
 # endif /* USE_PAM */
 # if defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY)
diff -up openssh-4.7p1/sshd.c.pam-session openssh-4.7p1/sshd.c
--- openssh-4.7p1/sshd.c.pam-session	2007-09-06 17:37:46.000000000 +0200
+++ openssh-4.7p1/sshd.c	2007-09-06 17:37:46.000000000 +0200
@@ -1831,7 +1831,21 @@ main(int ac, char **av)
 	audit_event(SSH_AUTH_SUCCESS);
 #endif
 
-	/*
+#ifdef GSSAPI
+	if (options.gss_authentication) {
+		temporarily_use_uid(authctxt->pw);
+		ssh_gssapi_storecreds();
+		restore_uid();
+	}
+#endif
+#ifdef USE_PAM
+	if (options.use_pam) {
+		do_pam_setcred(1);
+		do_pam_session();
+	}
+#endif
+
+ 	/*
 	 * In privilege separation, we fork another child and prepare
 	 * file descriptor passing.
 	 */
diff -up openssh-4.7p1/monitor.c.pam-session openssh-4.7p1/monitor.c
--- openssh-4.7p1/monitor.c.pam-session	2007-09-06 17:37:46.000000000 +0200
+++ openssh-4.7p1/monitor.c	2007-09-06 17:37:46.000000000 +0200
@@ -1566,6 +1566,11 @@ mm_answer_term(int sock, Buffer *req)
 	/* The child is terminating */
 	session_destroy_all(&mm_session_close);
 
+#ifdef USE_PAM
+	if (options.use_pam)
+		sshpam_cleanup();
+#endif
+
 	while (waitpid(pmonitor->m_pid, &status, 0) == -1)
 		if (errno != EINTR)
 			exit(1);
diff -up openssh-4.7p1/auth-pam.c.pam-session openssh-4.7p1/auth-pam.c
--- openssh-4.7p1/auth-pam.c.pam-session	2007-08-10 06:32:34.000000000 +0200
+++ openssh-4.7p1/auth-pam.c	2007-09-06 17:37:46.000000000 +0200
@@ -598,15 +598,17 @@ static struct pam_conv store_conv = { ss
 void
 sshpam_cleanup(void)
 {
-	debug("PAM: cleanup");
-	if (sshpam_handle == NULL)
+	if (sshpam_handle == NULL || (use_privsep && !mm_is_monitor()))
 		return;
+	debug("PAM: cleanup");
 	pam_set_item(sshpam_handle, PAM_CONV, (const void *)&null_conv);
 	if (sshpam_cred_established) {
+		debug("PAM: deleting credentials");
 		pam_setcred(sshpam_handle, PAM_DELETE_CRED);
 		sshpam_cred_established = 0;
 	}
 	if (sshpam_session_open) {
+		debug("PAM: closing session");
 		pam_close_session(sshpam_handle, PAM_SILENT);
 		sshpam_session_open = 0;
 	}

openssh-4.7p1-redhat.patch:

--- NEW FILE openssh-4.7p1-redhat.patch ---
diff -up openssh-4.7p1/sshd_config.redhat openssh-4.7p1/sshd_config
--- openssh-4.7p1/sshd_config.redhat	2007-03-21 10:42:25.000000000 +0100
+++ openssh-4.7p1/sshd_config	2007-09-06 16:23:58.000000000 +0200
@@ -33,6 +33,7 @@ Protocol 2
 # Logging
 # obsoletes QuietMode and FascistLogging
 #SyslogFacility AUTH
+SyslogFacility AUTHPRIV
 #LogLevel INFO
 
 # Authentication:
@@ -59,9 +60,11 @@ Protocol 2
 # To disable tunneled clear text passwords, change to no here!
 #PasswordAuthentication yes
 #PermitEmptyPasswords no
+PasswordAuthentication yes
 
 # Change to no to disable s/key passwords
 #ChallengeResponseAuthentication yes
+ChallengeResponseAuthentication no
 
 # Kerberos options
 #KerberosAuthentication no
@@ -71,7 +74,9 @@ Protocol 2
 
 # GSSAPI options
 #GSSAPIAuthentication no
+GSSAPIAuthentication yes
 #GSSAPICleanupCredentials yes
+GSSAPICleanupCredentials yes
 
 # Set this to 'yes' to enable PAM authentication, account processing, 
 # and session processing. If this is enabled, PAM authentication will 
@@ -83,10 +88,16 @@ Protocol 2
 # PAM authentication, then enable this but set PasswordAuthentication
 # and ChallengeResponseAuthentication to 'no'.
 #UsePAM no
+UsePAM yes
 
+# Accept locale-related environment variables
+AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES 
+AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT 
+AcceptEnv LC_IDENTIFICATION LC_ALL
 #AllowTcpForwarding yes
 #GatewayPorts no
 #X11Forwarding no
+X11Forwarding yes
 #X11DisplayOffset 10
 #X11UseLocalhost yes
 #PrintMotd yes
diff -up openssh-4.7p1/ssh_config.redhat openssh-4.7p1/ssh_config
--- openssh-4.7p1/ssh_config.redhat	2007-06-11 06:04:42.000000000 +0200
+++ openssh-4.7p1/ssh_config	2007-09-06 16:21:49.000000000 +0200
@@ -43,3 +43,13 @@
 #   Tunnel no
 #   TunnelDevice any:any
 #   PermitLocalCommand no
+Host *
+	GSSAPIAuthentication yes
+# If this option is set to yes then remote X11 clients will have full access
+# to the original X11 display. As virtually no X11 client supports the untrusted
+# mode correctly we set this to yes.
+	ForwardX11Trusted yes
+# Send locale-related environment variables
+	SendEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES 
+	SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT 
+	SendEnv LC_IDENTIFICATION LC_ALL
diff -up openssh-4.7p1/sshd_config.0.redhat openssh-4.7p1/sshd_config.0
--- openssh-4.7p1/sshd_config.0.redhat	2007-09-04 08:50:11.000000000 +0200
+++ openssh-4.7p1/sshd_config.0	2007-09-06 16:21:49.000000000 +0200
@@ -435,9 +435,9 @@ DESCRIPTION
 
      SyslogFacility
              Gives the facility code that is used when logging messages from
-             sshd(8).  The possible values are: DAEMON, USER, AUTH, LOCAL0,
-             LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.  The de-
-             fault is AUTH.
+             sshd(8).  The possible values are: DAEMON, USER, AUTH, AUTHPRIV,
+             LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
+             The default is AUTH.
 
      TCPKeepAlive
              Specifies whether the system should send TCP keepalive messages
diff -up openssh-4.7p1/sshd_config.5.redhat openssh-4.7p1/sshd_config.5
--- openssh-4.7p1/sshd_config.5.redhat	2007-06-11 06:07:13.000000000 +0200
+++ openssh-4.7p1/sshd_config.5	2007-09-06 16:21:49.000000000 +0200
@@ -748,7 +748,7 @@ Note that this option applies to protoco
 .It Cm SyslogFacility
 Gives the facility code that is used when logging messages from
 .Xr sshd 8 .
-The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2,
+The possible values are: DAEMON, USER, AUTH, AUTHPRIV, LOCAL0, LOCAL1, LOCAL2,
 LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
 The default is AUTH.
 .It Cm TCPKeepAlive

openssh-4.7p1-selinux.patch:

--- NEW FILE openssh-4.7p1-selinux.patch ---
diff -up openssh-4.7p1/configure.ac.selinux openssh-4.7p1/configure.ac
--- openssh-4.7p1/configure.ac.selinux	2007-09-06 19:46:32.000000000 +0200
+++ openssh-4.7p1/configure.ac	2007-09-06 19:52:23.000000000 +0200
@@ -3211,6 +3211,7 @@ AC_ARG_WITH(selinux,
 		AC_CHECK_LIB(selinux, setexeccon, [ LIBSELINUX="-lselinux" ],
 		    AC_MSG_ERROR(SELinux support requires libselinux library))
 		SSHDLIBS="$SSHDLIBS $LIBSELINUX"
+		LIBS="$LIBS $LIBSELINUX"
 		AC_CHECK_FUNCS(getseuserbyname get_default_context_with_level)
 		LIBS="$save_LIBS"
 	fi ]
diff -up openssh-4.7p1/auth1.c.selinux openssh-4.7p1/auth1.c
--- openssh-4.7p1/auth1.c.selinux	2007-09-06 19:46:32.000000000 +0200
+++ openssh-4.7p1/auth1.c	2007-09-06 19:46:32.000000000 +0200
@@ -388,7 +388,7 @@ void
 do_authentication(Authctxt *authctxt)
 {
 	u_int ulen;
-	char *user, *style = NULL;
+	char *user, *style = NULL, *role=NULL;
 
 	/* Get the name of the user that we wish to log in as. */
 	packet_read_expect(SSH_CMSG_USER);
@@ -397,11 +397,19 @@ do_authentication(Authctxt *authctxt)
 	user = packet_get_string(&ulen);
 	packet_check_eom();
 
+	if ((role = strchr(user, '/')) != NULL)
+		*role++ = '\0';
+
 	if ((style = strchr(user, ':')) != NULL)
 		*style++ = '\0';
+	else
+		if (role && (style = strchr(role, ':')) != NULL)
+			*style++ = '\0';
+			
 
 	authctxt->user = user;
 	authctxt->style = style;
+	authctxt->role = role;
 
 	/* Verify that the user is a valid user. */
 	if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL)
diff -up openssh-4.7p1/monitor_wrap.h.selinux openssh-4.7p1/monitor_wrap.h
--- openssh-4.7p1/monitor_wrap.h.selinux	2006-08-05 04:39:40.000000000 +0200
+++ openssh-4.7p1/monitor_wrap.h	2007-09-06 19:46:32.000000000 +0200
@@ -41,6 +41,7 @@ int mm_is_monitor(void);
 DH *mm_choose_dh(int, int, int);
 int mm_key_sign(Key *, u_char **, u_int *, u_char *, u_int);
 void mm_inform_authserv(char *, char *);
+void mm_inform_authrole(char *);
 struct passwd *mm_getpwnamallow(const char *);
 char *mm_auth2_read_banner(void);
 int mm_auth_password(struct Authctxt *, char *);
diff -up openssh-4.7p1/monitor.h.selinux openssh-4.7p1/monitor.h
--- openssh-4.7p1/monitor.h.selinux	2006-03-26 05:30:02.000000000 +0200
+++ openssh-4.7p1/monitor.h	2007-09-06 19:46:32.000000000 +0200
@@ -30,7 +30,7 @@
 
 enum monitor_reqtype {
 	MONITOR_REQ_MODULI, MONITOR_ANS_MODULI,
-	MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV,
+	MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV,MONITOR_REQ_AUTHROLE,
 	MONITOR_REQ_SIGN, MONITOR_ANS_SIGN,
 	MONITOR_REQ_PWNAM, MONITOR_ANS_PWNAM,
 	MONITOR_REQ_AUTH2_READ_BANNER, MONITOR_ANS_AUTH2_READ_BANNER,
diff -up openssh-4.7p1/monitor_wrap.c.selinux openssh-4.7p1/monitor_wrap.c
--- openssh-4.7p1/monitor_wrap.c.selinux	2007-06-11 06:01:42.000000000 +0200
+++ openssh-4.7p1/monitor_wrap.c	2007-09-06 19:46:32.000000000 +0200
@@ -294,6 +294,23 @@ mm_inform_authserv(char *service, char *
 	buffer_free(&m);
 }
 
+/* Inform the privileged process about role */
+
+void
+mm_inform_authrole(char *role)
+{
+	Buffer m;
+
+	debug3("%s entering", __func__);
+
+	buffer_init(&m);
+	buffer_put_cstring(&m, role ? role : "");
+
+	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHROLE, &m);
+
+	buffer_free(&m);
+}
+
 /* Do the password authentication */
 int
 mm_auth_password(Authctxt *authctxt, char *password)
diff -up openssh-4.7p1/openbsd-compat/port-linux.c.selinux openssh-4.7p1/openbsd-compat/port-linux.c
--- openssh-4.7p1/openbsd-compat/port-linux.c.selinux	2007-06-28 00:48:03.000000000 +0200
+++ openssh-4.7p1/openbsd-compat/port-linux.c	2007-09-06 19:46:32.000000000 +0200
@@ -30,11 +30,16 @@
 #ifdef WITH_SELINUX
 #include "log.h"
 #include "port-linux.h"
+#include "key.h"
+#include "hostfile.h"
+#include "auth.h"
 
 #include <selinux/selinux.h>
 #include <selinux/flask.h>
 #include <selinux/get_context_list.h>
 
+extern Authctxt *the_authctxt;
+
 /* Wrapper around is_selinux_enabled() to log its return value once only */
 static int
 ssh_selinux_enabled(void)
@@ -53,23 +58,36 @@ ssh_selinux_enabled(void)
 static security_context_t
 ssh_selinux_getctxbyname(char *pwname)
 {
-	security_context_t sc;
-	char *sename = NULL, *lvl = NULL;
-	int r;
+	security_context_t sc = NULL;
+	char *sename, *lvl;
+	char *role = NULL;
+	int r = 0;
 
+	if (the_authctxt) 
+		role=the_authctxt->role;
 #ifdef HAVE_GETSEUSERBYNAME
-	if (getseuserbyname(pwname, &sename, &lvl) != 0)
-		return NULL;
+	if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) {
+		sename = NULL;
+		lvl = NULL;
+	}
 #else
 	sename = pwname;
 	lvl = NULL;
 #endif
 
+	if (r == 0) {
 #ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
-	r = get_default_context_with_level(sename, lvl, NULL, &sc);
+		if (role != NULL && role[0])
+			r = get_default_context_with_rolelevel(sename, role, lvl, NULL, &sc);
+		else
+			r = get_default_context_with_level(sename, lvl, NULL, &sc);
 #else
-	r = get_default_context(sename, NULL, &sc);
+		if (role != NULL && role[0])
+			r = get_default_context_with_role(sename, role, NULL, &sc);
+		else
+			r = get_default_context(sename, NULL, &sc);
 #endif
+	}
 
 	if (r != 0) {
 		switch (security_getenforce()) {
diff -up openssh-4.7p1/auth.h.selinux openssh-4.7p1/auth.h
--- openssh-4.7p1/auth.h.selinux	2006-08-18 16:32:46.000000000 +0200
+++ openssh-4.7p1/auth.h	2007-09-06 19:46:32.000000000 +0200
@@ -58,6 +58,7 @@ struct Authctxt {
 	char		*service;
 	struct passwd	*pw;		/* set if 'valid' */
 	char		*style;
+	char		*role;
 	void		*kbdintctxt;
 #ifdef BSD_AUTH
 	auth_session_t	*as;
diff -up openssh-4.7p1/auth2.c.selinux openssh-4.7p1/auth2.c
--- openssh-4.7p1/auth2.c.selinux	2007-05-20 06:58:41.000000000 +0200
+++ openssh-4.7p1/auth2.c	2007-09-06 19:46:32.000000000 +0200
@@ -141,7 +141,7 @@ input_userauth_request(int type, u_int32
 {
 	Authctxt *authctxt = ctxt;
 	Authmethod *m = NULL;
-	char *user, *service, *method, *style = NULL;
+	char *user, *service, *method, *style = NULL, *role = NULL;
 	int authenticated = 0;
 
 	if (authctxt == NULL)
@@ -153,6 +153,9 @@ input_userauth_request(int type, u_int32
 	debug("userauth-request for user %s service %s method %s", user, service, method);
 	debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
 
+	if ((role = strchr(user, '/')) != NULL)
+		*role++ = 0;
+
 	if ((style = strchr(user, ':')) != NULL)
 		*style++ = 0;
 
@@ -178,8 +181,11 @@ input_userauth_request(int type, u_int32
 		    use_privsep ? " [net]" : "");
 		authctxt->service = xstrdup(service);
 		authctxt->style = style ? xstrdup(style) : NULL;
-		if (use_privsep)
+		authctxt->role = role ? xstrdup(role) : NULL;
+		if (use_privsep) {
 			mm_inform_authserv(service, style);
+			mm_inform_authrole(role);
+		}
 	} else if (strcmp(user, authctxt->user) != 0 ||
 	    strcmp(service, authctxt->service) != 0) {
 		packet_disconnect("Change of username or service not allowed: "
diff -up openssh-4.7p1/monitor.c.selinux openssh-4.7p1/monitor.c
--- openssh-4.7p1/monitor.c.selinux	2007-05-20 07:10:16.000000000 +0200
+++ openssh-4.7p1/monitor.c	2007-09-06 19:46:32.000000000 +0200
@@ -133,6 +133,7 @@ int mm_answer_sign(int, Buffer *);
 int mm_answer_pwnamallow(int, Buffer *);
 int mm_answer_auth2_read_banner(int, Buffer *);
 int mm_answer_authserv(int, Buffer *);
+int mm_answer_authrole(int, Buffer *);
 int mm_answer_authpassword(int, Buffer *);
 int mm_answer_bsdauthquery(int, Buffer *);
 int mm_answer_bsdauthrespond(int, Buffer *);
@@ -204,6 +205,7 @@ struct mon_table mon_dispatch_proto20[] 
     {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
     {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
     {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
+    {MONITOR_REQ_AUTHROLE, MON_ONCE, mm_answer_authrole},
     {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner},
     {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
 #ifdef USE_PAM
@@ -657,6 +659,7 @@ mm_answer_pwnamallow(int sock, Buffer *m
 	else {
 		/* Allow service/style information on the auth context */
 		monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
+		monitor_permit(mon_dispatch, MONITOR_REQ_AUTHROLE, 1);
 		monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1);
 	}
 
@@ -702,6 +705,23 @@ mm_answer_authserv(int sock, Buffer *m)
 }
 
 int
+mm_answer_authrole(int sock, Buffer *m)
+{
+	monitor_permit_authentications(1);
+
+	authctxt->role = buffer_get_string(m, NULL);
+	debug3("%s: role=%s",
+	    __func__, authctxt->role);
+
+	if (strlen(authctxt->role) == 0) {
+		xfree(authctxt->role);
+		authctxt->role = NULL;
+	}
+
+	return (0);
+}
+
+int
 mm_answer_authpassword(int sock, Buffer *m)
 {
 	static int call_count;

openssh-4.7p1-sftp-drain-acks.patch:

--- NEW FILE openssh-4.7p1-sftp-drain-acks.patch ---
diff -up openssh-4.7p1/sftp-client.c.drain-acks openssh-4.7p1/sftp-client.c
--- openssh-4.7p1/sftp-client.c.drain-acks	2007-02-19 12:13:39.000000000 +0100
+++ openssh-4.7p1/sftp-client.c	2007-09-06 17:54:41.000000000 +0200
@@ -992,7 +992,8 @@ int
 do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
     int pflag)
 {
-	int local_fd, status;
+	int local_fd;
+	int status = SSH2_FX_OK;
 	u_int handle_len, id, type;
 	u_int64_t offset;
 	char *handle, *data;
@@ -1074,7 +1075,7 @@ do_upload(struct sftp_conn *conn, char *
 		 * Simulate an EOF on interrupt, allowing ACKs from the
 		 * server to drain.
 		 */
-		if (interrupted)
+		if (interrupted || status != SSH2_FX_OK)
 			len = 0;
 		else do
 			len = read(local_fd, data, conn->transfer_buflen);
@@ -1131,18 +1132,6 @@ do_upload(struct sftp_conn *conn, char *
 				fatal("Can't find request for ID %u", r_id);
 			TAILQ_REMOVE(&acks, ack, tq);
 
-			if (status != SSH2_FX_OK) {
-				error("Couldn't write to remote file \"%s\": %s",
-				    remote_path, fx2txt(status));
-				if (showprogress)
-					stop_progress_meter();
-				do_close(conn, handle, handle_len);
-				close(local_fd);
-				xfree(data);
-				xfree(ack);
-				status = -1;
-				goto done;
-			}
 			debug3("In write loop, ack for %u %u bytes at %llu",
 			    ack->id, ack->len, (unsigned long long)ack->offset);
 			++ackid;
@@ -1154,21 +1143,25 @@ do_upload(struct sftp_conn *conn, char *
 		stop_progress_meter();
 	xfree(data);
 
+	if (status != SSH2_FX_OK) {
+		error("Couldn't write to remote file \"%s\": %s",
+		    remote_path, fx2txt(status));
+		status = -1;
+	}
+
 	if (close(local_fd) == -1) {
 		error("Couldn't close local file \"%s\": %s", local_path,
 		    strerror(errno));
-		do_close(conn, handle, handle_len);
 		status = -1;
-		goto done;
 	}
 
 	/* Override umask and utimes if asked */
 	if (pflag)
 		do_fsetstat(conn, handle, handle_len, &a);
 
-	status = do_close(conn, handle, handle_len);
+	if (do_close(conn, handle, handle_len) != SSH2_FX_OK)
+		status = -1;
 
-done:
 	xfree(handle);
 	buffer_free(&msg);
 	return(status);

openssh-4.7p1-vendor.patch:

--- NEW FILE openssh-4.7p1-vendor.patch ---
diff -up openssh-4.7p1/configure.ac.vendor openssh-4.7p1/configure.ac
--- openssh-4.7p1/configure.ac.vendor	2007-09-06 16:27:47.000000000 +0200
+++ openssh-4.7p1/configure.ac	2007-09-06 16:27:47.000000000 +0200
@@ -3792,6 +3792,12 @@ AC_ARG_WITH(lastlog,
 		fi
 	]
 )
+AC_ARG_ENABLE(vendor-patchlevel,
+  [  --enable-vendor-patchlevel=TAG  specify a vendor patch level],
+  [AC_DEFINE_UNQUOTED(SSH_VENDOR_PATCHLEVEL,[SSH_RELEASE "-" "$enableval"],[Define to your vendor patch level, if it has been modified from the upstream source release.])
+   SSH_VENDOR_PATCHLEVEL="$enableval"],
+  [AC_DEFINE(SSH_VENDOR_PATCHLEVEL,SSH_RELEASE,[Define to your vendor patch level, if it has been modified from the upstream source release.])
+   SSH_VENDOR_PATCHLEVEL=none])
 
 dnl lastlog, [uw]tmpx? detection
 dnl  NOTE: set the paths in the platform section to avoid the
@@ -4041,6 +4047,7 @@ echo "       IP address in \$DISPLAY hac
 echo "           Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG"
 echo "                  BSD Auth support: $BSD_AUTH_MSG"
 echo "              Random number source: $RAND_MSG"
+echo "                Vendor patch level: $SSH_VENDOR_PATCHLEVEL"
 if test ! -z "$USE_RAND_HELPER" ; then
 echo "     ssh-rand-helper collects from: $RAND_HELPER_MSG"
 fi
diff -up openssh-4.7p1/sshd_config.5.vendor openssh-4.7p1/sshd_config.5
--- openssh-4.7p1/sshd_config.5.vendor	2007-09-06 16:27:47.000000000 +0200
+++ openssh-4.7p1/sshd_config.5	2007-09-06 16:27:47.000000000 +0200
@@ -725,6 +725,14 @@ This option applies to protocol version 
 .It Cm ServerKeyBits
 Defines the number of bits in the ephemeral protocol version 1 server key.
 The minimum value is 512, and the default is 768.
+.It Cm ShowPatchLevel
+Specifies whether
+.Nm sshd
+will display the patch level of the binary in the identification string.
+The patch level is set at compile-time.
+The default is
+.Dq no .
+This option applies to protocol version 1 only.
 .It Cm StrictModes
 Specifies whether
 .Xr sshd 8
diff -up openssh-4.7p1/servconf.h.vendor openssh-4.7p1/servconf.h
--- openssh-4.7p1/servconf.h.vendor	2007-02-19 12:25:38.000000000 +0100
+++ openssh-4.7p1/servconf.h	2007-09-06 16:27:47.000000000 +0200
@@ -120,6 +120,7 @@ typedef struct {
 	int	max_startups;
 	int	max_authtries;
 	char   *banner;			/* SSH-2 banner message */
+	int	show_patchlevel;	/* Show vendor patch level to clients */
 	int	use_dns;
 	int	client_alive_interval;	/*
 					 * poke the client this often to
diff -up openssh-4.7p1/servconf.c.vendor openssh-4.7p1/servconf.c
--- openssh-4.7p1/servconf.c.vendor	2007-05-20 07:03:16.000000000 +0200
+++ openssh-4.7p1/servconf.c	2007-09-06 16:29:11.000000000 +0200
@@ -113,6 +113,7 @@ initialize_server_options(ServerOptions 
 	options->max_startups = -1;
 	options->max_authtries = -1;
 	options->banner = NULL;
+	options->show_patchlevel = -1;
 	options->use_dns = -1;
 	options->client_alive_interval = -1;
 	options->client_alive_count_max = -1;
@@ -250,6 +251,9 @@ fill_default_server_options(ServerOption
 	if (options->permit_tun == -1)
 		options->permit_tun = SSH_TUNMODE_NO;
 
+	if (options->show_patchlevel == -1)
+		options->show_patchlevel = 0;
+
 	/* Turn privilege separation on by default */
 	if (use_privsep == -1)
 		use_privsep = 1;
@@ -293,6 +297,7 @@ typedef enum {
 	sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
 	sMatch, sPermitOpen, sForceCommand,
 	sUsePrivilegeSeparation,
+	sShowPatchLevel,
 	sDeprecated, sUnsupported
 } ServerOpCodes;
 
@@ -390,6 +395,7 @@ static struct {
 	{ "maxstartups", sMaxStartups, SSHCFG_GLOBAL },
 	{ "maxauthtries", sMaxAuthTries, SSHCFG_GLOBAL },
 	{ "banner", sBanner, SSHCFG_ALL },
+	{ "showpatchlevel", sShowPatchLevel, SSHCFG_GLOBAL },
 	{ "usedns", sUseDNS, SSHCFG_GLOBAL },
 	{ "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
 	{ "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL },
@@ -1005,6 +1011,10 @@ parse_flag:
 		intptr = &use_privsep;
 		goto parse_flag;
 
+	case sShowPatchLevel:
+		intptr = &options->show_patchlevel;
+		goto parse_flag;
+
 	case sAllowUsers:
 		while ((arg = strdelim(&cp)) && *arg != '\0') {
 			if (options->num_allow_users >= MAX_ALLOW_USERS)
diff -up openssh-4.7p1/sshd_config.0.vendor openssh-4.7p1/sshd_config.0
--- openssh-4.7p1/sshd_config.0.vendor	2007-09-06 16:27:47.000000000 +0200
+++ openssh-4.7p1/sshd_config.0	2007-09-06 16:27:47.000000000 +0200
@@ -418,6 +418,11 @@ DESCRIPTION
              Defines the number of bits in the ephemeral protocol version 1
              server key.  The minimum value is 512, and the default is 768.
 
+     ShowPatchLevel
+	     Specifies whether sshd will display the specific patch level of
+	     the binary in the server identification string.  The patch level
+	     is set at compile-time.  The default is M-bM-^@M-^\noM-bM-^@M-^].
+
      StrictModes
              Specifies whether sshd(8) should check file modes and ownership
              of the user's files and home directory before accepting login.
diff -up openssh-4.7p1/sshd_config.vendor openssh-4.7p1/sshd_config
--- openssh-4.7p1/sshd_config.vendor	2007-09-06 16:27:47.000000000 +0200
+++ openssh-4.7p1/sshd_config	2007-09-06 16:27:47.000000000 +0200
@@ -109,6 +109,7 @@ X11Forwarding yes
 #Compression delayed
 #ClientAliveInterval 0
 #ClientAliveCountMax 3
+#ShowPatchLevel no
 #UseDNS yes
 #PidFile /var/run/sshd.pid
 #MaxStartups 10
diff -up openssh-4.7p1/sshd.c.vendor openssh-4.7p1/sshd.c
--- openssh-4.7p1/sshd.c.vendor	2007-06-05 10:22:32.000000000 +0200
+++ openssh-4.7p1/sshd.c	2007-09-06 16:27:47.000000000 +0200
@@ -419,7 +419,8 @@ sshd_exchange_identification(int sock_in
 		major = PROTOCOL_MAJOR_1;
 		minor = PROTOCOL_MINOR_1;
 	}
-	snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", major, minor, SSH_VERSION);
+	snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", major, minor,
+		 (options.show_patchlevel == 1) ? SSH_VENDOR_PATCHLEVEL : SSH_VERSION);
 	server_version_string = xstrdup(buf);
 
 	/* Send our protocol version identification. */
@@ -1434,7 +1435,8 @@ main(int ac, char **av)
 		exit(1);
 	}
 
-	debug("sshd version %.100s", SSH_RELEASE);
+	debug("sshd version %.100s",
+	      (options.show_patchlevel == 1) ? SSH_VENDOR_PATCHLEVEL : SSH_RELEASE);
 
 	/* Store privilege separation user for later use if required. */
 	if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) {


Index: .cvsignore
===================================================================
RCS file: /cvs/pkgs/rpms/openssh/devel/.cvsignore,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- .cvsignore	21 Dec 2006 13:42:47 -0000	1.19
+++ .cvsignore	6 Sep 2007 19:49:16 -0000	1.20
@@ -1 +1 @@
-openssh-4.5p1-noacss.tar.bz2
+openssh-4.7p1-noacss.tar.bz2


Index: openssh.spec
===================================================================
RCS file: /cvs/pkgs/rpms/openssh/devel/openssh.spec,v
retrieving revision 1.112
retrieving revision 1.113
diff -u -r1.112 -r1.113
--- openssh.spec	9 Aug 2007 18:33:41 -0000	1.112
+++ openssh.spec	6 Sep 2007 19:49:16 -0000	1.113
@@ -1,10 +1,5 @@
+# Do we want SELinux & Audit
 %define WITH_SELINUX 1
-%if %{WITH_SELINUX}
-# Audit patch applicable only over SELinux patch
-%define WITH_AUDIT 1
-%else
-%define WITH_AUDIT 0
-%endif
 
 # OpenSSH privilege separation requires a user & group ID
 %define sshd_uid    74
@@ -28,6 +23,9 @@
 # Do we want kerberos5 support (1=yes 0=no)
 %define kerberos5 1
 
+# Do we want libedit support
+%define libedit 1
+
 # Do we want NSS tokens support
 %define nss 1
 
@@ -59,42 +57,44 @@
 # Turn off some stuff for resuce builds
 %if %{rescue}
 %define kerberos5 0
+%define libedit 0
 %endif
 
 Summary: The OpenSSH implementation of SSH protocol versions 1 and 2
 Name: openssh
-Version: 4.5p1
-Release: 8%{?dist}%{?rescue_rel}
+Version: 4.7p1
+Release: 1%{?dist}%{?rescue_rel}
 URL: http://www.openssh.com/portable.html
 #Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz
-#Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.sig
+#Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc
 # This package differs from the upstream OpenSSH tarball in that
 # the ACSS cipher is removed by running openssh-nukeacss.sh in
 # the unpacked source directory.
 Source0: openssh-%{version}-noacss.tar.bz2
 Source1: openssh-nukeacss.sh
-Patch0: openssh-4.5p1-redhat.patch
+Patch0: openssh-4.7p1-redhat.patch
 Patch2: openssh-3.8.1p1-skip-initial.patch
 Patch3: openssh-3.8.1p1-krb5-config.patch
-Patch4: openssh-4.5p1-vendor.patch
+Patch4: openssh-4.7p1-vendor.patch
 Patch5: openssh-4.3p2-initscript.patch
-Patch12: openssh-4.5p1-selinux.patch
-Patch16: openssh-4.5p1-audit.patch
+Patch10: openssh-4.7p1-pam-session.patch
+Patch12: openssh-4.7p1-selinux.patch
+Patch13: openssh-4.7p1-mls.patch
+Patch16: openssh-4.7p1-audit.patch
+Patch17: openssh-4.3p2-cve-2007-3102.patch
 Patch22: openssh-3.9p1-askpass-keep-above.patch
 Patch24: openssh-4.3p1-fromto-remote.patch
 Patch26: openssh-4.2p1-pam-no-stack.patch
-Patch27: openssh-3.9p1-log-in-chroot.patch
+Patch27: openssh-4.7p1-log-in-chroot.patch
 Patch30: openssh-4.0p1-exit-deadlock.patch
 Patch31: openssh-3.9p1-skip-used.patch
 Patch35: openssh-4.2p1-askpass-progress.patch
 Patch38: openssh-4.3p2-askpass-grab-info.patch
 Patch39: openssh-4.3p2-no-v6only.patch
 Patch44: openssh-4.3p2-allow-ip-opts.patch
-Patch48: openssh-4.3p2-pam-session.patch
 Patch49: openssh-4.3p2-gssapi-canohost.patch
-Patch50: openssh-4.5p1-mls.patch
-Patch51: openssh-4.5p1-nss-keys.patch
-Patch52: openssh-4.5p1-sftp-drain-acks.patch
+Patch51: openssh-4.7p1-nss-keys.patch
+Patch52: openssh-4.7p1-sftp-drain-acks.patch
 License: BSD
 Group: Applications/Internet
 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
@@ -126,6 +126,10 @@
 BuildRequires: krb5-devel
 %endif
 
+%if %{libedit}
+BuildRequires: libedit-devel
+%endif
+
 %if %{nss}
 BuildRequires: nss-devel
 %endif
@@ -133,9 +137,6 @@
 %if %{WITH_SELINUX}
 Requires: libselinux >= 1.27.7
 BuildRequires: libselinux-devel >= 1.27.7
-%endif
-
-%if %{WITH_AUDIT}
 Requires: audit-libs >= 1.0.8
 BuildRequires: audit-libs >= 1.0.8
 %endif
@@ -204,13 +205,14 @@
 %patch4 -p1 -b .vendor
 %patch5 -p1 -b .initscript
 
+%patch10 -p1 -b .pam-session
+
 %if %{WITH_SELINUX}
 #SELinux
 %patch12 -p1 -b .selinux
-%endif
-
-%if %{WITH_AUDIT}
+%patch13 -p1 -b .mls
 %patch16 -p1 -b .audit
+%patch17 -p1 -b .inject-fix
 %endif
 
 %patch22 -p1 -b .keep-above
@@ -223,9 +225,7 @@
 %patch38 -p1 -b .grab-info
 %patch39 -p1 -b .no-v6only
 %patch44 -p1 -b .ip-opts
-%patch48 -p1 -b .pam-sesssion
 %patch49 -p1 -b .canohost
-%patch50 -p1 -b .mls
 %patch51 -p1 -b .nss-keys
 %patch52 -p1 -b .drain-acks
 
@@ -282,15 +282,17 @@
 	--with-pam \
 %endif
 %if %{WITH_SELINUX}
-	--with-selinux \
-%endif
-%if %{WITH_AUDIT}
-	--with-linux-audit \
+	--with-selinux --with-linux-audit \
 %endif
 %if %{kerberos5}
-	--with-kerberos5${krb5_prefix:+=${krb5_prefix}}
+	--with-kerberos5${krb5_prefix:+=${krb5_prefix}} \
 %else
-	--without-kerberos5
+	--without-kerberos5 \
+%endif
+%if %{libedit}
+	--with-libedit
+%else
+	--without-libedit
 %endif
 
 %if %{static_libcrypto}
@@ -478,6 +480,11 @@
 %endif
 
 %changelog
+* Thu Sep  6 2007 Tomas Mraz <tmraz at redhat.com> - 4.7p1-1
+- upgrade to latest upstream
+- use libedit in sftp (#203009)
+- fixed audit log injection problem (CVE-2007-3102)
+
 * Thu Aug  9 2007 Tomas Mraz <tmraz at redhat.com> - 4.5p1-8
 - fix sftp client problems on write error (#247802)
 - allow disabling autocreation of server keys (#235466)


Index: sources
===================================================================
RCS file: /cvs/pkgs/rpms/openssh/devel/sources,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- sources	21 Dec 2006 13:42:47 -0000	1.19
+++ sources	6 Sep 2007 19:49:16 -0000	1.20
@@ -1 +1 @@
-9ef9bf019945105f2ac1760c95c9b339  openssh-4.5p1-noacss.tar.bz2
+21634329a8f1cd0e7a7974ade7280bdc  openssh-4.7p1-noacss.tar.bz2


--- openssh-3.9p1-log-in-chroot.patch DELETED ---


--- openssh-4.3p2-pam-session.patch DELETED ---


--- openssh-4.5p1-audit.patch DELETED ---


--- openssh-4.5p1-mls.patch DELETED ---


--- openssh-4.5p1-nss-keys.patch DELETED ---


--- openssh-4.5p1-redhat.patch DELETED ---


--- openssh-4.5p1-selinux.patch DELETED ---


--- openssh-4.5p1-sftp-drain-acks.patch DELETED ---


--- openssh-4.5p1-vendor.patch DELETED ---




More information about the fedora-extras-commits mailing list