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

Collapse All | Expand All

(-)a/auth2.c (-2 / +2 lines)
Lines 676-682 auth2_record_key(Authctxt *authctxt, int authenticated, Link Here
676
	struct sshkey **tmp, *dup;
676
	struct sshkey **tmp, *dup;
677
	int r;
677
	int r;
678
678
679
	if ((r = sshkey_from_private(key, &dup)) != 0)
679
	if ((r = sshkey_copy_public(key, &dup)) != 0)
680
		fatal("%s: copy key: %s", __func__, ssh_err(r));
680
		fatal("%s: copy key: %s", __func__, ssh_err(r));
681
	sshkey_free(authctxt->auth_method_key);
681
	sshkey_free(authctxt->auth_method_key);
682
	authctxt->auth_method_key = dup;
682
	authctxt->auth_method_key = dup;
Lines 685-691 auth2_record_key(Authctxt *authctxt, int authenticated, Link Here
685
		return;
685
		return;
686
686
687
	/* If authenticated, make sure we don't accept this key again */
687
	/* If authenticated, make sure we don't accept this key again */
688
	if ((r = sshkey_from_private(key, &dup)) != 0)
688
	if ((r = sshkey_copy_public(key, &dup)) != 0)
689
		fatal("%s: copy key: %s", __func__, ssh_err(r));
689
		fatal("%s: copy key: %s", __func__, ssh_err(r));
690
	if (authctxt->nprev_keys >= INT_MAX ||
690
	if (authctxt->nprev_keys >= INT_MAX ||
691
	    (tmp = recallocarray(authctxt->prev_keys, authctxt->nprev_keys,
691
	    (tmp = recallocarray(authctxt->prev_keys, authctxt->nprev_keys,
(-)a/authfd.c (+25 lines)
Lines 470-475 ssh_add_identity_constrained(int sock, const struct sshkey *key, Link Here
470
	return r;
470
	return r;
471
}
471
}
472
472
473
/*
474
 * Adds a cert to the authentication server that may be later joined with a
475
 * private key.
476
 * This call is intended only for use by ssh-add(1) and like applications.
477
 */
478
int
479
ssh_add_certificate(int sock, const struct sshkey *cert)
480
{
481
	struct sshbuf *msg;
482
	int r;
483
	u_char type = 0;
484
485
	if ((msg = sshbuf_new()) == NULL)
486
		return SSH_ERR_ALLOC_FAIL;
487
	if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_ADD_CERTIFICATES)) != 0 ||
488
	    (r = sshkey_puts(cert, msg)) != 0 ||
489
	    (r = ssh_request_reply(sock, msg, msg)) != 0 ||
490
	    (r = sshbuf_get_u8(msg, &type)) != 0)
491
		goto out;
492
	r = decode_reply(type);
493
 out:
494
	sshbuf_free(msg);
495
	return r;
496
}
497
473
/*
498
/*
474
 * Removes an identity from the authentication server.
499
 * Removes an identity from the authentication server.
475
 * This call is intended only for use by ssh-add(1) and like applications.
500
 * This call is intended only for use by ssh-add(1) and like applications.
(-)a/authfd.h (+4 lines)
Lines 31-36 int ssh_fetch_identitylist(int sock, struct ssh_identitylist **idlp); Link Here
31
void	ssh_free_identitylist(struct ssh_identitylist *idl);
31
void	ssh_free_identitylist(struct ssh_identitylist *idl);
32
int	ssh_add_identity_constrained(int sock, const struct sshkey *key,
32
int	ssh_add_identity_constrained(int sock, const struct sshkey *key,
33
	    const char *comment, u_int life, u_int confirm, u_int maxsign);
33
	    const char *comment, u_int life, u_int confirm, u_int maxsign);
34
int	ssh_add_certificate(int sock, const struct sshkey *key);
34
int	ssh_remove_identity(int sock, struct sshkey *key);
35
int	ssh_remove_identity(int sock, struct sshkey *key);
35
int	ssh_update_card(int sock, int add, const char *reader_id,
36
int	ssh_update_card(int sock, int add, const char *reader_id,
36
	    const char *pin, u_int life, u_int confirm);
37
	    const char *pin, u_int life, u_int confirm);
Lines 73-78 int ssh_agent_sign(int sock, const struct sshkey *key, Link Here
73
#define SSH2_AGENTC_ADD_ID_CONSTRAINED		25
74
#define SSH2_AGENTC_ADD_ID_CONSTRAINED		25
74
#define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26
75
#define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26
75
76
77
/* certificates */
78
#define SSH2_AGENTC_ADD_CERTIFICATES		27
79
76
#define	SSH_AGENT_CONSTRAIN_LIFETIME		1
80
#define	SSH_AGENT_CONSTRAIN_LIFETIME		1
77
#define	SSH_AGENT_CONSTRAIN_CONFIRM		2
81
#define	SSH_AGENT_CONSTRAIN_CONFIRM		2
78
#define	SSH_AGENT_CONSTRAIN_MAXSIGN		3
82
#define	SSH_AGENT_CONSTRAIN_MAXSIGN		3
(-)a/krl.c (-2 / +2 lines)
Lines 230-236 revoked_certs_for_ca_key(struct ssh_krl *krl, const struct sshkey *ca_key, Link Here
230
		return SSH_ERR_ALLOC_FAIL;
230
		return SSH_ERR_ALLOC_FAIL;
231
	if (ca_key == NULL)
231
	if (ca_key == NULL)
232
		rc->ca_key = NULL;
232
		rc->ca_key = NULL;
233
	else if ((r = sshkey_from_private(ca_key, &rc->ca_key)) != 0) {
233
	else if ((r = sshkey_copy_public(ca_key, &rc->ca_key)) != 0) {
234
		free(rc);
234
		free(rc);
235
		return r;
235
		return r;
236
	}
236
	}
Lines 369-375 plain_key_blob(const struct sshkey *key, u_char **blob, size_t *blen) Link Here
369
	struct sshkey *kcopy;
369
	struct sshkey *kcopy;
370
	int r;
370
	int r;
371
371
372
	if ((r = sshkey_from_private(key, &kcopy)) != 0)
372
	if ((r = sshkey_copy_public(key, &kcopy)) != 0)
373
		return r;
373
		return r;
374
	if (sshkey_is_cert(kcopy)) {
374
	if (sshkey_is_cert(kcopy)) {
375
		if ((r = sshkey_drop_cert(kcopy)) != 0) {
375
		if ((r = sshkey_drop_cert(kcopy)) != 0) {
(-)a/ssh-add.c (-28 / +93 lines)
Lines 60-65 Link Here
60
#include "misc.h"
60
#include "misc.h"
61
#include "ssherr.h"
61
#include "ssherr.h"
62
#include "digest.h"
62
#include "digest.h"
63
#include "authfile.h"
63
64
64
/* argv0 */
65
/* argv0 */
65
extern char *__progname;
66
extern char *__progname;
Lines 381-386 add_file(int agent_fd, const char *filename, int key_only, int qflag) Link Here
381
	return ret;
382
	return ret;
382
}
383
}
383
384
385
static int
386
add_cert(int agent_fd, const char *filename, int qflag)
387
{
388
	struct sshkey *cert = NULL;
389
	char *comment = NULL;
390
	int r, ret = -1;
391
392
	if ((r = sshkey_load_public(filename, &cert, &comment)) != 0) {
393
		if (r == SSH_ERR_INVALID_FORMAT)
394
			return 0; /* ignore; probably a private key */
395
		fprintf(stderr, "Error loading key \"%s\": %s\n",
396
		    filename, ssh_err(r));
397
		return -1;
398
	}
399
	if (!sshkey_is_cert(cert)) {
400
		debug("%s: key %s is not a cert", __func__, sshkey_type(cert));
401
		ret = 0; /* not an error */
402
		goto out;
403
	}
404
	ret = 1;
405
	if ((r = ssh_add_certificate(agent_fd, cert)) == 0) {
406
		if (!qflag) {
407
			fprintf(stderr, "Certificate added pending "
408
			    "private key load: %s (%s)\n", filename, comment);
409
		}
410
	} else {
411
		fprintf(stderr, "Could not add certificate \"%s\": %s\n",
412
		    filename, ssh_err(r));
413
	}
414
 out:
415
	sshkey_free(cert);
416
	free(comment);
417
418
	return ret;
419
}
420
384
static int
421
static int
385
update_card(int agent_fd, int add, const char *id, int qflag)
422
update_card(int agent_fd, int add, const char *id, int qflag)
386
{
423
{
Lines 519-532 lock_agent(int agent_fd, int lock) Link Here
519
}
556
}
520
557
521
static int
558
static int
522
do_file(int agent_fd, int deleting, int key_only, char *file, int qflag)
559
do_files(int agent_fd, int deleting, int key_only, int qflag,
560
    char **files, size_t nfiles)
523
{
561
{
562
	size_t i;
563
	int r;
564
524
	if (deleting) {
565
	if (deleting) {
525
		if (delete_file(agent_fd, file, key_only, qflag) == -1)
566
		for (i = 0; i < nfiles; i++) {
526
			return -1;
567
			if (delete_file(agent_fd, files[i],
568
			    key_only, qflag) == -1)
569
				return -1;
570
		}
527
	} else {
571
	} else {
528
		if (add_file(agent_fd, file, key_only, qflag) == -1)
572
		/*
529
			return -1;
573
		 * Load plain certificates first, so they are there ready for
574
		 * private keys to find them.
575
		 */
576
		for (i = 0; !key_only && i < nfiles; i++) {
577
			if (strcmp(files[i], "-") == 0)
578
				continue;
579
			if ((r = add_cert(agent_fd, files[i], qflag)) == -1)
580
				return -1;
581
			else if (r == 1) {
582
				/* consume file */
583
				free(files[i]);
584
				files[i] = NULL;
585
			}
586
		}
587
		for (i = 0; i < nfiles; i++) {
588
			if (files[i] == NULL)
589
				continue;
590
			if (add_file(agent_fd, files[i],
591
			    key_only, qflag) == -1)
592
				return -1;
593
		}
530
	}
594
	}
531
	return 0;
595
	return 0;
532
}
596
}
Lines 560-568 main(int argc, char **argv) Link Here
560
{
624
{
561
	extern char *optarg;
625
	extern char *optarg;
562
	extern int optind;
626
	extern int optind;
563
	int agent_fd;
627
	char *pkcs11provider = NULL, **files = NULL;
564
	char *pkcs11provider = NULL;
628
	size_t j, nfiles = 0;
565
	int r, i, ch, deleting = 0, ret = 0, key_only = 0;
629
	int i, agent_fd, r, ch, deleting = 0, ret = 0, key_only = 0;
566
	int xflag = 0, lflag = 0, Dflag = 0, qflag = 0, Tflag = 0;
630
	int xflag = 0, lflag = 0, Dflag = 0, qflag = 0, Tflag = 0;
567
	SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
631
	SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
568
	LogLevel log_level = SYSLOG_LEVEL_INFO;
632
	LogLevel log_level = SYSLOG_LEVEL_INFO;
Lines 703-713 main(int argc, char **argv) Link Here
703
			ret = 1;
767
			ret = 1;
704
		goto done;
768
		goto done;
705
	}
769
	}
706
	if (argc == 0) {
770
	if (argc <= 0) {
707
		char buf[PATH_MAX];
771
		char *cp;
708
		struct passwd *pw;
772
		struct passwd *pw;
709
		struct stat st;
773
		struct stat st;
710
		int count = 0;
711
774
712
		if ((pw = getpwuid(getuid())) == NULL) {
775
		if ((pw = getpwuid(getuid())) == NULL) {
713
			fprintf(stderr, "No user found with uid %u\n",
776
			fprintf(stderr, "No user found with uid %u\n",
Lines 716-743 main(int argc, char **argv) Link Here
716
			goto done;
779
			goto done;
717
		}
780
		}
718
781
719
		for (i = 0; default_files[i]; i++) {
782
		for (j = 0; default_files[j]; j++) {
720
			snprintf(buf, sizeof(buf), "%s/%s", pw->pw_dir,
783
			xasprintf(&cp, "%s/%s", pw->pw_dir, default_files[j]);
721
			    default_files[i]);
784
			if (stat(cp, &st) < 0) {
722
			if (stat(buf, &st) < 0)
785
				free(cp);
723
				continue;
786
				continue;
724
			if (do_file(agent_fd, deleting, key_only, buf,
787
			}
725
			    qflag) == -1)
788
			files = xrecallocarray(files, nfiles, nfiles + 1,
726
				ret = 1;
789
			    sizeof(*files));
727
			else
790
			files[nfiles++] = cp;
728
				count++;
729
		}
791
		}
730
		if (count == 0)
731
			ret = 1;
732
	} else {
792
	} else {
733
		for (i = 0; i < argc; i++) {
793
		/* Copy argv as we need to modify the list later */
734
			if (do_file(agent_fd, deleting, key_only,
794
		nfiles = (size_t)argc;
735
			    argv[i], qflag) == -1)
795
		files = xcalloc(nfiles, sizeof(*files));
736
				ret = 1;
796
		for (j = 0; j < nfiles; j++)
737
		}
797
			files[j] = xstrdup(argv[j]);
738
	}
798
	}
799
	if (nfiles == 0 ||
800
	    do_files(agent_fd, deleting, key_only, qflag, files, nfiles) == -1)
801
		ret = 1;
802
	for (j = 0; j < nfiles; j++)
803
		free(files[j]);
804
	free(files);
739
	clear_pass();
805
	clear_pass();
740
741
done:
806
done:
742
	ssh_close_authentication_socket(agent_fd);
807
	ssh_close_authentication_socket(agent_fd);
743
	return ret;
808
	return ret;
(-)a/ssh-agent.c (-31 / +247 lines)
Lines 116-121 struct idtable { Link Here
116
/* private key table */
116
/* private key table */
117
struct idtable *idtab;
117
struct idtable *idtab;
118
118
119
/* certificates waiting for private keys */
120
struct idtable *pending_certs;
121
119
int max_fd = 0;
122
int max_fd = 0;
120
123
121
/* pid of shell == parent of agent */
124
/* pid of shell == parent of agent */
Lines 159-169 close_socket(SocketEntry *e) Link Here
159
}
162
}
160
163
161
static void
164
static void
162
idtab_init(void)
165
idtable_init(struct idtable **tab)
163
{
166
{
164
	idtab = xcalloc(1, sizeof(*idtab));
167
	*tab = xcalloc(1, sizeof(**tab));
165
	TAILQ_INIT(&idtab->idlist);
168
	TAILQ_INIT(&(*tab)->idlist);
166
	idtab->nentries = 0;
169
	(*tab)->nentries = 0;
167
}
170
}
168
171
169
static void
172
static void
Lines 175-191 free_identity(Identity *id) Link Here
175
	free(id);
178
	free(id);
176
}
179
}
177
180
181
static Identity *
182
idtable_lookup(struct idtable *tab, struct sshkey *key, int public)
183
{
184
	Identity *id;
185
186
	TAILQ_FOREACH(id, &tab->idlist, next) {
187
		if (public) {
188
			if (sshkey_equal_public(key, id->key))
189
				return (id);
190
		} else {
191
			if (sshkey_equal(key, id->key))
192
				return (id);
193
		}
194
	}
195
	return (NULL);
196
}
197
178
/* return matching private key for given public key */
198
/* return matching private key for given public key */
179
static Identity *
199
static Identity *
180
lookup_identity(struct sshkey *key)
200
lookup_identity(struct sshkey *key)
181
{
201
{
182
	Identity *id;
202
	return idtable_lookup(idtab, key, 0);
203
}
183
204
184
	TAILQ_FOREACH(id, &idtab->idlist, next) {
205
static Identity *
185
		if (sshkey_equal(key, id->key))
206
lookup_identity_plain(struct sshkey *key)
186
			return (id);
207
{
187
	}
208
	return idtable_lookup(idtab, key, 1);
188
	return (NULL);
209
}
210
211
/* return matching certificate key for given key */
212
static Identity *
213
lookup_cert(struct sshkey *key)
214
{
215
	return idtable_lookup(pending_certs, key, 1);
189
}
216
}
190
217
191
/* Check confirmation of keysign request */
218
/* Check confirmation of keysign request */
Lines 309-314 process_sign_request2(SocketEntry *e) Link Here
309
	free(signature);
336
	free(signature);
310
}
337
}
311
338
339
/* Remove an entry from an idtable; NB. frees 'id' in the process */
340
static void
341
idtable_remove(struct idtable *tab, Identity *id)
342
{
343
	if (tab->nentries < 1) {
344
		fatal("%s: internal error: nentries %d",
345
		    __func__, tab->nentries);
346
	}
347
	TAILQ_REMOVE(&tab->idlist, id, next);
348
	free_identity(id);
349
	tab->nentries--;
350
}
351
312
/* shared */
352
/* shared */
313
static void
353
static void
314
process_remove_identity(SocketEntry *e)
354
process_remove_identity(SocketEntry *e)
Lines 326-357 process_remove_identity(SocketEntry *e) Link Here
326
		goto done;
366
		goto done;
327
	}
367
	}
328
	/* We have this key, free it. */
368
	/* We have this key, free it. */
329
	if (idtab->nentries < 1)
369
	idtable_remove(idtab, id);
330
		fatal("%s: internal error: nentries %d",
370
331
		    __func__, idtab->nentries);
332
	TAILQ_REMOVE(&idtab->idlist, id, next);
333
	free_identity(id);
334
	idtab->nentries--;
335
	sshkey_free(key);
336
	success = 1;
371
	success = 1;
337
 done:
372
 done:
373
	/* Clobber any pending certificates that happen to match too */
374
	if ((id = lookup_cert(key)) != NULL)
375
		idtable_remove(pending_certs, id);
376
377
	sshkey_free(key);
338
	send_status(e, success);
378
	send_status(e, success);
339
}
379
}
340
380
341
static void
381
static void
342
process_remove_all_identities(SocketEntry *e)
382
idtable_clear(struct idtable *tab)
343
{
383
{
344
	Identity *id;
384
	Identity *id;
345
385
346
	/* Loop over all identities and clear the keys. */
386
	/* Loop over all identities and clear the keys. */
347
	for (id = TAILQ_FIRST(&idtab->idlist); id;
387
	for (id = TAILQ_FIRST(&tab->idlist); id != NULL;
348
	    id = TAILQ_FIRST(&idtab->idlist)) {
388
	    id = TAILQ_FIRST(&tab->idlist)) {
349
		TAILQ_REMOVE(&idtab->idlist, id, next);
389
		TAILQ_REMOVE(&tab->idlist, id, next);
350
		free_identity(id);
390
		free_identity(id);
351
	}
391
	}
392
}
393
394
static void
395
process_remove_all_identities(SocketEntry *e)
396
{
397
	idtable_clear(idtab);
398
	idtable_clear(pending_certs);
352
399
353
	/* Mark that there are no identities. */
400
	/* Mark that there are no identities. */
354
	idtab->nentries = 0;
401
	idtab->nentries = 0;
402
	pending_certs->nentries = 0;
355
403
356
	/* Send success. */
404
	/* Send success. */
357
	send_status(e, 1);
405
	send_status(e, 1);
Lines 383-388 reaper(void) Link Here
383
		return (deadline - now);
431
		return (deadline - now);
384
}
432
}
385
433
434
static int
435
promote_cert(Identity *private_id, Identity *cert)
436
{
437
	Identity *id;
438
	struct sshkey *grafted = NULL;
439
	int r = SSH_ERR_INTERNAL_ERROR;
440
441
	if ((r = sshkey_copy_private(private_id->key, &grafted)) != 0) {
442
		error("%s: sshkey_copy_private: %s", __func__, ssh_err(r));
443
		goto out;
444
	}
445
	if ((r = sshkey_to_certified(grafted)) != 0) {
446
		error("%s: sshkey_to_certified: %s", __func__, ssh_err(r));
447
		goto out;
448
	}
449
	if ((r = sshkey_cert_copy(cert->key, grafted)) != 0) {
450
		error("%s: sshkey_cert_copy: %s", __func__, ssh_err(r));
451
		goto out;
452
	}
453
454
	/* Check whether the grafted cert is already recorded */
455
	if ((id = lookup_identity(grafted)) == NULL) {
456
		debug("%s: added new %s private cert, now have %d private keys",
457
		    __func__, sshkey_type(grafted), idtab->nentries);
458
		id = xcalloc(1, sizeof(*id));
459
		TAILQ_INSERT_TAIL(&idtab->idlist, id, next);
460
		idtab->nentries++;
461
		id->key = grafted;
462
		grafted = NULL; /* transfer */
463
	} else {
464
		debug("%s: existing %s private cert",
465
		    __func__, sshkey_type(grafted));
466
		/* Update the identity, as constraints may have changed */
467
		free(id->comment);
468
		free(id->provider);
469
	}
470
	id->comment = private_id->comment != NULL ?
471
	    xstrdup(private_id->comment) : NULL;
472
	id->provider = private_id->provider != NULL?
473
	    xstrdup(private_id->provider) : NULL;
474
	id->death = private_id->death;
475
	id->confirm = private_id->confirm;
476
477
	/* success */
478
	r = 0;
479
 out:
480
	sshkey_free(grafted);
481
	return r;
482
}
483
484
/* Check whether an incoming private key against the pending cert list */
485
static int
486
check_pending_by_key(Identity *private_id)
487
{
488
	Identity *cert;
489
	int r;
490
491
	debug3("%s: entering for %s, npending = %d", __func__,
492
	    sshkey_type(private_id->key), pending_certs->nentries);
493
	/* A private key could conceivable match multiple certificates */
494
	while ((cert = lookup_cert(private_id->key)) != NULL) {
495
		debug3("%s: found matching cert %s",
496
		    __func__, sshkey_type(cert->key));
497
		if ((r = promote_cert(private_id, cert)) != 0)
498
			return r;
499
		/* Remove the cert from the pending list */
500
		idtable_remove(pending_certs, cert);
501
		debug("%s: remove pending cert, now have %d pending",
502
		    __func__, pending_certs->nentries);
503
	}
504
	return 0;
505
}
506
507
/* Check whether an incoming cert against the pending cert list */
508
static int
509
check_pending_by_cert(Identity *cert, int *matched)
510
{
511
	Identity *private_id;
512
	int r;
513
514
	*matched = 0;
515
	debug3("%s: entering for %s", __func__, sshkey_type(cert->key));
516
	/* A certificate should match at most one private key */
517
	if ((private_id = lookup_identity_plain(cert->key)) != NULL) {
518
		debug3("%s: found matching key %s",
519
		    __func__, sshkey_type(private_id->key));
520
		if ((r = promote_cert(private_id, cert)) != 0)
521
			return r;
522
		*matched = 1;
523
	}
524
	return 0;
525
}
526
386
static void
527
static void
387
process_add_identity(SocketEntry *e)
528
process_add_identity(SocketEntry *e)
388
{
529
{
Lines 402-407 process_add_identity(SocketEntry *e) Link Here
402
		goto err;
543
		goto err;
403
	}
544
	}
