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

Collapse All | Expand All

(-)ssh.org/authfd.c (+48 lines)
Lines 667-669 decode_reply(int type) Link Here
667
	/* NOTREACHED */
667
	/* NOTREACHED */
668
	return 0;
668
	return 0;
669
}
669
}
670
671
#ifdef ENABLE_PKCS11
672
673
int
674
ssh_pkcs11_add_provider(AuthenticationConnection *auth,
675
	const PKCS11Provider *const provider)
676
{
677
	Buffer msg;
678
	int type;
679
680
	buffer_init(&msg);
681
	buffer_put_char(&msg, SSH_AGENTC_PKCS11_ADD_PROVIDER);
682
	buffer_put_cstring(&msg, provider->provider);
683
	buffer_put_int(&msg, (unsigned)provider->protected_authentication);
684
	buffer_put_int(&msg, provider->private_mode);
685
	buffer_put_int(&msg, (unsigned)provider->cert_is_private);
686
687
	if (ssh_request_reply(auth, &msg, &msg) == 0) {
688
		buffer_free(&msg);
689
		return 0;
690
	}
691
	type = buffer_get_char(&msg);
692
	buffer_free(&msg);
693
	return decode_reply(type);
694
}
695
696
int
697
ssh_pkcs11_id(AuthenticationConnection *auth, const PKCS11Id *const id, int remove)
698
{
699
	Buffer msg;
700
	int type;
701
702
	buffer_init(&msg);
703
	buffer_put_char(&msg, remove ? SSH_AGENTC_PKCS11_REMOVE_ID : SSH_AGENTC_PKCS11_ADD_ID);
704
	buffer_put_cstring(&msg, id->id);
705
	buffer_put_int(&msg, (unsigned)id->pin_cache_period);
706
	buffer_put_cstring(&msg, id->cert_file == NULL ? "" : id->cert_file);
707
708
	if (ssh_request_reply(auth, &msg, &msg) == 0) {
709
		buffer_free(&msg);
710
		return 0;
711
	}
712
	type = buffer_get_char(&msg);
713
	buffer_free(&msg);
714
	return decode_reply(type);
715
}
716
717
#endif /* ENABLE_PKCS11 */
(-)ssh.org/authfd.h (+12 lines)
Lines 16-21 Link Here
16
#ifndef AUTHFD_H
16
#ifndef AUTHFD_H
17
#define AUTHFD_H
17
#define AUTHFD_H
18
18
19
#include "pkcs11.h"
20
19
/* Messages for the authentication agent connection. */
21
/* Messages for the authentication agent connection. */
20
#define SSH_AGENTC_REQUEST_RSA_IDENTITIES	1
22
#define SSH_AGENTC_REQUEST_RSA_IDENTITIES	1
21
#define SSH_AGENT_RSA_IDENTITIES_ANSWER		2
23
#define SSH_AGENT_RSA_IDENTITIES_ANSWER		2
Lines 49-54 Link Here
49
#define SSH2_AGENTC_ADD_ID_CONSTRAINED		25
51
#define SSH2_AGENTC_ADD_ID_CONSTRAINED		25
50
#define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26
52
#define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26
51
53
54
#define SSH_AGENTC_PKCS11_ADD_PROVIDER		27
55
#define SSH_AGENTC_PKCS11_ADD_ID		28
56
#define SSH_AGENTC_PKCS11_REMOVE_ID		29
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 92-95 int Link Here
92
ssh_agent_sign(AuthenticationConnection *, Key *, u_char **, u_int *, u_char *,
98
ssh_agent_sign(AuthenticationConnection *, Key *, u_char **, u_int *, u_char *,
93
    u_int);
99
    u_int);
94
100
101
#ifdef ENABLE_PKCS11
102
int	ssh_pkcs11_add_provider(AuthenticationConnection *, 
103
    const PKCS11Provider *const);
104
int	ssh_pkcs11_id(AuthenticationConnection *, const PKCS11Id *const, int remove);
105
#endif /* ENABLE_PKCS11 */
106
95
#endif				/* AUTHFD_H */
107
#endif				/* AUTHFD_H */
(-)ssh.org/pkcs11.c (+944 lines)
Line 0 Link Here
1
/*
2
 * Copyright(c) 2005-2006 Alon Bar-Lev.  All rights reserved.
3
 *
4
 * The _ssh_from_x509 is dirived of Tatu and Markus work.
5
 * Copyright(c) 2006 Alon bar-Lev <alon.barlev@gmail.com>.  All rights reserved.
6
 * Copyright(c) 2000, 2001 Markus Friedl.  All rights reserved.
7
 * Copyright(c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT
23
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
 *(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 */
29
30
#ifdef ENABLE_PKCS11
31
32
#include <string.h>
33
#include <unistd.h>
34
#include <sys/wait.h>
35
#include <errno.h>
36
#include <pkcs11-helper-1.0/pkcs11h-certificate.h>
37
#include <pkcs11-helper-1.0/pkcs11h-openssl.h>
38
#include "openssl/pem.h"
39
#include "misc.h"
40
#include "xmalloc.h"
41
#include "log.h"
42
#include "pkcs11.h"
43
44
static char *
45
_ssh_from_x509(X509 *);
46
47
static time_t
48
__mytime(void)
49
{
50
	return time(NULL);
51
}
52
53
static void
54
__mysleep(const unsigned long usec)
55
{
56
	usleep((unsigned)usec);
57
}
58
59
static int
60
__mygettimeofday(struct timeval *tv)
61
{
62
	return gettimeofday(tv, NULL);
63
}
64
65
static pkcs11h_engine_system_t s_pkcs11h_sys_engine = {
66
	xmalloc,
67
	xfree,
68
	__mytime,
69
	__mysleep,
70
	__mygettimeofday
71
};
72
73
static LogLevel
74
_pkcs11_msg_pkcs112openssh(const unsigned flags)
75
{
76
	LogLevel openssh_flags;
77
78
	switch (flags) {
79
	case PKCS11H_LOG_DEBUG2:
80
		openssh_flags = SYSLOG_LEVEL_DEBUG3;
81
		break;
82
	case PKCS11H_LOG_DEBUG1:
83
		openssh_flags = SYSLOG_LEVEL_DEBUG2;
84
		break;
85
	case PKCS11H_LOG_INFO:
86
		openssh_flags = SYSLOG_LEVEL_INFO;
87
		break;
88
	case PKCS11H_LOG_WARN:
89
		openssh_flags = SYSLOG_LEVEL_ERROR;
90
		break;
91
	case PKCS11H_LOG_ERROR:
92
		openssh_flags = SYSLOG_LEVEL_FATAL;
93
		break;
94
	default:
95
		openssh_flags = SYSLOG_LEVEL_FATAL;
96
		break;
97
	}
98
99
	return openssh_flags;
100
}
101
102
static unsigned
103
_pkcs11_msg_openssh2pkcs11(const LogLevel flags)
104
{
105
	unsigned pkcs11_flags;
106
107
	switch (flags) {
108
	case SYSLOG_LEVEL_DEBUG3:
109
		pkcs11_flags = PKCS11H_LOG_DEBUG2;
110
		break;
111
	case SYSLOG_LEVEL_DEBUG2:
112
		pkcs11_flags = PKCS11H_LOG_DEBUG1;
113
		break;
114
	case SYSLOG_LEVEL_INFO:
115
		pkcs11_flags = PKCS11H_LOG_INFO;
116
		break;
117
	case SYSLOG_LEVEL_ERROR:
118
		pkcs11_flags = PKCS11H_LOG_WARN;
119
		break;
120
	case SYSLOG_LEVEL_FATAL:
121
		pkcs11_flags = PKCS11H_LOG_ERROR;
122
		break;
123
	default:
124
		pkcs11_flags = PKCS11H_LOG_ERROR;
125
		break;
126
	}
127
128
	return pkcs11_flags;
129
}
130
131
static void
132
_pkcs11_openssh_log(void *const global_data, unsigned flags,
133
	const char *const format, va_list args)
