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

Collapse All | Expand All

(-)ssh/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 pkcs11_provider *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 pkcs11_id *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/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 pkcs11_provider *const);
104
int	ssh_pkcs11_id(AuthenticationConnection *, const pkcs11_id *const, int remove);
105
#endif /* ENABLE_PKCS11 */
106
95
#endif				/* AUTHFD_H */
107
#endif				/* AUTHFD_H */
(-)ssh/pkcs11.c (+871 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
#ifdef ENABLE_PKCS11
26
27
#include <string.h>
28
#include <unistd.h>
29
#include <sys/wait.h>
30
#include <errno.h>
31
#include <pkcs11-helper-1.0/pkcs11h-certificate.h>
32
#include <pkcs11-helper-1.0/pkcs11h-openssl.h>
33
#include "openssl/pem.h"
34
#include "misc.h"
35
#include "buffer.h"
36
#include "xmalloc.h"
37
#include "log.h"
38
#include "pkcs11.h"
39
40
static char *
41
ssh_from_x509(X509 *);
42
43
static time_t
44
mytime(void)
45
{
46
	return time(NULL);
47
}
48
49
static void
50
mysleep(const unsigned long usec)
51
{
52
	usleep((unsigned)usec);
53
}
54
55
static int
56
mygettimeofday(struct timeval *tv)
57
{
58
	return gettimeofday(tv, NULL);
59
}
60
61
static pkcs11h_engine_system_t s_pkcs11h_sys_engine = {
62
	xmalloc,
63
	xfree,
64
	mytime,
65
	mysleep,
66
	mygettimeofday
67
};
68
69
static LogLevel
70
pkcs11_msg_pkcs112openssh(const unsigned flags)
71
{
72
	LogLevel openssh_flags;
73
74
	switch (flags) {
75
	case PKCS11H_LOG_DEBUG2:
76
		openssh_flags = SYSLOG_LEVEL_DEBUG3;
77
		break;
78
	case PKCS11H_LOG_DEBUG1:
79
		openssh_flags = SYSLOG_LEVEL_DEBUG2;
80
		break;
81
	case PKCS11H_LOG_INFO:
82
		openssh_flags = SYSLOG_LEVEL_INFO;
83
		break;
84
	case PKCS11H_LOG_WARN:
85
		openssh_flags = SYSLOG_LEVEL_ERROR;
86
		break;
87
	case PKCS11H_LOG_ERROR:
88
		openssh_flags = SYSLOG_LEVEL_FATAL;
89
		break;
90
	default:
91
		openssh_flags = SYSLOG_LEVEL_FATAL;
92
		break;
93
	}
94
95
	return openssh_flags;
96
}
97
98
static unsigned
99
pkcs11_msg_openssh2pkcs11(const LogLevel flags)
100
{
101
	unsigned pkcs11_flags;
102
103
	switch (flags) {
104
	case SYSLOG_LEVEL_DEBUG3:
105
		pkcs11_flags = PKCS11H_LOG_DEBUG2;
106
		break;
107
	case SYSLOG_LEVEL_DEBUG2:
108
		pkcs11_flags = PKCS11H_LOG_DEBUG1;
109
		break;
110
	case SYSLOG_LEVEL_INFO:
111
		pkcs11_flags = PKCS11H_LOG_INFO;
112
		break;
113
	case SYSLOG_LEVEL_ERROR:
114
		pkcs11_flags = PKCS11H_LOG_WARN;
115
		break;
116
	case SYSLOG_LEVEL_FATAL:
117
		pkcs11_flags = PKCS11H_LOG_ERROR;
118
		break;
119
	default:
120
		pkcs11_flags = PKCS11H_LOG_ERROR;
121
		break;
122
	}
123
124
	return pkcs11_flags;
125
}
126
127
/* ARGSUSED */
128
static void
129
pkcs11_openssh_log(void *const global_data, unsigned flags,
130
	const char *const format, va_list args)
131
{
132
	do_log(pkcs11_msg_pkcs112openssh(flags), format, args);
133
}
134
135
/* ARGSUSED */
136
static PKCS11H_BOOL
137
pkcs11_ssh_token_prompt(void *const global_data,
138
	void *const user_data,
139
	const pkcs11h_token_id_t token, IN const unsigned retry)
140
{
141
	return ask_permission("Please insert token '%s'", token->display);
142
}
143
144
/* ARGSUSED */
145
static PKCS11H_BOOL
146
_pkcs11_ssh_pin_prompt(void *const global_data,
147
	void *const user_data, const pkcs11h_token_id_t token,
148
	const unsigned retry, char *const pin, const size_t pin_max)
149
{
150
	char prompt[1024];
151
	char *passphrase = NULL;
152
	PKCS11H_BOOL ret = FALSE;
153
154
	if (snprintf(prompt, sizeof(prompt), "Please enter PIN for token '%s': ",
155
		token->display) < 0)
156
		goto cleanup;
157
158
	passphrase = read_passphrase(prompt, RP_ALLOW_EOF);
159
160
	if (passphrase == NULL || strlen(passphrase) == 0 ||
161
		strlen(passphrase) > pin_max-1)
162
		goto cleanup;
163
	
164
	strlcpy(pin, passphrase, pin_max);
165
	bzero(passphrase, strlen(passphrase));
166
167
	ret = TRUE;
168
169
cleanup:
170
171
	if (passphrase != NULL)
172
		xfree(passphrase);
173
174
	return ret;
175
}
176
177
static int
178
pkcs11_convert_to_ssh_key(const pkcs11h_certificate_id_t certificate_id, Key **const key,
179
	char **const comment, const int pin_cache_period)
180
{
181
	pkcs11h_certificate_t certificate = NULL;
182
	pkcs11h_certificate_id_t certificate_id_new = NULL;
183
	pkcs11h_openssl_session_t openssl_session = NULL;
184
	Key *internal_key = NULL;
185
	char *internal_comment = NULL;
186
	RSA *rsa = NULL;
187
	size_t temp;
188
	CK_RV rv = CKR_OK;
189
190
	*key = NULL;
191
	*comment = NULL;
192
193
	debug3("PKCS#11: pkcs11_convert_to_ssh_key - entered - certificate=%p, "
194
		"key=%p, comment=%p, pin_cache_period=%d", (void *) certificate,
195
		(void *) key, (void *) comment, pin_cache_period);
196
197
	if ((rv = pkcs11h_certificate_create(certificate_id, NULL,
198
		PKCS11H_PROMPT_MASK_ALLOW_ALL, pin_cache_period,
199
		&certificate)) != CKR_OK) {
200
		error("PKCS#11: Cannot get certificate %ld-'%s'", rv,
201
			pkcs11h_getMessage(rv));
202
		goto cleanup;
203
	}
204
205
	/*
206
	 * New certificate_id is constructed from certificate
207
	 * blob so that it will contian the proper description.
208
	 */
209
210
	if ((rv = pkcs11h_certificate_getCertificateBlob(certificate,
211
				NULL, &temp)) != CKR_OK) {
212
		error("PKCS#11: Cannot get certificate blob %ld-'%s'", rv,
213
			pkcs11h_getMessage(rv));
214
		goto cleanup;
215
	}
216
217
	if ((rv = pkcs11h_certificate_getCertificateId(certificate,
218
		&certificate_id_new)) != CKR_OK) {
219
		error("PKCS#11: Cannot get certificate_id %ld-'%s'", rv,
220
			pkcs11h_getMessage(rv));
221
		goto cleanup;
222
	}
223
224
	if ((internal_comment = xstrdup(certificate_id_new->displayName)) == NULL) {
225
		error("PKCS#11: Memory allocation error");
226
		goto cleanup;
227
	}
228
229
	if ((openssl_session =
230
			pkcs11h_openssl_createSession(certificate)) == NULL) {
231
		error("PKCS#11: Cannot initialize openssl session");
232
		goto cleanup;
233
	}
234
235
	/*
236
	 * will be release by openssl_session
237
	 */
238
	certificate = NULL;
239
240
	if ((rsa = pkcs11h_openssl_session_getRSA(openssl_session)) == NULL) {
241
		error("PKCS#11: Unable get rsa object");
242
		goto cleanup;
243
	}
244
245
	internal_key = key_new_private(KEY_UNSPEC);
246
	internal_key->flags |= KEY_FLAG_EXT;
247
	internal_key->rsa = rsa;
248
	rsa = NULL;
249
	internal_key->type = KEY_RSA;
250
251
	*key = internal_key;
252
	internal_key = NULL;
253
	*comment = internal_comment;
254
	internal_comment = NULL;
255
256
cleanup:
257
	if (internal_key != NULL) {
258
		key_free(internal_key);
259
		internal_key = NULL;
260
	}
261
262
	if (internal_comment != NULL) {
263
		xfree(internal_comment);
264
		internal_comment = NULL;
265
	}
266
267
	if (rsa != NULL) {
268
		RSA_free (rsa);
269
		rsa = NULL;
270
	}
271
272
	if (openssl_session != NULL) {
273
		pkcs11h_openssl_freeSession(openssl_session);
274
		openssl_session = NULL;
275
	}
276
277
	if (certificate_id_new != NULL) {
278
		pkcs11h_certificate_freeCertificateId(certificate_id_new);
279
		certificate_id_new = NULL;
280
	}
281
282
	if (certificate != NULL) {
283
		pkcs11h_certificate_freeCertificate(certificate);
284
		certificate = NULL;
285
	}
286
287
	debug3("PKCS#11: pkcs11_convert_to_ssh_key - return *key=%p", (void *) *key);
288
289
	return *key != NULL;
290
}
291
292
int
293
pkcs11_initialize(const int protected_authentication, const int pin_cache_period)
294
{
295
	CK_RV rv = CKR_FUNCTION_FAILED;
296
297
	debug3("PKCS#11: pkcs11_initialize - entered protected_authentication=%d, "
298
		"pin_cache_period=%d", protected_authentication, pin_cache_period);
299
300
	if ((rv = pkcs11h_engine_setSystem(&s_pkcs11h_sys_engine)) != CKR_OK) {
301
		error("PKCS#11: Cannot set system engine %ld-'%s'", rv,
302
			pkcs11h_getMessage(rv));
303
		goto cleanup;
304
	}
305
306
	if ((rv = pkcs11h_initialize()) != CKR_OK) {
307
		error("PKCS#11: Cannot initialize %ld-'%s'", rv,
308
			pkcs11h_getMessage(rv));
309
		goto cleanup;
310
	}
311
312
	if ((rv = pkcs11h_setLogHook(pkcs11_openssh_log, NULL)) != CKR_OK) {
313
		error("PKCS#11: Cannot set hooks %ld-'%s'", rv,
314
			pkcs11h_getMessage(rv));
315
		goto cleanup;
316
	}
317
318
	pkcs11h_setLogLevel(pkcs11_msg_openssh2pkcs11(get_log_level ()));
319
320
	if ((rv = pkcs11h_setTokenPromptHook(pkcs11_ssh_token_prompt,
321
		NULL)) != CKR_OK) {
322
		error("PKCS#11: Cannot set hooks %ld-'%s'", rv,
323
			pkcs11h_getMessage(rv));
324
		goto cleanup;
325
	}
326
327
	if ((rv = pkcs11h_setPINPromptHook(_pkcs11_ssh_pin_prompt,
328
		NULL)) != CKR_OK) {
329
		error("PKCS#11: Cannot set hooks %ld-'%s'", rv,
330
			pkcs11h_getMessage(rv));
331
		goto cleanup;
332
	}
333
334
	if ((rv = pkcs11h_setProtectedAuthentication(protected_authentication)) !=
335
		CKR_OK) {
336
		error("PKCS#11: Cannot set protected authentication mode %ld-'%s'",
337
			rv, pkcs11h_getMessage(rv));
338
		goto cleanup;
339
	}
340
341
	if ((rv = pkcs11h_setPINCachePeriod(pin_cache_period)) != CKR_OK) {
342
		error("PKCS#11: Cannot set PIN cache period %ld-'%s'", rv,
343
			pkcs11h_getMessage(rv));
344
		goto cleanup;
345
	}
346
347
	rv = CKR_OK;
348
349
cleanup:
350
	debug3("PKCS#11: pkcs11_initialize - return rv=%ld-'%s'",
351
		rv, pkcs11h_getMessage(rv));
352
353
	return rv == CKR_OK;
354
}
355
356
void
357
pkcs11_terminate(void)
358
{
359
	debug3("PKCS#11: pkcs11_terminate - entered");
360
361
	pkcs11h_terminate();
362
363
	debug3("PKCS#11: pkcs11_terminate - return");
364
}
365
366
void
367
pkcs11_free_provider(pkcs11_provider *const provider) {
368
	if (provider != NULL) {
369
		if (provider->provider != NULL)
370
			xfree(provider->provider);
371
		xfree(provider);
372
	}
373
}
374
375
pkcs11_provider *
376
pkcs11_parse_provider(const char *const info)
377
{
378
	pkcs11_provider *provider = NULL;
379
	pkcs11_provider *ret = NULL;
380
	char *split[4];
381
	char *s = NULL;
382
	char *p;
383
	int i;
384
385
	if (info == NULL)
386
		goto cleanup;
387
388
	if ((provider = (pkcs11_provider *) xmalloc(sizeof(*provider))) == NULL)
389
		goto cleanup;
390
391
	memset(provider, 0, sizeof(*provider));
392
	memset(split, 0, sizeof(split));
393
394
	if ((s=xstrdup(info)) == NULL)
395
		goto cleanup;
396
397
	p = s;
398
	i=0;
399
	while(i<4 && p != NULL) {
400
		char *t;
401
		if ((t = strchr(p, ':')) != NULL)
402
			*t = '\x0';
403
		split[i++] = p;
404
		if (t != NULL)
405
			p = t+1;
406
		else
407
			p = NULL;
408
	}
409
410
	/*
411
	 * provider[:protected_authentication[:private_mode[:cert_is_private]]]
412
	 * string:1|0:hex:1|0
413
	 */
414
	if (split[0] != NULL)
415
		provider->provider = xstrdup(split[0]);
416
	if (split[1] != NULL)
417
		provider->protected_authentication = atoi(split[1]) != 0;
418
	if (split[2] != NULL)
419
		sscanf(split[2], "%x", &provider->private_mode);
420
	if (split[3] != NULL)
421
		provider->cert_is_private = atoi(split[3]) != 0;
422
	
423
	if (provider->provider == NULL || strlen(provider->provider) == 0)
424
		goto cleanup;
425
426
	ret = provider;
427
	provider = NULL;
428
429
cleanup:
430
	if (s != NULL)
431
		xfree(s);
432
433
	if (provider != NULL)
434
		pkcs11_free_provider(provider);
435
436
	return ret;
437
}
438
439
int
440
pkcs11_add_provider(const pkcs11_provider *const provider)
441
{
442
	CK_RV rv = CKR_OK;
443
444
	debug3("PKCS#11: pkcs11_add_provider - entered - provider='%s', "
445
		"protected_authentication=%d, private_mode='%08x', cert_is_private=%d",
446
		provider->provider, provider->protected_authentication ? 1 : 0,
447
		provider->private_mode,	provider->cert_is_private ? 1 : 0);
448
449
	debug("PKCS#11: Adding PKCS#11 provider '%s'", provider->provider);
450
451
	if (rv == CKR_OK &&
452
		(rv = pkcs11h_addProvider(provider->provider, provider->provider,
453
			provider->protected_authentication, provider->private_mode,
454
				PKCS11H_SLOTEVENT_METHOD_AUTO,
455
				0, provider->cert_is_private)) != CKR_OK) {
456
		error("PKCS#11: Cannot initialize provider '%s' %ld-'%s'",
457
			provider->provider, rv, pkcs11h_getMessage(rv));
458
	}
459
460
	debug3("PKCS#11: pkcs11_add_provider - return rv=%ld-'%s'",
461
		rv, pkcs11h_getMessage(rv));
462
463
	return rv == CKR_OK;
464
}
465
466
pkcs11_id *
467
pkcs11_id_new(void)
468
{
469
	pkcs11_id *id = (pkcs11_id *) xmalloc(sizeof(*id));
470
	if (id != NULL) {
471
		memset(id, 0, sizeof(*id));
472
		id->pin_cache_period = PKCS11H_PIN_CACHE_INFINITE;
473
	}
474
	return id;
475
}
476
477
void
478
pkcs11_id_free(pkcs11_id *const id)
479
{
480
	if (id != NULL)
481
		xfree(id);
482
}
483
484
int
485
pkcs11_get_key(const pkcs11_id *const id, Key **const key,
486
	char **const comment)
487
{
488
	pkcs11h_certificate_id_t certificate_id = NULL;
489
	CK_RV rv = CKR_OK;
490
491
	debug3("PKCS#11: pkcs11_get_key - entered - id=%p, key=%p, "
492
		"comment=%p", (const void *) id, (void *) key, (void *) comment);
493
494
	debug3("PKCS#11: pkcs11_get_key - id - id=%s, "
495
		"pin_cache_period=%d, cert_file=%s",
496
		id->id, id->pin_cache_period, id->cert_file);
497
498
	if (pkcs11h_certificate_deserializeCertificateId(&certificate_id, id->id)) {
499
		error("PKCS#11: Cannot deserialize id %ld-'%s'", rv,
500
			pkcs11h_getMessage(rv));
501
		goto cleanup;
502
	}
503
504
	if (id->cert_file != NULL && id->cert_file[0] != '\x0') {
505
		X509 *x509 = NULL;
506
		unsigned char *p = NULL;
507
		unsigned char *certificate_blob = NULL;
508
		size_t certificate_blob_size = 0;
509
		int size;
510
		FILE *fp = NULL;
511
512
		if ((fp = fopen(id->cert_file, "r")) == NULL) {
513
			error("PKCS#11: Cannot open file '%s'", id->cert_file);
514
			goto cleanup1;
515
		}
516
517
		if (!PEM_read_X509(fp, &x509, NULL, 0)) {
518
			x509 = NULL;
519
			error("PKCS#11: Cannot read PEM from file '%s'", id->cert_file);
520
			goto cleanup1;
521
		}
522
523
		if ((size = i2d_X509(x509, NULL)) < 0) {
524
			error("PKCS#11: Cannot read decode certificate");
525
			goto cleanup1;
526
		}
527
		certificate_blob_size = (size_t)size;
528
529
		if ((certificate_blob =
530
				(unsigned char *) xmalloc(certificate_blob_size)) == NULL) {
531
			error("PKCS#11: Cannot allocate memory");
532
			goto cleanup1;
533
		}
534
535
		/*
536
		 * i2d_X509 increments p!!!
537
		 */
538
		p = certificate_blob;
539
540
		if ((size = i2d_X509(x509, &p)) < 0) {
541
			error("PKCS#11: Cannot read decode certificate");
542
			goto cleanup1;
543
		}
544
		certificate_blob_size = (size_t)size;
545
546
		if (pkcs11h_certificate_setCertificateIdCertificateBlob
547
			(certificate_id, certificate_blob, certificate_blob_size)
548
			!= CKR_OK) {
549
			error("PKCS#11: Cannot set certificate blob %ld-'%s'", rv,
550
				pkcs11h_getMessage(rv));
551
			goto cleanup1;
552
		}
553
554
	cleanup1:
555
		if (x509 != NULL) {
556
			X509_free(x509);
557
			x509 = NULL;
558
		}
559
560
		if (certificate_blob != NULL) {
561
			xfree(certificate_blob);
562
			certificate_blob = NULL;
563
		}
564
565
		if (fp != NULL) {
566
			fclose(fp);
567
			fp = NULL;
568
		}
569
	}
570
571
	pkcs11_convert_to_ssh_key(certificate_id, key, comment, id->pin_cache_period);
572
573
cleanup:
574
575
	if (certificate_id != NULL) {
576
		pkcs11h_certificate_freeCertificateId(certificate_id);
577
		certificate_id = NULL;
578
	}
579
580
	debug3("PKCS#11: pkcs11_get_key - return rv=%ld, *key=%p", rv, ( void *) *key);
581
582
	return *key != NULL;
583
}
584
585
int
586
pkcs11_get_keys(Key ***const keys, char ***const comments)
587
{
588
#define PKCS11_MAX_KEYS 10
589
	Key **internal_keys = NULL;
590
	char **internal_comments = NULL;
591
	pkcs11h_certificate_id_list_t user_certificates = NULL;
592
	pkcs11h_certificate_id_list_t current = NULL;
593
	CK_RV rv = CKR_FUNCTION_FAILED;
594
	int i;
595
596
	debug3("PKCS#11: pkcs11_get_keys - entered - sshkey=%p, "
597
		"comment=%p",
598
		(void *) keys, (void *) comments);
599
	
600
	*keys = NULL;
601
	*comments = NULL;
602
	
603
	if((internal_keys = (Key **) xcalloc(sizeof(*internal_keys), PKCS11_MAX_KEYS+1)) == NULL) {
604
		rv = CKR_HOST_MEMORY;
605
		goto cleanup;
606
	}
607
608
	if((internal_comments = (char **) xcalloc(sizeof(*internal_comments), PKCS11_MAX_KEYS+1)) == NULL) {
609
		rv = CKR_HOST_MEMORY;
610
		goto cleanup;
611
	}
612
613
	memset(internal_keys, 0, (PKCS11_MAX_KEYS+1)*sizeof(*internal_keys));
614
	memset(internal_comments, 0, (PKCS11_MAX_KEYS+1)*sizeof(*internal_comments));
615
616
	if ((rv = pkcs11h_certificate_enumCertificateIds(
617
		PKCS11H_ENUM_METHOD_CACHE_EXIST, NULL,
618
		PKCS11H_PROMPT_MASK_ALLOW_ALL, NULL,
619
		&user_certificates)) != CKR_OK) {
620
		error("PKCS#11: Cannot enumerate certificates %ld-'%s'", rv,
621
			pkcs11h_getMessage(rv));
622
		goto cleanup;
623
	}
624
625
	i = 0;
626
	for (current = user_certificates; current != NULL && i<PKCS11_MAX_KEYS;
627
		current = current->next) {
628
629
		if (pkcs11_convert_to_ssh_key(current->certificate_id, &internal_keys[i],
630
			&internal_comments[i], PKCS11H_PIN_CACHE_INFINITE)) {
631
			i++;
632
		}
633
	}
634
635
	*keys = internal_keys;
636
	internal_keys = NULL;
637
	*comments = internal_comments;
638
	internal_comments = NULL;
639
	rv = CKR_OK;
640
641
cleanup:
642
	if (user_certificates != NULL) {
643
		pkcs11h_certificate_freeCertificateIdList(user_certificates);
644
		user_certificates = NULL;
645
	}
646
647
	if (internal_keys != NULL) {
648
		Key **t = internal_keys;
649
		while (*t != NULL) {
650
			key_free(*t);
651
			t++;
652
		}
653
		xfree(internal_keys);
654
	}
655
656
	if (internal_comments != NULL) {
657
		char **t = internal_comments;
658
		while (*t != NULL) {
659
			xfree(*t);
660
			t++;
661
		}
662
		xfree(internal_comments);
663
	}
664
665
	debug3("PKCS#11: pkcs11_get_keys - return rv=%ld, *keys=%p", rv, (void *) *keys);
666
667
	return *keys != NULL;
668
#undef PKCS11_MAX_KEYS
669
}
670
671
void
672
pkcs11_show_ids(void)
673
{
674
	pkcs11h_certificate_id_list_t user_certificates = NULL;
675
	pkcs11h_certificate_id_list_t current = NULL;
676
	CK_RV rv = CKR_FUNCTION_FAILED;
677
678
	if ((rv = pkcs11h_certificate_enumCertificateIds(
679
		PKCS11H_ENUM_METHOD_CACHE_EXIST, NULL,
680
		PKCS11H_PROMPT_MASK_ALLOW_ALL, NULL,
681
		&user_certificates)) != CKR_OK) {
682
		error("PKCS#11: Cannot enumerate certificates %ld-'%s'", rv,
683
			pkcs11h_getMessage(rv));
684
		goto cleanup;
685
	}
686
687
	for (current = user_certificates; current != NULL;
688
		current = current->next) {
689
690
		pkcs11h_certificate_t certificate = NULL;
691
		X509 *x509 = NULL;
692
693
		BIO *bio = NULL;
694
		char dn[1024] = { 0 };
695
		char serial[1024] = { 0 };
696
		char *ser = NULL;
697
		char *ssh_key = NULL;
698
		size_t ser_len = 0;
699
		int n;
700
701
		if ((rv = pkcs11h_certificate_serializeCertificateId(NULL,
702
			&ser_len, current->certificate_id)) != CKR_OK) {
703
			error("PKCS#11: Cannot serialize certificate id "
704
				"certificates %ld-'%s'", rv,
705
				pkcs11h_getMessage(rv));
706
			goto cleanup1;
707
		}
708
709
		if ((ser = (char *) xmalloc(ser_len)) == NULL) {
710
			error("PKCS#11: Cannot allocate memory");
711
			goto cleanup1;
712
		}
713
714
		if ((rv = pkcs11h_certificate_serializeCertificateId(ser,
715
			&ser_len, current->certificate_id)) != CKR_OK) {
716
			error("PKCS#11: Cannot serialize certificate "
717
				"id certificates %ld-'%s'",
718
				rv, pkcs11h_getMessage(rv));
719
			goto cleanup1;
720
		}
721
722
		if ((rv = pkcs11h_certificate_create(current->certificate_id,
723
			NULL, PKCS11H_PROMPT_MASK_ALLOW_ALL,
724
			PKCS11H_PIN_CACHE_INFINITE, &certificate)) != CKR_OK) {
725
			error("PKCS#11: Cannot create certificate %ld-'%s'", rv,
726
				pkcs11h_getMessage(rv));
727
			goto cleanup1;
728
		}
729
730
		if ((x509 = pkcs11h_openssl_getX509(certificate)) == NULL) {
731
			error("PKCS#11: Cannot get X509");
732
			goto cleanup1;
733
		}
734
735
		X509_NAME_oneline(X509_get_subject_name(x509), dn, sizeof(dn));
736
737
		if ((bio = BIO_new(BIO_s_mem())) == NULL) {
738
			error("PKCS#11: Cannot create BIO");
739
			goto cleanup1;
740
		}
741
742
		i2a_ASN1_INTEGER(bio, X509_get_serialNumber(x509));
743
		n = BIO_read(bio, serial, sizeof(serial) - 1);
744
		if (n < 0)
745
			serial[0] = '\x0';
746
		else
747
			serial[n] = 0;
748
749
		printf(("\n"
750
				"********************************************\n"
751
				"IDENTITY:\n"
752
				"       DN:             %s\n"
753
				"       Serial:         %s\n"
754
				"       Serialized id:  %s\n"
755
				"\n" "       Certificate:\n"), dn, serial, ser);
756
		PEM_write_X509(stdout, x509);
757
758
		if ((ssh_key = ssh_from_x509(x509)) != NULL) {
759
			printf(("\n" "        SSH:\n" "%s\n"), ssh_key);
760
761
			xfree(ssh_key);
762
		}
763
764
	cleanup1:
765
		if (x509 != NULL) {
766
			X509_free(x509);
767
			x509 = NULL;
768
		}
769
770
		if (bio != NULL) {
771
			BIO_free_all(bio);
772
			bio = NULL;
773
		}
774
775
		if (certificate != NULL) {
776
			pkcs11h_certificate_freeCertificate(certificate);
777
			certificate = NULL;
778
		}
779
780
		if (ser != NULL) {
781
			xfree(ser);
782
			ser = NULL;
783
		}
784
	}
785
786
cleanup:
787
	if (user_certificates != NULL) {
788
		pkcs11h_certificate_freeCertificateIdList(user_certificates);
789
		user_certificates = NULL;
790
	}
791
}
792
793
static char *
794
ssh_from_x509(X509 * x509)
795
{
796
	Buffer b;
797
	EVP_PKEY *pubkey = NULL;
798
	BIO *bio = NULL, *bio2 = NULL, *bio64 = NULL;
799
	char *ret = NULL;
800
	size_t retsize = 0;
801
	char *p;
802
	int n;
803
	const char *keyname = "ssh-rsa";
804
	int ok = 0;
805
806
	buffer_init(&b);
807
808
	if ((pubkey = X509_get_pubkey(x509)) == NULL)
809
		goto cleanup;
810
811
	if ((bio64 = BIO_new(BIO_f_base64())) == NULL)
812
		goto cleanup;
813
814
	if ((bio = BIO_new(BIO_s_mem())) == NULL)
815
		goto cleanup;
816
817
	if ((bio2 = BIO_push(bio64, bio)) == NULL)
818
		goto cleanup;
819
820
	if (pubkey->type != EVP_PKEY_RSA)
821
		goto cleanup;
822
823
	buffer_put_cstring(&b, keyname);
824
	buffer_put_bignum2(&b, pubkey->pkey.rsa->e);
825
	buffer_put_bignum2(&b, pubkey->pkey.rsa->n);
826
827
	if (BIO_write(bio2, buffer_ptr(&b), buffer_len(&b)) == -1)
828
		goto cleanup;
829
	if (BIO_flush(bio2) == -1)
830
		goto cleanup;
831
	if ((n = BIO_read(bio, NULL, 10*1024)) == -1)
832
		goto cleanup;
833
	retsize = n+1+strlen(keyname)+1;	/* including null terminate and keyname prefix */
834
	if ((ret = (char *) xmalloc(retsize)) == NULL)
835
		goto cleanup;
836
	snprintf (ret, retsize, "%s ", keyname);
837
	if ((n = BIO_read(bio, ret+strlen(ret), n)) == -1)
838
		goto cleanup;
839
	ret[retsize-1] = '\0';
840
841
	while ((p = strchr(ret, '\n')) != NULL)
842
		memmove(p, p + 1, strlen(p));
843
	while ((p = strchr(ret, '\r')) != NULL)
844
		memmove(p, p + 1, strlen(p));
845
846
	ok = 1;
847
848
cleanup:
849
	if (bio != NULL) {
850
		BIO_free_all(bio);
851
		bio = NULL;
852
	}
853
854
	if (pubkey != NULL) {
855
		EVP_PKEY_free(pubkey);
856
		pubkey = NULL;
857
	}
858
859
	buffer_free(&b);
860
861
	if (!ok) {
862
		if (ret != NULL) {
863
			xfree(ret);
864
			ret = NULL;
865
		}
866
	}
867
868
	return ret;
869
}
870
871
#endif /* ENABLE_PKCS11 */
(-)ssh/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
} pkcs11_provider;
38
39
typedef struct {
40
	char *id;
41
	int pin_cache_period;
42
	char *cert_file;
43
} pkcs11_id;
44
45
int
46
pkcs11_initialize(const int, const int);
47
48
void
49
pkcs11_terminate(void);
50
51
void
52
pkcs11_free_provider(pkcs11_provider *const);
53
54
pkcs11_provider *
55
pkcs11_parse_provider(const char *const);
56
57
int
58
pkcs11_add_provider(const pkcs11_provider *const);
59
60
pkcs11_id *
61
pkcs11_id_new(void);
62
63
void
64
pkcs11_id_free(pkcs11_id *const);
65
66
int
67
pkcs11_get_key(const pkcs11_id *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/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
	pkcs11_provider *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
		pkcs11_id *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/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 689-694 send: Link Here
689
}
690
}
690
#endif /* SMARTCARD */
691
#endif /* SMARTCARD */
691
692
693
#ifdef ENABLE_PKCS11
694
695
static void
696
process_pkcs11_add_provider (SocketEntry *e)
697
{
698
	pkcs11_provider provider;
699
	int success = 0;
700
701
	provider.provider = buffer_get_string(&e->request, NULL);
702
	provider.protected_authentication = buffer_get_int(&e->request);
703
	provider.private_mode = (unsigned)buffer_get_int(&e->request);
704
	provider.cert_is_private = buffer_get_int(&e->request);
705
706
	success = pkcs11_add_provider(&provider);
707
708
	buffer_put_int(&e->output, 1);
709
	buffer_put_char(&e->output,
710
	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
711
}
712
713
static
714
void
715
process_pkcs11_add_id (SocketEntry *e)
716
{
717
	pkcs11_id *pkcs11_id = NULL;
718
	Key *k = NULL;
719
	char *comment = NULL;
720
	int success = 0;
721
	int version = 2;
722
723
	pkcs11_id = pkcs11_id_new();
724
	if (pkcs11_id != NULL) {
725
		pkcs11_id->id = strdup (buffer_get_string(&e->request, NULL));
726
		pkcs11_id->pin_cache_period = buffer_get_int(&e->request);
727
		pkcs11_id->cert_file = strdup (buffer_get_string(&e->request, NULL));
728
729
		if (pkcs11_get_key (pkcs11_id, &k, &comment)) {
730
			if (lookup_identity(k, version) == NULL) {
731
				Identity *id = xmalloc(sizeof(Identity));
732
				Idtab *tab = NULL;
733
	
734
				id->key = k;
735
				k = NULL;
736
				id->comment = comment;
737
				id->death = 0;		/* handled by pkcs#11 helper */
738
				id->confirm = 0;
739
	
740
				tab = idtab_lookup(version);
741
				TAILQ_INSERT_TAIL(&tab->idlist, id, next);
742
				/* Increment the number of identities. */
743
				tab->nentries++;
744
				success = 1;
745
			}
746
		}
747
	}
748
749
	if (k != NULL)
750
		key_free(k);
751
752
	if (pkcs11_id != NULL)
753
		pkcs11_id_free(pkcs11_id);
754
755
	buffer_put_int(&e->output, 1);
756
	buffer_put_char(&e->output,
757
	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
758
}
759
760
static
761
void
762
process_pkcs11_remove_id (SocketEntry *e)
763
{
764
	Identity *id = NULL;
765
	char *comment = NULL;
766
	pkcs11_id *pkcs11_id = NULL;
767
	Key *k = NULL;
768
	int version = 2;
769
	int success = 0;
770
771
	pkcs11_id = pkcs11_id_new();
772
	if (pkcs11_id != NULL) {
773
		pkcs11_id->id = strdup(buffer_get_string(&e->request, NULL));
774
		pkcs11_id->pin_cache_period = buffer_get_int(&e->request);
775
		pkcs11_id->cert_file = strdup(buffer_get_string(&e->request, NULL));
776
777
		if (pkcs11_get_key(pkcs11_id, &k, &comment)) {
778
			id = lookup_identity (k, version);
779
			xfree(comment);
780
			comment = NULL;
781
		}
782
783
		if (id != NULL) {
784
			Idtab *tab = NULL;
785
786
			tab = idtab_lookup(version);
787
			TAILQ_REMOVE(&tab->idlist, id, next);
788
			tab->nentries--;
789
			free_identity(id);
790
			id = NULL;
791
			success = 1;
792
		}
793
	}
794
795
	if (k != NULL)
796
		key_free(k);
797
798
	if (pkcs11_id != NULL)
799
		pkcs11_id_free(pkcs11_id);
800
801
	buffer_put_int(&e->output, 1);
802
	buffer_put_char(&e->output,
803
	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
804
}
805
806
#endif /* ENABLE_PKCS11 */
807
692
/* dispatch incoming messages */
808
/* dispatch incoming messages */
693
809
694
static void
810
static void
Lines 781-786 process_message(SocketEntry *e) Link Here
781
		process_remove_smartcard_key(e);
897
		process_remove_smartcard_key(e);
782
		break;
898
		break;
783
#endif /* SMARTCARD */
899
#endif /* SMARTCARD */
900
901
#ifdef ENABLE_PKCS11
902
	case SSH_AGENTC_PKCS11_ADD_PROVIDER:
903
		process_pkcs11_add_provider(e);
904
		break;
905
	case SSH_AGENTC_PKCS11_ADD_ID:
906
		process_pkcs11_add_id(e);
907
		break;
908
	case SSH_AGENTC_PKCS11_REMOVE_ID:
909
		process_pkcs11_remove_id(e);
910
		break;
911
#endif /* ENABLE_PKCS11 */
784
	default:
912
	default:
785
		/* Unknown message.  Respond with failure. */
913
		/* Unknown message.  Respond with failure. */
786
		error("Unknown message %d", type);
914
		error("Unknown message %d", type);
Lines 988-993 static void Link Here
988
cleanup_handler(int sig)
1116
cleanup_handler(int sig)
989
{
1117
{
990
	cleanup_socket();
1118
	cleanup_socket();
1119
#ifdef ENABLE_PKCS11
1120
	pkcs11_terminate ();
1121
#endif /* ENABLE_PKCS11 */
991
	_exit(2);
1122
	_exit(2);
992
}
1123
}
993
1124
Lines 1216-1221 main(int ac, char **av) Link Here
1216
	}
1347
	}
1217
1348
1218
skip:
1349
skip:
1350
1351
#ifdef ENABLE_PKCS11
1352
	pkcs11_initialize (1, -1);
1353
#endif /* ENABLE_PKCS11 */
1354
1219
	new_socket(AUTH_SOCKET, sock);
1355
	new_socket(AUTH_SOCKET, sock);
1220
	if (ac > 0)
1356
	if (ac > 0)
1221
		parent_alive_interval = 10;
1357
		parent_alive_interval = 10;
(-)ssh/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 pkcs11_provider *use_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
"           [-# use_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 ((use_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 673-678 main(int ac, char **av) Link Here
673
690
674
	timeout_ms = options.connection_timeout * 1000;
691
	timeout_ms = options.connection_timeout * 1000;
675
692
693
#ifdef ENABLE_PKCS11
694
	if (use_pkcs11_provider != NULL) {
695
		if (!pkcs11_initialize (1, -1))
696
			fatal("Cannot initialize PKCS#11 interface.\n");
697
		if (!pkcs11_add_provider(use_pkcs11_provider))
698
			fatal("Cannot add PKCS#11 provider '%s'.\n",
699
				use_pkcs11_provider->provider);
700
	}
701
#endif
702
676
	/* Open a connection to the remote host. */
703
	/* Open a connection to the remote host. */
677
	if (ssh_connect(host, &hostaddr, options.port,
704
	if (ssh_connect(host, &hostaddr, options.port,
678
	    options.address_family, options.connection_attempts, &timeout_ms,
705
	    options.address_family, options.connection_attempts, &timeout_ms,
Lines 798-803 main(int ac, char **av) Link Here
798
	if (proxy_command_pid > 1)
825
	if (proxy_command_pid > 1)
799
		kill(proxy_command_pid, SIGHUP);
826
		kill(proxy_command_pid, SIGHUP);
800
827
828
#ifdef ENABLE_PKCS11
829
	if (use_pkcs11_provider != NULL) {
830
		pkcs11_terminate();
831
		pkcs11_free_provider(use_pkcs11_provider);
832
		use_pkcs11_provider = NULL;
833
	}
834
#endif
835
801
	return exit_status;
836
	return exit_status;
802
}
837
}
803
838
Lines 1238-1243 load_public_identity_files(void) Link Here
1238
		xfree(keys);
1273
		xfree(keys);
1239
	}
1274
	}
1240
#endif /* SMARTCARD */
1275
#endif /* SMARTCARD */
1276
#ifdef ENABLE_PKCS11
1277
	if (use_pkcs11_provider != NULL) {
1278
		Key **keys = NULL;
1279
		char **comments = NULL;
1280
1281
		if (pkcs11_get_keys(&keys, &comments)) {
1282
			int count = 0;
1283
			while (options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
1284
				keys[count] != NULL) {
1285
				memmove(&options.identity_files[1], &options.identity_files[0],
1286
				    sizeof(char *) * (SSH_MAX_IDENTITY_FILES - 1));
1287
				memmove(&options.identity_keys[1], &options.identity_keys[0],
1288
				    sizeof(Key *) * (SSH_MAX_IDENTITY_FILES - 1));
1289
				options.num_identity_files++;
1290
				options.identity_keys[0] = keys[count];
1291
				options.identity_files[0] = comments[count];
1292
				count++;
1293
			}
1294
			i += count;
1295
			xfree(keys);
1296
			xfree(comments);
1297
		}
1298
	
1299
	}
1300
#endif
1241
	if ((pw = getpwuid(original_real_uid)) == NULL)
1301
	if ((pw = getpwuid(original_real_uid)) == NULL)
1242
		fatal("load_public_identity_files: getpwuid failed");
1302
		fatal("load_public_identity_files: getpwuid failed");
1243
	pwname = xstrdup(pw->pw_name);
1303
	pwname = xstrdup(pw->pw_name);
(-)ssh/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 1014-1019 usage(void) Link Here
1014
	fprintf(stderr, "  -g          Use generic DNS resource record format.\n");
1015
	fprintf(stderr, "  -g          Use generic DNS resource record format.\n");
1015
	fprintf(stderr, "  -H          Hash names in known_hosts file.\n");
1016
	fprintf(stderr, "  -H          Hash names in known_hosts file.\n");
1016
	fprintf(stderr, "  -i          Convert RFC 4716 to OpenSSH key file.\n");
1017
	fprintf(stderr, "  -i          Convert RFC 4716 to OpenSSH key file.\n");
1018
#ifdef ENABLE_PKCS11
1019
	fprintf(stderr, "  -K provider Show PKCS#11 provider ids, format:\n");
1020
	fprintf(stderr, "              lib[:prot_auth[:private_mode[:cert_is_private]]]\n");
1021
	fprintf(stderr, "              prot_auth - 1 to allow protected mode authentication.\n");
1022
	fprintf(stderr, "              private_mode - Private key mode, see man page.\n");
1023
	fprintf(stderr, "              cert_is_private - 1 if login is required to access certificates.\n");
1024
#endif /* ENABLE_PKCS11 */
1017
	fprintf(stderr, "  -l          Show fingerprint of key file.\n");
1025
	fprintf(stderr, "  -l          Show fingerprint of key file.\n");
1018
	fprintf(stderr, "  -M memory   Amount of memory (MB) to use for generating DH-GEX moduli.\n");
1026
	fprintf(stderr, "  -M memory   Amount of memory (MB) to use for generating DH-GEX moduli.\n");
1019
	fprintf(stderr, "  -N phrase   Provide new passphrase.\n");
1027
	fprintf(stderr, "  -N phrase   Provide new passphrase.\n");
Lines 1054-1059 main(int argc, char **argv) Link Here
1054
	BIGNUM *start = NULL;
1062
	BIGNUM *start = NULL;
1055
	FILE *f;
1063
	FILE *f;
1056
	const char *errstr;
1064
	const char *errstr;
1065
#ifdef ENABLE_PKCS11
1066
	pkcs11_provider *pkcs11_provider = NULL;
1067
#endif /* ENABLE_PKCS11 */
1057
1068
1058
	extern int optind;
1069
	extern int optind;
1059
	extern char *optarg;
1070
	extern char *optarg;
Lines 1076-1082 main(int argc, char **argv) Link Here
1076
	}