404
545
546
	debug3("%s: have %s key constraint len %zu", __func__,
547
	    sshkey_type(k), sshbuf_len(e->request));
548
405
	while (sshbuf_len(e->request)) {
549
	while (sshbuf_len(e->request)) {
406
		if ((r = sshbuf_get_u8(e->request, &ctype)) != 0) {
550
		if ((r = sshbuf_get_u8(e->request, &ctype)) != 0) {
407
			error("%s: buffer error: %s", __func__, ssh_err(r));
551
			error("%s: buffer error: %s", __func__, ssh_err(r));
Lines 441-447 process_add_identity(SocketEntry *e) Link Here
441
		}
585
		}
442
	}
586
	}
443
587
444
	success = 1;
445
	if (lifetime && !death)
588
	if (lifetime && !death)
446
		death = monotime() + lifetime;
589
		death = monotime() + lifetime;
447
	if ((id = lookup_identity(k)) == NULL) {
590
	if ((id = lookup_identity(k)) == NULL) {
Lines 449-467 process_add_identity(SocketEntry *e) Link Here
449
		TAILQ_INSERT_TAIL(&idtab->idlist, id, next);
592
		TAILQ_INSERT_TAIL(&idtab->idlist, id, next);
450
		/* Increment the number of identities. */
593
		/* Increment the number of identities. */
451
		idtab->nentries++;
594
		idtab->nentries++;
595
		debug("%s: new key, now have %d", __func__, idtab->nentries);
452
	} else {
596
	} else {
453
		/* key state might have been updated */
597
		/* key state might have been updated */
454
		sshkey_free(id->key);
598
		sshkey_free(id->key);
455
		free(id->comment);
599
		free(id->comment);
600
		debug("%s: existing key", __func__);
456
	}
601
	}
