summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ssh-add.114
-rw-r--r--ssh-add.c52
2 files changed, 60 insertions, 6 deletions
diff --git a/ssh-add.1 b/ssh-add.1
index d5da9279c..35ab04426 100644
--- a/ssh-add.1
+++ b/ssh-add.1
@@ -1,4 +1,4 @@
1.\" $OpenBSD: ssh-add.1,v 1.66 2017/08/29 13:05:58 jmc Exp $ 1.\" $OpenBSD: ssh-add.1,v 1.67 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
@@ -35,7 +35,7 @@
35.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 35.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
36.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37.\" 37.\"
38.Dd $Mdocdate: August 29 2017 $ 38.Dd $Mdocdate: January 20 2019 $
39.Dt SSH-ADD 1 39.Dt SSH-ADD 1
40.Os 40.Os
41.Sh NAME 41.Sh NAME
@@ -43,7 +43,7 @@
43.Nd adds private key identities to the authentication agent 43.Nd adds private key identities to the authentication agent
44.Sh SYNOPSIS 44.Sh SYNOPSIS
45.Nm ssh-add 45.Nm ssh-add
46.Op Fl cDdkLlqXx 46.Op Fl cDdkLlqTXx
47.Op Fl E Ar fingerprint_hash 47.Op Fl E Ar fingerprint_hash
48.Op Fl t Ar life 48.Op Fl t Ar life
49.Op Ar 49.Op Ar
@@ -51,6 +51,10 @@
51.Fl s Ar pkcs11 51.Fl s Ar pkcs11
52.Nm ssh-add 52.Nm ssh-add
53.Fl e Ar pkcs11 53.Fl e Ar pkcs11
54.Nm ssh-add
55.Fl T
56.Ar pubkey
57.Op Ar ...
54.Sh DESCRIPTION 58.Sh DESCRIPTION
55.Nm 59.Nm
56adds private key identities to the authentication agent, 60adds private key identities to the authentication agent,
@@ -131,6 +135,10 @@ Be quiet after a successful operation.
131.It Fl s Ar pkcs11 135.It Fl s Ar pkcs11
132Add keys provided by the PKCS#11 shared library 136Add keys provided by the PKCS#11 shared library
133.Ar pkcs11 . 137.Ar pkcs11 .
138.It Fl T Ar pubkey Op Ar ...
139Tests whether the private keys that correspond to the specified
140.Ar pubkey
141files are usable by performing sign and verify operations on each.
134.It Fl t Ar life 142.It Fl t Ar life
135Set a maximum lifetime when adding identities to an agent. 143Set a maximum lifetime when adding identities to an agent.
136The lifetime may be specified in seconds or in a time format 144The lifetime may be specified in seconds or in a time format
diff --git a/ssh-add.c b/ssh-add.c
index 50165e7d6..eb2552ad5 100644
--- a/ssh-add.c
+++ b/ssh-add.c
@@ -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
420static int 420static int
421test_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
454static int
421list_identities(int agent_fd, int do_fp) 455list_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)