134
{
135
	(void) global_data;
136
137
	do_log(_pkcs11_msg_pkcs112openssh(flags), format, args);
138
}
139
140
static PKCS11H_BOOL
141
_pkcs11_ssh_token_prompt(void *const global_data,
142
	void *const user_data,
143
	const pkcs11h_token_id_t token, IN const unsigned retry)
144
{
145
	(void) global_data;
146
	(void) user_data;
147
	(void) retry;
148
149
	return ask_permission("Please insert token '%s'", token->display);
150
}
151
152
static PKCS11H_BOOL
153
_pkcs11_ssh_pin_prompt(void *const global_data,
154
	void *const user_data, const pkcs11h_token_id_t token,
155
	const unsigned retry, char *const pin, const size_t pin_max)
156
{
157
	char prompt[1024];
158
	char *passphrase = NULL;
159
	PKCS11H_BOOL ret = FALSE;
160
161
	(void) global_data;
162
	(void) user_data;
163
	(void) retry;
164
165
	if (snprintf(prompt, sizeof(prompt), "Please enter PIN for token '%s': ",
166
		token->display) < 0)
167
		goto cleanup;
168
169
	passphrase = read_passphrase(prompt, RP_ALLOW_EOF);
170
171
	if (passphrase == NULL || strlen(passphrase) == 0 ||
172
		strlen(passphrase) > pin_max-1)
173
		goto cleanup;
174
	
175
	strncpy(pin, passphrase, pin_max);
176
177
	ret = TRUE;
178
179
cleanup:
180
181
	if (passphrase != NULL)
182
		xfree(passphrase);
183
184
	return ret;
185
}
186
187
static int
188
_pkcs11_convert_to_ssh_key(const pkcs11h_certificate_id_t certificate_id, Key **const key,
189
	char **const comment, const int pin_cache_period)
190
{
191
	pkcs11h_certificate_t certificate = NULL;
192
	pkcs11h_certificate_id_t certificate_id_new = NULL;
193
	pkcs11h_openssl_session_t openssl_session = NULL;
194
	Key *internal_key = NULL;
195
	char *internal_comment = NULL;
196
	RSA *rsa = NULL;
197
	size_t temp;
198
	CK_RV rv = CKR_OK;
199
200
	*key = NULL;
201
	*comment = NULL;
202
203
	debug3("PKCS#11: _pkcs11_convert_to_ssh_key - entered - certificate=%p, "
204
		"key=%p, comment=%p, pin_cache_period=%d", (void *) certificate,
205
		(void *) key, (void *) comment, pin_cache_period);
206
207
	if ((rv = pkcs11h_certificate_create(certificate_id, NULL,
208
		PKCS11H_PROMPT_MASK_ALLOW_ALL, pin_cache_period,
209
		&certificate)) != CKR_OK) {
210
		error("PKCS#11: Cannot get certificate %ld-'%s'", rv,
211
			pkcs11h_getMessage(rv));
212
		goto cleanup;
213
	}
214
215
	/*
216
	 * New certificate_id is constructed from certificate
217
	 * blob so that it will contian the proper description.
218
	 */
219
220
	if ((rv = pkcs11h_certificate_getCertificateBlob(certificate,
221
				NULL, &temp)) != CKR_OK) {
222
		error("PKCS#11: Cannot get certificate blob %ld-'%s'", rv,
223
			pkcs11h_getMessage(rv));
224
		goto cleanup;
225
	}
226
227
	if ((rv = pkcs11h_certificate_getCertificateId(certificate,
228
		&certificate_id_new)) != CKR_OK) {
229
		error("PKCS#11: Cannot get certificate_id %ld-'%s'", rv,
230
			pkcs11h_getMessage(rv));
231
		goto cleanup;
232
	}
233
234
	if ((internal_comment = xstrdup(certificate_id_new->displayName)) == NULL) {
235
		error("PKCS#11: Memory allocation error");
236
		goto cleanup;
237
	}
238
239
	if ((openssl_session =
240
			pkcs11h_openssl_createSession(certificate)) == NULL) {
241
		error("PKCS#11: Cannot initialize openssl session");
242
		goto cleanup;
243
	}
244
245
	/*
246
	 * will be release by openssl_session
247
	 */
248
	certificate = NULL;
249
250
	if ((rsa = pkcs11h_openssl_session_getRSA(openssl_session)) == NULL) {
251
		error("PKCS#11: Unable get rsa object");
252
		goto cleanup;
253
	}
254
255
	internal_key = key_new_private(KEY_UNSPEC);
256
	internal_key->flags |= KEY_FLAG_EXT;
257
	internal_key->rsa = rsa;
258
	rsa = NULL;
259
	internal_key->type = KEY_RSA;
260
261
	*key = internal_key;
262
	internal_key = NULL;
263
	*comment = internal_comment;
264
	internal_comment = NULL;
265
266
cleanup:
267
	if (internal_key != NULL) {
268
		key_free(internal_key);
269
		internal_key = NULL;
270
	}
271
272
	if (internal_comment != NULL) {
273
		xfree(internal_comment);
274
		internal_comment = NULL;
275
	}
276
277
	if (rsa != NULL) {
278
		RSA_free (rsa);
279
		rsa = NULL;
280
	}
281
282
	if (openssl_session != NULL) {
283
		pkcs11h_openssl_freeSession(openssl_session);
284
		openssl_session = NULL;
285
	}
286
287
	if (certificate_id_new != NULL) {
288
		pkcs11h_certificate_freeCertificateId(certificate_id_new);
289
		certificate_id_new = NULL;
290
	}
291
292
	if (certificate != NULL) {
293
		pkcs11h_certificate_freeCertificate(certificate);
294
		certificate = NULL;
295
	}
296
297
	debug3("PKCS#11: _pkcs11_convert_to_ssh_key - return *key=%p", (void *) *key);
298
299
	return *key != NULL;
300
}
301
302
int
303
pkcs11_initialize(const int protected_authentication, const int pin_cache_period)
304
{
305
	CK_RV rv = CKR_FUNCTION_FAILED;
306
307
	debug3("PKCS#11: pkcs11_initialize - entered protected_authentication=%d, "
308
		"pin_cache_period=%d", protected_authentication, pin_cache_period);
309
310
	if ((rv = pkcs11h_engine_setSystem(&s_pkcs11h_sys_engine)) != CKR_OK) {
311
		error("PKCS#11: Cannot set system engine %ld-'%s'", rv,
312
			pkcs11h_getMessage(rv));
313
		goto cleanup;
314
	}
315
316
	if ((rv = pkcs11h_initialize()) != CKR_OK) {
317
		error("PKCS#11: Cannot initialize %ld-'%s'", rv,
318
			pkcs11h_getMessage(rv));
319
		goto cleanup;
320
	}
321
322
	if ((rv = pkcs11h_setLogHook(_pkcs11_openssh_log, NULL)) != CKR_OK) {
323
		error("PKCS#11: Cannot set hooks %ld-'%s'", rv,
324
			pkcs11h_getMessage(rv));
325
		goto cleanup;
326
	}
327
328
	pkcs11h_setLogLevel(_pkcs11_msg_openssh2pkcs11(get_log_level ()));
329
330
	if ((rv = pkcs11h_setTokenPromptHook(_pkcs11_ssh_token_prompt,
331
		NULL)) != CKR_OK) {
332
		error("PKCS#11: Cannot set hooks %ld-'%s'", rv,
333
			pkcs11h_getMessage(rv));
334
		goto cleanup;
335
	}
336
337
	if ((rv = pkcs11h_setPINPromptHook(_pkcs11_ssh_pin_prompt,
338
		NULL)) != CKR_OK) {
339
		error("PKCS#11: Cannot set hooks %ld-'%s'", rv,
340
			pkcs11h_getMessage(rv));
341
		goto cleanup;
342
	}
343
344
	if ((rv = pkcs11h_setProtectedAuthentication(protected_authentication)) !=
345
		CKR_OK) {
346
		error("PKCS#11: Cannot set protected authentication mode %ld-'%s'",
347
			rv, pkcs11h_getMessage(rv));
348
		goto cleanup;
349
	}
350
351
	if ((rv = pkcs11h_setPINCachePeriod(pin_cache_period)) != CKR_OK) {
352
		error("PKCS#11: Cannot set PIN cache period %ld-'%s'", rv,
353
			pkcs11h_getMessage(rv));
354
		goto cleanup;
355
	}
356
357
	rv = CKR_OK;
358
359
cleanup:
360
	debug3("PKCS#11: pkcs11_initialize - return rv=%ld-'%s'",
361
		rv, pkcs11h_getMessage(rv));
362
363
	return rv == CKR_OK;
364
}
365
366
void
367
pkcs11_terminate(void)
368
{
369
	debug3("PKCS#11: pkcs11_terminate - entered");
370
371
	pkcs11h_terminate();
372
373
	debug3("PKCS#11: pkcs11_terminate - return");
374
}
375
376
void
377
pkcs11_free_provider(PKCS11Provider *const provider) {
378
	if (provider != NULL) {
379
		if (provider->provider != NULL)
380
			xfree(provider->provider);
381
		xfree(provider);
382
	}
383
}
384
385
PKCS11Provider *
386
pkcs11_parse_provider(const char *const info)
387
{
388
	PKCS11Provider *provider = NULL;
389
	PKCS11Provider *ret = NULL;
390
	char *split[4];
391
	char *s = NULL;
392
	char *p;
393
	int i;
394
395
	if (info == NULL)
396
		goto cleanup;
397
398
	if ((provider = (PKCS11Provider *) xmalloc(sizeof(*provider))) == NULL)
399
		goto cleanup;
400
401
	memset(provider, 0, sizeof(*provider));
402
	memset(split, 0, sizeof(split));
403
404
	if ((s=xstrdup(info)) == NULL)
405
		goto cleanup;
406
407
	p = s;
408
	i=0;
409
	while(i<4 && p != NULL) {
410
		char *t;
411
		if ((t = strchr(p, ':')) != NULL)
412
			*t = '\x0';
413
		split[i++] = p;
414
		if (t != NULL)
415
			p = t+1;
416
		else
417
			p = NULL;
418
	}
419
420
	/*
421
	 * provider[:protected_authentication[:private_mode[:cert_is_private]]]
422
	 * string:1|0:hex:1|0
423
	 */
424
	if (split[0] != NULL)
425
		provider->provider = xstrdup(split[0]);
426
	if (split[1] != NULL)
427
		provider->protected_authentication = atoi(split[1]) != 0;
428
	if (split[2] != NULL)
429
		sscanf(split[2], "%x", &provider->private_mode);
430
	if (split[3] != NULL)
431
		provider->cert_is_private = atoi(split[3]) != 0;
432
	
433
	if (provider->provider == NULL || strlen(provider->provider) == 0)
434
		goto cleanup;
435
436
	ret = provider;
437
	provider = NULL;
438
439
cleanup:
440
	if (s != NULL)
441
		xfree(s);
442
443
	if (provider != NULL)
444
		pkcs11_free_provider(provider);
445
446
	return ret;
447
}
448
449
int
450
pkcs11_add_provider(const PKCS11Provider *const provider)
451
{
452
	CK_RV rv = CKR_OK;
453
454
	debug3("PKCS#11: pkcs11_add_provider - entered - provider='%s', "
455
		"protected_authentication=%d, private_mode='%08x', cert_is_private=%d",
456
		provider->provider, provider->protected_authentication ? 1 : 0,
457
		provider->private_mode,	provider->cert_is_private ? 1 : 0);
458
459
	debug("PKCS#11: Adding PKCS#11 provider '%s'", provider->provider);
460
461
	if (rv == CKR_OK &&
462
		(rv = pkcs11h_addProvider(provider->provider, provider->provider,
463
			provider->protected_authentication, provider->private_mode,
464
				PKCS11H_SLOTEVENT_METHOD_AUTO,
465
				0, provider->cert_is_private)) != CKR_OK) {
466
		error("PKCS#11: Cannot initialize provider '%s' %ld-'%s'",
467
			provider->provider, rv, pkcs11h_getMessage(rv));
468
	}
469
470
	debug3("PKCS#11: pkcs11_add_provider - return rv=%ld-'%s'",
471
		rv, pkcs11h_getMessage(rv));
472
473
	return rv == CKR_OK;
474
}
475
476
PKCS11Id *
477
pkcs11_id_new(void)
478
{
479
	PKCS11Id *id = (PKCS11Id *) xmalloc(sizeof(*id));
480
	if (id != NULL) {
481
		memset(id, 0, sizeof(*id));
482
		id->pin_cache_period = PKCS11H_PIN_CACHE_INFINITE;
483
	}
484
	return id;
485
}
486
487
void
488
pkcs11_id_free(PKCS11Id *const id)
489
{
490
	if (id != NULL)
491
		xfree(id);
492
}
493
494
int
495
pkcs11_get_key(const PKCS11Id *const id, Key **const key,
496
	char **const comment)