457
	id->key = k;
602
	id->key = k;
458
	id->comment = comment;
603
	id->comment = comment;
459
	id->death = death;
604
	id->death = death;
460
	id->confirm = confirm;
605
	id->confirm = confirm;
606
607
	/* Can this key matriculate a pending_cert? */
608
	if (!sshkey_is_cert(id->key) && check_pending_by_key(id) != 0)
609
		goto send;
610
611
	success = 1;
461
send:
612
send:
462
	send_status(e, success);
613
	send_status(e, success);
463
}
614
}
464
615
616
static void
617
process_add_certificates(SocketEntry *e)
618
{
619
	Identity *id;
620
	int matched, success = 0;
621
	struct sshkey *k = NULL;
622
	int r = SSH_ERR_INTERNAL_ERROR;
623
624
	debug3("%s: entering len = %zu", __func__, sshbuf_len(e->request));
625
626
	while (sshbuf_len(e->request)) {
627
		sshkey_free(k);
628
		k = NULL;
629
		if ((r = sshkey_froms(e->request, &k)) != 0) {
630
			error("%s: buffer error: %s", __func__, ssh_err(r));
631
			goto send;
632
		}
633
		debug2("%s: key type %s", __func__, sshkey_type(k));
634
		if (!sshkey_is_cert(k)) {
635
			error("%s: key is not a certificate", __func__);
636
			goto send;
637
		}
638
		if ((id = lookup_identity(k)) != NULL) {
639
			debug("%s: cert already has key", __func__);
640
		} else if ((id = lookup_cert(k)) != NULL) {
641
			debug("%s: cert already enqueued", __func__);
642
			if ((r = check_pending_by_cert(id, &matched)) != 0)
643
				goto send;
644
			if (matched) {
645
				debug("%s: cert matches, remove from pending",
646
				    __func__);
647
				idtable_remove(pending_certs, id);
648
			}
649
		} else {
650
			id = xcalloc(1, sizeof(Identity));
651
			id->key = k;
652
			k = NULL; /* transfer */
653
			if ((r = check_pending_by_cert(id, &matched)) != 0)
654
				goto send;
655
			if (matched)
656
				free_identity(id);
657
			else {
658
				TAILQ_INSERT_TAIL(&pending_certs->idlist,
659
				    id, next);
660
				pending_certs->nentries++;
661
				debug("%s: add cert, nentries %d",
662
				    __func__, pending_certs->nentries);
663
			}
664
		}
665
	}
666
	success = 1;
667
send:
668
	sshkey_free(k);
669
	send_status(e, success);
670
}
671
672
465
/* XXX todo: encrypt sensitive data with passphrase */
673
/* XXX todo: encrypt sensitive data with passphrase */
466
static void
674
static void
467
process_lock_agent(SocketEntry *e, int lock)
675
process_lock_agent(SocketEntry *e, int lock)
Lines 539-545 process_add_smartcard_key(SocketEntry *e) Link Here
539
	u_int seconds;