1087
	}
1077
1088
1078
	while ((opt = getopt(argc, argv,
1089
	while ((opt = getopt(argc, argv,
1079
	    "degiqpclBHvxXyF:b:f:t:U:D:P:N:C:r:g:R:T:G:M:S:a:W:")) != -1) {
1090
	    "degiqpclBHvxXyF:b:f:t:U:D:P:N:C:r:g:R:T:G:M:S:a:W:K:")) != -1) {
1080
		switch (opt) {
1091
		switch (opt) {
1081
		case 'b':
1092
		case 'b':
1082
			bits = (u_int32_t)strtonum(optarg, 768, 32768, &errstr);
1093
			bits = (u_int32_t)strtonum(optarg, 768, 32768, &errstr);
Lines 1201-1206 main(int argc, char **argv) Link Here
1201
			if (BN_hex2bn(&start, optarg) == 0)
1212
			if (BN_hex2bn(&start, optarg) == 0)
1202
				fatal("Invalid start point.");
1213
				fatal("Invalid start point.");
1203
			break;
1214
			break;
1215
#ifdef ENABLE_PKCS11
1216
		case 'K':
1217
			if ((pkcs11_provider = pkcs11_parse_provider(optarg)) == NULL)
1218
				fatal("Cannot parse PKCS#11 provider.");
1219
			break;
1220
#endif /* ENABLE_PKCS11 */
1204
		case '?':
1221
		case '?':
1205
		default:
1222
		default:
1206
			usage();
1223
			usage();
Lines 1255-1260 main(int argc, char **argv) Link Here
1255
			exit(0);
1272
			exit(0);
1256
		}
1273
		}
1257
	}
1274
	}
1275
#ifdef ENABLE_PKCS11
1276
	if (pkcs11_provider != NULL) {
1277
		pkcs11_initialize(1, -1);
1278
		pkcs11_add_provider(pkcs11_provider);
1279
		pkcs11_show_ids();
1280
		pkcs11_terminate();
1281
		pkcs11_free_provider(pkcs11_provider);
1282
		return (0);
1283
	}
1284
#endif /* ENABLE_PKCS11 */
1258
	if (reader_id != NULL) {
1285
	if (reader_id != NULL) {
1259
#ifdef SMARTCARD
1286
#ifdef SMARTCARD
1260
		if (download)
1287
		if (download)

Return to bug 1371