diff options
-rw-r--r-- | ssh-add.1 | 13 | ||||
-rw-r--r-- | ssh-add.c | 37 |
2 files changed, 38 insertions, 12 deletions
@@ -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 |
135 | Add keys provided by the PKCS#11 shared library | 136 | Add keys provided by the PKCS#11 shared library |
136 | .Ar pkcs11 . | 137 | .Ar pkcs11 . |
138 | .It Fl S Ar provider | ||
139 | Specifies a path to a security key provider library that will be used when | ||
140 | adding any security key-hosted keys, overriding the default of using the | ||
141 | .Ev "SSH_SK_PROVIDER" | ||
142 | environment variable to specify a provider. | ||
137 | .It Fl T Ar pubkey ... | 143 | .It Fl T Ar pubkey ... |
138 | Tests whether the private keys that correspond to the specified | 144 | Tests whether the private keys that correspond to the specified |
139 | .Ar pubkey | 145 | .Ar pubkey |
@@ -189,6 +195,9 @@ to make this work.) | |||
189 | Identifies the path of a | 195 | Identifies the path of a |
190 | .Ux Ns -domain | 196 | .Ux Ns -domain |
191 | socket used to communicate with the agent. | 197 | socket used to communicate with the agent. |
198 | .It Ev SSH_SK_PROVIDER | ||
199 | Specifies the path to a security key provider library used to interact with | ||
200 | hardware security keys. | ||
192 | .El | 201 | .El |
193 | .Sh FILES | 202 | .Sh FILES |
194 | .Bl -tag -width Ds | 203 | .Bl -tag -width Ds |
@@ -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 | } |