rpms/openssh/F-12 openssh-5.2p1-nss-keys.patch, 1.2, 1.3 openssh.spec, 1.169, 1.170

Jan F. Chadima jfch2222 at fedoraproject.org
Tue Oct 27 15:59:35 UTC 2009


Author: jfch2222

Update of /cvs/pkgs/rpms/openssh/F-12
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv15697

Modified Files:
	openssh-5.2p1-nss-keys.patch openssh.spec 
Log Message:
Resolve locking in ssh-add


openssh-5.2p1-nss-keys.patch:
 openssh-5.2p1/README.nss   |   36 ++++
 openssh-5.3p1/Makefile.in  |    2 
 openssh-5.3p1/authfd.c     |   39 +++++
 openssh-5.3p1/authfd.h     |    8 +
 openssh-5.3p1/configure.ac |   15 ++
 openssh-5.3p1/key.c        |   61 ++++++++
 openssh-5.3p1/key.h        |   20 ++
 openssh-5.3p1/nsskeys.c    |  327 +++++++++++++++++++++++++++++++++++++++++++++
 openssh-5.3p1/nsskeys.h    |   39 +++++
 openssh-5.3p1/readconf.c   |   20 ++
 openssh-5.3p1/readconf.h   |    2 
 openssh-5.3p1/ssh-add.c    |  181 ++++++++++++++++++++++++
 openssh-5.3p1/ssh-agent.c  |  121 ++++++++++++++++
 openssh-5.3p1/ssh-dss.c    |   36 ++++
 openssh-5.3p1/ssh-keygen.c |   51 ++++++-
 openssh-5.3p1/ssh-rsa.c    |   42 +++++
 openssh-5.3p1/ssh.c        |   28 +++
 17 files changed, 1016 insertions(+), 12 deletions(-)

Index: openssh-5.2p1-nss-keys.patch
===================================================================
RCS file: /cvs/pkgs/rpms/openssh/F-12/openssh-5.2p1-nss-keys.patch,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -p -r1.2 -r1.3
--- openssh-5.2p1-nss-keys.patch	10 Mar 2009 13:39:03 -0000	1.2
+++ openssh-5.2p1-nss-keys.patch	27 Oct 2009 15:59:35 -0000	1.3
@@ -1,289 +1,55 @@
-diff -up openssh-5.2p1/key.c.nss-keys openssh-5.2p1/key.c
---- openssh-5.2p1/key.c.nss-keys	2008-07-11 09:35:09.000000000 +0200
-+++ openssh-5.2p1/key.c	2008-11-18 19:11:41.000000000 +0100
-@@ -96,6 +96,54 @@ key_new(int type)
- 	return k;
- }
- 
-+#ifdef HAVE_LIBNSS
-+Key *
-+key_new_nss(int type)
-+{
-+	Key *k = key_new(type);
-+
-+	k->nss = xcalloc(1, sizeof(*k->nss));
-+	k->flags = KEY_FLAG_EXT | KEY_FLAG_NSS;
-+
-+	return k;
-+}
-+
-+Key *
-+key_new_nss_copy(int type, const Key *c)
-+{
-+	Key *k = key_new_nss(type);
-+
-+	switch (k->type) {
-+		case KEY_RSA:
-+			if ((BN_copy(k->rsa->n, c->rsa->n) == NULL) ||
-+				(BN_copy(k->rsa->e, c->rsa->e) == NULL))
-+				fatal("key_new_nss_copy: BN_copy failed");
-+			break;
-+		case KEY_DSA:
-+			if ((BN_copy(k->dsa->p, c->rsa->p) == NULL) ||
-+				(BN_copy(k->dsa->q, c->dsa->q) == NULL) ||
-+				(BN_copy(k->dsa->g, c->dsa->g) == NULL) ||
-+				(BN_copy(k->dsa->pub_key, c->dsa->pub_key) == NULL))
-+				fatal("key_new_nss_copy: BN_copy failed");
-+			break;
-+	}
-+		
-+	k->nss->privk = SECKEY_CopyPrivateKey(c->nss->privk);
-+	if (k->nss->privk == NULL)
-+		fatal("key_new_nss_copy: SECKEY_CopyPrivateKey failed");
-+
-+	k->nss->pubk = SECKEY_CopyPublicKey(c->nss->pubk);
-+	if (k->nss->pubk == NULL)
-+		fatal("key_new_nss_copy: SECKEY_CopyPublicKey failed");
-+	
-+	if (c->nss->privk->wincx)
-+		k->nss->privk->wincx = xstrdup(c->nss->privk->wincx);
-+
-+	return k;
-+}
-+#endif
-+
-+
- Key *
- key_new_private(int type)
- {
-@@ -151,6 +199,19 @@ key_free(Key *k)
- 		fatal("key_free: bad key type %d", k->type);
- 		break;
- 	}
-+#ifdef HAVE_LIBNSS
-+	if (k->flags & KEY_FLAG_NSS) {
-+		if (k->nss->privk != NULL && k->nss->privk->wincx != NULL) {
-+			memset(k->nss->privk->wincx, 0,
-+				strlen(k->nss->privk->wincx));
-+			xfree(k->nss->privk->wincx);
-+			k->nss->privk->wincx = NULL;
-+		}
-+		SECKEY_DestroyPrivateKey(k->nss->privk);
-+		SECKEY_DestroyPublicKey(k->nss->pubk);
-+		xfree(k->nss);
-+	}
-+#endif
- 	xfree(k);
- }
- 
-diff -up openssh-5.2p1/ssh-dss.c.nss-keys openssh-5.2p1/ssh-dss.c
---- openssh-5.2p1/ssh-dss.c.nss-keys	2006-11-07 13:14:42.000000000 +0100
-+++ openssh-5.2p1/ssh-dss.c	2008-11-18 19:11:41.000000000 +0100
-@@ -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-5.2p1/ssh-agent.c.nss-keys openssh-5.2p1/ssh-agent.c
---- openssh-5.2p1/ssh-agent.c.nss-keys	2008-07-04 15:10:49.000000000 +0200
-+++ openssh-5.2p1/ssh-agent.c	2008-11-18 19:11:41.000000000 +0100
-@@ -80,6 +80,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
-@@ -714,6 +718,114 @@ send:
+diff -up openssh-5.3p1/authfd.c.nss-keys openssh-5.3p1/authfd.c
+--- openssh-5.3p1/authfd.c.nss-keys	2006-09-01 07:38:36.000000000 +0200
++++ openssh-5.3p1/authfd.c	2009-10-02 14:09:01.000000000 +0200
+@@ -626,6 +626,45 @@ ssh_update_card(AuthenticationConnection
+ 	return decode_reply(type);
  }