747
	u_int seconds;
540
	time_t death = 0;
748
	time_t death = 0;
541
	u_char type;
749
	u_char type;
542
	struct sshkey **keys = NULL, *k;
750
	struct sshkey **keys = NULL;
543
	Identity *id;
751
	Identity *id;
544
752
545
	if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 ||
753
	if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 ||
Lines 586-610 process_add_smartcard_key(SocketEntry *e) Link Here
586
794
587
	count = pkcs11_add_provider(canonical_provider, pin, &keys);
795
	count = pkcs11_add_provider(canonical_provider, pin, &keys);
588
	for (i = 0; i < count; i++) {
796
	for (i = 0; i < count; i++) {
589
		k = keys[i];
797
		if ((id = lookup_identity(keys[i])) == NULL) {
590
		if (lookup_identity(k) == NULL) {
591
			id = xcalloc(1, sizeof(Identity));
798
			id = xcalloc(1, sizeof(Identity));
592
			id->key = k;
593
			id->provider = xstrdup(canonical_provider);
799
			id->provider = xstrdup(canonical_provider);
594
			id->comment = xstrdup(canonical_provider); /* XXX */
800
			id->comment = xstrdup(canonical_provider); /* XXX */
595
			id->death = death;
801
			id->death = death;
596
			id->confirm = confirm;
802
			id->confirm = confirm;
803
			id->key = keys[i];
804
			keys[i] = NULL; /* transfer */
597
			TAILQ_INSERT_TAIL(&idtab->idlist, id, next);
805
			TAILQ_INSERT_TAIL(&idtab->idlist, id, next);
598
			idtab->nentries++;
806
			idtab->nentries++;
599
			success = 1;
600
		} else {
601
			sshkey_free(k);
602
		}
807
		}
603
		keys[i] = NULL;
808
		/* Can this key matriculate a pending_cert? */
809
		if (!sshkey_is_cert(id->key) && check_pending_by_key(id) != 0) {
810
			success = 0;
811
			goto send;
812
		}
813
		success = 1;
604
	}
814
	}