497
{
498
	pkcs11h_certificate_id_t certificate_id = NULL;
499
	CK_RV rv = CKR_OK;
500
501
	debug3("PKCS#11: pkcs11_get_key - entered - id=%p, key=%p, "
502
		"comment=%p", (const void *) id, (void *) key, (void *) comment);
503
504
	debug3("PKCS#11: pkcs11_get_key - id - id=%s, "
505
		"pin_cache_period=%d, cert_file=%s",
506
		id->id, id->pin_cache_period, id->cert_file);
507
508
	if (pkcs11h_certificate_deserializeCertificateId(&certificate_id, id->id)) {
509
		error("PKCS#11: Cannot deserialize id %ld-'%s'", rv,
510
			pkcs11h_getMessage(rv));
511
		goto cleanup;
512
	}
513
514
	if (id->cert_file != NULL && id->cert_file[0] != '\x0') {
515
		X509 *x509 = NULL;
516
		unsigned char *p = NULL;
517
		unsigned char *certificate_blob = NULL;
518
		size_t certificate_blob_size = 0;
519
		int size;
520
		FILE *fp = NULL;
521
522
		if ((fp = fopen(id->cert_file, "r")) == NULL) {
523
			error("PKCS#11: Cannot open file '%s'", id->cert_file);
524
			goto cleanup1;
525
		}
526
527
		if (!PEM_read_X509(fp, &x509, NULL, 0)) {
528
			x509 = NULL;
529
			error("PKCS#11: Cannot read PEM from file '%s'", id->cert_file);
530
			goto cleanup1;
531
		}
532
533
		if ((size = i2d_X509(x509, NULL)) < 0) {
534
			error("PKCS#11: Cannot read decode certificate");
535
			goto cleanup1;
536
		}
537
		certificate_blob_size = (size_t)size;
538
539
		if ((certificate_blob =
540
				(unsigned char *) xmalloc(certificate_blob_size)) == NULL) {
541
			error("PKCS#11: Cannot allocate memory");
542
			goto cleanup1;
543
		}
544
545
		/*
546
		 * i2d_X509 increments p!!!
547
		 */
548
		p = certificate_blob;
549
550
		if ((size = i2d_X509(x509, &p)) < 0) {
551
			error("PKCS#11: Cannot read decode certificate");
552
			goto cleanup1;
553
		}
554
		certificate_blob_size = (size_t)size;
555
556
		if (pkcs11h_certificate_setCertificateIdCertificateBlob
557
			(certificate_id, certificate_blob, certificate_blob_size)
558
			!= CKR_OK) {
559
			error("PKCS#11: Cannot set certificate blob %ld-'%s'", rv,
560
				pkcs11h_getMessage(rv));
561
			goto cleanup1;
562
		}
563
564
	cleanup1:
565
		if (x509 != NULL) {
566
			X509_free(x509);
567
			x509 = NULL;
568
		}
569
570
		if (certificate_blob != NULL) {
571
			xfree(certificate_blob);
572
			certificate_blob = NULL;
573
		}
574
575
		if (fp != NULL) {
576
			fclose(fp);
577
			fp = NULL;
578
		}
579
	}
580
581
	_pkcs11_convert_to_ssh_key(certificate_id, key, comment, id->pin_cache_period);
582
583
cleanup:
584
585
	if (certificate_id != NULL) {
586
		pkcs11h_certificate_freeCertificateId(certificate_id);
587
		certificate_id = NULL;
588
	}
589
590
	debug3("PKCS#11: pkcs11_get_key - return rv=%ld, *key=%p", rv, ( void *) *key);
591
592
	return *key != NULL;
593
}
594
595
int
596
pkcs11_get_keys(Key ***const keys, char ***const comments)
597
{
598
#define PKCS11_MAX_KEYS 10
599
	Key **internal_keys = NULL;
600
	char **internal_comments = NULL;
601
	pkcs11h_certificate_id_list_t user_certificates = NULL;
602
	pkcs11h_certificate_id_list_t current = NULL;
603
	CK_RV rv = CKR_FUNCTION_FAILED;
604
	int i;
605
606
	debug3("PKCS#11: pkcs11_get_keys - entered - sshkey=%p, "
607
		"comment=%p",
608
		(void *) keys, (void *) comments);
609
	
610
	*keys = NULL;
611
	*comments = NULL;
612
	
613
	if((internal_keys = xmalloc((PKCS11_MAX_KEYS+1)*sizeof(*internal_keys))) == NULL) {
614
		rv = CKR_HOST_MEMORY;
615
		goto cleanup;
616
	}
617
618
	if((internal_comments = xmalloc((PKCS11_MAX_KEYS+1)*sizeof(*internal_comments))) == NULL) {
619
		rv = CKR_HOST_MEMORY;
620
		goto cleanup;
621
	}
622
623
	memset(internal_keys, 0, (PKCS11_MAX_KEYS+1)*sizeof(*internal_keys));
624
	memset(internal_comments, 0, (PKCS11_MAX_KEYS+1)*sizeof(*internal_comments));
625
626
	if ((rv = pkcs11h_certificate_enumCertificateIds(
627
		PKCS11H_ENUM_METHOD_CACHE_EXIST, NULL,
628
		PKCS11H_PROMPT_MASK_ALLOW_ALL, NULL,
629
		&user_certificates)) != CKR_OK) {
630
		error("PKCS#11: Cannot enumerate certificates %ld-'%s'", rv,
631
			pkcs11h_getMessage(rv));
632
		goto cleanup;
633
	}
634
635
	i = 0;
636
	for (current = user_certificates; current != NULL && i<PKCS11_MAX_KEYS;
637
		current = current->next) {
638
639
		if (_pkcs11_convert_to_ssh_key(current->certificate_id, &internal_keys[i],
640
			&internal_comments[i], PKCS11H_PIN_CACHE_INFINITE)) {
641
			i++;
642
		}
643
	}
644
645
	*keys = internal_keys;
646
	internal_keys = NULL;
647
	*comments = internal_comments;
648
	internal_comments = NULL;
649
	rv = CKR_OK;
650
651
cleanup:
652
	if (user_certificates != NULL) {
653
		pkcs11h_certificate_freeCertificateIdList(user_certificates);
654
		user_certificates = NULL;
655
	}
656
657
	if (internal_keys != NULL) {
658
		Key **t = internal_keys;
659
		while (*t != NULL) {
660
			key_free(*t);
661
			t++;
662
		}
663
		xfree(internal_keys);
664
	}
665
666
	if (internal_comments != NULL) {
667
		char **t = internal_comments;
668
		while (*t != NULL) {
669
			xfree(*t);
670
			t++;
671
		}
672
		xfree(internal_comments);
673
	}
674
675
	debug3("PKCS#11: pkcs11_get_keys - return rv=%ld, *keys=%p", rv, (void *) *keys);
676
677
	return *keys != NULL;
678
#undef PKCS11_MAX_KEYS
679
}
680
681
void
682
pkcs11_show_ids(void)
683
{
684
	pkcs11h_certificate_id_list_t user_certificates = NULL;
685
	pkcs11h_certificate_id_list_t current = NULL;
686
	CK_RV rv = CKR_FUNCTION_FAILED;
687
688
	if ((rv = pkcs11h_certificate_enumCertificateIds(
689
		PKCS11H_ENUM_METHOD_CACHE_EXIST, NULL,
690
		PKCS11H_PROMPT_MASK_ALLOW_ALL, NULL,
691
		&user_certificates)) != CKR_OK) {
692
		error("PKCS#11: Cannot enumerate certificates %ld-'%s'", rv,
693
			pkcs11h_getMessage(rv));
694
		goto cleanup;
695
	}
696
697
	for (current = user_certificates; current != NULL;
698
		current = current->next) {
699
700
		pkcs11h_certificate_t certificate = NULL;
701
		X509 *x509 = NULL;
702
703
		BIO *bio = NULL;
704
		char dn[1024] = { 0 };
705
		char serial[1024] = { 0 };
706
		char *ser = NULL;
707
		char *ssh_key = NULL;
708
		size_t ser_len = 0;
709
		int n;
710
711
		if ((rv = pkcs11h_certificate_serializeCertificateId(NULL,
712
			&ser_len, current->certificate_id)) != CKR_OK) {
713
			error("PKCS#11: Cannot serialize certificate id "
714
				"certificates %ld-'%s'", rv,
715
				pkcs11h_getMessage(rv));
716
			goto cleanup1;
717
		}
718
719
		if ((ser = (char *) xmalloc(ser_len)) == NULL) {
720
			error("PKCS#11: Cannot allocate memory");
721
			goto cleanup1;
722
		}
723
724
		if ((rv = pkcs11h_certificate_serializeCertificateId(ser,
725
			&ser_len, current->certificate_id)) != CKR_OK) {
726
			error("PKCS#11: Cannot serialize certificate "
727
				"id certificates %ld-'%s'",
728
				rv, pkcs11h_getMessage(rv));
729
			goto cleanup1;
730
		}
731
732
		if ((rv = pkcs11h_certificate_create(current->certificate_id,
733
			NULL, PKCS11H_PROMPT_MASK_ALLOW_ALL,
734
			PKCS11H_PIN_CACHE_INFINITE, &certificate)) != CKR_OK) {
735
			error("PKCS#11: Cannot create certificate %ld-'%s'", rv,
736
				pkcs11h_getMessage(rv));
737
			goto cleanup1;
738
		}
739
740
		if ((x509 = pkcs11h_openssl_getX509(certificate)) == NULL) {
741
			error("PKCS#11: Cannot get X509");
742
			goto cleanup1;
743
		}
744
745
		X509_NAME_oneline(X509_get_subject_name(x509), dn, sizeof(dn));
746
747
		if ((bio = BIO_new(BIO_s_mem())) == NULL) {
748
			error("PKCS#11: Cannot create BIO");
749
			goto cleanup1;
750
		}
751
752
		i2a_ASN1_INTEGER(bio, X509_get_serialNumber(x509));
753
		n = BIO_read(bio, serial, sizeof(serial) - 1);
754
		if (n < 0)
755
			serial[0] = '\x0';
756
		else
757
			serial[n] = 0;
758
759
		printf(("\n"
760
				"********************************************\n"
761
				"IDENTITY:\n"
762
				"       DN:             %s\n"
763
				"       Serial:         %s\n"
764
				"       Serialized id:  %s\n"
765
				"\n" "       Certificate:\n"), dn, serial, ser);
766
		PEM_write_X509(stdout, x509);
767
768
		if ((ssh_key = _ssh_from_x509(x509)) != NULL) {
769
			printf(("\n" "        SSH:\n" "%s\n"), ssh_key);
770
771
			xfree(ssh_key);
772
		}
773
774
	cleanup1:
775
		if (x509 != NULL) {
776
			X509_free(x509);
777
			x509 = NULL;
778
		}
779
780
		if (bio != NULL) {
781
			BIO_free_all(bio);
782
			bio = NULL;
783
		}
784
785
		if (certificate != NULL) {
786
			pkcs11h_certificate_freeCertificate(certificate);
787
			certificate = NULL;
788
		}
789
790
		if (ser != NULL) {
791
			xfree(ser);
792
			ser = NULL;
793
		}
794
	}
795
796
cleanup:
797
	if (user_certificates != NULL) {
798
		pkcs11h_certificate_freeCertificateIdList(user_certificates);
799
		user_certificates = NULL;
800
	}
801
}
802
803
static char *
804
_ssh_from_x509(X509 * x509)
805
{
806
#define PUT_32BIT(cp, value) ( \
807
	(cp)[0] = (unsigned char)((value) >> 24), \
808
	(cp)[1] = (unsigned char)((value) >> 16), \
809
	(cp)[2] = (unsigned char)((value) >> 8), \
810
	(cp)[3] = (unsigned char)((value) >> 0) )
