View | Details | Raw Unified | Return to bug 1676 | Differences between
and this patch

Collapse All | Expand All

(-)openssh-5.3p1/authfd.c.nss-keys (+39 lines)
Lines 626-631 ssh_update_card(AuthenticationConnection Link Here
626
	return decode_reply(type);
626
	return decode_reply(type);
627
}
627
}
628
628
629
int
630
ssh_update_nss_key(AuthenticationConnection *auth, int add,
631
    const char *tokenname, const char *keyname,
632
    const char *pass, u_int life, u_int confirm)
633
{
634
	Buffer msg;
635
	int type, constrained = (life || confirm);
636
637
	if (add) {
638
		type = constrained ?
639
		    SSH_AGENTC_ADD_NSS_KEY_CONSTRAINED :
640
		    SSH_AGENTC_ADD_NSS_KEY;
641
	} else
642
		type = SSH_AGENTC_REMOVE_NSS_KEY;
643
644
	buffer_init(&msg);
645
	buffer_put_char(&msg, type);
646
	buffer_put_cstring(&msg, tokenname);
647
	buffer_put_cstring(&msg, keyname);
648
	buffer_put_cstring(&msg, pass);
649
650
	if (constrained) {
651
		if (life != 0) {
652
			buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_LIFETIME);
653
			buffer_put_int(&msg, life);
654
		}
655
		if (confirm != 0)
656
			buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_CONFIRM);
657
	}
658
659
	if (ssh_request_reply(auth, &msg, &msg) == 0) {
660
		buffer_free(&msg);
661
		return 0;
662
	}
663
	type = buffer_get_char(&msg);
664
	buffer_free(&msg);
665
	return decode_reply(type);
666
}
667
629
/*
668
/*
630
 * Removes all identities from the agent.  This call is not meant to be used
669
 * Removes all identities from the agent.  This call is not meant to be used
631
 * by normal applications.
670
 * by normal applications.
(-)openssh-5.3p1/authfd.h.nss-keys (+8 lines)
Lines 49-54 Link Here
49
#define SSH2_AGENTC_ADD_ID_CONSTRAINED		25
49
#define SSH2_AGENTC_ADD_ID_CONSTRAINED		25
50
#define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26
50
#define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26
51
51
52
/* nss */
53
#define SSH_AGENTC_ADD_NSS_KEY			30
54
#define SSH_AGENTC_REMOVE_NSS_KEY		31
55
#define SSH_AGENTC_ADD_NSS_KEY_CONSTRAINED	32
56
57
52
#define	SSH_AGENT_CONSTRAIN_LIFETIME		1
58
#define	SSH_AGENT_CONSTRAIN_LIFETIME		1
53
#define	SSH_AGENT_CONSTRAIN_CONFIRM		2
59
#define	SSH_AGENT_CONSTRAIN_CONFIRM		2
54
60
Lines 83-88 int ssh_remove_all_identities(Authentic Link Here
83
int	 ssh_lock_agent(AuthenticationConnection *, int, const char *);
89
int	 ssh_lock_agent(AuthenticationConnection *, int, const char *);
84
int	 ssh_update_card(AuthenticationConnection *, int, const char *,
90
int	 ssh_update_card(AuthenticationConnection *, int, const char *,
85
    const char *, u_int, u_int);
91
    const char *, u_int, u_int);
92
int	 ssh_update_nss_key(AuthenticationConnection *, int, const char *,
93
    const char *, const char *, u_int, u_int);
86
94
87
int
95
int
88
ssh_decrypt_challenge(AuthenticationConnection *, Key *, BIGNUM *, u_char[16],
96
ssh_decrypt_challenge(AuthenticationConnection *, Key *, BIGNUM *, u_char[16],
(-)openssh-5.3p1/configure.ac.nss-keys (+16 lines)
Lines 3526-3531 AC_ARG_WITH(kerberos5, Link Here
3526
	]
3526
	]
3527
)
3527
)
3528
3528
3529
# Check whether user wants NSS support
3530
LIBNSS_MSG="no"
3531
AC_ARG_WITH(nss,
3532
	[  --with-nss   Enable NSS support],
3533
	[ if test "x$withval" != "xno" ; then
3534
		AC_DEFINE(HAVE_LIBNSS,1,[Define if you want NSS support.])
3535
		LIBNSS_MSG="yes"
3536
		CPPFLAGS="$CPPFLAGS -I/usr/include/nss3 -I/usr/include/nspr4"
3537
		AC_CHECK_HEADERS(pk11pub.h)
3538
		LIBS="$LIBS -lnss3 -lplc4"
3539
		AC_CHECK_DECLS([SEC_ERROR_LOCKED_PASSWORD], [], [], [#include <secerr.h>])
3540
	fi
3541
	])
3542
AC_SUBST(LIBNSS)
3543
3529
# Looking for programs, paths and files
3544
# Looking for programs, paths and files
3530
3545
3531
PRIVSEP_PATH=/var/empty
3546
PRIVSEP_PATH=/var/empty
Lines 4253-4258 echo " TCP Wrappers support Link Here
4253
echo "              MD5 password support: $MD5_MSG"
4269
echo "              MD5 password support: $MD5_MSG"
4254
echo "                   libedit support: $LIBEDIT_MSG"
4270
echo "                   libedit support: $LIBEDIT_MSG"
4255
echo "  Solaris process contract support: $SPC_MSG"
4271
echo "  Solaris process contract support: $SPC_MSG"
4272
echo "                       NSS support: $LIBNSS_MSG"
4256
echo "       IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG"
4273
echo "       IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG"
4257
echo "           Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG"
4274
echo "           Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG"
4258
echo "                  BSD Auth support: $BSD_AUTH_MSG"
4275
echo "                  BSD Auth support: $BSD_AUTH_MSG"
(-)openssh-5.3p1/key.c.nss-keys (+61 lines)
Lines 96-101 key_new(int type) Link Here
96
	return k;
96
	return k;
97
}
97
}
98
98
99
#ifdef HAVE_LIBNSS
100
Key *
101
key_new_nss(int type)
102
{
103
	Key *k = key_new(type);
104
105
	k->nss = xcalloc(1, sizeof(*k->nss));
106
	k->flags = KEY_FLAG_EXT | KEY_FLAG_NSS;
107
108
	return k;
109
}
110
111
Key *
112
key_new_nss_copy(int type, const Key *c)
113
{
114
	Key *k = key_new_nss(type);
115
116
	switch (k->type) {
117
		case KEY_RSA:
118
			if ((BN_copy(k->rsa->n, c->rsa->n) == NULL) ||
119
				(BN_copy(k->rsa->e, c->rsa->e) == NULL))
120
				fatal("key_new_nss_copy: BN_copy failed");
121
			break;
122
		case KEY_DSA:
123
			if ((BN_copy(k->dsa->p, c->rsa->p) == NULL) ||
124
				(BN_copy(k->dsa->q, c->dsa->q) == NULL) ||
125
				(BN_copy(k->dsa->g, c->dsa->g) == NULL) ||
126
				(BN_copy(k->dsa->pub_key, c->dsa->pub_key) == NULL))
127
				fatal("key_new_nss_copy: BN_copy failed");
128
			break;
129
	}
130
		
131
	k->nss->privk = SECKEY_CopyPrivateKey(c->nss->privk);
132
	if (k->nss->privk == NULL)
133
		fatal("key_new_nss_copy: SECKEY_CopyPrivateKey failed");
134
135
	k->nss->pubk = SECKEY_CopyPublicKey(c->nss->pubk);
136
	if (k->nss->pubk == NULL)
137
		fatal("key_new_nss_copy: SECKEY_CopyPublicKey failed");
138
	
139
	if (c->nss->privk->wincx)
140
		k->nss->privk->wincx = xstrdup(c->nss->privk->wincx);
141
142
	return k;
143
}
144
#endif
145
146
99
Key *
147
Key *
100
key_new_private(int type)
148
key_new_private(int type)
101
{
149
{
Lines 151-156 key_free(Key *k) Link Here
151
		fatal("key_free: bad key type %d", k->type);
199
		fatal("key_free: bad key type %d", k->type);
152
		break;
200
		break;
153
	}
201
	}