605
send:
815
send:
606
	free(pin);
816
	free(pin);
607
	free(provider);
817
	free(provider);
818
	for (i = 0; i < count; i++)
819
		sshkey_free(keys[i]);
608
	free(keys);
820
	free(keys);
609
	send_status(e, success);
821
	send_status(e, success);
610
}
822
}
Lines 743-748 process_message(u_int socknum) Link Here
743
		process_remove_smartcard_key(e);
955
		process_remove_smartcard_key(e);
744
		break;
956
		break;
745
#endif /* ENABLE_PKCS11 */
957
#endif /* ENABLE_PKCS11 */
958
	case SSH2_AGENTC_ADD_CERTIFICATES:
959
		process_add_certificates(e);
960
		break;
746
	default:
961
	default:
747
		/* Unknown message.  Respond with failure. */
962
		/* Unknown message.  Respond with failure. */
748
		error("Unknown message %d", type);
963
		error("Unknown message %d", type);
Lines 1287-1293 skip: Link Here
1287
	new_socket(AUTH_SOCKET, sock);
1502
	new_socket(AUTH_SOCKET, sock);
1288
	if (ac > 0)
1503
	if (ac > 0)
1289
		parent_alive_interval = 10;
1504
		parent_alive_interval = 10;
1290
	idtab_init();