811
812
	EVP_PKEY *pubkey = NULL;
813
	BIO *bio = NULL, *bio2 = NULL, *bio64 = NULL;
814
	unsigned char *blob = NULL, *buffer = NULL;
815
	char *ret = NULL;
816
	size_t blobsize = 0, retsize = 0;
817
	size_t bytes_name = 0, bytes_exponent = 0, bytes_modulus = 0;
818
	unsigned char *bp;
819
	char *p;
820
	int n;
821
	const char *keyname = NULL;
822
	int ok = 0;
823
824
	if ((pubkey = X509_get_pubkey(x509)) == NULL)
825
		goto cleanup;
826
827
	if ((bio64 = BIO_new(BIO_f_base64())) == NULL)
828
		goto cleanup;
829
830
	if ((bio = BIO_new(BIO_s_mem())) == NULL)
831
		goto cleanup;
832
833
	if ((bio2 = BIO_push(bio64, bio)) == NULL)
834
		goto cleanup;
835
836
	if (pubkey->type != EVP_PKEY_RSA)
837
		goto cleanup;
838
839
	keyname = "ssh-rsa";
840
841
	bytes_name = strlen(keyname);
842
	bytes_exponent = (size_t)BN_num_bytes(pubkey->pkey.rsa->e);
843
	bytes_modulus = (size_t)BN_num_bytes(pubkey->pkey.rsa->n);
