summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2019-10-31 21:19:56 +0000
committerDamien Miller <djm@mindrot.org>2019-11-01 09:46:09 +1100
commit486164d060314a7f8bca2a00f53be9e900c5e74d (patch)
treefd88518f7ef5c9e8b8ea168f670e929b1a81c4a1
parentb9dd14d3091e31fb836f69873d3aa622eb7b4a1c (diff)
upstream: ssh-add support for U2F/FIDO keys
OpenBSD-Commit-ID: 7f88a5181c982687afedf3130c6ab2bba60f7644
-rw-r--r--ssh-add.113
-rw-r--r--ssh-add.c37
2 files changed, 38 insertions, 12 deletions
diff --git a/ssh-add.1 b/ssh-add.1
index d4e1c603b..9dc44fa74 100644
--- a/ssh-add.1
+++ b/ssh-add.1
@@ -1,4 +1,4 @@
1.\" $OpenBSD: ssh-add.1,v 1.69 2019/01/21 12:53:35 djm Exp $ 1.\" $OpenBSD: ssh-add.1,v 1.70 2019/10/31 21:19:56 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: January 21 2019 $ 38.Dd $Mdocdate: October 31 2019 $
39.Dt SSH-ADD 1 39.Dt SSH-ADD 1
40.Os 40.Os
41.Sh NAME 41.Sh NAME
@@ -46,6 +46,7 @@
46.Op Fl cDdkLlqvXx 46.Op Fl cDdkLlqvXx
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 Fl S Ar provider
49.Op Ar 50.Op Ar
50.Nm ssh-add 51.Nm ssh-add
51.Fl s Ar pkcs11 52.Fl s Ar pkcs11
@@ -134,6 +135,11 @@ Be quiet after a successful operation.
134.It Fl s Ar pkcs11 135.It Fl s Ar pkcs11
135Add keys provided by the PKCS#11 shared library 136Add keys provided by the PKCS#11 shared library
136.Ar pkcs11 . 137.Ar pkcs11 .
138.It Fl S Ar provider
139Specifies a path to a security key provider library that will be used when
140adding any security key-hosted keys, overriding the default of using the
141.Ev "SSH_SK_PROVIDER"
142environment variable to specify a provider.
137.It Fl T Ar pubkey ... 143.It Fl T Ar pubkey ...
138Tests whether the private keys that correspond to the specified 144Tests whether the private keys that correspond to the specified
139.Ar pubkey 145.Ar pubkey
@@ -189,6 +195,9 @@ to make this work.)
189Identifies the path of a 195Identifies the path of a
190.Ux Ns -domain 196.Ux Ns -domain
191socket used to communicate with the agent. 197socket used to communicate with the agent.
198.It Ev SSH_SK_PROVIDER
199Specifies the path to a security key provider library used to interact with
200hardware security keys.
192.El 201.El
193.Sh FILES 202.Sh FILES
194.Bl -tag -width Ds 203.Bl -tag -width Ds
diff --git a/ssh-add.c b/ssh-add.c
index 2c65d0272..3c8849ac4 100644
--- a/ssh-add.c
+++ b/ssh-add.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-add.c,v 1.142 2019/10/31 21:19:15 djm Exp $ */ 1/* $OpenBSD: ssh-add.c,v 1.143 2019/10/31 21:19:56 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
@@ -77,6 +77,7 @@ static char *default_files[] = {
77 _PATH_SSH_CLIENT_ID_DSA, 77 _PATH_SSH_CLIENT_ID_DSA,
78#ifdef OPENSSL_HAS_ECC 78#ifdef OPENSSL_HAS_ECC
79 _PATH_SSH_CLIENT_ID_ECDSA, 79 _PATH_SSH_CLIENT_ID_ECDSA,
80 _PATH_SSH_CLIENT_ID_ECDSA_SK,
80#endif 81#endif
81#endif /* WITH_OPENSSL */ 82#endif /* WITH_OPENSSL */
82 _PATH_SSH_CLIENT_ID_ED25519, 83 _PATH_SSH_CLIENT_ID_ED25519,
@@ -191,7 +192,8 @@ delete_all(int agent_fd, int qflag)
191} 192}
192 193
193static int 194static int
194add_file(int agent_fd, const char *filename, int key_only, int qflag) 195add_file(int agent_fd, const char *filename, int key_only, int qflag,
196 const char *skprovider)
195{ 197{
196 struct sshkey *private, *cert; 198 struct sshkey *private, *cert;
197 char *comment = NULL; 199 char *comment = NULL;
@@ -310,8 +312,16 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag)
310 ssh_free_identitylist(idlist); 312 ssh_free_identitylist(idlist);
311 } 313 }
312 314
315 if (sshkey_type_plain(private->type) != KEY_ECDSA_SK)
316 skprovider = NULL; /* Don't send constraint for other keys */
317 else if (skprovider == NULL) {
318 fprintf(stderr, "Cannot load security key %s without "
319 "provider\n", filename);
320 goto out;
321 }
322
313 if ((r = ssh_add_identity_constrained(agent_fd, private, comment, 323 if ((r = ssh_add_identity_constrained(agent_fd, private, comment,
314 lifetime, confirm, maxsign, NULL)) == 0) { 324 lifetime, confirm, maxsign, skprovider)) == 0) {
315 ret = 0; 325 ret = 0;
316 if (!qflag) { 326 if (!qflag) {
317 fprintf(stderr, "Identity added: %s (%s)\n", 327 fprintf(stderr, "Identity added: %s (%s)\n",
@@ -364,7 +374,7 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag)
364 sshkey_free(cert); 374 sshkey_free(cert);
365 375
366 if ((r = ssh_add_identity_constrained(agent_fd, private, comment, 376 if ((r = ssh_add_identity_constrained(agent_fd, private, comment,
367 lifetime, confirm, maxsign, NULL)) != 0) { 377 lifetime, confirm, maxsign, skprovider)) != 0) {
368 error("Certificate %s (%s) add failed: %s", certpath, 378 error("Certificate %s (%s) add failed: %s", certpath,
369 private->cert->key_id, ssh_err(r)); 379 private->cert->key_id, ssh_err(r));
370 goto out; 380 goto out;
@@ -529,13 +539,14 @@ lock_agent(int agent_fd, int lock)
529} 539}
530 540
531static int 541static int
532do_file(int agent_fd, int deleting, int key_only, char *file, int qflag) 542do_file(int agent_fd, int deleting, int key_only, char *file, int qflag,
543 const char *skprovider)
533{ 544{
534 if (deleting) { 545 if (deleting) {
535 if (delete_file(agent_fd, file, key_only, qflag) == -1) 546 if (delete_file(agent_fd, file, key_only, qflag) == -1)
536 return -1; 547 return -1;
537 } else { 548 } else {
538 if (add_file(agent_fd, file, key_only, qflag) == -1) 549 if (add_file(agent_fd, file, key_only, qflag, skprovider) == -1)
539 return -1; 550 return -1;
540 } 551 }
541 return 0; 552 return 0;
@@ -561,6 +572,7 @@ usage(void)
561 fprintf(stderr, " -s pkcs11 Add keys from PKCS#11 provider.\n"); 572 fprintf(stderr, " -s pkcs11 Add keys from PKCS#11 provider.\n");
562 fprintf(stderr, " -e pkcs11 Remove keys provided by PKCS#11 provider.\n"); 573 fprintf(stderr, " -e pkcs11 Remove keys provided by PKCS#11 provider.\n");
563 fprintf(stderr, " -T pubkey Test if ssh-agent can access matching private key.\n"); 574 fprintf(stderr, " -T pubkey Test if ssh-agent can access matching private key.\n");
575 fprintf(stderr, " -S provider Specify security key provider.\n");
564 fprintf(stderr, " -q Be quiet after a successful operation.\n"); 576 fprintf(stderr, " -q Be quiet after a successful operation.\n");
565 fprintf(stderr, " -v Be more verbose.\n"); 577 fprintf(stderr, " -v Be more verbose.\n");
566} 578}
@@ -571,7 +583,7 @@ main(int argc, char **argv)
571 extern char *optarg; 583 extern char *optarg;
572 extern int optind; 584 extern int optind;
573 int agent_fd; 585 int agent_fd;
574 char *pkcs11provider = NULL; 586 char *pkcs11provider = NULL, *skprovider = NULL;
575 int r, i, ch, deleting = 0, ret = 0, key_only = 0; 587 int r, i, ch, deleting = 0, ret = 0, key_only = 0;
576 int xflag = 0, lflag = 0, Dflag = 0, qflag = 0, Tflag = 0; 588 int xflag = 0, lflag = 0, Dflag = 0, qflag = 0, Tflag = 0;
577 SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; 589 SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
@@ -600,7 +612,9 @@ main(int argc, char **argv)
600 exit(2); 612 exit(2);
601 } 613 }
602 614
603 while ((ch = getopt(argc, argv, "vklLcdDTxXE:e:M:m:qs:t:")) != -1) { 615 skprovider = getenv("SSH_SK_PROVIDER");
616
617 while ((ch = getopt(argc, argv, "vklLcdDTxXE:e:M:m:qs:S:t:")) != -1) {
604 switch (ch) { 618 switch (ch) {
605 case 'v': 619 case 'v':
606 if (log_level == SYSLOG_LEVEL_INFO) 620 if (log_level == SYSLOG_LEVEL_INFO)
@@ -656,6 +670,9 @@ main(int argc, char **argv)
656 case 's': 670 case 's':
657 pkcs11provider = optarg; 671 pkcs11provider = optarg;
658 break; 672 break;
673 case 'S':
674 skprovider = optarg;
675 break;
659 case 'e': 676 case 'e':
660 deleting = 1; 677 deleting = 1;
661 pkcs11provider = optarg; 678 pkcs11provider = optarg;
@@ -732,7 +749,7 @@ main(int argc, char **argv)
732 if (stat(buf, &st) == -1) 749 if (stat(buf, &st) == -1)
733 continue; 750 continue;
734 if (do_file(agent_fd, deleting, key_only, buf, 751 if (do_file(agent_fd, deleting, key_only, buf,
735 qflag) == -1) 752 qflag, skprovider) == -1)
736 ret = 1; 753 ret = 1;
737 else 754 else
738 count++; 755 count++;
@@ -742,7 +759,7 @@ main(int argc, char **argv)
742 } else { 759 } else {
743 for (i = 0; i < argc; i++) { 760 for (i = 0; i < argc; i++) {
744 if (do_file(agent_fd, deleting, key_only, 761 if (do_file(agent_fd, deleting, key_only,
745 argv[i], qflag) == -1) 762 argv[i], qflag, skprovider) == -1)
746 ret = 1; 763 ret = 1;
747 } 764 }
748 } 765 }