- #endif /* SMARTCARD */
  
-+#ifdef HAVE_LIBNSS
-+static void
-+process_add_nss_key (SocketEntry *e)
++int
++ssh_update_nss_key(AuthenticationConnection *auth, int add,
++    const char *tokenname, const char *keyname,
++    const char *pass, u_int life, u_int confirm)
 +{
-+	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);
++	Buffer msg;
++	int type, constrained = (life || confirm);
 +
-+	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;
++	if (add) {
++		type = constrained ?
++		    SSH_AGENTC_ADD_NSS_KEY_CONSTRAINED :
++		    SSH_AGENTC_ADD_NSS_KEY;
++	} else
++		type = SSH_AGENTC_REMOVE_NSS_KEY;
 +
-+	keys = nss_get_keys(tokenname, keyname, password);
-+	/* password is owned by keys[0] now */
-+	xfree(tokenname);
-+	xfree(keyname);
++	buffer_init(&msg);
++	buffer_put_char(&msg, type);
++	buffer_put_cstring(&msg, tokenname);
++	buffer_put_cstring(&msg, keyname);
++	buffer_put_cstring(&msg, pass);
 +
-+	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);
++	if (constrained) {
++		if (life != 0) {
++			buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_LIFETIME);
++			buffer_put_int(&msg, life);
 +		}
-+		keys[i] = NULL;
++		if (confirm != 0)
++			buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_CONFIRM);
 +	}
-+	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;
++	if (ssh_request_reply(auth, &msg, &msg) == 0) {
++		buffer_free(&msg);
++		return 0;
 +	}
-+	xfree(keys);
-+send:
-+	buffer_put_int(&e->output, 1);
-+	buffer_put_char(&e->output,
-+	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
++	type = buffer_get_char(&msg);
++	buffer_free(&msg);
++	return decode_reply(type);
 +}
-+#endif /* HAVE_LIBNSS */
 +