202
#ifdef HAVE_LIBNSS
203
	if (k->flags & KEY_FLAG_NSS) {
204
		if (k->nss->privk != NULL && k->nss->privk->wincx != NULL) {
205
			memset(k->nss->privk->wincx, 0,
206
				strlen(k->nss->privk->wincx));
207
			xfree(k->nss->privk->wincx);
208
			k->nss->privk->wincx = NULL;
209
		}
210
		SECKEY_DestroyPrivateKey(k->nss->privk);
211
		SECKEY_DestroyPublicKey(k->nss->pubk);
212
		xfree(k->nss);
213
	}
214
#endif
154
	xfree(k);
215
	xfree(k);
155
}
216
}
156
217
(-)openssh-5.3p1/key.h.nss-keys (+20 lines)
Lines 29-39 Link Here
29
#include <openssl/rsa.h>
29
#include <openssl/rsa.h>
30
#include <openssl/dsa.h>
30
#include <openssl/dsa.h>
31
31
32
#ifdef HAVE_LIBNSS
33
#include <nss.h>
34
#include <keyhi.h>
35
#endif
36
32
typedef struct Key Key;
37
typedef struct Key Key;
33
enum types {
38
enum types {
34
	KEY_RSA1,
39
	KEY_RSA1,
35
	KEY_RSA,
40
	KEY_RSA,
36
	KEY_DSA,
41
	KEY_DSA,
42
	KEY_NSS,
37
	KEY_UNSPEC
43
	KEY_UNSPEC
38
};
44
};
39
enum fp_type {
45
enum fp_type {
Lines 48-63 enum fp_rep { Link Here
48
54
49
/* key is stored in external hardware */
55
/* key is stored in external hardware */
50
#define KEY_FLAG_EXT		0x0001
56
#define KEY_FLAG_EXT		0x0001
57
#define KEY_FLAG_NSS		0x0002
58
59
#ifdef HAVE_LIBNSS
60
typedef struct NSSKey NSSKey;
61
struct NSSKey {
62
	SECKEYPrivateKey *privk;
63
	SECKEYPublicKey *pubk;
64
};
65
#endif
51
66
52
struct Key {
67
struct Key {
53
	int	 type;
68
	int	 type;
54
	int	 flags;
69
	int	 flags;
55
	RSA	*rsa;
70
	RSA	*rsa;
56
	DSA	*dsa;
71
	DSA	*dsa;
72
#ifdef HAVE_LIBNSS
73
	NSSKey  *nss;
74
#endif
57
};
75
};
58
76
59
Key		*key_new(int);
77
Key		*key_new(int);
60
Key		*key_new_private(int);
78
Key		*key_new_private(int);
79
Key 		*key_new_nss(int);
80
Key		*key_new_nss_copy(int, const Key *);
61
void		 key_free(Key *);
81
void		 key_free(Key *);
62
Key		*key_demote(const Key *);
82
Key		*key_demote(const Key *);
63
int		 key_equal(const Key *, const Key *);
83
int		 key_equal(const Key *, const Key *);
(-)openssh-5.3p1/Makefile.in.nss-keys (-1 / +1 lines)
Lines 71-77 LIBSSH_OBJS=acss.o authfd.o authfile.o b Link Here
71
	atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \
71
	atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \
72
	monitor_fdpass.o rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o \
72
	monitor_fdpass.o rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o \
73
	kexgex.o kexdhc.o kexgexc.o scard.o msg.o progressmeter.o dns.o \
73
	kexgex.o kexdhc.o kexgexc.o scard.o msg.o progressmeter.o dns.o \
74
	entropy.o scard-opensc.o gss-genr.o umac.o jpake.o schnorr.o
74
	entropy.o scard-opensc.o gss-genr.o umac.o jpake.o schnorr.o nsskeys.o
75
75
76
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
76
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
77
	sshconnect.o sshconnect1.o sshconnect2.o mux.o \
77
	sshconnect.o sshconnect1.o sshconnect2.o mux.o \
(-)/dev/null (+443 lines)
Added Link Here
1
/*
2
 * Copyright (c) 2001 Markus Friedl.  All rights reserved.
3
 * Copyright (c) 2007 Red Hat, Inc. All rights reserved.
4
 * Copyright (c) 2009 Pierre Ossman for Cendio AB
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
 */
26
27
#include "includes.h"
28
#ifdef HAVE_LIBNSS
29
30
#include <sys/types.h>
31
32
#include <stdarg.h>
33
#include <string.h>
34
#include <unistd.h>
35
36
#include <openssl/evp.h>
37
38
#include <nss.h>
39
#include <keyhi.h>
40
#include <pk11pub.h>
41
#include <cert.h>
42
#include <secmod.h>
43
#include <secerr.h>
44
45
#include "xmalloc.h"
46
#include "key.h"
47
#include "log.h"
48
#include "misc.h"
49
#include "nsskeys.h"
50
#include "pathnames.h"
51
52
static char *
53
password_cb(PK11SlotInfo *slot, PRBool retry, void *arg)
54
{
55
	char *password = arg;
56
	if (retry || password == NULL)
57
		return NULL;
58
	
59
	return PL_strdup(password);
60
}
61
62
int
63
nss_init(PK11PasswordFunc pwfn)
64
{
65
	char *dbpath;
66
	char buf[MAXPATHLEN];
67
68
	if (NSS_IsInitialized())
69
		return 0;
70
71
	if ((dbpath=getenv("NSS_DB_PATH")) == NULL) {
72
		struct passwd *pw;
73
		if ((pw = getpwuid(getuid())) == NULL ||
74
			pw->pw_dir == NULL) {
75
			return -1;
76
		}
77
		snprintf(buf, sizeof(buf), "%s/%s", pw->pw_dir,
78
			    _PATH_SSH_USER_DIR);
79
		dbpath = buf;
80
	}
81
82
	if (NSS_Init(dbpath) != SECSuccess) {
83
		debug("Failed to initialize NSS library. Attempting without DB...");
84
		if (NSS_NoDB_Init(NULL) != SECSuccess)
85
			return -1;
86
	}
87
88
	if (pwfn == NULL) {
89
		pwfn = password_cb;
90
	}
91
92
	PK11_SetPasswordFunc(pwfn);
93
	
94
	return 0;
95
}
96
97
int
98
nss_load_module(const char *modpath)
99
{
100
	char spec[MAXPATHLEN + 40];
101
	SECMODModule *module;
102
103
	debug("loading PKCS#11 module '%s'", modpath);
104
105
	snprintf(spec, sizeof(spec), "library=\"%s\" name=\"Foobar\"", modpath);
106
	module = SECMOD_LoadUserModule(spec, NULL, PR_FALSE);
107
	if (!module || !module->loaded) {
108
		if (module)
109
			SECMOD_DestroyModule(module);
110
		return -1;
111
	}
112
113
	return 0;
114
}
115
116
static Key *
117
make_key_from_privkey(SECKEYPrivateKey *privk, char *password)
118
{
119
	Key *k;
120
	switch (SECKEY_GetPrivateKeyType(privk)) {
121
		case rsaKey:
122
			k = key_new_nss(KEY_RSA);
123
			break;
124
		case dsaKey:
125
			k = key_new_nss(KEY_DSA);
126
			break;
127
		default:
128
			return NULL;
129
	}
130
	k->nss->pubk = SECKEY_ConvertToPublicKey(privk);
131
	if (k->nss->pubk != NULL) {
132
		k->nss->privk = SECKEY_CopyPrivateKey(privk);
133
	}
134
	if (k->nss->privk != NULL) {
135
		if (password != NULL) {
136
			k->nss->privk->wincx = xstrdup(password);
137
		}
138
		return k;
139
	}
140
	key_free(k);
141
	return NULL;
142
}
143
144
static Key **
145
add_key_to_list(Key *k, Key **keys, size_t *i, size_t *allocated)
146
{
147
	if (*allocated < *i + 2) {
148
		*allocated += 16;
149
		keys = xrealloc(keys, *allocated, sizeof(k));
150
	}
151
	keys[*i] = k;
152
	(*i)++;
153
	keys[*i] = NULL;
154
	return keys;
155
}
156
157
static int
158
nss_convert_pubkey(Key *k)
159
{
160
	u_char *n;
161
	unsigned int len;
162
	char *p;
163
164
	switch (k->type) {
165
		case KEY_RSA:
166
			n = k->nss->pubk->u.rsa.modulus.data;
167
			len = k->nss->pubk->u.rsa.modulus.len;
168
169
			if (BN_bin2bn(n, len, k->rsa->n) == NULL) {
170
				fatal("nss_convert_pubkey: BN_bin2bn failed");
171
			}
172
173
			n = k->nss->pubk->u.rsa.publicExponent.data;
174
			len = k->nss->pubk->u.rsa.publicExponent.len;
175
176
			if (BN_bin2bn(n, len, k->rsa->e) == NULL) {
177
				fatal("nss_convert_pubkey: BN_bin2bn failed");
178
			}
179
			break;
180
		case KEY_DSA:
181
			n = k->nss->pubk->u.dsa.params.prime.data;
182
			len = k->nss->pubk->u.dsa.params.prime.len;
183
184
			if (BN_bin2bn(n, len, k->dsa->p) == NULL) {
185
				fatal("nss_convert_pubkey: BN_bin2bn failed");
186
			}
187
188
			n = k->nss->pubk->u.dsa.params.subPrime.data;
189
			len = k->nss->pubk->u.dsa.params.subPrime.len;
190
191
			if (BN_bin2bn(n, len, k->dsa->q) == NULL) {
192
				fatal("nss_convert_pubkey: BN_bin2bn failed");
193
			}
194
195
			n = k->nss->pubk->u.dsa.params.base.data;
196
			len = k->nss->pubk->u.dsa.params.base.len;
197
198
			if (BN_bin2bn(n, len, k->dsa->g) == NULL) {
199
				fatal("nss_convert_pubkey: BN_bin2bn failed");
200
			}
201
202
			n = k->nss->pubk->u.dsa.publicValue.data;
203
			len = k->nss->pubk->u.dsa.publicValue.len;
204
205
			if (BN_bin2bn(n, len, k->dsa->pub_key) == NULL) {
206
				fatal("nss_convert_pubkey: BN_bin2bn failed");
207
			}
208
			break;
209
	}
210
211
	p = key_fingerprint(k, SSH_FP_MD5, SSH_FP_HEX);
212
	debug("fingerprint %u %s", key_size(k), p);
213
	xfree(p);
214
215
	return 0;
216
}
217
218
static int
219
nss_authenticate(PK11SlotInfo *slot, char *password, int pwprompts, char **output)
220
{
221
	int i, quit;
222
223
	*output = NULL;
224
225
	if (!PK11_NeedLogin(slot))
226
		return 0;
227
228
	for (i = 0; i < pwprompts; i++) {
229
		SECStatus rv;
230
		CK_TOKEN_INFO info;
231
232
		rv = PK11_GetTokenInfo(slot, &info);
233
		if (rv != SECSuccess) {
234
			error("Failed to get information for token %s",
235
				PK11_GetTokenName(slot));
236
			return -1;
237
		}
238
239
		if (info.flags & CKF_USER_PIN_LOCKED) {
240
			error("Passphrase for token %s is locked",
241
				PK11_GetTokenName(slot));
242
			return -1;
243
		}
244
245
		if (info.flags & CKF_USER_PIN_FINAL_TRY)
246
			debug2("Final passphrase attempt for token %s",
247
				PK11_GetTokenName(slot));
248
		else if (info.flags & CKF_USER_PIN_COUNT_LOW)
249
			debug2("Previous failed passphrase attempt for token %s",
250
				PK11_GetTokenName(slot));
251
252
		if (password != NULL)
253
			*output = xstrdup(password);
254
		else {
255
			char *prompt;
256
			if (asprintf(&prompt, "Enter passphrase for token %s: ",
257
				PK11_GetTokenName(slot)) < 0)
258
				fatal("password_cb: asprintf failed");
259
			*output = read_passphrase(prompt, RP_ALLOW_STDIN);
260
		}
261
262
		if (strcmp(*output, "") == 0) {
263
			debug2("no passphrase given, ignoring slot");
264
			quit = 1;
265
			goto cleanup;
266
		}
267
268
		quit = 0;
269
270
		rv = PK11_Authenticate(slot, PR_TRUE, *output);
271
		if (rv == SECSuccess)
272
			return 0;
273
274
		switch (PORT_GetError()) {
275
		case SEC_ERROR_BAD_PASSWORD:
276
			debug2("Incorrect passphrase, try again...");
277
			break;
278
		case SEC_ERROR_INVALID_ARGS:
279
		case SEC_ERROR_BAD_DATA:
280
			debug2("Invalid passphrase, try again...");
281
			break;
282
#if HAVE_SEC_ERROR_LOCKED_PASSWORD
283
		case SEC_ERROR_LOCKED_PASSWORD:
284
			error("Unable to authenticate, token passphrase is locked");
285
			quit = 1;
286
			break;
287
#endif
288
		default:
289
			error("Failure while authenticating against token");
290
			quit = 1;
291
		}
292
293
cleanup:
294
		memset(*output, 0, strlen(*output));
295
		xfree(*output);
296
		*output = NULL;
297
298
		/* No point in retrying the same password */
299
		if (password != NULL)
300
			break;
301
302
		if (quit)
303
			break;
304
	}
305
306
	return -1;
307
}
308
309
static Key **
310
nss_find_privkeys(const char *tokenname, const char *keyname,
311
    char *password, int pwprompts)
312
{
313
	Key *k = NULL;
314
	Key **keys = NULL;
315
	PK11SlotList *slots;
316
	PK11SlotListElement *sle;
317
	size_t allocated = 0;
318
	size_t i = 0;
319
320
	if ((slots=PK11_FindSlotsByNames(NULL, NULL, tokenname, PR_TRUE)) == NULL) {
321
		if (tokenname == NULL) {
322
			debug("No NSS token found");
323
		} else {
324
			debug("NSS token not found: %s", tokenname);
325
		}
326
		return NULL;
327
	}
328
	
329
	for (sle = slots->head; sle; sle = sle->next) {
330
		SECKEYPrivateKeyList *list;
331
		SECKEYPrivateKeyListNode *node;
332
		char *tmppass;
333
334
		if (nss_authenticate(sle->slot, password, pwprompts, &tmppass) == -1)
335
			break;
336
337
		debug("Looking for: %s:%s", tokenname, keyname);
338
		list = PK11_ListPrivKeysInSlot(sle->slot, (char *)keyname,
339
			tmppass);
340
		if (list == NULL && keyname != NULL) {
341
			char *fooname;
342
			/* NSS bug workaround */
343
			if (asprintf(&fooname, "%s~", keyname) < 0) {
344
				error("nss_find_privkey: asprintf failed");
345
				PK11_FreeSlotList(slots);
346
				return NULL;
347
			}
348
			list = PK11_ListPrivKeysInSlot(sle->slot, fooname,
349
			tmppass);
350
			free(fooname);
351
		}
352
		if (list == NULL && keyname != NULL) {
353
			CERTCertificate *cert;
354
			SECKEYPrivateKey *privk;
355
			cert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(),
356
				(char *)keyname);
357
			if (cert == NULL)
358
				goto cleanup;
359
			privk = PK11_FindPrivateKeyFromCert(sle->slot, cert, tmppass);
360
			CERT_DestroyCertificate(cert);
361
			if (privk == NULL)
362
				goto cleanup;
363
			if ((k=make_key_from_privkey(privk, tmppass)) != NULL) {
364
				nss_convert_pubkey(k);
365
				keys = add_key_to_list(k, keys, &i, &allocated);
366
			}
367
			SECKEY_DestroyPrivateKey(privk);
368
		} else {
369
			if (list == NULL)
370
				goto cleanup;
371
			for (node=PRIVKEY_LIST_HEAD(list); !PRIVKEY_LIST_END(node, list);
372
				node=PRIVKEY_LIST_NEXT(node))
373
				if ((k=make_key_from_privkey(node->key, tmppass)) != NULL) {
374
					nss_convert_pubkey(k);
375
					keys = add_key_to_list(k, keys, &i, &allocated);
376
				}
377
			SECKEY_DestroyPrivateKeyList(list);
378
		}
379
cleanup:
380
		if (tmppass != NULL) {
381
			memset(tmppass, 0, strlen(tmppass));
382
			xfree(tmppass);
383
		}
384
	}
385
	PK11_FreeSlotList(slots);
386
387
	return keys;
388
}
389
390
Key **
391
nss_get_keys(const char *tokenname, const char *keyname,
392
    char *password, int pwprompts, int num_modules, const char **modules)
393
{
394
	int i;
395
	Key **keys;
396
397
	if (nss_init(NULL) == -1) {
398
		error("Failed to initialize NSS library");
399
		return NULL;
400
	}
401
402
	for (i = 0;i < num_modules;i++) {
403
		if (nss_load_module(modules[i]) == -1) {
404
			error("Failed to load PKCS#11 module '%s'", modules[i]);
405
			return NULL;
406
		}
407
	}
408
409
	keys = nss_find_privkeys(tokenname, keyname, password, pwprompts);
410
	if (keys == NULL && keyname != NULL) {
411
		error("Cannot find key in nss, token removed");
412
		return NULL;
413
	}
414
#if 0
415
	keys = xcalloc(3, sizeof(Key *));
416
417
	if (k->type == KEY_RSA) {
418
		n = key_new_nss_copy(KEY_RSA1, k);
419
420
		keys[0] = n;
421
		keys[1] = k;
422
		keys[2] = NULL;
423
	} else {
424
		keys[0] = k;
425
		keys[1] = NULL;
426
	}
427
#endif
428
	return keys;
429
}
430
431
char *
432
nss_get_key_label(Key *key)
433
{
434
	char *label, *nickname;
435
	
436
	nickname = PK11_GetPrivateKeyNickname(key->nss->privk);
437
	label = xstrdup(nickname);
438
	PORT_Free(nickname);
439
440
	return label;
441
}
442
443
#endif /* HAVE_LIBNSS */
(-)/dev/null (+39 lines)
Added Link Here
1
/*
2
 * Copyright (c) 2001 Markus Friedl.  All rights reserved.
3
 * Copyright (c) 2007 Red Hat, Inc.  All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 *
14
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
#ifndef NSSKEYS_H
27
#define NSSKEYS_H
28
#ifdef HAVE_LIBNSS
29
#include <pk11func.h>
30
#include <prtypes.h>
31
32
int	nss_init(PK11PasswordFunc);
33
Key	**nss_get_keys(const char *, const char *, char *, int , int , const char **);
34
char	*nss_get_key_label(Key *);
35
/*void	 sc_close(void);*/
36
/*int	 sc_put_key(Key *, const char *);*/
37
38
#endif
39
#endif
(-)openssh-5.3p1/readconf.c.nss-keys (+37 lines)
Lines 124-129 typedef enum { Link Here
124
	oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
124
	oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
125
	oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
125
	oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
126
	oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
126
	oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
127
	oUseNSS, oNSSToken, oNSSModule,
127
	oClearAllForwardings, oNoHostAuthenticationForLocalhost,
128
	oClearAllForwardings, oNoHostAuthenticationForLocalhost,
128
	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
129
	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
129
	oAddressFamily, oGssAuthentication, oGssDelegateCreds,
130
	oAddressFamily, oGssAuthentication, oGssDelegateCreds,
Lines 210-215 static struct { Link Here
210
#else
211
#else
211
	{ "smartcarddevice", oUnsupported },
212
	{ "smartcarddevice", oUnsupported },
212
#endif
213
#endif
214
#ifdef HAVE_LIBNSS
215
	{ "usenss", oUseNSS },
216
	{ "nsstoken", oNSSToken },
217
	{ "nssmodule", oNSSModule },
218
#else
219
	{ "usenss", oUnsupported },
220
	{ "nsstoken", oNSSToken },
221
	{ "nssmodule", oUnsupported },
222
#endif
213
	{ "clearallforwardings", oClearAllForwardings },
223
	{ "clearallforwardings", oClearAllForwardings },
214
	{ "enablesshkeysign", oEnableSSHKeysign },
224
	{ "enablesshkeysign", oEnableSSHKeysign },
215
	{ "verifyhostkeydns", oVerifyHostKeyDNS },
225
	{ "verifyhostkeydns", oVerifyHostKeyDNS },
Lines 613-618 parse_string: Link Here
613
		charptr = &options->smartcard_device;
623
		charptr = &options->smartcard_device;
614
		goto parse_string;
624
		goto parse_string;
615
625
626
	case oUseNSS:
627
		intptr = &options->use_nss;
628
		goto parse_flag;
629
630
	case oNSSToken:
631
		charptr = &options->nss_token;
632
		goto parse_command;
633
634
	case oNSSModule:
635
		arg = strdelim(&s);
636
		if (!arg || *arg == '\0')
637
			fatal("%.200s line %d: Missing argument.", filename, linenum);
638
		if (*activep) {
639
			intptr = &options->num_nss_modules;
640
			if (*intptr >= SSH_MAX_NSS_MODULES)
641
				fatal("%.200s line %d: Too many PKCS#11 modules specified (max %d).",
642
				    filename, linenum, SSH_MAX_NSS_MODULES);
643
			charptr = &options->nss_modules[*intptr];
644
			*charptr = xstrdup(arg);
645
			*intptr = *intptr + 1;
646
		}
647
		break;
616
	case oProxyCommand:
648
	case oProxyCommand:
617
		charptr = &options->proxy_command;
649
		charptr = &options->proxy_command;
618
parse_command:
650
parse_command:
Lines 1052-1057 initialize_options(Options * options) Link Here
1052
	options->preferred_authentications = NULL;
1084
	options->preferred_authentications = NULL;
1053
	options->bind_address = NULL;
1085
	options->bind_address = NULL;
1054
	options->smartcard_device = NULL;
1086
	options->smartcard_device = NULL;
1087
	options->use_nss = -1;
1088
	options->nss_token = NULL;
1089
	options->num_nss_modules = 0;
1055
	options->enable_ssh_keysign = - 1;
1090
	options->enable_ssh_keysign = - 1;
1056
	options->no_host_authentication_for_localhost = - 1;
1091
	options->no_host_authentication_for_localhost = - 1;
1057
	options->identities_only = - 1;
1092
	options->identities_only = - 1;
Lines 1183-1188 fill_default_options(Options * options) Link Here
1183
		options->no_host_authentication_for_localhost = 0;
1218
		options->no_host_authentication_for_localhost = 0;
1184
	if (options->identities_only == -1)
1219
	if (options->identities_only == -1)
1185
		options->identities_only = 0;
1220
		options->identities_only = 0;
1221
	if (options->use_nss == -1)
1222
		options->use_nss = 0;
1186
	if (options->enable_ssh_keysign == -1)
1223
	if (options->enable_ssh_keysign == -1)
1187
		options->enable_ssh_keysign = 0;
1224
		options->enable_ssh_keysign = 0;
1188
	if (options->rekey_limit == -1)
1225
	if (options->rekey_limit == -1)
(-)openssh-5.3p1/readconf.h.nss-keys (+4 lines)
Lines 85-90 typedef struct { Link Here
85
	char   *preferred_authentications;
85
	char   *preferred_authentications;
86
	char   *bind_address;	/* local socket address for connection to sshd */
86
	char   *bind_address;	/* local socket address for connection to sshd */
87
	char   *smartcard_device; /* Smartcard reader device */
87
	char   *smartcard_device; /* Smartcard reader device */
88
	int     use_nss;        /* Use NSS library for keys */
89
	char   *nss_token;      /* Look for NSS keys on token */
90
	int     num_nss_modules; /* Number of PCKS#11 modules. */
91
	char   *nss_modules[SSH_MAX_NSS_MODULES];
88
	int	verify_host_key_dns;	/* Verify host key using DNS */
92
	int	verify_host_key_dns;	/* Verify host key using DNS */
89
93
90
	int     num_identity_files;	/* Number of files for RSA/DSA identities. */
94
	int     num_identity_files;	/* Number of files for RSA/DSA identities. */
(-)openssh-5.3p1/ssh-add.c.nss-keys (-1 / +180 lines)
Lines 44-49 Link Here
44
#include <openssl/evp.h>
44
#include <openssl/evp.h>
45
#include "openbsd-compat/openssl-compat.h"
45
#include "openbsd-compat/openssl-compat.h"
46
46
47
#ifdef HAVE_LIBNSS
48
#include <nss.h>
49
#include <secmod.h>
50
#include <pk11pub.h>
51
#include <keyhi.h>
52
#include <cert.h>
53
#endif
54
47
#include <fcntl.h>
55
#include <fcntl.h>
48
#include <pwd.h>
56
#include <pwd.h>
49
#include <stdarg.h>
57
#include <stdarg.h>
Lines 57-62 Link Here
57
#include "rsa.h"
65
#include "rsa.h"
58
#include "log.h"
66
#include "log.h"
59
#include "key.h"
67
#include "key.h"
68
#include "nsskeys.h"
60
#include "buffer.h"
69
#include "buffer.h"
61
#include "authfd.h"
70
#include "authfd.h"
62
#include "authfile.h"
71
#include "authfile.h"
Lines 307-312 do_file(AuthenticationConnection *ac, in Link Here
307
	return 0;
316
	return 0;
308
}
317
}
309
318
319
#ifdef HAVE_LIBNSS
320
static char *
321
password_cb(PK11SlotInfo *slot, PRBool retry, void *arg)
322
{
323
	char **passcache = arg;
324
	char *password, *p2 = NULL;
325
	char *prompt;
326
	
327
	if (retry)
328
		return NULL;
329
	
330
	if (asprintf(&prompt, "Enter passphrase for token %s: ",
331
		PK11_GetTokenName(slot)) < 0)
332
		fatal("password_cb: asprintf failed");
333
334
	password = read_passphrase(prompt, RP_ALLOW_STDIN);
335
	
336
	if (password != NULL && (p2=PL_strdup(password)) == NULL) {
337
		memset(password, 0, strlen(password));
338
		fatal("password_cb: PL_strdup failed");
339
	}
340
341
	if (passcache != NULL) {
342
		if (*passcache != NULL) {
343
			memset(*passcache, 0, strlen(*passcache));
344
			xfree(*passcache);
345
		}
346
		*passcache = password;
347
	} else {
348
		memset(password, 0, strlen(password));
349
		xfree(password);
350
	}
351
	
352
	return p2;
353
}
354
355
static int
356
add_slot_keys(AuthenticationConnection *ac, PK11SlotInfo *slot, int add)
357
{
358
	SECKEYPrivateKeyList *list;
359
	SECKEYPrivateKeyListNode *node;
360
	char *passcache = NULL;
361
	char *tokenname;
362
	char **xkeyname = NULL;
363
	
364
	int count = 0;
365
	int i;
366
	
367
	if (PK11_NeedLogin(slot))
368
		PK11_Authenticate(slot, PR_TRUE, &passcache);
369
		
370
	if ((list=PK11_ListPrivKeysInSlot(slot, NULL, NULL)) == NULL) {
371
		return 0;
372
	}
373
	
374
	tokenname = PK11_GetTokenName(slot);
375
	
376
	for (node=PRIVKEY_LIST_HEAD(list); !PRIVKEY_LIST_END(node, list);
377
		node=PRIVKEY_LIST_NEXT(node)) {
378
		char *keyname;
379
		SECKEYPublicKey *pub;
380
		
381
		keyname = PK11_GetPrivateKeyNickname(node->key);
382
		if (keyname == NULL || *keyname == '\0') {
383
			/* no nickname to refer to */
384
			CERTCertificate *cert;
385
			char *kn;
386
			cert = PK11_GetCertFromPrivateKey(node->key);
387
			if (cert == NULL)
388
				continue;
389
			kn = strchr(cert->nickname, ':');
390
			if (kn == NULL)
391
				kn = cert->nickname;
392
			else
393
				kn++;
394
			keyname = PORT_Strdup(kn);
395
			CERT_DestroyCertificate(cert);
396
			if (keyname == NULL)
397
				continue;
398
		}
399
		pub = SECKEY_ConvertToPublicKey(node->key);
400
		if (pub == NULL) {
401
			fprintf(stderr, "No public key for: %s:%s\n",
402
				tokenname, keyname);
403
			continue; /* not possible to obtain public key */
404
		}
405
		SECKEY_DestroyPublicKey(pub);
406
	
407
		if ((count % 10) == 0)	
408
			xkeyname = xrealloc (xkeyname, count + 10, sizeof (char *));
409
		
410
		xkeyname[count++] = keyname;
411
	}
412
413
	PK11_Logout(slot);
414
415
	for (i = 0; i < count; i++) {
416
		if (ssh_update_nss_key(ac, add, tokenname, xkeyname[i],
417
			passcache?passcache:"",	lifetime, confirm)) {
418
			fprintf(stderr, "Key %s: %s:%s\n",
419
				add?"added":"removed", tokenname, xkeyname[i]);
420
		} else {
421
			fprintf(stderr, "Could not %s key: %s:%s\n",
422
				add?"add":"remove", tokenname, xkeyname[i]);
423
		}
424
		PORT_Free(xkeyname[i]);
425
	}
426
427
	if (xkeyname != NULL)
428
		free (xkeyname);
429
430
	if (passcache != NULL) {
431
		memset(passcache, 0, strlen(passcache));
432
		xfree(passcache);
433
	}
434
	
435
	SECKEY_DestroyPrivateKeyList(list);
436
	
437
	return count;
438
}
439
#endif
440
310
static void
441
static void
311
usage(void)
442
usage(void)
312
{
443
{
Lines 334-339 main(int argc, char **argv) Link Here
334
	AuthenticationConnection *ac = NULL;
465
	AuthenticationConnection *ac = NULL;
335
	char *sc_reader_id = NULL;
466
	char *sc_reader_id = NULL;
336
	int i, ch, deleting = 0, ret = 0;
467
	int i, ch, deleting = 0, ret = 0;
468
#ifdef HAVE_LIBNSS
469
	char *token_id = NULL;
470
	int use_nss = 0;
471
#endif
337
472
338
	/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
473
	/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
339
	sanitise_stdfd();
474
	sanitise_stdfd();
Lines 351-357 main(int argc, char **argv) Link Here
351
		    "Could not open a connection to your authentication agent.\n");
486
		    "Could not open a connection to your authentication agent.\n");
352
		exit(2);
487
		exit(2);
353
	}
488
	}
354
	while ((ch = getopt(argc, argv, "lLcdDxXe:s:t:")) != -1) {
489
	while ((ch = getopt(argc, argv, "lLcdDnxXe:s:t:T:")) != -1) {
355
		switch (ch) {
490
		switch (ch) {
356
		case 'l':
491
		case 'l':
357
		case 'L':
492
		case 'L':
Lines 373-378 main(int argc, char **argv) Link Here
373
			if (delete_all(ac) == -1)
508
			if (delete_all(ac) == -1)
374
				ret = 1;
509
				ret = 1;
375
			goto done;
510
			goto done;
511
#ifdef HAVE_LIBNSS
512
		case 'n':
513
			use_nss = 1;
514
			break;
515
#endif
376
		case 's':
516
		case 's':
377
			sc_reader_id = optarg;
517
			sc_reader_id = optarg;
378
			break;
518
			break;
Lines 387-392 main(int argc, char **argv) Link Here
387
				goto done;
527
				goto done;
388
			}
528
			}
389
			break;
529
			break;
530
#ifdef HAVE_LIBNSS
531
		case 'T':
532
			token_id = optarg;
533
			break;
534
#endif
390
		default:
535
		default:
391
			usage();
536
			usage();
392
			ret = 1;
537
			ret = 1;
Lines 400-405 main(int argc, char **argv) Link Here
400
			ret = 1;
545
			ret = 1;
401
		goto done;
546
		goto done;
402
	}
547
	}
548
#ifdef HAVE_LIBNSS
549
	if (use_nss) {
550
		PK11SlotList *slots;
551
		PK11SlotListElement *sle;
552
		int count = 0;
553
		if (nss_init(password_cb) == -1) {
554
			fprintf(stderr, "Failed to initialize NSS library\n");
555
			ret = 1;
556
			goto done;
557
		}
558
		
559
		if ((slots=PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE,
560
			NULL)) == NULL) {
561
			fprintf(stderr, "No tokens found\n");
562
			ret = 1;
563
			goto nss_done;
564
		}
565
566
		for (sle = slots->head; sle; sle = sle->next) {
567
			int rv;
568
			if ((rv=add_slot_keys(ac, sle->slot, !deleting)) == -1) {
569
				ret = 1;
570
			}
571
			count += rv;
572
		}
573
		if (count == 0) {
574
			ret = 1;
575
		}
576
nss_done:		
577
		NSS_Shutdown();
578
		clear_pass();
579
		goto done;
580
	}
581
#endif
403
	if (argc == 0) {
582
	if (argc == 0) {
404
		char buf[MAXPATHLEN];
583
		char buf[MAXPATHLEN];
405
		struct passwd *pw;
584
		struct passwd *pw;
(-)openssh-5.3p1/ssh-agent.c.nss-keys (+121 lines)
Lines 80-85 Link Here
80
#include "scard.h"
80
#include "scard.h"
81
#endif
81
#endif
82
82
83
#ifdef HAVE_LIBNSS
84
#include "nsskeys.h"
85
#endif
86
83
#if defined(HAVE_SYS_PRCTL_H)
87
#if defined(HAVE_SYS_PRCTL_H)
84
#include <sys/prctl.h>	/* For prctl() and PR_SET_DUMPABLE */
88
#include <sys/prctl.h>	/* For prctl() and PR_SET_DUMPABLE */
85
#endif
89
#endif
Lines 714-719 send: Link Here
714
}
718
}
715
#endif /* SMARTCARD */
719
#endif /* SMARTCARD */
716
720
721
#ifdef HAVE_LIBNSS
722
static void
723
process_add_nss_key (SocketEntry *e)
724
{
725
	char *tokenname = NULL, *keyname = NULL, *password = NULL;
726
	int i, version, success = 0, death = 0, confirm = 0;
727
	Key **keys, *k;
728
	Identity *id;
729
	Idtab *tab;
730
731
	tokenname = buffer_get_string(&e->request, NULL);
732
	keyname = buffer_get_string(&e->request, NULL);
733
	password = buffer_get_string(&e->request, NULL);
734
735
	while (buffer_len(&e->request)) {
736
		switch (buffer_get_char(&e->request)) {
737
		case SSH_AGENT_CONSTRAIN_LIFETIME:
738
			death = time(NULL) + buffer_get_int(&e->request);
739
			break;
740
		case SSH_AGENT_CONSTRAIN_CONFIRM:
741
			confirm = 1;
742
			break;
743
		default:
744
			break;
745
		}
746
	}
747
	if (lifetime && !death)
748
		death = time(NULL) + lifetime;
749
750
	keys = nss_get_keys(tokenname, keyname, password, 1, 0, NULL);
751
	/* password is owned by keys[0] now */
752
	xfree(tokenname);
753
	xfree(keyname);
754
755
	if (keys == NULL) {
756
		memset(password, 0, strlen(password));
757
		xfree(password);
758
		error("nss_get_keys failed");
759
		goto send;
760
	}
761
	for (i = 0; keys[i] != NULL; i++) {
762
		k = keys[i];
763
		version = k->type == KEY_RSA1 ? 1 : 2;
764
		tab = idtab_lookup(version);
765
		if (lookup_identity(k, version) == NULL) {
766
			id = xmalloc(sizeof(Identity));
767
			id->key = k;
768
			id->comment = nss_get_key_label(k);
769
			id->death = death;
770
			id->confirm = confirm;
771
			TAILQ_INSERT_TAIL(&tab->idlist, id, next);
772
			tab->nentries++;
773
			success = 1;
774
		} else {
775
			key_free(k);
776
		}
777
		keys[i] = NULL;
778
	}
779
	xfree(keys);
780
send:
781
	buffer_put_int(&e->output, 1);
782
	buffer_put_char(&e->output,
783
	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
784
}
785
786
static void
787
process_remove_nss_key(SocketEntry *e)
788
{
789
	char *tokenname = NULL, *keyname = NULL, *password = NULL;
790
	int i, version, success = 0;
791
	Key **keys, *k = NULL;
792
	Identity *id;
793
	Idtab *tab;
794
795
	tokenname = buffer_get_string(&e->request, NULL);
796
	keyname = buffer_get_string(&e->request, NULL);
797
	password = buffer_get_string(&e->request, NULL);
798
799
	keys = nss_get_keys(tokenname, keyname, password, 1, 0, NULL);
800
	xfree(tokenname);
801
	xfree(keyname);
802
	xfree(password);
803
804
	if (keys == NULL || keys[0] == NULL) {
805
		error("nss_get_keys failed");
806
		goto send;
807
	}
808
	for (i = 0; keys[i] != NULL; i++) {
809
		k = keys[i];
810
		version = k->type == KEY_RSA1 ? 1 : 2;
811
		if ((id = lookup_identity(k, version)) != NULL) {
812
			tab = idtab_lookup(version);
813
			TAILQ_REMOVE(&tab->idlist, id, next);
814
			tab->nentries--;
815
			free_identity(id);
816
			success = 1;
817
		}
818
		key_free(k);
819
		keys[i] = NULL;
820
	}
821
	xfree(keys);
822
send:
823
	buffer_put_int(&e->output, 1);
824
	buffer_put_char(&e->output,
825
	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
826
}
827
#endif /* HAVE_LIBNSS */
828
717
/* dispatch incoming messages */
829
/* dispatch incoming messages */
718
830
719
static void
831
static void
Lines 806-811 process_message(SocketEntry *e) Link Here
806
		process_remove_smartcard_key(e);
918
		process_remove_smartcard_key(e);
807
		break;
919
		break;
808
#endif /* SMARTCARD */
920
#endif /* SMARTCARD */
921
#ifdef HAVE_LIBNSS
922
	case SSH_AGENTC_ADD_NSS_KEY:
923
	case SSH_AGENTC_ADD_NSS_KEY_CONSTRAINED:
924
		process_add_nss_key(e);
925
		break;
926
	case SSH_AGENTC_REMOVE_NSS_KEY:
927
		process_remove_nss_key(e);
928
		break;
929
#endif /* SMARTCARD */
809
	default:
930
	default:
810
		/* Unknown message.  Respond with failure. */
931
		/* Unknown message.  Respond with failure. */
811
		error("Unknown message %d", type);
932
		error("Unknown message %d", type);
(-)openssh-5.3p1/ssh.c.nss-keys (-1 / +29 lines)
Lines 105-110 Link Here
105
#ifdef SMARTCARD
105
#ifdef SMARTCARD
106
#include "scard.h"
106
#include "scard.h"
107
#endif
107
#endif
108
#ifdef HAVE_LIBNSS
109
#include "nsskeys.h"
110
#endif
108
111
109
extern char *__progname;
112
extern char *__progname;
110
113
Lines 1234-1242 load_public_identity_files(void) Link Here
1234
	int i = 0;
1237
	int i = 0;
1235
	Key *public;
1238
	Key *public;
1236
	struct passwd *pw;
1239
	struct passwd *pw;
1237
#ifdef SMARTCARD
1240
#if defined(SMARTCARD) || defined(HAVE_LIBNSS)
1238
	Key **keys;
1241
	Key **keys;
1242
#endif
1239
1243
1244
#ifdef SMARTCARD
1240
	if (options.smartcard_device != NULL &&
1245
	if (options.smartcard_device != NULL &&
1241
	    options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
1246
	    options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
1242
	    (keys = sc_get_keys(options.smartcard_device, NULL)) != NULL) {
1247
	    (keys = sc_get_keys(options.smartcard_device, NULL)) != NULL) {
Lines 1259-1264 load_public_identity_files(void) Link Here
1259
		xfree(keys);
1264
		xfree(keys);
1260
	}
1265
	}
1261
#endif /* SMARTCARD */
1266
#endif /* SMARTCARD */
1267
#ifdef HAVE_LIBNSS
1268
	if (options.use_nss &&
1269
	    options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
1270
	    (keys = nss_get_keys(options.nss_token, NULL, NULL, 
1271
	    	options.number_of_password_prompts, options.num_nss_modules,
1272
	    	options.nss_modules)) != NULL) {
1273
		int count;
1274
		for (count = 0; keys[count] != NULL; count++) {
1275
			memmove(&options.identity_files[1], &options.identity_files[0],
1276
			    sizeof(char *) * (SSH_MAX_IDENTITY_FILES - 1));
1277
			memmove(&options.identity_keys[1], &options.identity_keys[0],
1278
			    sizeof(Key *) * (SSH_MAX_IDENTITY_FILES - 1));
1279
			options.num_identity_files++;
1280
			options.identity_keys[0] = keys[count];
1281
			options.identity_files[0] = nss_get_key_label(keys[count]);
1282
		}
1283
		if (options.num_identity_files > SSH_MAX_IDENTITY_FILES)
1284
			options.num_identity_files = SSH_MAX_IDENTITY_FILES;
1285
		i += count;
1286
		xfree(keys);
1287
	}
1288
#endif /* HAVE_LIBNSS */
1289
1262
	if ((pw = getpwuid(original_real_uid)) == NULL)
1290
	if ((pw = getpwuid(original_real_uid)) == NULL)
1263
		fatal("load_public_identity_files: getpwuid failed");
1291
		fatal("load_public_identity_files: getpwuid failed");
1264
	pwname = xstrdup(pw->pw_name);
1292
	pwname = xstrdup(pw->pw_name);
(-)openssh-5.3p1/ssh-dss.c.nss-keys (-1 / +35 lines)
Lines 39-44 Link Here
39
#include "log.h"
39
#include "log.h"
40
#include "key.h"
40
#include "key.h"
41
41
42
#ifdef HAVE_LIBNSS
43
#include <cryptohi.h>
44
#endif
45
42
#define INTBLOB_LEN	20
46
#define INTBLOB_LEN	20
43
#define SIGBLOB_LEN	(2*INTBLOB_LEN)
47
#define SIGBLOB_LEN	(2*INTBLOB_LEN)
44
48
Lines 57-62 ssh_dss_sign(const Key *key, u_char **si Link Here
57
		error("ssh_dss_sign: no DSA key");
61
		error("ssh_dss_sign: no DSA key");
58
		return -1;
62
		return -1;
59
	}
63
	}
64
#ifdef HAVE_LIBNSS
65
	if (key->flags & KEY_FLAG_NSS) {
66
		SECItem sigitem;
67
		SECItem *rawsig;
68
69
		memset(&sigitem, 0, sizeof(sigitem));
70
		if (SEC_SignData(&sigitem, (u_char *)data, datalen, key->nss->privk,
71
			SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) != SECSuccess) {
72
			error("ssh_dss_sign: sign failed");
73
			return -1;
74
		}
75
		
76
		if ((rawsig=DSAU_DecodeDerSig(&sigitem)) == NULL) {
77
			error("ssh_dss_sign: der decode failed");
78
			SECITEM_ZfreeItem(&sigitem, PR_FALSE);
79
			return -1;
80
		}
81
		SECITEM_ZfreeItem(&sigitem, PR_FALSE);
82
		if (rawsig->len != SIGBLOB_LEN) {
83
			error("ssh_dss_sign: unsupported signature length %d",
84
				rawsig->len);
85
			SECITEM_ZfreeItem(rawsig, PR_TRUE);
86
			return -1;
87
		}
88
		memcpy(sigblob, rawsig->data, SIGBLOB_LEN);
89
		SECITEM_ZfreeItem(rawsig, PR_TRUE);
90
	} else {
91
#endif
60
	EVP_DigestInit(&md, evp_md);
92
	EVP_DigestInit(&md, evp_md);
61
	EVP_DigestUpdate(&md, data, datalen);
93
	EVP_DigestUpdate(&md, data, datalen);
62
	EVP_DigestFinal(&md, digest, &dlen);
94
	EVP_DigestFinal(&md, digest, &dlen);
Lines 80-86 ssh_dss_sign(const Key *key, u_char **si Link Here
80
	BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen);
112
	BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen);
81
	BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen);
113
	BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen);