1505
	idtable_init(&idtab);
1506
	idtable_init(&pending_certs);
1291
	signal(SIGPIPE, SIG_IGN);
1507
	signal(SIGPIPE, SIG_IGN);
1292
	signal(SIGINT, (d_flag | D_flag) ? cleanup_handler : SIG_IGN);
1508
	signal(SIGINT, (d_flag | D_flag) ? cleanup_handler : SIG_IGN);
1293
	signal(SIGHUP, cleanup_handler);
1509
	signal(SIGHUP, cleanup_handler);
(-)a/ssh-keygen.c (-8 / +8 lines)
Lines 1052-1059 do_gen_all_hostkeys(struct passwd *pw) Link Here
1052
			error("sshkey_generate failed: %s", ssh_err(r));
1052
			error("sshkey_generate failed: %s", ssh_err(r));
1053
			goto failnext;
1053
			goto failnext;
1054
		}
1054
		}
1055
		if ((r = sshkey_from_private(private, &public)) != 0)
1055
		if ((r = sshkey_copy_public(private, &public)) != 0)
1056
			fatal("sshkey_from_private failed: %s", ssh_err(r));
1056
			fatal("sshkey_copy_public failed: %s", ssh_err(r));
1057
		snprintf(comment, sizeof comment, "%s@%s", pw->pw_name,
1057
		snprintf(comment, sizeof comment, "%s@%s", pw->pw_name,
1058
		    hostname);
1058
		    hostname);
