Bugzilla – Attachment 1734 Details for
Bug 1676
Add NSS keys support
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
patch adding the functionality
openssh-5.3p1-nss-keys.patch (text/plain), 40.75 KB, created by
jchadima
on 2009-11-28 00:55:31 AEDT
(
hide
)
Description:
patch adding the functionality
Filename:
MIME Type:
Creator:
jchadima
Created:
2009-11-28 00:55:31 AEDT
Size:
40.75 KB
patch
obsolete
>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-11-27 13:43:00.000000000 +0100 >@@ -626,6 +626,45 @@ ssh_update_card(AuthenticationConnection > return decode_reply(type); > } > >+int >+ssh_update_nss_key(AuthenticationConnection *auth, int add, >+ const char *tokenname, const char *keyname, >+ const char *pass, u_int life, u_int confirm) >+{ >+ Buffer msg; >+ int type, constrained = (life || confirm); >+ >+ if (add) { >+ type = constrained ? >+ SSH_AGENTC_ADD_NSS_KEY_CONSTRAINED : >+ SSH_AGENTC_ADD_NSS_KEY; >+ } else >+ type = SSH_AGENTC_REMOVE_NSS_KEY; >+ >+ buffer_init(&msg); >+ buffer_put_char(&msg, type); >+ buffer_put_cstring(&msg, tokenname); >+ buffer_put_cstring(&msg, keyname); >+ buffer_put_cstring(&msg, pass); >+ >+ if (constrained) { >+ if (life != 0) { >+ buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_LIFETIME); >+ buffer_put_int(&msg, life); >+ } >+ if (confirm != 0) >+ buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_CONFIRM); >+ } >+ >+ if (ssh_request_reply(auth, &msg, &msg) == 0) { >+ buffer_free(&msg); >+ return 0; >+ } >+ type = buffer_get_char(&msg); >+ buffer_free(&msg); >+ return decode_reply(type); >+} >+ > /* > * Removes all identities from the agent. This call is not meant to be used > * by normal applications. >diff -up openssh-5.3p1/authfd.h.nss-keys openssh-5.3p1/authfd.h >--- openssh-5.3p1/authfd.h.nss-keys 2006-08-05 04:39:39.000000000 +0200 >+++ openssh-5.3p1/authfd.h 2009-11-27 13:43:01.000000000 +0100 >@@ -49,6 +49,12 @@ > #define SSH2_AGENTC_ADD_ID_CONSTRAINED 25 > #define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26 > >+/* nss */ >+#define SSH_AGENTC_ADD_NSS_KEY 30 >+#define SSH_AGENTC_REMOVE_NSS_KEY 31 >+#define SSH_AGENTC_ADD_NSS_KEY_CONSTRAINED 32 >+ >+ > #define SSH_AGENT_CONSTRAIN_LIFETIME 1 > #define SSH_AGENT_CONSTRAIN_CONFIRM 2 > >@@ -83,6 +89,8 @@ int ssh_remove_all_identities(Authentic > int ssh_lock_agent(AuthenticationConnection *, int, const char *); > int ssh_update_card(AuthenticationConnection *, int, const char *, > const char *, u_int, u_int); >+int ssh_update_nss_key(AuthenticationConnection *, int, const char *, >+ const char *, const char *, u_int, u_int); > > int > ssh_decrypt_challenge(AuthenticationConnection *, Key *, BIGNUM *, u_char[16], >diff -up openssh-5.3p1/configure.ac.nss-keys openssh-5.3p1/configure.ac >--- openssh-5.3p1/configure.ac.nss-keys 2009-11-27 13:42:57.000000000 +0100 >+++ openssh-5.3p1/configure.ac 2009-11-27 13:48:44.000000000 +0100 >@@ -3526,6 +3526,21 @@ AC_ARG_WITH(kerberos5, > ] > ) > >+# Check whether user wants NSS support >+LIBNSS_MSG="no" >+AC_ARG_WITH(nss, >+ [ --with-nss Enable NSS support], >+ [ if test "x$withval" != "xno" ; then >+ AC_DEFINE(HAVE_LIBNSS,1,[Define if you want NSS support.]) >+ LIBNSS_MSG="yes" >+ CPPFLAGS="$CPPFLAGS -I/usr/include/nss3 -I/usr/include/nspr4" >+ AC_CHECK_HEADERS(pk11pub.h) >+ LIBS="$LIBS -lnss3" >+ AC_CHECK_DECLS([SEC_ERROR_LOCKED_PASSWORD], [], [], [#include <secerr.h>]) >+ fi >+ ]) >+AC_SUBST(LIBNSS) >+ > # Looking for programs, paths and files > > PRIVSEP_PATH=/var/empty >@@ -4253,6 +4269,7 @@ echo " TCP Wrappers support > echo " MD5 password support: $MD5_MSG" > echo " libedit support: $LIBEDIT_MSG" > echo " Solaris process contract support: $SPC_MSG" >+echo " NSS support: $LIBNSS_MSG" > echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG" > echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG" > echo " BSD Auth support: $BSD_AUTH_MSG" >diff -up openssh-5.3p1/key.c.nss-keys openssh-5.3p1/key.c >--- openssh-5.3p1/key.c.nss-keys 2008-11-03 09:24:17.000000000 +0100 >+++ openssh-5.3p1/key.c 2009-11-27 13:43:01.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.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-11-27 13:43:01.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; >+}; >+#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-11-27 13:43:01.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 /dev/null openssh-5.3p1/nsskeys.c >--- /dev/null 2009-11-27 11:08:21.619709673 +0100 >+++ openssh-5.3p1/nsskeys.c 2009-11-27 13:45:42.000000000 +0100 >@@ -0,0 +1,443 @@ >+/* >+ * Copyright (c) 2001 Markus Friedl. All rights reserved. >+ * Copyright (c) 2007 Red Hat, Inc. All rights reserved. >+ * Copyright (c) 2009 Pierre Ossman for Cendio AB >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR >+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES >+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. >+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, >+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT >+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, >+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY >+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF >+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include "includes.h" >+#ifdef HAVE_LIBNSS >+ >+#include <sys/types.h> >+ >+#include <stdarg.h> >+#include <string.h> >+#include <unistd.h> >+ >+#include <openssl/evp.h> >+ >+#include <nss.h> >+#include <keyhi.h> >+#include <pk11pub.h> >+#include <cert.h> >+#include <secmod.h> >+#include <secerr.h> >+ >+#include "xmalloc.h" >+#include "key.h" >+#include "log.h" >+#include "misc.h" >+#include "nsskeys.h" >+#include "pathnames.h" >+ >+static char * >+password_cb(PK11SlotInfo *slot, PRBool retry, void *arg) >+{ >+ char *password = arg; >+ if (retry || password == NULL) >+ return NULL; >+ >+ return PL_strdup(password); >+} >+ >+int >+nss_init(PK11PasswordFunc pwfn) >+{ >+ char *dbpath; >+ char buf[MAXPATHLEN]; >+ >+ if (NSS_IsInitialized()) >+ return 0; >+ >+ if ((dbpath=getenv("NSS_DB_PATH")) == NULL) { >+ struct passwd *pw; >+ if ((pw = getpwuid(getuid())) == NULL || >+ pw->pw_dir == NULL) { >+ return -1; >+ } >+ snprintf(buf, sizeof(buf), "%s/%s", pw->pw_dir, >+ _PATH_SSH_USER_DIR); >+ dbpath = buf; >+ } >+ >+ if (NSS_Init(dbpath) != SECSuccess) { >+ debug("Failed to initialize NSS library. Attempting without DB..."); >+ if (NSS_NoDB_Init(NULL) != SECSuccess) >+ return -1; >+ } >+ >+ if (pwfn == NULL) { >+ pwfn = password_cb; >+ } >+ >+ PK11_SetPasswordFunc(pwfn); >+ >+ return 0; >+} >+ >+int >+nss_load_module(const char *modpath) >+{ >+ char spec[MAXPATHLEN + 40]; >+ SECMODModule *module; >+ >+ debug("loading PKCS#11 module '%s'", modpath); >+ >+ snprintf(spec, sizeof(spec), "library=\"%s\" name=\"Foobar\"", modpath); >+ module = SECMOD_LoadUserModule(spec, NULL, PR_FALSE); >+ if (!module || !module->loaded) { >+ if (module) >+ SECMOD_DestroyModule(module); >+ return -1; >+ } >+ >+ return 0; >+} >+ >+static Key * >+make_key_from_privkey(SECKEYPrivateKey *privk, char *password) >+{ >+ Key *k; >+ switch (SECKEY_GetPrivateKeyType(privk)) { >+ case rsaKey: >+ k = key_new_nss(KEY_RSA); >+ break; >+ case dsaKey: >+ k = key_new_nss(KEY_DSA); >+ break; >+ default: >+ return NULL; >+ } >+ k->nss->pubk = SECKEY_ConvertToPublicKey(privk); >+ if (k->nss->pubk != NULL) { >+ k->nss->privk = SECKEY_CopyPrivateKey(privk); >+ } >+ if (k->nss->privk != NULL) { >+ if (password != NULL) { >+ k->nss->privk->wincx = xstrdup(password); >+ } >+ return k; >+ } >+ key_free(k); >+ return NULL; >+} >+ >+static Key ** >+add_key_to_list(Key *k, Key **keys, size_t *i, size_t *allocated) >+{ >+ if (*allocated < *i + 2) { >+ *allocated += 16; >+ keys = xrealloc(keys, *allocated, sizeof(k)); >+ } >+ keys[*i] = k; >+ (*i)++; >+ keys[*i] = NULL; >+ return keys; >+} >+ >+static int >+nss_convert_pubkey(Key *k) >+{ >+ u_char *n; >+ unsigned int len; >+ char *p; >+ >+ switch (k->type) { >+ case KEY_RSA: >+ n = k->nss->pubk->u.rsa.modulus.data; >+ len = k->nss->pubk->u.rsa.modulus.len; >+ >+ if (BN_bin2bn(n, len, k->rsa->n) == NULL) { >+ fatal("nss_convert_pubkey: BN_bin2bn failed"); >+ } >+ >+ n = k->nss->pubk->u.rsa.publicExponent.data; >+ len = k->nss->pubk->u.rsa.publicExponent.len; >+ >+ if (BN_bin2bn(n, len, k->rsa->e) == NULL) { >+ fatal("nss_convert_pubkey: BN_bin2bn failed"); >+ } >+ break; >+ case KEY_DSA: >+ n = k->nss->pubk->u.dsa.params.prime.data; >+ len = k->nss->pubk->u.dsa.params.prime.len; >+ >+ if (BN_bin2bn(n, len, k->dsa->p) == NULL) { >+ fatal("nss_convert_pubkey: BN_bin2bn failed"); >+ } >+ >+ n = k->nss->pubk->u.dsa.params.subPrime.data; >+ len = k->nss->pubk->u.dsa.params.subPrime.len; >+ >+ if (BN_bin2bn(n, len, k->dsa->q) == NULL) { >+ fatal("nss_convert_pubkey: BN_bin2bn failed"); >+ } >+ >+ n = k->nss->pubk->u.dsa.params.base.data; >+ len = k->nss->pubk->u.dsa.params.base.len; >+ >+ if (BN_bin2bn(n, len, k->dsa->g) == NULL) { >+ fatal("nss_convert_pubkey: BN_bin2bn failed"); >+ } >+ >+ n = k->nss->pubk->u.dsa.publicValue.data; >+ len = k->nss->pubk->u.dsa.publicValue.len; >+ >+ if (BN_bin2bn(n, len, k->dsa->pub_key) == NULL) { >+ fatal("nss_convert_pubkey: BN_bin2bn failed"); >+ } >+ break; >+ } >+ >+ p = key_fingerprint(k, SSH_FP_MD5, SSH_FP_HEX); >+ debug("fingerprint %u %s", key_size(k), p); >+ xfree(p); >+ >+ return 0; >+} >+ >+static int >+nss_authenticate(PK11SlotInfo *slot, char *password, int pwprompts, char **output) >+{ >+ int i, quit; >+ >+ *output = NULL; >+ >+ if (!PK11_NeedLogin(slot)) >+ return 0; >+ >+ for (i = 0; i < pwprompts; i++) { >+ SECStatus rv; >+ CK_TOKEN_INFO info; >+ >+ rv = PK11_GetTokenInfo(slot, &info); >+ if (rv != SECSuccess) { >+ error("Failed to get information for token %s", >+ PK11_GetTokenName(slot)); >+ return -1; >+ } >+ >+ if (info.flags & CKF_USER_PIN_LOCKED) { >+ error("Passphrase for token %s is locked", >+ PK11_GetTokenName(slot)); >+ return -1; >+ } >+ >+ if (info.flags & CKF_USER_PIN_FINAL_TRY) >+ debug2("Final passphrase attempt for token %s", >+ PK11_GetTokenName(slot)); >+ else if (info.flags & CKF_USER_PIN_COUNT_LOW) >+ debug2("Previous failed passphrase attempt for token %s", >+ PK11_GetTokenName(slot)); >+ >+ if (password != NULL) >+ *output = xstrdup(password); >+ else { >+ char *prompt; >+ if (asprintf(&prompt, "Enter passphrase for token %s: ", >+ PK11_GetTokenName(slot)) < 0) >+ fatal("password_cb: asprintf failed"); >+ *output = read_passphrase(prompt, RP_ALLOW_STDIN); >+ } >+ >+ if (strcmp(*output, "") == 0) { >+ debug2("no passphrase given, ignoring slot"); >+ quit = 1; >+ goto cleanup; >+ } >+ >+ quit = 0; >+ >+ rv = PK11_Authenticate(slot, PR_TRUE, *output); >+ if (rv == SECSuccess) >+ return 0; >+ >+ switch (PORT_GetError()) { >+ case SEC_ERROR_BAD_PASSWORD: >+ debug2("Incorrect passphrase, try again..."); >+ break; >+ case SEC_ERROR_INVALID_ARGS: >+ case SEC_ERROR_BAD_DATA: >+ debug2("Invalid passphrase, try again..."); >+ break; >+#if HAVE_SEC_ERROR_LOCKED_PASSWORD >+ case SEC_ERROR_LOCKED_PASSWORD: >+ error("Unable to authenticate, token passphrase is locked"); >+ quit = 1; >+ break; >+#endif >+ default: >+ error("Failure while authenticating against token"); >+ quit = 1; >+ } >+ >+cleanup: >+ memset(*output, 0, strlen(*output)); >+ xfree(*output); >+ *output = NULL; >+ >+ /* No point in retrying the same password */ >+ if (password != NULL) >+ break; >+ >+ if (quit) >+ break; >+ } >+ >+ return -1; >+} >+ >+static Key ** >+nss_find_privkeys(const char *tokenname, const char *keyname, >+ char *password, int pwprompts) >+{ >+ Key *k = NULL; >+ Key **keys = NULL; >+ PK11SlotList *slots; >+ PK11SlotListElement *sle; >+ size_t allocated = 0; >+ size_t i = 0; >+ >+ if ((slots=PK11_FindSlotsByNames(NULL, NULL, tokenname, PR_TRUE)) == NULL) { >+ if (tokenname == NULL) { >+ debug("No NSS token found"); >+ } else { >+ debug("NSS token not found: %s", tokenname); >+ } >+ return NULL; >+ } >+ >+ for (sle = slots->head; sle; sle = sle->next) { >+ SECKEYPrivateKeyList *list; >+ SECKEYPrivateKeyListNode *node; >+ char *tmppass; >+ >+ if (nss_authenticate(sle->slot, password, pwprompts, &tmppass) == -1) >+ break; >+ >+ debug("Looking for: %s:%s", tokenname, keyname); >+ list = PK11_ListPrivKeysInSlot(sle->slot, (char *)keyname, >+ tmppass); >+ if (list == NULL && keyname != NULL) { >+ char *fooname; >+ /* NSS bug workaround */ >+ if (asprintf(&fooname, "%s~", keyname) < 0) { >+ error("nss_find_privkey: asprintf failed"); >+ PK11_FreeSlotList(slots); >+ return NULL; >+ } >+ list = PK11_ListPrivKeysInSlot(sle->slot, fooname, >+ tmppass); >+ free(fooname); >+ } >+ if (list == NULL && keyname != NULL) { >+ CERTCertificate *cert; >+ SECKEYPrivateKey *privk; >+ cert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), >+ (char *)keyname); >+ if (cert == NULL) >+ goto cleanup; >+ privk = PK11_FindPrivateKeyFromCert(sle->slot, cert, tmppass); >+ CERT_DestroyCertificate(cert); >+ if (privk == NULL) >+ goto cleanup; >+ if ((k=make_key_from_privkey(privk, tmppass)) != NULL) { >+ nss_convert_pubkey(k); >+ keys = add_key_to_list(k, keys, &i, &allocated); >+ } >+ SECKEY_DestroyPrivateKey(privk); >+ } else { >+ if (list == NULL) >+ goto cleanup; >+ for (node=PRIVKEY_LIST_HEAD(list); !PRIVKEY_LIST_END(node, list); >+ node=PRIVKEY_LIST_NEXT(node)) >+ if ((k=make_key_from_privkey(node->key, tmppass)) != NULL) { >+ nss_convert_pubkey(k); >+ keys = add_key_to_list(k, keys, &i, &allocated); >+ } >+ SECKEY_DestroyPrivateKeyList(list); >+ } >+cleanup: >+ if (tmppass != NULL) { >+ memset(tmppass, 0, strlen(tmppass)); >+ xfree(tmppass); >+ } >+ } >+ PK11_FreeSlotList(slots); >+ >+ return keys; >+} >+ >+Key ** >+nss_get_keys(const char *tokenname, const char *keyname, >+ char *password, int pwprompts, int num_modules, const char **modules) >+{ >+ int i; >+ Key **keys; >+ >+ if (nss_init(NULL) == -1) { >+ error("Failed to initialize NSS library"); >+ return NULL; >+ } >+ >+ for (i = 0;i < num_modules;i++) { >+ if (nss_load_module(modules[i]) == -1) { >+ error("Failed to load PKCS#11 module '%s'", modules[i]); >+ return NULL; >+ } >+ } >+ >+ keys = nss_find_privkeys(tokenname, keyname, password, pwprompts); >+ if (keys == NULL && keyname != NULL) { >+ error("Cannot find key in nss, token removed"); >+ return NULL; >+ } >+#if 0 >+ keys = xcalloc(3, sizeof(Key *)); >+ >+ if (k->type == KEY_RSA) { >+ n = key_new_nss_copy(KEY_RSA1, k); >+ >+ keys[0] = n; >+ keys[1] = k; >+ keys[2] = NULL; >+ } else { >+ keys[0] = k; >+ keys[1] = NULL; >+ } >+#endif >+ return keys; >+} >+ >+char * >+nss_get_key_label(Key *key) >+{ >+ char *label, *nickname; >+ >+ nickname = PK11_GetPrivateKeyNickname(key->nss->privk); >+ label = xstrdup(nickname); >+ PORT_Free(nickname); >+ >+ return label; >+} >+ >+#endif /* HAVE_LIBNSS */ >diff -up /dev/null openssh-5.3p1/nsskeys.h >--- /dev/null 2009-11-27 11:08:21.619709673 +0100 >+++ openssh-5.3p1/nsskeys.h 2009-11-27 13:43:01.000000000 +0100 >@@ -0,0 +1,39 @@ >+/* >+ * Copyright (c) 2001 Markus Friedl. All rights reserved. >+ * Copyright (c) 2007 Red Hat, Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR >+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES >+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. >+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, >+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT >+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, >+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY >+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF >+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#ifndef NSSKEYS_H >+#define NSSKEYS_H >+#ifdef HAVE_LIBNSS >+#include <pk11func.h> >+#include <prtypes.h> >+ >+int nss_init(PK11PasswordFunc); >+Key **nss_get_keys(const char *, const char *, char *, int , int , const char **); >+char *nss_get_key_label(Key *); >+/*void sc_close(void);*/ >+/*int sc_put_key(Key *, const char *);*/ >+ >+#endif >+#endif >diff -up openssh-5.3p1/readconf.c.nss-keys openssh-5.3p1/readconf.c >--- openssh-5.3p1/readconf.c.nss-keys 2009-07-05 23:12:27.000000000 +0200 >+++ openssh-5.3p1/readconf.c 2009-11-27 13:43:01.000000000 +0100 >@@ -124,6 +124,7 @@ typedef enum { > oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, > oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, > oHostKeyAlgorithms, oBindAddress, oSmartcardDevice, >+ oUseNSS, oNSSToken, oNSSModule, > oClearAllForwardings, oNoHostAuthenticationForLocalhost, > oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, > oAddressFamily, oGssAuthentication, oGssDelegateCreds, >@@ -210,6 +211,15 @@ static struct { > #else > { "smartcarddevice", oUnsupported }, > #endif >+#ifdef HAVE_LIBNSS >+ { "usenss", oUseNSS }, >+ { "nsstoken", oNSSToken }, >+ { "nssmodule", oNSSModule }, >+#else >+ { "usenss", oUnsupported }, >+ { "nsstoken", oNSSToken }, >+ { "nssmodule", oUnsupported }, >+#endif > { "clearallforwardings", oClearAllForwardings }, > { "enablesshkeysign", oEnableSSHKeysign }, > { "verifyhostkeydns", oVerifyHostKeyDNS }, >@@ -613,6 +623,28 @@ parse_string: > charptr = &options->smartcard_device; > goto parse_string; > >+ case oUseNSS: >+ intptr = &options->use_nss; >+ goto parse_flag; >+ >+ case oNSSToken: >+ charptr = &options->nss_token; >+ goto parse_command; >+ >+ case oNSSModule: >+ arg = strdelim(&s); >+ if (!arg || *arg == '\0') >+ fatal("%.200s line %d: Missing argument.", filename, linenum); >+ if (*activep) { >+ intptr = &options->num_nss_modules; >+ if (*intptr >= SSH_MAX_NSS_MODULES) >+ fatal("%.200s line %d: Too many PKCS#11 modules specified (max %d).", >+ filename, linenum, SSH_MAX_NSS_MODULES); >+ charptr = &options->nss_modules[*intptr]; >+ *charptr = xstrdup(arg); >+ *intptr = *intptr + 1; >+ } >+ break; > case oProxyCommand: > charptr = &options->proxy_command; > parse_command: >@@ -1052,6 +1084,9 @@ 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->num_nss_modules = 0; > options->enable_ssh_keysign = - 1; > options->no_host_authentication_for_localhost = - 1; > options->identities_only = - 1; >@@ -1183,6 +1218,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-11-27 13:43:01.000000000 +0100 >@@ -85,6 +85,10 @@ 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 num_nss_modules; /* Number of PCKS#11 modules. */ >+ char *nss_modules[SSH_MAX_NSS_MODULES]; > 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-11-27 13:43:01.000000000 +0100 >@@ -44,6 +44,14 @@ > #include <openssl/evp.h> > #include "openbsd-compat/openssl-compat.h" > >+#ifdef HAVE_LIBNSS >+#include <nss.h> >+#include <secmod.h> >+#include <pk11pub.h> >+#include <keyhi.h> >+#include <cert.h> >+#endif >+ > #include <fcntl.h> > #include <pwd.h> > #include <stdarg.h> >@@ -57,6 +65,7 @@ > #include "rsa.h" > #include "log.h" > #include "key.h" >+#include "nsskeys.h" > #include "buffer.h" > #include "authfd.h" > #include "authfile.h" >@@ -307,6 +316,128 @@ do_file(AuthenticationConnection *ac, in > return 0; > } > >+#ifdef HAVE_LIBNSS >+static char * >+password_cb(PK11SlotInfo *slot, PRBool retry, void *arg) >+{ >+ char **passcache = arg; >+ char *password, *p2 = NULL; >+ char *prompt; >+ >+ if (retry) >+ return NULL; >+ >+ if (asprintf(&prompt, "Enter passphrase for token %s: ", >+ PK11_GetTokenName(slot)) < 0) >+ fatal("password_cb: asprintf failed"); >+ >+ password = read_passphrase(prompt, RP_ALLOW_STDIN); >+ >+ if (password != NULL && (p2=PL_strdup(password)) == NULL) { >+ memset(password, 0, strlen(password)); >+ fatal("password_cb: PL_strdup failed"); >+ } >+ >+ if (passcache != NULL) { >+ if (*passcache != NULL) { >+ memset(*passcache, 0, strlen(*passcache)); >+ xfree(*passcache); >+ } >+ *passcache = password; >+ } else { >+ memset(password, 0, strlen(password)); >+ xfree(password); >+ } >+ >+ return p2; >+} >+ >+static int >+add_slot_keys(AuthenticationConnection *ac, PK11SlotInfo *slot, int add) >+{ >+ SECKEYPrivateKeyList *list; >+ SECKEYPrivateKeyListNode *node; >+ char *passcache = NULL; >+ char *tokenname; >+ char **xkeyname = NULL; >+ >+ int count = 0; >+ int i; >+ >+ if (PK11_NeedLogin(slot)) >+ PK11_Authenticate(slot, PR_TRUE, &passcache); >+ >+ if ((list=PK11_ListPrivKeysInSlot(slot, NULL, NULL)) == NULL) { >+ return 0; >+ } >+ >+ tokenname = PK11_GetTokenName(slot); >+ >+ for (node=PRIVKEY_LIST_HEAD(list); !PRIVKEY_LIST_END(node, list); >+ node=PRIVKEY_LIST_NEXT(node)) { >+ char *keyname; >+ SECKEYPublicKey *pub; >+ >+ keyname = PK11_GetPrivateKeyNickname(node->key); >+ if (keyname == NULL || *keyname == '\0') { >+ /* no nickname to refer to */ >+ CERTCertificate *cert; >+ char *kn; >+ cert = PK11_GetCertFromPrivateKey(node->key); >+ if (cert == NULL) >+ continue; >+ kn = strchr(cert->nickname, ':'); >+ if (kn == NULL) >+ kn = cert->nickname; >+ else >+ kn++; >+ keyname = PORT_Strdup(kn); >+ CERT_DestroyCertificate(cert); >+ if (keyname == NULL) >+ continue; >+ } >+ pub = SECKEY_ConvertToPublicKey(node->key); >+ if (pub == NULL) { >+ fprintf(stderr, "No public key for: %s:%s\n", >+ tokenname, keyname); >+ continue; /* not possible to obtain public key */ >+ } >+ SECKEY_DestroyPublicKey(pub); >+ >+ if ((count % 10) == 0) >+ xkeyname = xrealloc (xkeyname, count + 10, sizeof (char *)); >+ >+ xkeyname[count++] = keyname; >+ } >+ >+ PK11_Logout(slot); >+ >+ for (i = 0; i < count; i++) { >+ if (ssh_update_nss_key(ac, add, tokenname, xkeyname[i], >+ passcache?passcache:"", lifetime, confirm)) { >+ fprintf(stderr, "Key %s: %s:%s\n", >+ add?"added":"removed", tokenname, xkeyname[i]); >+ } else { >+ fprintf(stderr, "Could not %s key: %s:%s\n", >+ add?"add":"remove", tokenname, xkeyname[i]); >+ } >+ PORT_Free(xkeyname[i]); >+ } >+ >+ if (xkeyname != NULL) >+ free (xkeyname); >+ >+ if (passcache != NULL) { >+ memset(passcache, 0, strlen(passcache)); >+ xfree(passcache); >+ } >+ >+ SECKEY_DestroyPrivateKeyList(list); >+ >+ return count; >+} >+#endif >+ > static void > usage(void) > { >@@ -334,6 +465,10 @@ main(int argc, char **argv) > AuthenticationConnection *ac = NULL; > char *sc_reader_id = NULL; > int i, ch, deleting = 0, ret = 0; >+#ifdef HAVE_LIBNSS >+ char *token_id = NULL; >+ int use_nss = 0; >+#endif > > /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ > sanitise_stdfd(); >@@ -351,7 +486,7 @@ main(int argc, char **argv) > "Could not open a connection to your authentication agent.\n"); > exit(2); > } >- while ((ch = getopt(argc, argv, "lLcdDxXe:s:t:")) != -1) { >+ while ((ch = getopt(argc, argv, "lLcdDnxXe:s:t:T:")) != -1) { > switch (ch) { > case 'l': > case 'L': >@@ -373,6 +508,11 @@ main(int argc, char **argv) > if (delete_all(ac) == -1) > ret = 1; > goto done; >+#ifdef HAVE_LIBNSS >+ case 'n': >+ use_nss = 1; >+ break; >+#endif > case 's': > sc_reader_id = optarg; > break; >@@ -387,6 +527,11 @@ main(int argc, char **argv) > goto done; > } > break; >+#ifdef HAVE_LIBNSS >+ case 'T': >+ token_id = optarg; >+ break; >+#endif > default: > usage(); > ret = 1; >@@ -400,6 +545,40 @@ main(int argc, char **argv) > ret = 1; > goto done; > } >+#ifdef HAVE_LIBNSS >+ if (use_nss) { >+ PK11SlotList *slots; >+ PK11SlotListElement *sle; >+ int count = 0; >+ if (nss_init(password_cb) == -1) { >+ fprintf(stderr, "Failed to initialize NSS library\n"); >+ ret = 1; >+ goto done; >+ } >+ >+ if ((slots=PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, >+ NULL)) == NULL) { >+ fprintf(stderr, "No tokens found\n"); >+ ret = 1; >+ goto nss_done; >+ } >+ >+ for (sle = slots->head; sle; sle = sle->next) { >+ int rv; >+ if ((rv=add_slot_keys(ac, sle->slot, !deleting)) == -1) { >+ ret = 1; >+ } >+ count += rv; >+ } >+ if (count == 0) { >+ ret = 1; >+ } >+nss_done: >+ NSS_Shutdown(); >+ clear_pass(); >+ goto done; >+ } >+#endif > if (argc == 0) { > char buf[MAXPATHLEN]; > struct passwd *pw; >diff -up openssh-5.3p1/ssh-agent.c.nss-keys openssh-5.3p1/ssh-agent.c >--- openssh-5.3p1/ssh-agent.c.nss-keys 2009-06-21 09:50:15.000000000 +0200 >+++ openssh-5.3p1/ssh-agent.c 2009-11-27 13:43:01.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: > } > #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, 1, 0, NULL); >+ /* 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, 1, 0, NULL); >+ 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-11-27 13:43:01.000000000 +0100 >@@ -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,29 @@ 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, >+ options.number_of_password_prompts, options.num_nss_modules, >+ options.nss_modules)) != NULL) { >+ int count; >+ for (count = 0; keys[count] != NULL; count++) { >+ memmove(&options.identity_files[1], &options.identity_files[0], >+ sizeof(char *) * (SSH_MAX_IDENTITY_FILES - 1)); >+ memmove(&options.identity_keys[1], &options.identity_keys[0], >+ sizeof(Key *) * (SSH_MAX_IDENTITY_FILES - 1)); >+ options.num_identity_files++; >+ options.identity_keys[0] = keys[count]; >+ options.identity_files[0] = nss_get_key_label(keys[count]); >+ } >+ if (options.num_identity_files > SSH_MAX_IDENTITY_FILES) >+ options.num_identity_files = SSH_MAX_IDENTITY_FILES; >+ i += count; >+ xfree(keys); >+ } >+#endif /* HAVE_LIBNSS */ >+ > if ((pw = getpwuid(original_real_uid)) == NULL) > fatal("load_public_identity_files: getpwuid failed"); > pwname = xstrdup(pw->pw_name); >diff -up openssh-5.3p1/ssh-dss.c.nss-keys openssh-5.3p1/ssh-dss.c >--- openssh-5.3p1/ssh-dss.c.nss-keys 2006-11-07 13:14:42.000000000 +0100 >+++ openssh-5.3p1/ssh-dss.c 2009-11-27 13:43:01.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.3p1/ssh.h.nss-keys openssh-5.3p1/ssh.h >--- openssh-5.3p1/ssh.h.nss-keys 2006-08-05 04:39:41.000000000 +0200 >+++ openssh-5.3p1/ssh.h 2009-11-27 13:43:01.000000000 +0100 >@@ -28,6 +28,12 @@ > #define SSH_MAX_IDENTITY_FILES 100 > > /* >+ * Maximum number of PKCS#11 modules that can be specified in configuration >+ * files or on the command line. >+ */ >+#define SSH_MAX_NSS_MODULES 10 >+ >+/* > * Maximum length of lines in authorized_keys file. > * Current value permits 16kbit RSA and RSA1 keys and 8kbit DSA keys, with > * some room for options and comments. >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-11-27 13:43:01.000000000 +0100 >@@ -53,6 +53,11 @@ > #include "scard.h" > #endif > >+#ifdef HAVE_LIBNSS >+#include <nss.h> >+#include "nsskeys.h" >+#endif >+ > /* Number of bits in the RSA/DSA key. This value can be set on the command line. */ > #define DEFAULT_BITS 2048 > #define DEFAULT_BITS_DSA 1024 >@@ -501,6 +506,26 @@ do_download(struct passwd *pw, const cha > } > #endif /* SMARTCARD */ > >+#ifdef HAVE_LIBNSS >+static void >+do_nss_download(struct passwd *pw, const char *tokenname, const char *keyname) >+{ >+ Key **keys = NULL; >+ int i; >+ >+ keys = nss_get_keys(tokenname, keyname, NULL, 1, 0, NULL); >+ if (keys == NULL) >+ fatal("cannot find public key in NSS"); >+ for (i = 0; keys[i]; i++) { >+ key_write(keys[i], stdout); >+ key_free(keys[i]); >+ fprintf(stdout, "\n"); >+ } >+ xfree(keys); >+ exit(0); >+} >+#endif /* HAVE_LIBNSS */ >+ > static void > do_fingerprint(struct passwd *pw) > { >@@ -1083,7 +1108,8 @@ main(int argc, char **argv) > Key *private, *public; > struct passwd *pw; > struct stat st; >- int opt, type, fd, download = 0; >+ int opt, type, fd, download = 1; >+ int use_nss = 0; > u_int32_t memory = 0, generator_wanted = 0, trials = 100; > int do_gen_candidates = 0, do_screen_candidates = 0; > BIGNUM *start = NULL; >@@ -1116,7 +1142,7 @@ main(int argc, char **argv) > } > > while ((opt = getopt(argc, argv, >- "degiqpclBHvxXyF:b:f:t:U:D:P:N:C:r:g:R:T:G:M:S:a:W:")) != -1) { >+ "degiqpclnBHvxXyF:b:f:t:U:D:P:N:C:r:g:R:T:G:M:S:a:W:")) != -1) { > switch (opt) { > case 'b': > bits = (u_int32_t)strtonum(optarg, 768, 32768, &errstr); >@@ -1156,6 +1182,10 @@ main(int argc, char **argv) > case 'g': > print_generic = 1; > break; >+ case 'n': >+ use_nss = 1; >+ download = 1; >+ break; > case 'P': > identity_passphrase = optarg; > break; >@@ -1187,10 +1217,10 @@ main(int argc, char **argv) > case 't': > key_type_name = optarg; > break; >- case 'D': >- download = 1; >- /*FALLTHROUGH*/ > case 'U': >+ download = 0; >+ /*FALLTHROUGH*/ >+ case 'D': > reader_id = optarg; > break; > case 'v': >@@ -1299,6 +1329,17 @@ main(int argc, char **argv) > exit(0); > } > } >+ >+ if (use_nss) { >+#ifdef HAVE_LIBNSS >+ if (download) >+ do_nss_download(pw, reader_id, identity_file); >+ else >+ fatal("no support for NSS key upload."); >+#else >+ fatal("no support for NSS keys."); >+#endif >+ } > if (reader_id != NULL) { > #ifdef SMARTCARD > if (download) >diff -up openssh-5.3p1/ssh-rsa.c.nss-keys openssh-5.3p1/ssh-rsa.c >--- openssh-5.3p1/ssh-rsa.c.nss-keys 2006-09-01 07:38:37.000000000 +0200 >+++ openssh-5.3p1/ssh-rsa.c 2009-11-27 13:43:01.000000000 +0100 >@@ -32,6 +32,10 @@ > #include "compat.h" > #include "ssh.h" > >+#ifdef HAVE_LIBNSS >+#include <cryptohi.h> >+#endif >+ > static int openssh_RSA_verify(int, u_char *, u_int, u_char *, u_int, RSA *); > > /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ >@@ -50,6 +54,38 @@ ssh_rsa_sign(const Key *key, u_char **si > error("ssh_rsa_sign: no RSA key"); > return -1; > } >+ >+ slen = RSA_size(key->rsa); >+ sig = xmalloc(slen); >+ >+#ifdef HAVE_LIBNSS >+ if (key->flags & KEY_FLAG_NSS) { >+ SECItem sigitem; >+ SECOidTag alg; >+ >+ memset(&sigitem, 0, sizeof(sigitem)); >+ alg = (datafellows & SSH_BUG_RSASIGMD5) ? >+ SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION : >+ SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; >+ >+ if (SEC_SignData(&sigitem, (u_char *)data, datalen, key->nss->privk, >+ alg) != SECSuccess) { >+ error("ssh_rsa_sign: sign failed"); >+ return -1; >+ } >+ if (sigitem.len > slen) { >+ error("ssh_rsa_sign: slen %u slen2 %u", slen, sigitem.len); >+ xfree(sig); >+ SECITEM_ZfreeItem(&sigitem, PR_FALSE); >+ return -1; >+ } >+ if (sigitem.len < slen) { >+ memset(sig, 0, slen - sigitem.len); >+ } >+ memcpy(sig+slen-sigitem.len, sigitem.data, sigitem.len); >+ SECITEM_ZfreeItem(&sigitem, PR_FALSE); >+ } else { >+#endif > nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1; > if ((evp_md = EVP_get_digestbynid(nid)) == NULL) { > error("ssh_rsa_sign: EVP_get_digestbynid %d failed", nid); >@@ -59,9 +95,6 @@ ssh_rsa_sign(const Key *key, u_char **si > EVP_DigestUpdate(&md, data, datalen); > EVP_DigestFinal(&md, digest, &dlen); > >- slen = RSA_size(key->rsa); >- sig = xmalloc(slen); >- > ok = RSA_sign(nid, digest, dlen, sig, &len, key->rsa); > memset(digest, 'd', sizeof(digest)); > >@@ -83,6 +116,9 @@ ssh_rsa_sign(const Key *key, u_char **si > xfree(sig); > return -1; > } >+#ifdef HAVE_LIBNSS >+ } >+#endif > /* encode signature */ > buffer_init(&b); > buffer_put_cstring(&b, "ssh-rsa");
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 1676
: 1734 |
1793