82
	DSA_SIG_free(sig);
114
	DSA_SIG_free(sig);
83
115
#ifdef HAVE_LIBNSS
116
	}
117
#endif
84
	if (datafellows & SSH_BUG_SIGBLOB) {
118
	if (datafellows & SSH_BUG_SIGBLOB) {
85
		if (lenp != NULL)
119
		if (lenp != NULL)
86
			*lenp = SIGBLOB_LEN;
120
			*lenp = SIGBLOB_LEN;
(-)openssh-5.3p1/ssh.h.nss-keys (+6 lines)
Lines 28-33 Link Here
28
#define SSH_MAX_IDENTITY_FILES		100
28
#define SSH_MAX_IDENTITY_FILES		100
29
29
30
/*
30
/*
31
 * Maximum number of PKCS#11 modules that can be specified in configuration
32
 * files or on the command line.
33
 */
34
#define SSH_MAX_NSS_MODULES			10
35
36
/*
31
 * Maximum length of lines in authorized_keys file.
37
 * Maximum length of lines in authorized_keys file.
32
 * Current value permits 16kbit RSA and RSA1 keys and 8kbit DSA keys, with
38
 * Current value permits 16kbit RSA and RSA1 keys and 8kbit DSA keys, with
33
 * some room for options and comments.
39
 * some room for options and comments.
(-)openssh-5.3p1/ssh-keygen.c.nss-keys (-5 / +46 lines)
Lines 53-58 Link Here
53
#include "scard.h"
53
#include "scard.h"
54
#endif
54
#endif
55
55
56
#ifdef HAVE_LIBNSS
57
#include <nss.h>
58
#include "nsskeys.h"
59
#endif
60
56
/* Number of bits in the RSA/DSA key.  This value can be set on the command line. */
61
/* Number of bits in the RSA/DSA key.  This value can be set on the command line. */
57
#define DEFAULT_BITS		2048
62
#define DEFAULT_BITS		2048
58
#define DEFAULT_BITS_DSA	1024
63
#define DEFAULT_BITS_DSA	1024
Lines 501-506 do_download(struct passwd *pw, const cha Link Here
501
}
506
}
502
#endif /* SMARTCARD */
507
#endif /* SMARTCARD */
503
508
509
#ifdef HAVE_LIBNSS
510
static void
511
do_nss_download(struct passwd *pw, const char *tokenname, const char *keyname)
512
{
513
	Key **keys = NULL;
514
	int i;
515
	
516
	keys = nss_get_keys(tokenname, keyname, NULL, 1, 0, NULL);
517
	if (keys == NULL)
518
		fatal("cannot find public key in NSS");
519
	for (i = 0; keys[i]; i++) {
520
		key_write(keys[i], stdout);
521
		key_free(keys[i]);
522
		fprintf(stdout, "\n");
523
	}
524
	xfree(keys);
525
	exit(0);
526
}
527
#endif /* HAVE_LIBNSS */
528
504
static void
529
static void
505
do_fingerprint(struct passwd *pw)
530
do_fingerprint(struct passwd *pw)
506
{
531
{
Lines 1083-1089 main(int argc, char **argv) Link Here
1083
	Key *private, *public;
1108
	Key *private, *public;
1084
	struct passwd *pw;
1109
	struct passwd *pw;
1085
	struct stat st;
1110
	struct stat st;
1086
	int opt, type, fd, download = 0;
1111
	int opt, type, fd, download = 1;
1112
	int use_nss = 0;
1087
	u_int32_t memory = 0, generator_wanted = 0, trials = 100;
1113
	u_int32_t memory = 0, generator_wanted = 0, trials = 100;
1088
	int do_gen_candidates = 0, do_screen_candidates = 0;
1114
	int do_gen_candidates = 0, do_screen_candidates = 0;
1089
	BIGNUM *start = NULL;
1115
	BIGNUM *start = NULL;
Lines 1116-1122 main(int argc, char **argv) Link Here
1116
	}
1142
	}
1117
1143
1118
	while ((opt = getopt(argc, argv,
1144
	while ((opt = getopt(argc, argv,
1119
	    "degiqpclBHvxXyF:b:f:t:U:D:P:N:C:r:g:R:T:G:M:S:a:W:")) != -1) {
1145
	    "degiqpclnBHvxXyF:b:f:t:U:D:P:N:C:r:g:R:T:G:M:S:a:W:")) != -1) {
1120
		switch (opt) {
1146
		switch (opt) {
1121
		case 'b':
1147
		case 'b':
1122
			bits = (u_int32_t)strtonum(optarg, 768, 32768, &errstr);
1148
			bits = (u_int32_t)strtonum(optarg, 768, 32768, &errstr);
Lines 1156-1161 main(int argc, char **argv) Link Here
1156
		case 'g':
1182
		case 'g':
1157
			print_generic = 1;
1183
			print_generic = 1;
1158
			break;
1184
			break;
1185
		case 'n':
1186
			use_nss = 1;
1187
			download = 1;
1188
			break;
1159
		case 'P':
1189
		case 'P':
1160
			identity_passphrase = optarg;
1190
			identity_passphrase = optarg;
1161
			break;
1191
			break;
Lines 1187-1196 main(int argc, char **argv) Link Here
1187
		case 't':
1217
		case 't':
1188
			key_type_name = optarg;
1218
			key_type_name = optarg;
1189
			break;
1219
			break;
1190
		case 'D':
1191
			download = 1;
1192
			/*FALLTHROUGH*/
1193
		case 'U':
1220
		case 'U':
1221
			download = 0;
1222
			/*FALLTHROUGH*/
1223
		case 'D':
1194
			reader_id = optarg;
1224
			reader_id = optarg;
1195
			break;
1225
			break;
1196
		case 'v':
1226
		case 'v':
Lines 1299-1304 main(int argc, char **argv) Link Here
1299
			exit(0);
1329
			exit(0);
1300
		}
1330
		}
1301
	}
1331
	}
1332
1333
	if (use_nss) {
1334
#ifdef HAVE_LIBNSS
1335
		if (download)
1336
			do_nss_download(pw, reader_id, identity_file);
1337
		else
1338
			fatal("no support for NSS key upload.");
1339
#else
1340
		fatal("no support for NSS keys.");
1341
#endif
1342
	}
1302
	if (reader_id != NULL) {
1343
	if (reader_id != NULL) {
1303
#ifdef SMARTCARD
1344
#ifdef SMARTCARD
1304
		if (download)
1345
		if (download)
(-)openssh-5.3p1/ssh-rsa.c.nss-keys (-3 / +39 lines)
Lines 32-37 Link Here
32
#include "compat.h"
32
#include "compat.h"
33
#include "ssh.h"
33
#include "ssh.h"
34
34
35
#ifdef HAVE_LIBNSS
36
#include <cryptohi.h>
37
#endif
38
35
static int openssh_RSA_verify(int, u_char *, u_int, u_char *, u_int, RSA *);
39
static int openssh_RSA_verify(int, u_char *, u_int, u_char *, u_int, RSA *);
36
40
37
/* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */
41
/* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */
Lines 50-55 ssh_rsa_sign(const Key *key, u_char **si Link Here
50
		error("ssh_rsa_sign: no RSA key");
54
		error("ssh_rsa_sign: no RSA key");
51
		return -1;
55
		return -1;
52
	}
56
	}
57
58
	slen = RSA_size(key->rsa);
59
	sig = xmalloc(slen);
60
61
#ifdef HAVE_LIBNSS
62
	if (key->flags & KEY_FLAG_NSS) {
63
		SECItem sigitem;
64
		SECOidTag alg;
65
66
		memset(&sigitem, 0, sizeof(sigitem));
67
		alg = (datafellows & SSH_BUG_RSASIGMD5) ?
68
			SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION :
69
			SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
70
71
		if (SEC_SignData(&sigitem, (u_char *)data, datalen, key->nss->privk,
72
			alg) != SECSuccess) {
73
			error("ssh_rsa_sign: sign failed");
74
			return -1;
75
		}
76
		if (sigitem.len > slen) {
77
			error("ssh_rsa_sign: slen %u slen2 %u", slen, sigitem.len);
78
			xfree(sig);
79
			SECITEM_ZfreeItem(&sigitem, PR_FALSE);
80
			return -1;
81
		}
82
		if (sigitem.len < slen) {
83
			memset(sig, 0, slen - sigitem.len);
84
		}
85
		memcpy(sig+slen-sigitem.len, sigitem.data, sigitem.len);
86
		SECITEM_ZfreeItem(&sigitem, PR_FALSE);
87
	} else {
88
#endif
53
	nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1;
89
	nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1;
54
	if ((evp_md = EVP_get_digestbynid(nid)) == NULL) {
90
	if ((evp_md = EVP_get_digestbynid(nid)) == NULL) {
55
		error("ssh_rsa_sign: EVP_get_digestbynid %d failed", nid);
91
		error("ssh_rsa_sign: EVP_get_digestbynid %d failed", nid);
Lines 59-67 ssh_rsa_sign(const Key *key, u_char **si Link Here
59
	EVP_DigestUpdate(&md, data, datalen);
95
	EVP_DigestUpdate(&md, data, datalen);
60
	EVP_DigestFinal(&md, digest, &dlen);
96
	EVP_DigestFinal(&md, digest, &dlen);
61
97
62
	slen = RSA_size(key->rsa);
63
	sig = xmalloc(slen);
64
65
	ok = RSA_sign(nid, digest, dlen, sig, &len, key->rsa);
98
	ok = RSA_sign(nid, digest, dlen, sig, &len, key->rsa);
66
	memset(digest, 'd', sizeof(digest));
99
	memset(digest, 'd', sizeof(digest));
67
100
Lines 83-88 ssh_rsa_sign(const Key *key, u_char **si Link Here
83
		xfree(sig);
116
		xfree(sig);
84
		return -1;
117
		return -1;
85
	}
118
	}
119
#ifdef HAVE_LIBNSS
120
	}
121
#endif
86
	/* encode signature */
122
	/* encode signature */
87
	buffer_init(&b);
123
	buffer_init(&b);
88
	buffer_put_cstring(&b, "ssh-rsa");
124
	buffer_put_cstring(&b, "ssh-rsa");

Return to bug 1676