844
845
	blobsize = (4 + bytes_name + 4 + ((unsigned)bytes_exponent + 1) + 4 +
846
		((unsigned)bytes_modulus + 1) + 1);
847
848
	if ((blob = (unsigned char *) xmalloc(blobsize)) == NULL)
849
		goto cleanup;
850
851
	if ((buffer = (unsigned char *) xmalloc(blobsize)) == NULL)
852
		goto cleanup;
853
854
	bp = blob;
855
856
	PUT_32BIT(bp, bytes_name), bp += 4;
857
	memcpy(bp, keyname, bytes_name), bp += (ssize_t)bytes_name;
858
859
	BN_bn2bin(pubkey->pkey.rsa->e, buffer);
860
	if (buffer[0] & 0x80) {
861
		// highest bit set would indicate a negative number.
862
		// to avoid this, we have to spend an extra byte:
863
		PUT_32BIT(bp, bytes_exponent + 1), bp += 4;
864
		*(bp++) = 0;
865
	} else
866
		PUT_32BIT(bp, bytes_exponent), bp += 4;
867
868
	memcpy(bp, buffer, bytes_exponent), bp += (ssize_t)bytes_exponent;
869
870
	BN_bn2bin(pubkey->pkey.rsa->n, buffer);
871
	if (buffer[0] & 0x80) {
872
		PUT_32BIT(bp, bytes_modulus + 1), bp += 4;
873
		*(bp++) = 0;
874
	} else
875
		PUT_32BIT(bp, bytes_modulus), bp += 4;
876
877
	memcpy(bp, buffer, bytes_modulus), bp += (ssize_t)bytes_modulus;
878
879
	if (BIO_write(bio2, blob, (int)(bp - blob)) == -1)
880
		goto cleanup;
881
882
	if (BIO_flush(bio2) == -1)
883
		goto cleanup;
884
885
	/*
886
	 * Allocate the newline too... We will remove them later
887
	 * For MS, allocate return as well.
888
	 */
889
	retsize = strlen(keyname) + 1 + (blobsize * 4 / 3) + (blobsize * 2 / 50) +
890
		10 + 1;
891
892
	if ((ret = (char *) xmalloc(retsize)) == NULL)
893
		goto cleanup;
894
895
	if (snprintf(ret, retsize, "%s ", keyname) < 0)
896
		goto cleanup;
897
898
	if ((n = BIO_read(bio, ret + (ssize_t)strlen(ret),
899
		(int)(retsize - strlen(ret) - 1))) == -1)
900
		goto cleanup;
901
902
	ret[(int)strlen(keyname) + 1 + n] = '\x0';
903
904
	while ((p = strchr(ret, '\n')) != NULL)
905
		memmove(p, p + 1, strlen(p) + 1);
906
	while ((p = strchr(ret, '\r')) != NULL)
907
		memmove(p, p + 1, strlen(p) + 1);
908
909
	ok = 1;
910
911
cleanup:
912
	if (bio != NULL) {
913
		BIO_free_all(bio);
914
		bio = NULL;
915
	}
916
917
	if (pubkey != NULL) {
918
		EVP_PKEY_free(pubkey);
919
		pubkey = NULL;
920
	}
921
922
	if (buffer != NULL) {
923
		xfree(buffer);
924
		buffer = NULL;
925
	}
926
927
	if (blob != NULL) {
928
		xfree(blob);
929
		blob = NULL;
930
	}
931
932
	if (!ok) {
933
		if (ret != NULL) {
934
			xfree(ret);
935
			ret = NULL;
936
		}
937
	}
938
939
	return ret;
940
941
#undef PUT_32BIT
942
}
943
944
#endif /* ENABLE_PKCS11 */
(-)ssh.org/pkcs11.h (+77 lines)
Line 0 Link Here
1
/*
2
 * Copyright (c) 2005-2006 Alon Bar-Lev.  All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
 */
24
25
#ifndef SSH_PKCS11_H
26
#define SSH_PKCS11_H
27
28
#ifdef ENABLE_PKCS11
29
30
#include "key.h"
31
32
typedef struct {
33
	char *provider;
34
	int protected_authentication;
35
	unsigned private_mode;
36
	int cert_is_private;
37
} PKCS11Provider;
38
39
typedef struct {
40
	char *id;
41
	int pin_cache_period;
42
	char *cert_file;
43
}	PKCS11Id;
44
45
int
46
pkcs11_initialize(const int, const int);
47
48
void
49
pkcs11_terminate(void);
50
51
void
52
pkcs11_free_provider(PKCS11Provider *const);
53
54
PKCS11Provider *
55
pkcs11_parse_provider(const char *const);
56
57
int
58
pkcs11_add_provider(const PKCS11Provider *const);
59
60
PKCS11Id *
61
pkcs11_id_new(void);
62
63
void
64
pkcs11_id_free(PKCS11Id *const);
65
66
int
67
pkcs11_get_key(const PKCS11Id *const, Key **const, char **const);
68
69
int
70
pkcs11_get_keys(Key ***const, char ***const);
71
72
void
73
pkcs11_show_ids(void);
74
75
#endif /* ENABLE_PKCS11 */
76
77
#endif /* OPENSSH_PKCS11_H */
(-)ssh.org/ssh-add.c (-1 / +74 lines)
Lines 53-58 Link Here
53
#include "rsa.h"
53
#include "rsa.h"
54
#include "log.h"
54
#include "log.h"
55
#include "key.h"
55
#include "key.h"
56
#include "pkcs11.h"
56
#include "buffer.h"
57
#include "buffer.h"
57
#include "authfd.h"
58
#include "authfd.h"
58
#include "authfile.h"
59
#include "authfile.h"
Lines 316-321 usage(void) Link Here
316
	fprintf(stderr, "  -X          Unlock agent.\n");