- /* dispatch incoming messages */
- 
- static void
-@@ -806,6 +918,15 @@ process_message(SocketEntry *e)
- 		process_remove_smartcard_key(e);
- 		break;
- #endif /* SMARTCARD */
-+#ifdef HAVE_LIBNSS
-+	case SSH_AGENTC_ADD_NSS_KEY:
-+	case SSH_AGENTC_ADD_NSS_KEY_CONSTRAINED:
-+		process_add_nss_key(e);
-+		break;
-+	case SSH_AGENTC_REMOVE_NSS_KEY:
-+		process_remove_nss_key(e);
-+		break;
-+#endif /* SMARTCARD */
- 	default:
- 		/* Unknown message.  Respond with failure. */
- 		error("Unknown message %d", type);
-diff -up openssh-5.2p1/authfd.h.nss-keys openssh-5.2p1/authfd.h
---- openssh-5.2p1/authfd.h.nss-keys	2006-08-05 04:39:39.000000000 +0200
-+++ openssh-5.2p1/authfd.h	2008-11-18 19:11:41.000000000 +0100
+ /*
+  * Removes all identities from the agent.  This call is not meant to be used
+  * by normal applications.
+diff -up openssh-5.3p1/authfd.h.nss-keys openssh-5.3p1/authfd.h
+--- openssh-5.3p1/authfd.h.nss-keys	2006-08-05 04:39:39.000000000 +0200
++++ openssh-5.3p1/authfd.h	2009-10-02 14:09:01.000000000 +0200
 @@ -49,6 +49,12 @@
  #define SSH2_AGENTC_ADD_ID_CONSTRAINED		25
  #define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26
@@ -306,10 +72,10 @@ diff -up openssh-5.2p1/authfd.h.nss-keys
  
  int
  ssh_decrypt_challenge(AuthenticationConnection *, Key *, BIGNUM *, u_char[16],
-diff -up openssh-5.2p1/configure.ac.nss-keys openssh-5.2p1/configure.ac
---- openssh-5.2p1/configure.ac.nss-keys	2008-11-18 19:11:41.000000000 +0100
-+++ openssh-5.2p1/configure.ac	2008-11-18 19:12:38.000000000 +0100
-@@ -3436,6 +3436,20 @@ AC_ARG_WITH(kerberos5,
+diff -up openssh-5.3p1/configure.ac.nss-keys openssh-5.3p1/configure.ac
+--- openssh-5.3p1/configure.ac.nss-keys	2009-10-02 14:09:01.000000000 +0200
++++ openssh-5.3p1/configure.ac	2009-10-02 14:09:01.000000000 +0200
+@@ -3514,6 +3514,20 @@ AC_ARG_WITH(kerberos5,
  	]
  )
  
@@ -330,7 +96,7 @@ diff -up openssh-5.2p1/configure.ac.nss-
  # Looking for programs, paths and files
  
  PRIVSEP_PATH=/var/empty
-@@ -4163,6 +4177,7 @@ echo "              TCP Wrappers support
+@@ -4240,6 +4254,7 @@ echo "              TCP Wrappers support
  echo "              MD5 password support: $MD5_MSG"
  echo "                   libedit support: $LIBEDIT_MSG"
  echo "  Solaris process contract support: $SPC_MSG"
@@ -338,110 +104,151 @@ diff -up openssh-5.2p1/configure.ac.nss-
  echo "       IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG"
  echo "           Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG"
  echo "                  BSD Auth support: $BSD_AUTH_MSG"
-diff -up /dev/null openssh-5.2p1/README.nss
---- /dev/null	2008-11-17 17:51:52.160001870 +0100
-+++ openssh-5.2p1/README.nss	2008-11-18 19:11:41.000000000 +0100
-@@ -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-5.2p1/authfd.c.nss-keys openssh-5.2p1/authfd.c
---- openssh-5.2p1/authfd.c.nss-keys	2006-09-01 07:38:36.000000000 +0200
-+++ openssh-5.2p1/authfd.c	2008-11-18 19:11:41.000000000 +0100
-@@ -626,6 +626,45 @@ ssh_update_card(AuthenticationConnection
- 	return decode_reply(type);
+diff -up openssh-5.3p1/key.c.nss-keys openssh-5.3p1/key.c
+--- openssh-5.3p1/key.c.nss-keys	2008-11-03 09:24:17.000000000 +0100
++++ openssh-5.3p1/key.c	2009-10-02 14:09:01.000000000 +0200
+@@ -96,6 +96,54 @@ key_new(int type)
+ 	return k;
  }
  
-+int
-+ssh_update_nss_key(AuthenticationConnection *auth, int add,
-+    const char *tokenname, const char *keyname,
-+    const char *pass, u_int life, u_int confirm)
++#ifdef HAVE_LIBNSS
++Key *
++key_new_nss(int type)
 +{
-+	Buffer msg;
-+	int type, constrained = (life || confirm);
++	Key *k = key_new(type);
 +
-+	if (add) {
-+		type = constrained ?
-+		    SSH_AGENTC_ADD_NSS_KEY_CONSTRAINED :
-+		    SSH_AGENTC_ADD_NSS_KEY;
-+	} else
-+		type = SSH_AGENTC_REMOVE_NSS_KEY;
++	k->nss = xcalloc(1, sizeof(*k->nss));
++	k->flags = KEY_FLAG_EXT | KEY_FLAG_NSS;
 +
-+	buffer_init(&msg);
-+	buffer_put_char(&msg, type);
-+	buffer_put_cstring(&msg, tokenname);
-+	buffer_put_cstring(&msg, keyname);
-+	buffer_put_cstring(&msg, pass);
++	return k;
++}
 +
-+	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);
-+	}
++Key *
++key_new_nss_copy(int type, const Key *c)
++{
++	Key *k = key_new_nss(type);
 +
-+	if (ssh_request_reply(auth, &msg, &msg) == 0) {
-+		buffer_free(&msg);
-+		return 0;
++	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;
 +	}
-+	type = buffer_get_char(&msg);
-+	buffer_free(&msg);
-+	return decode_reply(type);
++		
++	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
 +
- /*
-  * Removes all identities from the agent.  This call is not meant to be used
-  * by normal applications.
-diff -up openssh-5.2p1/readconf.h.nss-keys openssh-5.2p1/readconf.h
---- openssh-5.2p1/readconf.h.nss-keys	2008-06-29 16:04:03.000000000 +0200
-+++ openssh-5.2p1/readconf.h	2008-11-18 19:11:41.000000000 +0100
-@@ -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 */
++
+ Key *
+ key_new_private(int type)
+ {
+@@ -151,6 +199,19 @@ key_free(Key *k)
+ 		fatal("key_free: bad key type %d", k->type);
+ 		break;
+ 	}
++#ifdef HAVE_LIBNSS
++	if (k->flags & KEY_FLAG_NSS) {
++		if (k->nss->privk != NULL && k->nss->privk->wincx != NULL) {
++			memset(k->nss->privk->wincx, 0,
++				strlen(k->nss->privk->wincx));
++			xfree(k->nss->privk->wincx);
++			k->nss->privk->wincx = NULL;
++		}
++		SECKEY_DestroyPrivateKey(k->nss->privk);
++		SECKEY_DestroyPublicKey(k->nss->pubk);
++		xfree(k->nss);
++	}
++#endif
+ 	xfree(k);
+ }
  
