diff --git a/.cvsignore b/.cvsignore index 8b7d36e..fcc5d1e 100644 --- a/.cvsignore +++ b/.cvsignore @@ -1,2 +1,2 @@ +pam_ssh_agent_auth-0.9.2.tar.bz2 openssh-5.4p1-noacss.tar.bz2 -pam_ssh_agent_auth-0.9-build.patch diff --git a/openssh-4.3p2-no-v6only.patch b/openssh-4.3p2-no-v6only.patch deleted file mode 100644 index a789812..0000000 --- a/openssh-4.3p2-no-v6only.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- openssh-4.3p2/channels.c.no-v6only 2006-07-17 15:39:31.000000000 +0200 -+++ openssh-4.3p2/channels.c 2006-08-08 12:44:51.000000000 +0200 -@@ -2794,7 +2794,7 @@ - } - } - #ifdef IPV6_V6ONLY -- if (ai->ai_family == AF_INET6) { -+ if (x11_use_localhost && ai->ai_family == AF_INET6) { - int on = 1; - if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) - error("setsockopt IPV6_V6ONLY: %.100s", strerror(errno)); diff --git a/openssh-5.4p1-noacss.tar.bz2 b/openssh-5.4p1-noacss.tar.bz2 deleted file mode 100644 index 7ee530f..0000000 Binary files a/openssh-5.4p1-noacss.tar.bz2 and /dev/null differ diff --git a/openssh-5.4p1-nss-keys.patch b/openssh-5.4p1-nss-keys.patch deleted file mode 100644 index 7321816..0000000 --- a/openssh-5.4p1-nss-keys.patch +++ /dev/null @@ -1,1526 +0,0 @@ -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 -lplc4" -+ AC_CHECK_DECLS([SEC_ERROR_LOCKED_PASSWORD], [], [], [#include ]) -+ 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 -@@ -30,6 +30,11 @@ - #include - #include - -+#ifdef HAVE_LIBNSS -+#include -+#include -+#endif -+ - typedef struct Key Key; - enum types { - KEY_RSA1, -@@ -37,6 +42,7 @@ - KEY_DSA, - KEY_RSA_CERT, - KEY_DSA_CERT, -+ KEY_NSS, - KEY_UNSPEC - }; - enum fp_type { -@@ -51,6 +57,15 @@ - - /* 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 - - #define CERT_MAX_PRINCIPALS 256 - struct KeyCert { -@@ -70,11 +85,16 @@ - RSA *rsa; - DSA *dsa; - struct KeyCert *cert; -+#ifdef HAVE_LIBNSS -+ NSSKey *nss; -+#endif - }; - - Key *key_new(int); - void key_add_private(Key *); - 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_public(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 -+ -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "xmalloc.h" -+#include "key.h" -+#include "log.h" -+#include "misc.h" -+#include "nsskeys.h" -+#include "pathnames.h" -+ -+static char * -+password_cb(PK11SlotInfo *slot, PRBool retry, void *arg) -+{ -+ char *password = arg; -+ if (retry || password == NULL) -+ return NULL; -+ -+ return PL_strdup(password); -+} -+ -+int -+nss_init(PK11PasswordFunc pwfn) -+{ -+ char *dbpath; -+ char buf[MAXPATHLEN]; -+ -+ if (NSS_IsInitialized()) -+ return 0; -+ -+ if ((dbpath=getenv("NSS_DB_PATH")) == NULL) { -+ struct passwd *pw; -+ if ((pw = getpwuid(getuid())) == NULL || -+ pw->pw_dir == NULL) { -+ return -1; -+ } -+ snprintf(buf, sizeof(buf), "%s/%s", pw->pw_dir, -+ _PATH_SSH_USER_DIR); -+ dbpath = buf; -+ } -+ -+ if (NSS_Init(dbpath) != SECSuccess) { -+ 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 -+#include -+ -+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 - #include "openbsd-compat/openssl-compat.h" - -+#ifdef HAVE_LIBNSS -+#include -+#include -+#include -+#include -+#include -+#endif -+ - #include - #include - #include -@@ -57,6 +65,7 @@ - #include "rsa.h" - #include "log.h" - #include "key.h" -+#include "nsskeys.h" - #include "buffer.h" - #include "authfd.h" - #include "authfile.h" -@@ -307,6 +316,128 @@ do_file(AuthenticationConnection *ac, in - return 0; - } - -+#ifdef HAVE_LIBNSS -+static char * -+password_cb(PK11SlotInfo *slot, PRBool retry, void *arg) -+{ -+ char **passcache = arg; -+ char *password, *p2 = NULL; -+ char *prompt; -+ -+ if (retry) -+ return NULL; -+ -+ if (asprintf(&prompt, "Enter passphrase for token %s: ", -+ PK11_GetTokenName(slot)) < 0) -+ fatal("password_cb: asprintf failed"); -+ -+ password = read_passphrase(prompt, RP_ALLOW_STDIN); -+ -+ if (password != NULL && (p2=PL_strdup(password)) == NULL) { -+ memset(password, 0, strlen(password)); -+ fatal("password_cb: PL_strdup failed"); -+ } -+ -+ if (passcache != NULL) { -+ if (*passcache != NULL) { -+ memset(*passcache, 0, strlen(*passcache)); -+ xfree(*passcache); -+ } -+ *passcache = password; -+ } else { -+ memset(password, 0, strlen(password)); -+ xfree(password); -+ } -+ -+ return p2; -+} -+ -+static int -+add_slot_keys(AuthenticationConnection *ac, PK11SlotInfo *slot, int add) -+{ -+ SECKEYPrivateKeyList *list; -+ SECKEYPrivateKeyListNode *node; -+ char *passcache = NULL; -+ char *tokenname; -+ char **xkeyname = NULL; -+ -+ int count = 0; -+ int i; -+ -+ if (PK11_NeedLogin(slot)) -+ PK11_Authenticate(slot, PR_TRUE, &passcache); -+ -+ if ((list=PK11_ListPrivKeysInSlot(slot, NULL, NULL)) == NULL) { -+ return 0; -+ } -+ -+ tokenname = PK11_GetTokenName(slot); -+ -+ for (node=PRIVKEY_LIST_HEAD(list); !PRIVKEY_LIST_END(node, list); -+ node=PRIVKEY_LIST_NEXT(node)) { -+ char *keyname; -+ SECKEYPublicKey *pub; -+ -+ keyname = PK11_GetPrivateKeyNickname(node->key); -+ if (keyname == NULL || *keyname == '\0') { -+ /* no nickname to refer to */ -+ CERTCertificate *cert; -+ char *kn; -+ cert = PK11_GetCertFromPrivateKey(node->key); -+ if (cert == NULL) -+ continue; -+ kn = strchr(cert->nickname, ':'); -+ if (kn == NULL) -+ kn = cert->nickname; -+ else -+ kn++; -+ keyname = PORT_Strdup(kn); -+ CERT_DestroyCertificate(cert); -+ if (keyname == NULL) -+ continue; -+ } -+ pub = SECKEY_ConvertToPublicKey(node->key); -+ if (pub == NULL) { -+ fprintf(stderr, "No public key for: %s:%s\n", -+ tokenname, keyname); -+ continue; /* not possible to obtain public key */ -+ } -+ SECKEY_DestroyPublicKey(pub); -+ -+ if ((count % 10) == 0) -+ xkeyname = xrealloc (xkeyname, count + 10, sizeof (char *)); -+ -+ xkeyname[count++] = keyname; -+ } -+ -+ PK11_Logout(slot); -+ -+ for (i = 0; i < count; i++) { -+ if (ssh_update_nss_key(ac, add, tokenname, xkeyname[i], -+ passcache?passcache:"", lifetime, confirm)) { -+ fprintf(stderr, "Key %s: %s:%s\n", -+ add?"added":"removed", tokenname, xkeyname[i]); -+ } else { -+ fprintf(stderr, "Could not %s key: %s:%s\n", -+ add?"add":"remove", tokenname, xkeyname[i]); -+ } -+ PORT_Free(xkeyname[i]); -+ } -+ -+ if (xkeyname != NULL) -+ free (xkeyname); -+ -+ if (passcache != NULL) { -+ memset(passcache, 0, strlen(passcache)); -+ xfree(passcache); -+ } -+ -+ SECKEY_DestroyPrivateKeyList(list); -+ -+ return count; -+} -+#endif -+ - static void - usage(void) - { -@@ -334,6 +465,10 @@ main(int argc, char **argv) - AuthenticationConnection *ac = NULL; - char *sc_reader_id = NULL; - int i, ch, deleting = 0, ret = 0; -+#ifdef HAVE_LIBNSS -+ char *token_id = NULL; -+ int use_nss = 0; -+#endif - - /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ - sanitise_stdfd(); -@@ -351,7 +486,7 @@ main(int argc, char **argv) - "Could not open a connection to your authentication agent.\n"); - exit(2); - } -- while ((ch = getopt(argc, argv, "lLcdDxXe:s:t:")) != -1) { -+ while ((ch = getopt(argc, argv, "lLcdDnxXe:s:t:T:")) != -1) { - switch (ch) { - case 'l': - case 'L': -@@ -373,6 +508,11 @@ main(int argc, char **argv) - if (delete_all(ac) == -1) - ret = 1; - goto done; -+#ifdef HAVE_LIBNSS -+ case 'n': -+ use_nss = 1; -+ break; -+#endif - case 's': - sc_reader_id = optarg; - break; -@@ -387,6 +527,11 @@ main(int argc, char **argv) - goto done; - } - break; -+#ifdef HAVE_LIBNSS -+ case 'T': -+ token_id = optarg; -+ break; -+#endif - default: - usage(); - ret = 1; -@@ -400,6 +545,40 @@ main(int argc, char **argv) - ret = 1; - goto done; - } -+#ifdef HAVE_LIBNSS -+ if (use_nss) { -+ PK11SlotList *slots; -+ PK11SlotListElement *sle; -+ int count = 0; -+ if (nss_init(password_cb) == -1) { -+ fprintf(stderr, "Failed to initialize NSS library\n"); -+ ret = 1; -+ goto done; -+ } -+ -+ if ((slots=PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, -+ NULL)) == NULL) { -+ fprintf(stderr, "No tokens found\n"); -+ ret = 1; -+ goto nss_done; -+ } -+ -+ for (sle = slots->head; sle; sle = sle->next) { -+ int rv; -+ if ((rv=add_slot_keys(ac, sle->slot, !deleting)) == -1) { -+ ret = 1; -+ } -+ count += rv; -+ } -+ if (count == 0) { -+ ret = 1; -+ } -+nss_done: -+ NSS_Shutdown(); -+ clear_pass(); -+ goto done; -+ } -+#endif - if (argc == 0) { - char buf[MAXPATHLEN]; - struct passwd *pw; -diff -up openssh-5.3p1/ssh-agent.c.nss-keys openssh-5.3p1/ssh-agent.c ---- openssh-5.3p1/ssh-agent.c.nss-keys 2009-06-21 09:50:15.000000000 +0200 -+++ openssh-5.3p1/ssh-agent.c 2009-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 /* 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 -+#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 -+#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 -+#endif -+ - static int openssh_RSA_verify(int, u_char *, u_int, u_char *, u_int, RSA *); - - /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ -@@ -50,6 +54,38 @@ ssh_rsa_sign(const Key *key, u_char **si - error("ssh_rsa_sign: no RSA key"); - return -1; - } -+ -+ slen = RSA_size(key->rsa); -+ sig = xmalloc(slen); -+ -+#ifdef HAVE_LIBNSS -+ if (key->flags & KEY_FLAG_NSS) { -+ SECItem sigitem; -+ SECOidTag alg; -+ -+ memset(&sigitem, 0, sizeof(sigitem)); -+ alg = (datafellows & SSH_BUG_RSASIGMD5) ? -+ SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION : -+ SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; -+ -+ if (SEC_SignData(&sigitem, (u_char *)data, datalen, key->nss->privk, -+ alg) != SECSuccess) { -+ error("ssh_rsa_sign: sign failed"); -+ return -1; -+ } -+ if (sigitem.len > slen) { -+ error("ssh_rsa_sign: slen %u slen2 %u", slen, sigitem.len); -+ xfree(sig); -+ SECITEM_ZfreeItem(&sigitem, PR_FALSE); -+ return -1; -+ } -+ if (sigitem.len < slen) { -+ memset(sig, 0, slen - sigitem.len); -+ } -+ memcpy(sig+slen-sigitem.len, sigitem.data, sigitem.len); -+ SECITEM_ZfreeItem(&sigitem, PR_FALSE); -+ } else { -+#endif - nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1; - if ((evp_md = EVP_get_digestbynid(nid)) == NULL) { - error("ssh_rsa_sign: EVP_get_digestbynid %d failed", nid); -@@ -59,9 +95,6 @@ ssh_rsa_sign(const Key *key, u_char **si - EVP_DigestUpdate(&md, data, datalen); - EVP_DigestFinal(&md, digest, &dlen); - -- slen = RSA_size(key->rsa); -- sig = xmalloc(slen); -- - ok = RSA_sign(nid, digest, dlen, sig, &len, key->rsa); - memset(digest, 'd', sizeof(digest)); - -@@ -83,6 +116,9 @@ ssh_rsa_sign(const Key *key, u_char **si - xfree(sig); - return -1; - } -+#ifdef HAVE_LIBNSS -+ } -+#endif - /* encode signature */ - buffer_init(&b); - buffer_put_cstring(&b, "ssh-rsa"); diff --git a/openssh.spec b/openssh.spec index 6821832..d632351 100644 --- a/openssh.spec +++ b/openssh.spec @@ -80,7 +80,7 @@ URL: http://www.openssh.com/portable.html # This package differs from the upstream OpenSSH tarball in that # the ACSS cipher is removed by running openssh-nukeacss.sh in # the unpacked source directory. -Source0: openssh-%{version}-snap20100302-noacss.tar.bz2 +Source0: openssh-%{version}-noacss.tar.bz2 Source1: openssh-nukeacss.sh Source2: sshd.pam Source3: sshd.init diff --git a/sources b/sources index 5ee3e5f..cf7b75c 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ +b68f1c385d7885fbe2c3626bf77aa3d6 pam_ssh_agent_auth-0.9.2.tar.bz2 96c95443133c2c5a459b95175ab7b555 openssh-5.4p1-noacss.tar.bz2 -86f3413435fbb1b65d46cd262fead5af pam_ssh_agent_auth-0.9-build.patch