diff options
author | djm@openbsd.org <djm@openbsd.org> | 2019-10-31 21:19:56 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2019-11-01 09:46:09 +1100 |
commit | 486164d060314a7f8bca2a00f53be9e900c5e74d (patch) | |
tree | fd88518f7ef5c9e8b8ea168f670e929b1a81c4a1 /ssh-add.c | |
parent | b9dd14d3091e31fb836f69873d3aa622eb7b4a1c (diff) |
upstream: ssh-add support for U2F/FIDO keys
OpenBSD-Commit-ID: 7f88a5181c982687afedf3130c6ab2bba60f7644
Diffstat (limited to 'ssh-add.c')
-rw-r--r-- | ssh-add.c | 37 |
1 files changed, 27 insertions, 10 deletions
@@ -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 | ||
193 | static int | 194 | static int |
194 | add_file(int agent_fd, const char *filename, int key_only, int qflag) | 195 | add_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 | ||
531 | static int | 541 | static int |
532 | do_file(int agent_fd, int deleting, int key_only, char *file, int qflag) | 542 | do_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 | } |