317
	fprintf(stderr, "  -X          Unlock agent.\n");
317
	fprintf(stderr, "  -t life     Set lifetime (in seconds) when adding identities.\n");
318
	fprintf(stderr, "  -t life     Set lifetime (in seconds) when adding identities.\n");
318
	fprintf(stderr, "  -c          Require confirmation to sign using identities\n");
319
	fprintf(stderr, "  -c          Require confirmation to sign using identities\n");
320
#ifdef ENABLE_PKCS11
321
	fprintf(stderr, "  -K provider Add PKCS#11 provider, format:\n");
322
	fprintf(stderr, "              lib[:prot_auth[:private_mode[:cert_is_private]]]\n");
323
	fprintf(stderr, "              prot_auth - 1 to allow protected mode authentication.\n");
324
	fprintf(stderr, "              private_mode - Private key mode, see man page.\n");
325
	fprintf(stderr, "              cert_is_private - 1 if login is required to access certificates.\n");
326
	fprintf(stderr, "  -I          Add PKCS#11 id, remainging arguments:\n");
327
	fprintf(stderr, "              pkcs11_id [session_cache [cert_file]]\n");
328
	fprintf(stderr, "              pkcs11_id - Serialized id, get from ssh-keygen -K.\n");
329
	fprintf(stderr, "              session_cache - Session cache timeout in seconds -1 for infinite.\n");
330
	fprintf(stderr, "              cert_file - Specify PEM file to load if token is unavailable.\n");
331
#endif
319
#ifdef SMARTCARD
332
#ifdef SMARTCARD
320
	fprintf(stderr, "  -s reader   Add key in smartcard reader.\n");
333
	fprintf(stderr, "  -s reader   Add key in smartcard reader.\n");
321
	fprintf(stderr, "  -e reader   Remove key in smartcard reader.\n");
334
	fprintf(stderr, "  -e reader   Remove key in smartcard reader.\n");
Lines 330-335 main(int argc, char **argv) Link Here
330
	AuthenticationConnection *ac = NULL;
343
	AuthenticationConnection *ac = NULL;
331
	char *sc_reader_id = NULL;
344
	char *sc_reader_id = NULL;
332
	int i, ch, deleting = 0, ret = 0;
345
	int i, ch, deleting = 0, ret = 0;
346
#ifdef ENABLE_PKCS11
347
	PKCS11Provider *pkcs11_provider = NULL;
348
	int doing_pkcs11 = 0;
349
#endif /* ENABLE_PKCS11 */
333
350
334
	/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
351
	/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
335
	sanitise_stdfd();
352
	sanitise_stdfd();
Lines 343-349 main(int argc, char **argv) Link Here
343
		    "Could not open a connection to your authentication agent.\n");
360
		    "Could not open a connection to your authentication agent.\n");
344
		exit(2);
361
		exit(2);
345
	}
362
	}
346
	while ((ch = getopt(argc, argv, "lLcdDxXe:s:t:")) != -1) {
363
	while ((ch = getopt(argc, argv, "lLcdDxXe:s:t:K:I")) != -1) {
347
		switch (ch) {
364
		switch (ch) {
348
		case 'l':
365
		case 'l':
349
		case 'L':
366
		case 'L':
Lines 379-384 main(int argc, char **argv) Link Here
379
				goto done;
396
				goto done;
380
			}
397
			}
381
			break;
398
			break;
399
#ifdef ENABLE_PKCS11
400
		case 'K':
401
			if ((pkcs11_provider = pkcs11_parse_provider(optarg)) == NULL) {
402
				fprintf(stderr, "Cannot parse PKCS#11 provider\n");
403
				ret = 1;
404
				goto done;
405
			}
406
			break;
407
		case 'I':
408
			doing_pkcs11 = 1;
409
			break;
410
#endif /* ENABLE_PKCS11 */
382
		default:
411
		default:
383
			usage();
412
			usage();
384
			ret = 1;
413
			ret = 1;
Lines 387-392 main(int argc, char **argv) Link Here
387
	}
416
	}
388
	argc -= optind;
417
	argc -= optind;
389
	argv += optind;
418
	argv += optind;
419
420
#ifdef ENABLE_PKCS11
421
	if (pkcs11_provider != NULL) {
422
		if (!ssh_pkcs11_add_provider(ac, pkcs11_provider)) {
423
			fprintf(stderr,
424
				"Cannot add provider '%s'\n", pkcs11_provider->provider);
425
			ret = 1;
426
			goto done;
427
		}
428
		fprintf(stderr, "Provider '%s' added successfully.\n", pkcs11_provider->provider);
429
		pkcs11_free_provider(pkcs11_provider);
430
	}
431
432
	if (doing_pkcs11) {
433
		PKCS11Id *pkcs11_id = NULL;
434
		if (argc < 1 || argc > 3) {
435
			fprintf(stderr,
436
				"Invalid PKCS#11 id format\n");
437
			ret = 1;
438
			goto done;
439
		}
440
		if ((pkcs11_id = pkcs11_id_new()) == NULL) {
441
			fprintf(stderr, "Memory allocation error.\n");
442
			ret = 1;
443
			goto done;
444
		}
445
		pkcs11_id->id = argv[0];
446
		if (argc > 1)
447
			pkcs11_id->pin_cache_period = atoi(argv[1]);
448
		if (argc > 2)
449
			pkcs11_id->cert_file = xstrdup(argv[2]);
450
451
		if (!ssh_pkcs11_id(ac, pkcs11_id, deleting)) {
452
			fprintf(stderr,
453
				"Cannot %s id '%s'\n", deleting ? "remove" : "add", pkcs11_id->id);
454
			ret = 1;
455
			goto done;
456
		}
457
		pkcs11_id_free(pkcs11_id);
458
		fprintf(stderr, "Identity %s successfully.\n", deleting ? "removed" : "added");
459
		goto done;
460
	}