1059
		if ((r = sshkey_save_private(private, prv_tmp, "",
1059
		if ((r = sshkey_save_private(private, prv_tmp, "",
Lines 1519-1526 do_change_comment(struct passwd *pw) Link Here
1519
	}
1519
	}
1520
	explicit_bzero(passphrase, strlen(passphrase));
1520
	explicit_bzero(passphrase, strlen(passphrase));
1521
	free(passphrase);
1521
	free(passphrase);
1522
	if ((r = sshkey_from_private(private, &public)) != 0)
1522
	if ((r = sshkey_copy_public(private, &public)) != 0)
1523
		fatal("sshkey_from_private failed: %s", ssh_err(r));
1523
		fatal("sshkey_copy_public failed: %s", ssh_err(r));
1524
	sshkey_free(private);
1524
	sshkey_free(private);
1525
1525
1526
	strlcat(identity_file, ".pub", sizeof(identity_file));
1526
	strlcat(identity_file, ".pub", sizeof(identity_file));
Lines 1750-1758 do_ca_sign(struct passwd *pw, int argc, char **argv) Link Here
1750
		prepare_options_buf(public->cert->critical, OPTIONS_CRITICAL);
1750
		prepare_options_buf(public->cert->critical, OPTIONS_CRITICAL);
1751
		prepare_options_buf(public->cert->extensions,
1751
		prepare_options_buf(public->cert->extensions,
1752
		    OPTIONS_EXTENSIONS);
1752
		    OPTIONS_EXTENSIONS);
1753
		if ((r = sshkey_from_private(ca,
1753
		if ((r = sshkey_copy_public(ca,
1754
		    &public->cert->signature_key)) != 0)
1754
		    &public->cert->signature_key)) != 0)
1755
			fatal("sshkey_from_private (ca key): %s", ssh_err(r));
1755
			fatal("sshkey_copy_public (ca key): %s", ssh_err(r));
1756
1756
1757
		if (agent_fd != -1 && (ca->flags & SSHKEY_FLAG_EXT) != 0) {
1757
		if (agent_fd != -1 && (ca->flags & SSHKEY_FLAG_EXT) != 0) {
1758
			if ((r = sshkey_certify_custom(public, ca,
1758
			if ((r = sshkey_certify_custom(public, ca,
Lines 2806-2813 main(int argc, char **argv) Link Here
2806
		    key_type_name);
2806
		    key_type_name);
2807
	if ((r = sshkey_generate(type, bits, &private)) != 0)
2807
	if ((r = sshkey_generate(type, bits, &private)) != 0)
2808
		fatal("sshkey_generate failed");
2808
		fatal("sshkey_generate failed");
2809
	if ((r = sshkey_from_private(private, &public)) != 0)
2809
	if ((r = sshkey_copy_public(private, &public)) != 0)
2810
		fatal("sshkey_from_private failed: %s\n", ssh_err(r));
2810
		fatal("sshkey_copy_public failed: %s\n", ssh_err(r));
2811
2811
2812
	if (!have_identity)
2812
	if (!have_identity)
2813
		ask_filename(pw, "Enter file in which to save the key");
2813
		ask_filename(pw, "Enter file in which to save the key");
(-)a/ssh_api.c (-1 / +1 lines)
Lines 174-180 ssh_add_hostkey(struct ssh *ssh, struct sshkey *key) Link Here
174
	int r;
174
	int r;
175
175
176
	if (ssh->kex->server) {
176
	if (ssh->kex->server) {
177
		if ((r = sshkey_from_private(key, &pubkey)) != 0)
177
		if ((r = sshkey_copy_public(key, &pubkey)) != 0)
178
			return r;
178
			return r;
179
		if ((k = malloc(sizeof(*k))) == NULL ||
179
		if ((k = malloc(sizeof(*k))) == NULL ||
180
		    (k_prv = malloc(sizeof(*k_prv))) == NULL) {
180
		    (k_prv = malloc(sizeof(*k_prv))) == NULL) {
(-)a/sshconnect.c (-4 / +4 lines)
Lines 1075-1082 fail: Link Here
1075
		 * search normally.
1075
		 * search normally.
1076
		 */
1076
		 */
1077
		debug("No matching CA found. Retry with plain key");
1077
		debug("No matching CA found. Retry with plain key");
1078
		if ((r = sshkey_from_private(host_key, &raw_key)) != 0)
1078
		if ((r = sshkey_copy_public(host_key, &raw_key)) != 0)
1079
			fatal("%s: sshkey_from_private: %s",
1079
			fatal("%s: sshkey_copy_public: %s",
1080
			    __func__, ssh_err(r));
1080
			    __func__, ssh_err(r));
1081
		if ((r = sshkey_drop_cert(raw_key)) != 0)
1081
		if ((r = sshkey_drop_cert(raw_key)) != 0)
1082
			fatal("Couldn't drop certificate: %s", ssh_err(r));
1082
			fatal("Couldn't drop certificate: %s", ssh_err(r));
Lines 1167-1173 verify_host_key(char *host, struct sockaddr *hostaddr, struct sshkey *host_key) Link Here
1167
		 * XXX certs are not yet supported for DNS, so downgrade
1167
		 * XXX certs are not yet supported for DNS, so downgrade
1168
		 * them and try the plain key.
1168
		 * them and try the plain key.
1169
		 */
1169
		 */
1170
		if ((r = sshkey_from_private(host_key, &plain)) != 0)
1170
		if ((r = sshkey_copy_public(host_key, &plain)) != 0)
1171
			goto out;
1171
			goto out;
1172
		if (sshkey_is_cert(plain))
1172
		if (sshkey_is_cert(plain))
1173
			sshkey_drop_cert(plain);
1173
			sshkey_drop_cert(plain);
Lines 1200-1206 out: Link Here
1200
	free(cafp);
1200
	free(cafp);
1201
	if (r == 0 && host_key != NULL) {
1201
	if (r == 0 && host_key != NULL) {
1202
		sshkey_free(previous_host_key);
1202
		sshkey_free(previous_host_key);
1203
		r = sshkey_from_private(host_key, &previous_host_key);
1203
		r = sshkey_copy_public(host_key, &previous_host_key);
1204
	}
1204
	}
1205
1205
1206
	return r;
1206
	return r;
(-)a/sshd.c (-2 / +2 lines)
Lines 363-369 demote_sensitive_data(void) Link Here
363
363
364
	for (i = 0; i < options.num_host_key_files; i++) {
364
	for (i = 0; i < options.num_host_key_files; i++) {
365
		if (sensitive_data.host_keys[i]) {
365
		if (sensitive_data.host_keys[i]) {
366
			if ((r = sshkey_from_private(
366
			if ((r = sshkey_copy_public(
367
			    sensitive_data.host_keys[i], &tmp)) != 0)
367
			    sensitive_data.host_keys[i], &tmp)) != 0)
368
				fatal("could not demote host %s key: %s",
368
				fatal("could not demote host %s key: %s",
369
				    sshkey_type(sensitive_data.host_keys[i]),
369
				    sshkey_type(sensitive_data.host_keys[i]),
Lines 1546-1552 main(int ac, char **av) Link Here
1546
			do_log2(ll, "Unable to load host key \"%s\": %s",
1546
			do_log2(ll, "Unable to load host key \"%s\": %s",
1547
			    options.host_key_files[i], ssh_err(r));
1547
			    options.host_key_files[i], ssh_err(r));
1548
		if (pubkey == NULL && key != NULL)
1548
		if (pubkey == NULL && key != NULL)
1549
			if ((r = sshkey_from_private(key, &pubkey)) != 0)
1549
			if ((r = sshkey_copy_public(key, &pubkey)) != 0)
1550
				fatal("Could not demote key: \"%s\": %s",
1550
				fatal("Could not demote key: \"%s\": %s",
1551
				    options.host_key_files[i], ssh_err(r));
1551
				    options.host_key_files[i], ssh_err(r));
1552
		sensitive_data.host_keys[i] = key;
1552
		sensitive_data.host_keys[i] = key;
(-)a/sshkey.c (-2 / +112 lines)
Lines 1646-1652 sshkey_cert_copy(const struct sshkey *from_key, struct sshkey *to_key) Link Here
1646
	to->valid_before = from->valid_before;
1646
	to->valid_before = from->valid_before;
1647
	if (from->signature_key == NULL)
1647
	if (from->signature_key == NULL)
1648
		to->signature_key = NULL;
1648
		to->signature_key = NULL;
1649
	else if ((r = sshkey_from_private(from->signature_key,
1649
	else if ((r = sshkey_copy_public(from->signature_key,
1650
	    &to->signature_key)) != 0)
1650
	    &to->signature_key)) != 0)
1651
		goto out;
1651
		goto out;
1652
	if (from->signature_type != NULL &&
1652
	if (from->signature_type != NULL &&
Lines 1686-1692 sshkey_cert_copy(const struct sshkey *from_key, struct sshkey *to_key) Link Here
1686
}
1686
}
1687
1687
1688
int
1688
int
1689
sshkey_from_private(const struct sshkey *k, struct sshkey **pkp)
1689
sshkey_copy_public(const struct sshkey *k, struct sshkey **pkp)
1690
{
1690
{
1691
	struct sshkey *n = NULL;
1691
	struct sshkey *n = NULL;
1692
	int r = SSH_ERR_INTERNAL_ERROR;
1692
	int r = SSH_ERR_INTERNAL_ERROR;
Lines 1825-1830 sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) Link Here
1825
	return r;
1825
	return r;
1826
}
1826
}
1827
1827
1828
int
1829
sshkey_copy_private(const struct sshkey *k, struct sshkey **pvp)
1830
{
1831
	struct sshkey *n = NULL;
1832
	int r = SSH_ERR_INTERNAL_ERROR;
1833
1834
	*pvp = NULL;
1835
	switch (k->type) {
1836
#ifdef WITH_OPENSSL
1837
	case KEY_DSA:
1838
	case KEY_DSA_CERT:
1839
		if ((n = sshkey_new(k->type)) == NULL) {
1840
			r = SSH_ERR_ALLOC_FAIL;
1841
			goto out;
1842
		}
1843
		n->dsa = k->dsa;
1844
		DSA_up_ref(n->dsa);
1845
		break;
1846
	case KEY_ECDSA:
1847
	case KEY_ECDSA_CERT:
1848
		if ((n = sshkey_new(k->type)) == NULL) {
1849
			r = SSH_ERR_ALLOC_FAIL;
1850
			goto out;
1851
		}
1852
		n->ecdsa_nid = k->ecdsa_nid;
1853
		n->ecdsa = k->ecdsa;
1854
		EC_KEY_up_ref(k->ecdsa);
1855
		break;
1856
	case KEY_RSA:
1857
	case KEY_RSA_CERT:
1858
		if ((n = sshkey_new(k->type)) == NULL) {
1859
			r = SSH_ERR_ALLOC_FAIL;
1860
			goto out;
1861
		}
1862
		n->rsa = k->rsa;
1863
		RSA_up_ref(k->rsa);
1864
		break;
1865
#endif /* WITH_OPENSSL */
1866
	case KEY_ED25519:
1867
	case KEY_ED25519_CERT:
1868
		if ((n = sshkey_new(k->type)) == NULL) {
1869
			r = SSH_ERR_ALLOC_FAIL;
1870
			goto out;
1871
		}
1872
		if (k->ed25519_pk != NULL) {
1873
			if ((n->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) {
1874
				r = SSH_ERR_ALLOC_FAIL;
1875
				goto out;
1876
			}
1877
			memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);
1878
		}
1879
		if (k->ed25519_sk != NULL) {
1880
			if ((n->ed25519_sk = malloc(ED25519_SK_SZ)) == NULL) {
1881
				r = SSH_ERR_ALLOC_FAIL;
1882
				goto out;
1883
			}
1884
			memcpy(n->ed25519_sk, k->ed25519_sk, ED25519_SK_SZ);
1885
		}
1886
		break;
1887
#ifdef WITH_XMSS
1888
	case KEY_XMSS:
1889
	case KEY_XMSS_CERT:
1890
		if ((n = sshkey_new(k->type)) == NULL) {
1891
			r = SSH_ERR_ALLOC_FAIL;
1892
			goto out;
1893
		}
1894
		if ((r = sshkey_xmss_init(n, k->xmss_name)) != 0)
1895
			goto out;
1896
		if (k->xmss_pk != NULL) {
1897
			size_t pklen = sshkey_xmss_pklen(k);
1898
			if (pklen == 0 || sshkey_xmss_pklen(n) != pklen) {
1899
				r = SSH_ERR_INTERNAL_ERROR;
1900
				goto out;
1901
			}
1902
			if ((n->xmss_pk = malloc(pklen)) == NULL) {
1903
				r = SSH_ERR_ALLOC_FAIL;
1904
				goto out;
1905
			}
1906
			memcpy(n->xmss_pk, k->xmss_pk, pklen);
1907
		}
1908
		if (k->xmss_sk != NULL) {
1909
			size_t sklen = sshkey_xmss_sklen(k);
1910
			if (sklen == 0 || sshkey_xmss_sklen(n) != pklen) {
1911
				r = SSH_ERR_INTERNAL_ERROR;
1912
				goto out;
1913
			}
1914
			if ((n->xmss_sk = malloc(sklen)) == NULL) {
1915
				r = SSH_ERR_ALLOC_FAIL;
1916
				goto out;
1917
			}
1918
			memcpy(n->xmss_sk, k->xmss_sk, sklen);
1919
		}
1920
		break;
1921
#endif /* WITH_XMSS */
1922
	default:
1923
		r = SSH_ERR_KEY_TYPE_UNKNOWN;
1924
		goto out;
1925
	}
1926
	if (sshkey_is_cert(k) && (r = sshkey_cert_copy(k, n)) != 0)
1927
		goto out;
1928
	/* success */
1929
	*pvp = n;
1930
	n = NULL;
1931
	r = 0;
1932
 out:
1933
	sshkey_free(n);
1934
	return r;
1935
}
1936
1937
1828
static int
1938
static int
1829
cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)
1939
cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)
1830
{
1940
{
(-)a/sshkey.h (-1 / +2 lines)
Lines 139-145 int sshkey_read(struct sshkey *, char **); Link Here
139
u_int		 sshkey_size(const struct sshkey *);
139
u_int		 sshkey_size(const struct sshkey *);
140
140
141
int		 sshkey_generate(int type, u_int bits, struct sshkey **keyp);
141
int		 sshkey_generate(int type, u_int bits, struct sshkey **keyp);
142
int		 sshkey_from_private(const struct sshkey *, struct sshkey **);
142
int		 sshkey_copy_public(const struct sshkey *, struct sshkey **);
143
int		 sshkey_copy_private(const struct sshkey *, struct sshkey **);
143
int	 sshkey_type_from_name(const char *);
144
int	 sshkey_type_from_name(const char *);
144
int	 sshkey_is_cert(const struct sshkey *);
145
int	 sshkey_is_cert(const struct sshkey *);
145
int	 sshkey_type_is_cert(int);
146
int	 sshkey_type_is_cert(int);

Return to bug 2472