summaryrefslogtreecommitdiff
path: root/ssh-add.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2019-12-30 09:22:49 +0000
committerDamien Miller <djm@mindrot.org>2019-12-30 20:58:19 +1100
commit79fe22d9bc2868c5118f032ec1200ac9c2e3aaef (patch)
tree2c83d1dd519ab593d7004de366df9a80b2767bed /ssh-add.c
parent27753a8e21887d47fe6b5c78a4aed0efe558a850 (diff)
upstream: implement loading resident keys in ssh-add
"ssh-add -O" will load resident keys from a FIDO2 token and add them to a ssh-agent. feedback and ok markus@ OpenBSD-Commit-ID: 608104ae957a7d65cb84e0a3a26c8f60e0df3290
Diffstat (limited to 'ssh-add.c')
-rw-r--r--ssh-add.c68
1 files changed, 63 insertions, 5 deletions
diff --git a/ssh-add.c b/ssh-add.c
index 1d85e9d60..c25b57cc1 100644
--- a/ssh-add.c
+++ b/ssh-add.c
@@ -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 */
71extern char *__progname; 72extern char *__progname;
@@ -540,6 +541,54 @@ lock_agent(int agent_fd, int lock)
540} 541}
541 542
542static int 543static int
544load_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
591static int
543do_file(int agent_fd, int deleting, int key_only, char *file, int qflag, 592do_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
774done: 831done:
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}