diff options
author | djm@openbsd.org <djm@openbsd.org> | 2019-01-20 22:03:29 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2019-01-21 10:46:04 +1100 |
commit | aa22c20e0c36c2fc610cfcc793b0d14079c38814 (patch) | |
tree | 45ca2015c7daa7b8cf7b66fb5f720a5d25109f76 /ssh-add.c | |
parent | a36b0b14a12971086034d53c0c3dfbad07665abe (diff) |
upstream: add option to test whether keys in an agent are usable,
by performing a signature and a verification using each key "ssh-add -T
pubkey [...]"
work by markus@, ok djm@
OpenBSD-Commit-ID: 931b888a600b6a883f65375bd5f73a4776c6d19b
Diffstat (limited to 'ssh-add.c')
-rw-r--r-- | ssh-add.c | 52 |
1 files changed, 49 insertions, 3 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-add.c,v 1.136 2018/09/19 02:03:02 djm Exp $ */ | 1 | /* $OpenBSD: ssh-add.c,v 1.137 2019/01/20 22:03:29 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -418,6 +418,40 @@ update_card(int agent_fd, int add, const char *id, int qflag) | |||
418 | } | 418 | } |
419 | 419 | ||
420 | static int | 420 | static int |
421 | test_key(int agent_fd, const char *filename) | ||
422 | { | ||
423 | struct sshkey *key = NULL; | ||
424 | u_char *sig = NULL; | ||
425 | size_t slen = 0; | ||
426 | int r, ret = -1; | ||
427 | char data[1024]; | ||
428 | |||
429 | if ((r = sshkey_load_public(filename, &key, NULL)) != 0) { | ||
430 | error("Couldn't read public key %s: %s", filename, ssh_err(r)); | ||
431 | return -1; | ||
432 | } | ||
433 | arc4random_buf(data, sizeof(data)); | ||
434 | if ((r = ssh_agent_sign(agent_fd, key, &sig, &slen, data, sizeof(data), | ||
435 | NULL, 0)) != 0) { | ||
436 | error("Agent signature failed for %s: %s", | ||
437 | filename, ssh_err(r)); | ||
438 | goto done; | ||
439 | } | ||
440 | if ((r = sshkey_verify(key, sig, slen, data, sizeof(data), | ||
441 | NULL, 0)) != 0) { | ||
442 | error("Signature verification failed for %s: %s", | ||
443 | filename, ssh_err(r)); | ||
444 | goto done; | ||
445 | } | ||
446 | /* success */ | ||
447 | ret = 0; | ||
448 | done: | ||
449 | free(sig); | ||
450 | sshkey_free(key); | ||
451 | return ret; | ||
452 | } | ||
453 | |||
454 | static int | ||
421 | list_identities(int agent_fd, int do_fp) | 455 | list_identities(int agent_fd, int do_fp) |
422 | { | 456 | { |
423 | char *fp; | 457 | char *fp; |
@@ -524,6 +558,7 @@ usage(void) | |||
524 | fprintf(stderr, " -X Unlock agent.\n"); | 558 | fprintf(stderr, " -X Unlock agent.\n"); |
525 | fprintf(stderr, " -s pkcs11 Add keys from PKCS#11 provider.\n"); | 559 | fprintf(stderr, " -s pkcs11 Add keys from PKCS#11 provider.\n"); |
526 | fprintf(stderr, " -e pkcs11 Remove keys provided by PKCS#11 provider.\n"); | 560 | fprintf(stderr, " -e pkcs11 Remove keys provided by PKCS#11 provider.\n"); |
561 | fprintf(stderr, " -T pubkey Test if ssh-agent can access matching private key.\n"); | ||
527 | fprintf(stderr, " -q Be quiet after a successful operation.\n"); | 562 | fprintf(stderr, " -q Be quiet after a successful operation.\n"); |
528 | } | 563 | } |
529 | 564 | ||
@@ -535,7 +570,7 @@ main(int argc, char **argv) | |||
535 | int agent_fd; | 570 | int agent_fd; |
536 | char *pkcs11provider = NULL; | 571 | char *pkcs11provider = NULL; |
537 | int r, i, ch, deleting = 0, ret = 0, key_only = 0; | 572 | int r, i, ch, deleting = 0, ret = 0, key_only = 0; |
538 | int xflag = 0, lflag = 0, Dflag = 0, qflag = 0; | 573 | int xflag = 0, lflag = 0, Dflag = 0, qflag = 0, Tflag = 0; |
539 | 574 | ||
540 | ssh_malloc_init(); /* must be called before any mallocs */ | 575 | ssh_malloc_init(); /* must be called before any mallocs */ |
541 | /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ | 576 | /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ |
@@ -559,7 +594,7 @@ main(int argc, char **argv) | |||
559 | exit(2); | 594 | exit(2); |
560 | } | 595 | } |
561 | 596 | ||
562 | while ((ch = getopt(argc, argv, "klLcdDxXE:e:M:m:qs:t:")) != -1) { | 597 | while ((ch = getopt(argc, argv, "klLcdDTxXE:e:M:m:qs:t:")) != -1) { |
563 | switch (ch) { | 598 | switch (ch) { |
564 | case 'E': | 599 | case 'E': |
565 | fingerprint_hash = ssh_digest_alg_by_name(optarg); | 600 | fingerprint_hash = ssh_digest_alg_by_name(optarg); |
@@ -623,6 +658,9 @@ main(int argc, char **argv) | |||
623 | case 'q': | 658 | case 'q': |
624 | qflag = 1; | 659 | qflag = 1; |
625 | break; | 660 | break; |
661 | case 'T': | ||
662 | Tflag = 1; | ||
663 | break; | ||
626 | default: | 664 | default: |
627 | usage(); | 665 | usage(); |
628 | ret = 1; | 666 | ret = 1; |
@@ -648,6 +686,14 @@ main(int argc, char **argv) | |||
648 | 686 | ||
649 | argc -= optind; | 687 | argc -= optind; |
650 | argv += optind; | 688 | argv += optind; |
689 | if (Tflag) { | ||
690 | if (argc <= 0) | ||
691 | fatal("no keys to test"); | ||
692 | for (r = i = 0; i < argc; i++) | ||
693 | r |= test_key(agent_fd, argv[i]); | ||
694 | ret = r == 0 ? 0 : 1; | ||
695 | goto done; | ||
696 | } | ||
651 | if (pkcs11provider != NULL) { | 697 | if (pkcs11provider != NULL) { |
652 | if (update_card(agent_fd, !deleting, pkcs11provider, | 698 | if (update_card(agent_fd, !deleting, pkcs11provider, |
653 | qflag) == -1) | 699 | qflag) == -1) |