461
#endif /* ENABLE_PKCS11 */
462
390
	if (sc_reader_id != NULL) {
463
	if (sc_reader_id != NULL) {
391
		if (update_card(ac, !deleting, sc_reader_id) == -1)
464
		if (update_card(ac, !deleting, sc_reader_id) == -1)
392
			ret = 1;
465
			ret = 1;
(-)ssh.org/ssh-agent.c (+136 lines)
Lines 62-67 Link Here
62
#include "buffer.h"
62
#include "buffer.h"
63
#include "key.h"
63
#include "key.h"
64
#include "authfd.h"
64
#include "authfd.h"
65
#include "pkcs11.h"
65
#include "compat.h"
66
#include "compat.h"
66
#include "log.h"
67
#include "log.h"
67
#include "misc.h"
68
#include "misc.h"
Lines 688-693 send: Link Here
688
}
689
}
689
#endif /* SMARTCARD */
690
#endif /* SMARTCARD */
690
691
692
#ifdef ENABLE_PKCS11
693
694
static void
695
process_pkcs11_add_provider (SocketEntry *e)
696
{
697
	PKCS11Provider provider;
698
	int success = 0;
699
700
	provider.provider = buffer_get_string(&e->request, NULL);
701
	provider.protected_authentication = buffer_get_int(&e->request);
702
	provider.private_mode = (unsigned)buffer_get_int(&e->request);
703
	provider.cert_is_private = buffer_get_int(&e->request);
704
705
	success = pkcs11_add_provider(&provider);
706
707
	buffer_put_int(&e->output, 1);
708
	buffer_put_char(&e->output,
709
	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
710
}
711
712
static
713
void
714
process_pkcs11_add_id (SocketEntry *e)
715
{
716
	PKCS11Id *pkcs11_id = NULL;
717
	Key *k = NULL;
718
	char *comment = NULL;
719
	int success = 0;
720
	int version = 2;
721
722
	pkcs11_id = pkcs11_id_new();
723
	if (pkcs11_id != NULL) {
724
		pkcs11_id->id = strdup (buffer_get_string(&e->request, NULL));
725
		pkcs11_id->pin_cache_period = buffer_get_int(&e->request);
726
		pkcs11_id->cert_file = strdup (buffer_get_string(&e->request, NULL));
727
728
		if (pkcs11_get_key (pkcs11_id, &k, &comment)) {
729
			if (lookup_identity(k, version) == NULL) {
730
				Identity *id = xmalloc(sizeof(Identity));
731
				Idtab *tab = NULL;
732
	
733
				id->key = k;
734
				k = NULL;
735
				id->comment = comment;
736
				id->death = 0;		/* handled by pkcs#11 helper */
737
				id->confirm = 0;
738
	
739
				tab = idtab_lookup(version);
740
				TAILQ_INSERT_TAIL(&tab->idlist, id, next);
741
				/* Increment the number of identities. */
742
				tab->nentries++;
743
				success = 1;
744
			}
745
		}
746
	}
747
748
	if (k != NULL)
749
		key_free(k);
750
751
	if (pkcs11_id != NULL)
752
		pkcs11_id_free(pkcs11_id);
753
754
	buffer_put_int(&e->output, 1);
755
	buffer_put_char(&e->output,
756
	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
757
}
758
759
static
760
void
761
process_pkcs11_remove_id (SocketEntry *e)
762
{
763
	Identity *id = NULL;
764
	char *comment = NULL;
765
	PKCS11Id *pkcs11_id = NULL;
766
	Key *k = NULL;
767
	int version = 2;
768
	int success = 0;
769
770
	pkcs11_id = pkcs11_id_new();
771
	if (pkcs11_id != NULL) {
772
		pkcs11_id->id = strdup(buffer_get_string(&e->request, NULL));
773
		pkcs11_id->pin_cache_period = buffer_get_int(&e->request);
774
		pkcs11_id->cert_file = strdup(buffer_get_string(&e->request, NULL));
775
776
		if (pkcs11_get_key(pkcs11_id, &k, &comment)) {
777
			id = lookup_identity (k, version);
778
			xfree(comment);
779
			comment = NULL;
780
		}
781
782
		if (id != NULL) {
783
			Idtab *tab = NULL;
784
785
			tab = idtab_lookup(version);
786
			TAILQ_REMOVE(&tab->idlist, id, next);
787
			tab->nentries--;
788
			free_identity(id);
789
			id = NULL;
790
			success = 1;
791
		}
792
	}
793
794
	if (k != NULL)
795
		key_free(k);
796
797
	if (pkcs11_id != NULL)
798
		pkcs11_id_free(pkcs11_id);
799
800
	buffer_put_int(&e->output, 1);
801
	buffer_put_char(&e->output,
802
	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
803
}
804
805
#endif /* ENABLE_PKCS11 */
806
691
/* dispatch incoming messages */
807
/* dispatch incoming messages */
692
808
693
static void
809
static void
Lines 780-785 process_message(SocketEntry *e) Link Here
780
		process_remove_smartcard_key(e);
896
		process_remove_smartcard_key(e);
781
		break;
897
		break;
782
#endif /* SMARTCARD */
898
#endif /* SMARTCARD */
899
900
#ifdef ENABLE_PKCS11
901
	case SSH_AGENTC_PKCS11_ADD_PROVIDER:
902
		process_pkcs11_add_provider(e);
903
		break;
904
	case SSH_AGENTC_PKCS11_ADD_ID:
905
		process_pkcs11_add_id(e);
906
		break;
907
	case SSH_AGENTC_PKCS11_REMOVE_ID:
908
		process_pkcs11_remove_id(e);
909
		break;
910
#endif /* ENABLE_PKCS11 */
783
	default:
911
	default:
784
		/* Unknown message.  Respond with failure. */
912
		/* Unknown message.  Respond with failure. */
785
		error("Unknown message %d", type);
913
		error("Unknown message %d", type);
Lines 987-992 static void Link Here
987
cleanup_handler(int sig)
1115
cleanup_handler(int sig)
988
{
1116
{
989
	cleanup_socket();
1117
	cleanup_socket();
1118
#ifdef ENABLE_PKCS11
1119
	pkcs11_terminate ();
1120
#endif /* ENABLE_PKCS11 */
990
	_exit(2);
1121
	_exit(2);
991
}
1122
}
992
1123
Lines 1215-1220 main(int ac, char **av) Link Here
1215
	}
1346
	}
1216
1347
1217
skip:
1348
skip:
1349
1350
#ifdef ENABLE_PKCS11
1351
	pkcs11_initialize (1, -1);
1352
#endif /* ENABLE_PKCS11 */
1353
1218
	new_socket(AUTH_SOCKET, sock);
1354
	new_socket(AUTH_SOCKET, sock);
1219
	if (ac > 0)
1355
	if (ac > 0)
1220
		parent_alive_interval = 10;
1356
		parent_alive_interval = 10;
(-)ssh.org/ssh.c (-1 / +61 lines)
Lines 84-89 Link Here
84
#include "readconf.h"
84
#include "readconf.h"
85
#include "sshconnect.h"
85
#include "sshconnect.h"
86
#include "misc.h"
86
#include "misc.h"
87
#include "pkcs11.h"
87
#include "kex.h"
88
#include "kex.h"
88
#include "mac.h"
89
#include "mac.h"
89
#include "sshpty.h"
90
#include "sshpty.h"
Lines 171-176 static u_int mux_command = 0; Link Here
171
volatile sig_atomic_t control_client_terminate = 0;
172
volatile sig_atomic_t control_client_terminate = 0;
172
u_int control_server_pid = 0;
173
u_int control_server_pid = 0;
173
174
175
#ifdef ENABLE_PKCS11
176
/* For PKCS#11 */
177
static PKCS11Provider *pkcs11_provider = NULL;
178
#endif
179
174
/* Prints a help message to the user.  This function never returns. */
180
/* Prints a help message to the user.  This function never returns. */
175
181
176
static void
182
static void
Lines 183-188 usage(void) Link Here
183
"           [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n"
189
"           [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n"
184
"           [-R [bind_address:]port:host:hostport] [-S ctl_path]\n"
190
"           [-R [bind_address:]port:host:hostport] [-S ctl_path]\n"
185
"           [-w local_tun[:remote_tun]] [user@]hostname [command]\n"
191
"           [-w local_tun[:remote_tun]] [user@]hostname [command]\n"
192
#ifdef ENABLE_PKCS11
193
"           [-# pkcs11_provider_info]\n"
194
#endif
186
	);
195
	);
187
	exit(255);
196
	exit(255);
188
}
197
}
Lines 259-266 main(int ac, char **av) Link Here
259
268
260
 again:
269
 again:
261
	while ((opt = getopt(ac, av,
270
	while ((opt = getopt(ac, av,
262
	    "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:KL:MNO:PR:S:TVw:XY")) != -1) {
271
	    "#:1246ab:c:e:fgi:k:l:m:no:p:qstvxACD:F:I:KL:MNO:PR:S:TVw:XY")) != -1) {
263
		switch (opt) {
272
		switch (opt) {
273
#ifdef ENABLE_PKCS11
274
		case '#':
275
			if ((pkcs11_provider = pkcs11_parse_provider(optarg)) == NULL) {
276
				fprintf(stderr, "Cannot parse PKCS#11 provider information.\n");
277
				exit(255);
278
			}
279
			break;
280
#endif
264
		case '1':
281
		case '1':
265
			options.protocol = SSH_PROTO_1;
282
			options.protocol = SSH_PROTO_1;
266
			break;
283
			break;
Lines 666-671 main(int ac, char **av) Link Here
666
	if (options.control_path != NULL)
683
	if (options.control_path != NULL)
667
		control_client(options.control_path);
684
		control_client(options.control_path);
668
685
686
#ifdef ENABLE_PKCS11
687
	if (pkcs11_provider != NULL) {
688
		if (!pkcs11_initialize (1, -1))
689
			fatal("Cannot initialize PKCS#11 interface.\n");
690
		if (!pkcs11_add_provider(pkcs11_provider))
691
			fatal("Cannot add PKCS#11 provider '%s'.\n",
692
				pkcs11_provider->provider);
693
	}
694
#endif
695
669
	/* Open a connection to the remote host. */
696
	/* Open a connection to the remote host. */
670
	if (ssh_connect(host, &hostaddr, options.port,
697
	if (ssh_connect(host, &hostaddr, options.port,
671
	    options.address_family, options.connection_attempts,
698
	    options.address_family, options.connection_attempts,
Lines 786-791 main(int ac, char **av) Link Here
786
	if (proxy_command_pid > 1)
813
	if (proxy_command_pid > 1)
787
		kill(proxy_command_pid, SIGHUP);
814
		kill(proxy_command_pid, SIGHUP);
788
815
816
#ifdef ENABLE_PKCS11
817
	if (pkcs11_provider != NULL) {
818
		pkcs11_terminate();
819
		pkcs11_free_provider(pkcs11_provider);
820
		pkcs11_provider = NULL;
821
	}
822
#endif
823
789
	return exit_status;
824
	return exit_status;
790
}
825
}
791
826
Lines 1220-1225 load_public_identity_files(void) Link Here
1220
		xfree(keys);
1255
		xfree(keys);
1221
	}
1256
	}
1222
#endif /* SMARTCARD */
1257
#endif /* SMARTCARD */
1258
#ifdef ENABLE_PKCS11
1259
	if (pkcs11_provider != NULL) {
1260
		Key **keys = NULL;
1261
		char **comments = NULL;
1262
1263
		if (pkcs11_get_keys(&keys, &comments)) {
1264
			int count = 0;
1265
			while (options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
1266
				keys[count] != NULL) {
1267
				memmove(&options.identity_files[1], &options.identity_files[0],
1268
				    sizeof(char *) * (SSH_MAX_IDENTITY_FILES - 1));
1269
				memmove(&options.identity_keys[1], &options.identity_keys[0],
1270
				    sizeof(Key *) * (SSH_MAX_IDENTITY_FILES - 1));
1271
				options.num_identity_files++;
1272
				options.identity_keys[0] = keys[count];
1273
				options.identity_files[0] = comments[count];
1274
				count++;
1275
			}
1276
			i += count;
1277
			xfree(keys);
1278
			xfree(comments);
1279
		}
1280
	
1281
	}
1282
#endif
1223
	if ((pw = getpwuid(original_real_uid)) == NULL)
1283
	if ((pw = getpwuid(original_real_uid)) == NULL)
1224
		fatal("load_public_identity_files: getpwuid failed");
1284
		fatal("load_public_identity_files: getpwuid failed");
1225
	if (gethostname(thishost, sizeof(thishost)) == -1)
1285
	if (gethostname(thishost, sizeof(thishost)) == -1)
(-)ssh.org/ssh-keygen.c (-1 / +28 lines)
Lines 35-40 Link Here
35
#include "uuencode.h"
35
#include "uuencode.h"
36
#include "buffer.h"
36
#include "buffer.h"
37
#include "pathnames.h"
37
#include "pathnames.h"
38
#include "pkcs11.h"
38
#include "log.h"
39
#include "log.h"
39
#include "misc.h"
40
#include "misc.h"
40
#include "match.h"
41
#include "match.h"
Lines 1016-1021 usage(void) Link Here
1016
	fprintf(stderr, "  -g          Use generic DNS resource record format.\n");
1017
	fprintf(stderr, "  -g          Use generic DNS resource record format.\n");
1017
	fprintf(stderr, "  -H          Hash names in known_hosts file.\n");
1018
	fprintf(stderr, "  -H          Hash names in known_hosts file.\n");
1018
	fprintf(stderr, "  -i          Convert RFC 4716 to OpenSSH key file.\n");
1019
	fprintf(stderr, "  -i          Convert RFC 4716 to OpenSSH key file.\n");
1020
#ifdef ENABLE_PKCS11
1021
	fprintf(stderr, "  -K provider Show PKCS#11 provider ids, format:\n");
1022
	fprintf(stderr, "              lib[:prot_auth[:private_mode[:cert_is_private]]]\n");
1023
	fprintf(stderr, "              prot_auth - 1 to allow protected mode authentication.\n");
1024
	fprintf(stderr, "              private_mode - Private key mode, see man page.\n");
1025
	fprintf(stderr, "              cert_is_private - 1 if login is required to access certificates.\n");
1026
#endif /* ENABLE_PKCS11 */
1019
	fprintf(stderr, "  -l          Show fingerprint of key file.\n");
1027
	fprintf(stderr, "  -l          Show fingerprint of key file.\n");
1020
	fprintf(stderr, "  -M memory   Amount of memory (MB) to use for generating DH-GEX moduli.\n");
1028
	fprintf(stderr, "  -M memory   Amount of memory (MB) to use for generating DH-GEX moduli.\n");
1021
	fprintf(stderr, "  -N phrase   Provide new passphrase.\n");
1029
	fprintf(stderr, "  -N phrase   Provide new passphrase.\n");
Lines 1056-1061 main(int argc, char **argv) Link Here
1056
	BIGNUM *start = NULL;
1064
	BIGNUM *start = NULL;
1057
	FILE *f;
1065
	FILE *f;
1058
	const char *errstr;
1066
	const char *errstr;
1067
#ifdef ENABLE_PKCS11
1068
	PKCS11Provider *pkcs11_provider = NULL;
1069
#endif /* ENABLE_PKCS11 */
1059
1070
1060
	extern int optind;
1071
	extern int optind;
1061
	extern char *optarg;
1072
	extern char *optarg;
Lines 1078-1084 main(int argc, char **argv) Link Here
1078
	}
1089
	}
1079
1090
1080
	while ((opt = getopt(argc, argv,
1091
	while ((opt = getopt(argc, argv,
1081
	    "degiqpclBHvxXyF:b:f:t:U:D:P:N:C:r:g:R:T:G:M:S:a:W:")) != -1) {
1092
	    "degiqpclBHvxXyF:b:f:t:U:D:P:N:C:r:g:R:T:G:M:S:a:W:K:")) != -1) {
1082
		switch (opt) {
1093
		switch (opt) {
1083
		case 'b':
1094
		case 'b':
1084
			bits = (u_int32_t)strtonum(optarg, 768, 32768, &errstr);
1095
			bits = (u_int32_t)strtonum(optarg, 768, 32768, &errstr);
Lines 1203-1208 main(int argc, char **argv) Link Here
1203
			if (BN_hex2bn(&start, optarg) == 0)
1214
			if (BN_hex2bn(&start, optarg) == 0)
1204
				fatal("Invalid start point.");
1215
				fatal("Invalid start point.");
1205
			break;
1216
			break;
1217
#ifdef ENABLE_PKCS11
1218
		case 'K':
1219
			if ((pkcs11_provider = pkcs11_parse_provider(optarg)) == NULL)
1220
				fatal("Cannot parse PKCS#11 provider.");
1221
			break;
1222
#endif /* ENABLE_PKCS11 */
1206
		case '?':
1223
		case '?':
1207
		default:
1224
		default:
1208
			usage();
1225
			usage();
Lines 1257-1262 main(int argc, char **argv) Link Here
1257
			exit(0);
1274
			exit(0);
1258
		}
1275
		}
1259
	}
1276
	}
1277
#ifdef ENABLE_PKCS11
1278
	if (pkcs11_provider != NULL) {
1279
		pkcs11_initialize(1, -1);
1280
		pkcs11_add_provider(pkcs11_provider);
1281
		pkcs11_show_ids();
1282
		pkcs11_terminate();
1283
		pkcs11_free_provider(pkcs11_provider);
1284
		return (0);
1285
	}
1286
#endif /* ENABLE_PKCS11 */
1260
	if (reader_id != NULL) {
1287
	if (reader_id != NULL) {
1261
#ifdef SMARTCARD
1288
#ifdef SMARTCARD
1262
		if (download)
1289
		if (download)

Return to bug 1371