diff options
Diffstat (limited to 'ssh-add.c')
-rw-r--r-- | ssh-add.c | 68 |
1 files changed, 63 insertions, 5 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-add.c,v 1.147 2019/11/25 00:51:37 djm Exp $ */ | 1 | /* $OpenBSD: ssh-add.c,v 1.148 2019/12/30 09:22:49 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 |
@@ -66,6 +66,7 @@ | |||
66 | #include "misc.h" | 66 | #include "misc.h" |
67 | #include "ssherr.h" | 67 | #include "ssherr.h" |
68 | #include "digest.h" | 68 | #include "digest.h" |
69 | #include "ssh-sk.h" | ||
69 | 70 | ||
70 | /* argv0 */ | 71 | /* argv0 */ |
71 | extern char *__progname; | 72 | extern char *__progname; |
@@ -540,6 +541,54 @@ lock_agent(int agent_fd, int lock) | |||
540 | } | 541 | } |
541 | 542 | ||
542 | static int | 543 | static int |
544 | load_resident_keys(int agent_fd, const char *skprovider, int qflag) | ||
545 | { | ||
546 | struct sshkey **keys; | ||
547 | size_t nkeys, i; | ||
548 | int r, ok = 0; | ||
549 | char *fp; | ||
550 | |||
551 | pass = read_passphrase("Enter PIN for security key: ", RP_ALLOW_STDIN); | ||
552 | if ((r = sshsk_load_resident(skprovider, pass, &keys, &nkeys)) != 0) { | ||
553 | error("Unable to load resident keys: %s", ssh_err(r)); | ||
554 | return r; | ||
555 | } | ||
556 | for (i = 0; i < nkeys; i++) { | ||
557 | if ((fp = sshkey_fingerprint(keys[i], | ||
558 | fingerprint_hash, SSH_FP_DEFAULT)) == NULL) | ||
559 | fatal("%s: sshkey_fingerprint failed", __func__); | ||
560 | if ((r = ssh_add_identity_constrained(agent_fd, keys[i], "", | ||
561 | lifetime, confirm, maxsign, skprovider)) != 0) { | ||
562 | error("Unable to add key %s %s", | ||
563 | sshkey_type(keys[i]), fp); | ||
564 | free(fp); | ||
565 | ok = r; | ||
566 | continue; | ||
567 | } | ||
568 | if (ok == 0) | ||
569 | ok = 1; | ||
570 | if (!qflag) { | ||
571 | fprintf(stderr, "Resident identity added: %s %s\n", | ||
572 | sshkey_type(keys[i]), fp); | ||
573 | if (lifetime != 0) { | ||
574 | fprintf(stderr, | ||
575 | "Lifetime set to %d seconds\n", lifetime); | ||
576 | } | ||
577 | if (confirm != 0) { | ||
578 | fprintf(stderr, "The user must confirm " | ||
579 | "each use of the key\n"); | ||
580 | } | ||
581 | } | ||
582 | free(fp); | ||
583 | sshkey_free(keys[i]); | ||
584 | } | ||
585 | free(keys); | ||
586 | if (nkeys == 0) | ||
587 | return SSH_ERR_KEY_NOT_FOUND; | ||
588 | return ok == 1 ? 0 : ok; | ||
589 | } | ||
590 | |||
591 | static int | ||
543 | do_file(int agent_fd, int deleting, int key_only, char *file, int qflag, | 592 | do_file(int agent_fd, int deleting, int key_only, char *file, int qflag, |
544 | const char *skprovider) | 593 | const char *skprovider) |
545 | { | 594 | { |
@@ -585,7 +634,7 @@ main(int argc, char **argv) | |||
585 | extern int optind; | 634 | extern int optind; |
586 | int agent_fd; | 635 | int agent_fd; |
587 | char *pkcs11provider = NULL, *skprovider = NULL; | 636 | char *pkcs11provider = NULL, *skprovider = NULL; |
588 | int r, i, ch, deleting = 0, ret = 0, key_only = 0; | 637 | int r, i, ch, deleting = 0, ret = 0, key_only = 0, do_download = 0; |
589 | int xflag = 0, lflag = 0, Dflag = 0, qflag = 0, Tflag = 0; | 638 | int xflag = 0, lflag = 0, Dflag = 0, qflag = 0, Tflag = 0; |
590 | SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; | 639 | SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; |
591 | LogLevel log_level = SYSLOG_LEVEL_INFO; | 640 | LogLevel log_level = SYSLOG_LEVEL_INFO; |
@@ -615,7 +664,7 @@ main(int argc, char **argv) | |||
615 | 664 | ||
616 | skprovider = getenv("SSH_SK_PROVIDER"); | 665 | skprovider = getenv("SSH_SK_PROVIDER"); |
617 | 666 | ||
618 | while ((ch = getopt(argc, argv, "vklLcdDTxXE:e:M:m:qs:S:t:")) != -1) { | 667 | while ((ch = getopt(argc, argv, "vklLcdDTxXE:e:M:m:Oqs:S:t:")) != -1) { |
619 | switch (ch) { | 668 | switch (ch) { |
620 | case 'v': | 669 | case 'v': |
621 | if (log_level == SYSLOG_LEVEL_INFO) | 670 | if (log_level == SYSLOG_LEVEL_INFO) |
@@ -637,6 +686,9 @@ main(int argc, char **argv) | |||
637 | fatal("-%c flag already specified", lflag); | 686 | fatal("-%c flag already specified", lflag); |
638 | lflag = ch; | 687 | lflag = ch; |
639 | break; | 688 | break; |
689 | case 'O': | ||
690 | do_download = 1; | ||
691 | break; | ||
640 | case 'x': | 692 | case 'x': |
641 | case 'X': | 693 | case 'X': |
642 | if (xflag != 0) | 694 | if (xflag != 0) |
@@ -736,6 +788,13 @@ main(int argc, char **argv) | |||
736 | ret = 1; | 788 | ret = 1; |
737 | goto done; | 789 | goto done; |
738 | } | 790 | } |
791 | if (do_download) { | ||
792 | if (skprovider == NULL) | ||
793 | fatal("Cannot download keys without provider"); | ||
794 | if (load_resident_keys(agent_fd, skprovider, qflag) != 0) | ||
795 | ret = 1; | ||
796 | goto done; | ||
797 | } | ||
739 | if (argc == 0) { | 798 | if (argc == 0) { |
740 | char buf[PATH_MAX]; | 799 | char buf[PATH_MAX]; |
741 | struct passwd *pw; | 800 | struct passwd *pw; |
@@ -769,9 +828,8 @@ main(int argc, char **argv) | |||
769 | ret = 1; | 828 | ret = 1; |
770 | } | 829 | } |
771 | } | 830 | } |
772 | clear_pass(); | ||
773 | |||
774 | done: | 831 | done: |
832 | clear_pass(); | ||
775 | ssh_close_authentication_socket(agent_fd); | 833 | ssh_close_authentication_socket(agent_fd); |
776 | return ret; | 834 | return ret; |
777 | } | 835 | } |