vishalmishra434 / rpms / openssh

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