- 	int     num_identity_files;	/* Number of files for RSA/DSA identities. */
-diff -up /dev/null openssh-5.2p1/nsskeys.c
---- /dev/null	2008-11-17 17:51:52.160001870 +0100
-+++ openssh-5.2p1/nsskeys.c	2008-11-18 19:11:41.000000000 +0100
+diff -up openssh-5.3p1/key.h.nss-keys openssh-5.3p1/key.h
+--- openssh-5.3p1/key.h.nss-keys	2008-06-12 20:40:35.000000000 +0200
++++ openssh-5.3p1/key.h	2009-10-02 14:09:01.000000000 +0200
+@@ -29,11 +29,17 @@
+ #include <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 {
+@@ -48,16 +54,30 @@ enum fp_rep {
+ 
+ /* key is stored in external hardware */
+ #define KEY_FLAG_EXT		0x0001
++#define KEY_FLAG_NSS		0x0002
++
++#ifdef HAVE_LIBNSS
++typedef struct NSSKey NSSKey;
++struct NSSKey {
++	SECKEYPrivateKey *privk;
++	SECKEYPublicKey *pubk;
++};
++#endif
+ 
+ struct Key {
+ 	int	 type;
+ 	int	 flags;
+ 	RSA	*rsa;
+ 	DSA	*dsa;
++#ifdef HAVE_LIBNSS
++	NSSKey  *nss;
++#endif
+ };
+ 
+ Key		*key_new(int);
+ Key		*key_new_private(int);
++Key 		*key_new_nss(int);
++Key		*key_new_nss_copy(int, const Key *);
+ void		 key_free(Key *);
+ Key		*key_demote(const Key *);
+ int		 key_equal(const Key *, const Key *);
+diff -up openssh-5.3p1/Makefile.in.nss-keys openssh-5.3p1/Makefile.in
+--- openssh-5.3p1/Makefile.in.nss-keys	2009-08-28 02:47:38.000000000 +0200
++++ openssh-5.3p1/Makefile.in	2009-10-02 14:09:53.000000000 +0200
+@@ -71,7 +71,7 @@ LIBSSH_OBJS=acss.o authfd.o authfile.o b
+ 	atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \
+ 	monitor_fdpass.o rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o \
+ 	kexgex.o kexdhc.o kexgexc.o scard.o msg.o progressmeter.o dns.o \
+-	entropy.o scard-opensc.o gss-genr.o umac.o jpake.o schnorr.o
++	entropy.o scard-opensc.o gss-genr.o umac.o jpake.o schnorr.o nsskeys.o
+ 
+ SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
+ 	sshconnect.o sshconnect1.o sshconnect2.o mux.o
+diff -up /dev/null openssh-5.3p1/nsskeys.c
+--- /dev/null	2009-09-11 09:35:58.778798825 +0200
++++ openssh-5.3p1/nsskeys.c	2009-10-02 14:09:01.000000000 +0200
 @@ -0,0 +1,327 @@
 +/*
 + * Copyright (c) 2001 Markus Friedl.  All rights reserved.
@@ -770,63 +577,9 @@ diff -up /dev/null openssh-5.2p1/nsskeys
 +}
 +
 +#endif /* HAVE_LIBNSS */
-diff -up openssh-5.2p1/ssh.c.nss-keys openssh-5.2p1/ssh.c
---- openssh-5.2p1/ssh.c.nss-keys	2008-07-04 04:53:50.000000000 +0200
-+++ openssh-5.2p1/ssh.c	2008-11-18 19:11:41.000000000 +0100
-@@ -104,6 +104,9 @@
- #ifdef SMARTCARD
- #include "scard.h"
- #endif
-+#ifdef HAVE_LIBNSS
-+#include "nsskeys.h"
-+#endif
- 
- extern char *__progname;
- 
-@@ -1235,9 +1238,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) {
-@@ -1260,6 +1265,27 @@ load_public_identity_files(void)
- 		xfree(keys);
- 	}
- #endif /* SMARTCARD */
-+#ifdef HAVE_LIBNSS
-+	if (options.use_nss &&
-+	    options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
-+	    (keys = nss_get_keys(options.nss_token, NULL, NULL)) != NULL) {
-+		int count;
-+		for (count = 0; keys[count] != NULL; count++) {
-+			memmove(&options.identity_files[1], &options.identity_files[0],
-+			    sizeof(char *) * (SSH_MAX_IDENTITY_FILES - 1));
-+			memmove(&options.identity_keys[1], &options.identity_keys[0],
-+			    sizeof(Key *) * (SSH_MAX_IDENTITY_FILES - 1));
-+			options.num_identity_files++;
-+			options.identity_keys[0] = keys[count];
-+			options.identity_files[0] = nss_get_key_label(keys[count]);
-+		}
-+		if (options.num_identity_files > SSH_MAX_IDENTITY_FILES)
-+			options.num_identity_files = SSH_MAX_IDENTITY_FILES;
-+		i += count;
-+		xfree(keys);
-+	}
-+#endif /* HAVE_LIBNSS */
-+
- 	if ((pw = getpwuid(original_real_uid)) == NULL)
- 		fatal("load_public_identity_files: getpwuid failed");
- 	pwname = xstrdup(pw->pw_name);
-diff -up /dev/null openssh-5.2p1/nsskeys.h
---- /dev/null	2008-11-17 17:51:52.160001870 +0100
-+++ openssh-5.2p1/nsskeys.h	2008-11-18 19:11:41.000000000 +0100
+diff -up /dev/null openssh-5.3p1/nsskeys.h
+--- /dev/null	2009-09-11 09:35:58.778798825 +0200
++++ openssh-5.3p1/nsskeys.h	2009-10-02 14:09:01.000000000 +0200
 @@ -0,0 +1,39 @@
 +/*
 + * Copyright (c) 2001 Markus Friedl.  All rights reserved.
@@ -862,78 +615,84 @@ diff -up /dev/null openssh-5.2p1/nsskeys
 +int	nss_init(PK11PasswordFunc);
 +Key	**nss_get_keys(const char *, const char *, char *);
 +char	*nss_get_key_label(Key *);
-+/*void	 sc_close(void);*/
-+/*int	 sc_put_key(Key *, const char *);*/
-+
-+#endif
-+#endif
-diff -up openssh-5.2p1/Makefile.in.nss-keys openssh-5.2p1/Makefile.in
---- openssh-5.2p1/Makefile.in.nss-keys	2008-07-08 16:21:12.000000000 +0200
-+++ openssh-5.2p1/Makefile.in	2008-11-18 19:11:41.000000000 +0100
-@@ -71,7 +71,7 @@ LIBSSH_OBJS=acss.o authfd.o authfile.o b
- 	atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \
- 	monitor_fdpass.o rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o \
- 	kexgex.o kexdhc.o kexgexc.o scard.o msg.o progressmeter.o dns.o \
--	entropy.o scard-opensc.o gss-genr.o umac.o jpake.o schnorr.o
-+	entropy.o scard-opensc.o gss-genr.o umac.o jpake.o schnorr.o nsskeys.o
- 
- SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
- 	sshconnect.o sshconnect1.o sshconnect2.o mux.o
-diff -up openssh-5.2p1/key.h.nss-keys openssh-5.2p1/key.h
---- openssh-5.2p1/key.h.nss-keys	2008-06-12 20:40:35.000000000 +0200
-+++ openssh-5.2p1/key.h	2008-11-18 19:11:41.000000000 +0100
-@@ -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 {
-@@ -48,16 +54,30 @@ enum fp_rep {
- 
- /* key is stored in external hardware */
- #define KEY_FLAG_EXT		0x0001
-+#define KEY_FLAG_NSS		0x0002
-+
-+#ifdef HAVE_LIBNSS
-+typedef struct NSSKey NSSKey;
-+struct NSSKey {
-+	SECKEYPrivateKey *privk;
-+	SECKEYPublicKey *pubk;
-+};
++/*void	 sc_close(void);*/
++/*int	 sc_put_key(Key *, const char *);*/
++
 +#endif
- 
- struct Key {
- 	int	 type;
- 	int	 flags;
- 	RSA	*rsa;
- 	DSA	*dsa;
++#endif
+diff -up openssh-5.3p1/readconf.c.nss-keys openssh-5.3p1/readconf.c
+--- openssh-5.3p1/readconf.c.nss-keys	2009-07-05 23:12:27.000000000 +0200
++++ openssh-5.3p1/readconf.c	2009-10-02 14:09:01.000000000 +0200
+@@ -124,6 +124,7 @@ typedef enum {
+ 	oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
+ 	oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
+ 	oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
++	oUseNSS, oNSSToken,
+ 	oClearAllForwardings, oNoHostAuthenticationForLocalhost,
+ 	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
+ 	oAddressFamily, oGssAuthentication, oGssDelegateCreds,
+@@ -210,6 +211,13 @@ static struct {
+ #else
+ 	{ "smartcarddevice", oUnsupported },
+ #endif
 +#ifdef HAVE_LIBNSS
-+	NSSKey  *nss;
++	{ "usenss", oUseNSS },
++	{ "nsstoken", oNSSToken },
++#else
++	{ "usenss", oUnsupported },
++	{ "nsstoken", oNSSToken },
 +#endif
- };
+ 	{ "clearallforwardings", oClearAllForwardings },
+ 	{ "enablesshkeysign", oEnableSSHKeysign },
+ 	{ "verifyhostkeydns", oVerifyHostKeyDNS },
+@@ -613,6 +621,14 @@ parse_string:
+ 		charptr = &options->smartcard_device;
+ 		goto parse_string;
  
- Key		*key_new(int);
- Key		*key_new_private(int);
-+Key 		*key_new_nss(int);
-+Key		*key_new_nss_copy(int, const Key *);
- void		 key_free(Key *);
- Key		*key_demote(const Key *);
- int		 key_equal(const Key *, const Key *);
-diff -up openssh-5.2p1/ssh-add.c.nss-keys openssh-5.2p1/ssh-add.c
---- openssh-5.2p1/ssh-add.c.nss-keys	2008-02-28 09:13:52.000000000 +0100
-+++ openssh-5.2p1/ssh-add.c	2008-11-18 19:11:41.000000000 +0100
++	case oUseNSS:
++		intptr = &options->use_nss;
++		goto parse_flag;
++
++	case oNSSToken:
++		charptr = &options->nss_token;
++		goto parse_command;
++
+ 	case oProxyCommand:
+ 		charptr = &options->proxy_command;
+ parse_command:
+@@ -1052,6 +1068,8 @@ initialize_options(Options * options)
+ 	options->preferred_authentications = NULL;
+ 	options->bind_address = NULL;
+ 	options->smartcard_device = NULL;
++	options->use_nss = -1;
++	options->nss_token = NULL;
+ 	options->enable_ssh_keysign = - 1;
+ 	options->no_host_authentication_for_localhost = - 1;
+ 	options->identities_only = - 1;
+@@ -1183,6 +1201,8 @@ fill_default_options(Options * options)
+ 		options->no_host_authentication_for_localhost = 0;
+ 	if (options->identities_only == -1)
+ 		options->identities_only = 0;
++	if (options->use_nss == -1)
++		options->use_nss = 0;
+ 	if (options->enable_ssh_keysign == -1)
+ 		options->enable_ssh_keysign = 0;
+ 	if (options->rekey_limit == -1)
+diff -up openssh-5.3p1/readconf.h.nss-keys openssh-5.3p1/readconf.h
+--- openssh-5.3p1/readconf.h.nss-keys	2009-07-05 23:12:27.000000000 +0200
++++ openssh-5.3p1/readconf.h	2009-10-02 14:09:01.000000000 +0200
+@@ -85,6 +85,8 @@ typedef struct {
+ 	char   *preferred_authentications;
+ 	char   *bind_address;	/* local socket address for connection to sshd */
+ 	char   *smartcard_device; /* Smartcard reader device */
++	int     use_nss;        /* Use NSS library for keys */
++	char   *nss_token;      /* Look for NSS keys on token */
+ 	int	verify_host_key_dns;	/* Verify host key using DNS */
+ 
+ 	int     num_identity_files;	/* Number of files for RSA/DSA identities. */
+diff -up openssh-5.3p1/ssh-add.c.nss-keys openssh-5.3p1/ssh-add.c
+--- openssh-5.3p1/ssh-add.c.nss-keys	2008-02-28 09:13:52.000000000 +0100
++++ openssh-5.3p1/ssh-add.c	2009-10-02 14:09:01.000000000 +0200
 @@ -44,6 +44,14 @@
  #include <openssl/evp.h>
  #include "openbsd-compat/openssl-compat.h"
@@ -957,7 +716,7 @@ diff -up openssh-5.2p1/ssh-add.c.nss-key
  #include "buffer.h"
  #include "authfd.h"
  #include "authfile.h"
-@@ -307,6 +316,117 @@ do_file(AuthenticationConnection *ac, in
+@@ -307,6 +316,128 @@ do_file(AuthenticationConnection *ac, in
  	return 0;
  }
  
@@ -1004,8 +763,10 @@ diff -up openssh-5.2p1/ssh-add.c.nss-key
 +	SECKEYPrivateKeyListNode *node;
 +	char *passcache = NULL;
 +	char *tokenname;
++	char **xkeyname = NULL;
 +	
 +	int count = 0;
++	int i;
 +	
 +	if (PK11_NeedLogin(slot))
 +		PK11_Authenticate(slot, PR_TRUE, &passcache);
@@ -1046,21 +807,30 @@ diff -up openssh-5.2p1/ssh-add.c.nss-key
 +			continue; /* not possible to obtain public key */
 +		}
 +		SECKEY_DestroyPublicKey(pub);
++	
++		if ((count % 10) == 0)	
++			xkeyname = xrealloc (xkeyname, count + 10, sizeof (char *));
 +		
-+		if (ssh_update_nss_key(ac, add, tokenname, keyname,
++		xkeyname[count++] = keyname;
++	}
++
++	PK11_Logout(slot);
++
++	for (i = 0; i < count; i++) {
++		if (ssh_update_nss_key(ac, add, tokenname, xkeyname[i],
 +			passcache?passcache:"",	lifetime, confirm)) {
 +			fprintf(stderr, "Key %s: %s:%s\n",
-+				add?"added":"removed", tokenname, keyname);
-+			count++;
++				add?"added":"removed", tokenname, xkeyname[i]);
 +		} else {
 +			fprintf(stderr, "Could not %s key: %s:%s\n",
-+				add?"add":"remove", tokenname, keyname);
++				add?"add":"remove", tokenname, xkeyname[i]);
 +		}
-+		
-+		PORT_Free(keyname);
-+		count++;
++		PORT_Free(xkeyname[i]);
 +	}
 +
++	if (xkeyname != NULL)
++		free (xkeyname);
++
 +	if (passcache != NULL) {
 +		memset(passcache, 0, strlen(passcache));
 +		xfree(passcache);
@@ -1075,7 +845,7 @@ diff -up openssh-5.2p1/ssh-add.c.nss-key
  static void
  usage(void)
  {
-@@ -334,6 +454,10 @@ main(int argc, char **argv)
+@@ -334,6 +465,10 @@ main(int argc, char **argv)
  	AuthenticationConnection *ac = NULL;
  	char *sc_reader_id = NULL;
  	int i, ch, deleting = 0, ret = 0;
@@ -1086,7 +856,7 @@ diff -up openssh-5.2p1/ssh-add.c.nss-key
  
  	/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
  	sanitise_stdfd();
-@@ -351,7 +475,7 @@ main(int argc, char **argv)
+@@ -351,7 +486,7 @@ main(int argc, char **argv)
  		    "Could not open a connection to your authentication agent.\n");
  		exit(2);
  	}
@@ -1095,7 +865,7 @@ diff -up openssh-5.2p1/ssh-add.c.nss-key
  		switch (ch) {
  		case 'l':
  		case 'L':
-@@ -373,6 +497,11 @@ main(int argc, char **argv)
+@@ -373,6 +508,11 @@ main(int argc, char **argv)
  			if (delete_all(ac) == -1)
  				ret = 1;
  			goto done;
@@ -1107,7 +877,7 @@ diff -up openssh-5.2p1/ssh-add.c.nss-key
  		case 's':
  			sc_reader_id = optarg;
  			break;
-@@ -387,6 +516,11 @@ main(int argc, char **argv)
+@@ -387,6 +527,11 @@ main(int argc, char **argv)
  				goto done;
  			}
  			break;
@@ -1119,7 +889,7 @@ diff -up openssh-5.2p1/ssh-add.c.nss-key
  		default:
  			usage();
  			ret = 1;
-@@ -400,6 +534,40 @@ main(int argc, char **argv)
+@@ -400,6 +545,40 @@ main(int argc, char **argv)
  			ret = 1;
  		goto done;
  	}
@@ -1151,91 +921,277 @@ diff -up openssh-5.2p1/ssh-add.c.nss-key
 +		if (count == 0) {
 +			ret = 1;
 +		}
-+nss_done:		
-+		NSS_Shutdown();
-+		clear_pass();
-+		goto done;
++nss_done:		
++		NSS_Shutdown();
++		clear_pass();
++		goto done;
++	}
++#endif
+ 	if (argc == 0) {
+ 		char buf[MAXPATHLEN];
+ 		struct passwd *pw;
+diff -up openssh-5.3p1/ssh-agent.c.nss-keys openssh-5.3p1/ssh-agent.c
+--- openssh-5.3p1/ssh-agent.c.nss-keys	2009-06-21 09:50:15.000000000 +0200
++++ openssh-5.3p1/ssh-agent.c	2009-10-02 14:09:01.000000000 +0200
+@@ -80,6 +80,10 @@
+ #include "scard.h"
+ #endif
+ 
++#ifdef HAVE_LIBNSS
++#include "nsskeys.h"
++#endif
++
+ #if defined(HAVE_SYS_PRCTL_H)
+ #include <sys/prctl.h>	/* For prctl() and PR_SET_DUMPABLE */
+ #endif
+@@ -714,6 +718,114 @@ send:
+ }
+ #endif /* SMARTCARD */
+ 
++#ifdef HAVE_LIBNSS
++static void
++process_add_nss_key (SocketEntry *e)
++{
++	char *tokenname = NULL, *keyname = NULL, *password = NULL;
++	int i, version, success = 0, death = 0, confirm = 0;
++	Key **keys, *k;
++	Identity *id;
++	Idtab *tab;
++
++	tokenname = buffer_get_string(&e->request, NULL);
++	keyname = buffer_get_string(&e->request, NULL);
++	password = buffer_get_string(&e->request, NULL);
++
++	while (buffer_len(&e->request)) {
++		switch (buffer_get_char(&e->request)) {
++		case SSH_AGENT_CONSTRAIN_LIFETIME:
++			death = time(NULL) + buffer_get_int(&e->request);
++			break;
++		case SSH_AGENT_CONSTRAIN_CONFIRM:
++			confirm = 1;
++			break;
++		default:
++			break;
++		}
++	}
++	if (lifetime && !death)
++		death = time(NULL) + lifetime;
++
++	keys = nss_get_keys(tokenname, keyname, password);
++	/* password is owned by keys[0] now */
++	xfree(tokenname);
++	xfree(keyname);
++
++	if (keys == NULL) {
++		memset(password, 0, strlen(password));
++		xfree(password);
++		error("nss_get_keys failed");
++		goto send;
++	}
++	for (i = 0; keys[i] != NULL; i++) {
++		k = keys[i];
++		version = k->type == KEY_RSA1 ? 1 : 2;
++		tab = idtab_lookup(version);
++		if (lookup_identity(k, version) == NULL) {
++			id = xmalloc(sizeof(Identity));
++			id->key = k;
++			id->comment = nss_get_key_label(k);
++			id->death = death;
++			id->confirm = confirm;
++			TAILQ_INSERT_TAIL(&tab->idlist, id, next);
++			tab->nentries++;
++			success = 1;
++		} else {
++			key_free(k);
++		}
++		keys[i] = NULL;
++	}
++	xfree(keys);
++send:
++	buffer_put_int(&e->output, 1);
++	buffer_put_char(&e->output,
++	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
++}
++
++static void
++process_remove_nss_key(SocketEntry *e)
++{
++	char *tokenname = NULL, *keyname = NULL, *password = NULL;
++	int i, version, success = 0;
++	Key **keys, *k = NULL;
++	Identity *id;
++	Idtab *tab;
++
++	tokenname = buffer_get_string(&e->request, NULL);
++	keyname = buffer_get_string(&e->request, NULL);
++	password = buffer_get_string(&e->request, NULL);
++
++	keys = nss_get_keys(tokenname, keyname, password);
++	xfree(tokenname);
++	xfree(keyname);
++	xfree(password);
++
++	if (keys == NULL || keys[0] == NULL) {
++		error("nss_get_keys failed");
++		goto send;
++	}
++	for (i = 0; keys[i] != NULL; i++) {
++		k = keys[i];
++		version = k->type == KEY_RSA1 ? 1 : 2;
++		if ((id = lookup_identity(k, version)) != NULL) {
++			tab = idtab_lookup(version);
++			TAILQ_REMOVE(&tab->idlist, id, next);
++			tab->nentries--;
++			free_identity(id);
++			success = 1;
++		}
++		key_free(k);
++		keys[i] = NULL;
++	}
++	xfree(keys);
++send:
++	buffer_put_int(&e->output, 1);
++	buffer_put_char(&e->output,
++	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
++}
++#endif /* HAVE_LIBNSS */
++
+ /* dispatch incoming messages */
+ 
+ static void
+@@ -806,6 +918,15 @@ process_message(SocketEntry *e)
+ 		process_remove_smartcard_key(e);
+ 		break;
+ #endif /* SMARTCARD */
++#ifdef HAVE_LIBNSS
++	case SSH_AGENTC_ADD_NSS_KEY:
++	case SSH_AGENTC_ADD_NSS_KEY_CONSTRAINED:
++		process_add_nss_key(e);
++		break;
++	case SSH_AGENTC_REMOVE_NSS_KEY:
++		process_remove_nss_key(e);
++		break;
++#endif /* SMARTCARD */
+ 	default:
+ 		/* Unknown message.  Respond with failure. */
+ 		error("Unknown message %d", type);
+diff -up openssh-5.3p1/ssh.c.nss-keys openssh-5.3p1/ssh.c
+--- openssh-5.3p1/ssh.c.nss-keys	2009-07-05 23:16:56.000000000 +0200
++++ openssh-5.3p1/ssh.c	2009-10-02 14:09:01.000000000 +0200
+@@ -105,6 +105,9 @@
+ #ifdef SMARTCARD
+ #include "scard.h"
+ #endif
++#ifdef HAVE_LIBNSS
++#include "nsskeys.h"
++#endif
+ 
+ extern char *__progname;
+ 
+@@ -1234,9 +1237,11 @@ load_public_identity_files(void)
+ 	int i = 0;
+ 	Key *public;
+ 	struct passwd *pw;
+-#ifdef SMARTCARD
++#if defined(SMARTCARD) || defined(HAVE_LIBNSS)
+ 	Key **keys;
++#endif
+ 
++#ifdef SMARTCARD
+ 	if (options.smartcard_device != NULL &&
+ 	    options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
+ 	    (keys = sc_get_keys(options.smartcard_device, NULL)) != NULL) {
+@@ -1259,6 +1264,27 @@ load_public_identity_files(void)
+ 		xfree(keys);
+ 	}
+ #endif /* SMARTCARD */
++#ifdef HAVE_LIBNSS
++	if (options.use_nss &&
++	    options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
++	    (keys = nss_get_keys(options.nss_token, NULL, NULL)) != NULL) {
++		int count;
++		for (count = 0; keys[count] != NULL; count++) {
++			memmove(&options.identity_files[1], &options.identity_files[0],
++			    sizeof(char *) * (SSH_MAX_IDENTITY_FILES - 1));
++			memmove(&options.identity_keys[1], &options.identity_keys[0],
++			    sizeof(Key *) * (SSH_MAX_IDENTITY_FILES - 1));
++			options.num_identity_files++;
++			options.identity_keys[0] = keys[count];
++			options.identity_files[0] = nss_get_key_label(keys[count]);
++		}
++		if (options.num_identity_files > SSH_MAX_IDENTITY_FILES)
++			options.num_identity_files = SSH_MAX_IDENTITY_FILES;
++		i += count;
++		xfree(keys);
 +	}
-+#endif
- 	if (argc == 0) {
- 		char buf[MAXPATHLEN];
- 		struct passwd *pw;
-diff -up openssh-5.2p1/ssh-rsa.c.nss-keys openssh-5.2p1/ssh-rsa.c
---- openssh-5.2p1/ssh-rsa.c.nss-keys	2006-09-01 07:38:37.000000000 +0200
-+++ openssh-5.2p1/ssh-rsa.c	2008-11-18 19:11:41.000000000 +0100
-@@ -32,6 +32,10 @@
- #include "compat.h"
- #include "ssh.h"
++#endif /* HAVE_LIBNSS */
++
+ 	if ((pw = getpwuid(original_real_uid)) == NULL)
+ 		fatal("load_public_identity_files: getpwuid failed");
+ 	pwname = xstrdup(pw->pw_name);
+diff -up openssh-5.3p1/ssh-dss.c.nss-keys openssh-5.3p1/ssh-dss.c
+--- openssh-5.3p1/ssh-dss.c.nss-keys	2006-11-07 13:14:42.000000000 +0100
++++ openssh-5.3p1/ssh-dss.c	2009-10-02 14:09:01.000000000 +0200
+@@ -39,6 +39,10 @@
+ #include "log.h"
+ #include "key.h"
  
 +#ifdef HAVE_LIBNSS
 +#include <cryptohi.h>
 +#endif
 +
- static int openssh_RSA_verify(int, u_char *, u_int, u_char *, u_int, RSA *);
+ #define INTBLOB_LEN	20
+ #define SIGBLOB_LEN	(2*INTBLOB_LEN)
  
- /* 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");
+@@ -57,6 +61,34 @@ ssh_dss_sign(const Key *key, u_char **si
+ 		error("ssh_dss_sign: no DSA key");
  		return -1;
  	}
-+
-+	slen = RSA_size(key->rsa);
-+	sig = xmalloc(slen);
-+
 +#ifdef HAVE_LIBNSS
 +	if (key->flags & KEY_FLAG_NSS) {
 +		SECItem sigitem;
-+		SECOidTag alg;
++		SECItem *rawsig;
 +
 +		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");
++			SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) != SECSuccess) {
++			error("ssh_dss_sign: sign failed");
 +			return -1;
 +		}
-+		if (sigitem.len > slen) {
-+			error("ssh_rsa_sign: slen %u slen2 %u", slen, sigitem.len);
-+			xfree(sig);
++		
++		if ((rawsig=DSAU_DecodeDerSig(&sigitem)) == NULL) {
++			error("ssh_dss_sign: der decode failed");
 +			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);
++		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
- 	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_DigestInit(&md, evp_md);
  	EVP_DigestUpdate(&md, data, datalen);
  	EVP_DigestFinal(&md, digest, &dlen);
- 
--	slen = RSA_size(key->rsa);
--	sig = xmalloc(slen);
+@@ -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);
 -
- 	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-5.2p1/ssh-keygen.c.nss-keys openssh-5.2p1/ssh-keygen.c
---- openssh-5.2p1/ssh-keygen.c.nss-keys	2008-07-14 03:28:29.000000000 +0200
-+++ openssh-5.2p1/ssh-keygen.c	2008-11-18 19:11:41.000000000 +0100
+ 	if (datafellows & SSH_BUG_SIGBLOB) {
+ 		if (lenp != NULL)
+ 			*lenp = SIGBLOB_LEN;
+diff -up openssh-5.3p1/ssh-keygen.c.nss-keys openssh-5.3p1/ssh-keygen.c
+--- openssh-5.3p1/ssh-keygen.c.nss-keys	2009-06-22 08:11:07.000000000 +0200
++++ openssh-5.3p1/ssh-keygen.c	2009-10-02 14:09:01.000000000 +0200
 @@ -53,6 +53,11 @@
  #include "scard.h"
  #endif
@@ -1337,61 +1293,116 @@ diff -up openssh-5.2p1/ssh-keygen.c.nss-
  	if (reader_id != NULL) {
  #ifdef SMARTCARD
  		if (download)
-diff -up openssh-5.2p1/readconf.c.nss-keys openssh-5.2p1/readconf.c
---- openssh-5.2p1/readconf.c.nss-keys	2008-06-29 16:04:03.000000000 +0200
-+++ openssh-5.2p1/readconf.c	2008-11-18 19:11:41.000000000 +0100
-@@ -124,6 +124,7 @@ typedef enum {
- 	oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
- 	oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
- 	oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
-+	oUseNSS, oNSSToken,
- 	oClearAllForwardings, oNoHostAuthenticationForLocalhost,
- 	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
- 	oAddressFamily, oGssAuthentication, oGssDelegateCreds,
-@@ -210,6 +211,13 @@ static struct {
- #else
- 	{ "smartcarddevice", oUnsupported },
- #endif
+diff -up openssh-5.3p1/ssh-rsa.c.nss-keys openssh-5.3p1/ssh-rsa.c
+--- openssh-5.3p1/ssh-rsa.c.nss-keys	2006-09-01 07:38:37.000000000 +0200
++++ openssh-5.3p1/ssh-rsa.c	2009-10-02 14:09:01.000000000 +0200
+@@ -32,6 +32,10 @@
+ #include "compat.h"
+ #include "ssh.h"
+ 
 +#ifdef HAVE_LIBNSS
-+	{ "usenss", oUseNSS },
-+	{ "nsstoken", oNSSToken },
-+#else
-+	{ "usenss", oUnsupported },
-+	{ "nsstoken", oNSSToken },
++#include <cryptohi.h>
 +#endif
- 	{ "clearallforwardings", oClearAllForwardings },
- 	{ "enablesshkeysign", oEnableSSHKeysign },
- 	{ "verifyhostkeydns", oVerifyHostKeyDNS },
-@@ -603,6 +611,14 @@ parse_string:
- 		charptr = &options->smartcard_device;
- 		goto parse_string;
++
+ static int openssh_RSA_verify(int, u_char *, u_int, u_char *, u_int, RSA *);
  
-+	case oUseNSS:
-+		intptr = &options->use_nss;
-+		goto parse_flag;
+ /* 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;
+ 	}
 +
-+	case oNSSToken:
-+		charptr = &options->nss_token;
-+		goto parse_command;
++	slen = RSA_size(key->rsa);
++	sig = xmalloc(slen);
 +
- 	case oProxyCommand:
- 		charptr = &options->proxy_command;
- parse_command:
-@@ -1055,6 +1071,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;
-@@ -1184,6 +1202,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)
++#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 /dev/null openssh-5.2p1/README.nss
+--- /dev/null	2008-11-17 17:51:52.160001870 +0100
++++ openssh-5.2p1/README.nss	2008-11-18 19:11:41.000000000 +0100
+@@ -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'


Index: openssh.spec
===================================================================
RCS file: /cvs/pkgs/rpms/openssh/F-12/openssh.spec,v
retrieving revision 1.169
retrieving revision 1.170
diff -u -p -r1.169 -r1.170
--- openssh.spec	24 Sep 2009 16:05:26 -0000	1.169
+++ openssh.spec	27 Oct 2009 15:59:35 -0000	1.170
@@ -63,7 +63,7 @@
 Summary: An open source implementation of SSH protocol versions 1 and 2
 Name: openssh
 Version: 5.2p1
-Release: 28%{?dist}%{?rescue_rel}
+Release: 29%{?dist}%{?rescue_rel}
 URL: http://www.openssh.com/portable.html
 #Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz
 #Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc
@@ -466,6 +466,9 @@ fi
 %endif
 
 %changelog
+* Tue Oct 27 2009 Jan F. Chadima <jchadima at redhat.com> - 5.2p1-29
+- Resolve locking in ssh-add (#491312)
+
 * Thu Sep 24 2009 Jan F. Chadima <jchadima at redhat.com> - 5.2p1-28
 - Repair initscript to be acord to guidelines (#521860)
 - Add bugzilla# to application of edns and xmodifiers patch




More information about the fedora-extras-commits mailing list