diff options
author | djm@openbsd.org <djm@openbsd.org> | 2019-01-20 22:03:29 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2019-01-21 10:46:04 +1100 |
commit | aa22c20e0c36c2fc610cfcc793b0d14079c38814 (patch) | |
tree | 45ca2015c7daa7b8cf7b66fb5f720a5d25109f76 /ssh-add.c | |
parent | a36b0b14a12971086034d53c0c3dfbad07665abe (diff) | |
download | openssh-git-aa22c20e0c36c2fc610cfcc793b0d14079c38814.tar.gz |
upstream: add option to test whether keys in an agent are usable,
by performing a signature and a verification using each key "ssh-add -T
pubkey [...]"
work by markus@, ok djm@
OpenBSD-Commit-ID: 931b888a600b6a883f65375bd5f73a4776c6d19b
Diffstat (limited to 'ssh-add.c')
-rw-r--r-- | ssh-add.c | 52 |
1 files changed, 49 insertions, 3 deletions
@@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-add.c,v 1.136 2018/09/19 02:03:02 djm Exp $ */ +/* $OpenBSD: ssh-add.c,v 1.137 2019/01/20 22:03:29 djm Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland @@ -418,6 +418,40 @@ update_card(int agent_fd, int add, const char *id, int qflag) } static int +test_key(int agent_fd, const char *filename) +{ + struct sshkey *key = NULL; + u_char *sig = NULL; + size_t slen = 0; + int r, ret = -1; + char data[1024]; + + if ((r = sshkey_load_public(filename, &key, NULL)) != 0) { + error("Couldn't read public key %s: %s", filename, ssh_err(r)); + return -1; + } + arc4random_buf(data, sizeof(data)); + if ((r = ssh_agent_sign(agent_fd, key, &sig, &slen, data, sizeof(data), + NULL, 0)) != 0) { + error("Agent signature failed for %s: %s", + filename, ssh_err(r)); + goto done; + } + if ((r = sshkey_verify(key, sig, slen, data, sizeof(data), + NULL, 0)) != 0) { + error("Signature verification failed for %s: %s", + filename, ssh_err(r)); + goto done; + } + /* success */ + ret = 0; + done: + free(sig); + sshkey_free(key); + return ret; +} + +static int list_identities(int agent_fd, int do_fp) { char *fp; @@ -524,6 +558,7 @@ usage(void) fprintf(stderr, " -X Unlock agent.\n"); fprintf(stderr, " -s pkcs11 Add keys from PKCS#11 provider.\n"); fprintf(stderr, " -e pkcs11 Remove keys provided by PKCS#11 provider.\n"); + fprintf(stderr, " -T pubkey Test if ssh-agent can access matching private key.\n"); fprintf(stderr, " -q Be quiet after a successful operation.\n"); } @@ -535,7 +570,7 @@ main(int argc, char **argv) int agent_fd; char *pkcs11provider = NULL; int r, i, ch, deleting = 0, ret = 0, key_only = 0; - int xflag = 0, lflag = 0, Dflag = 0, qflag = 0; + int xflag = 0, lflag = 0, Dflag = 0, qflag = 0, Tflag = 0; ssh_malloc_init(); /* must be called before any mallocs */ /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ @@ -559,7 +594,7 @@ main(int argc, char **argv) exit(2); } - while ((ch = getopt(argc, argv, "klLcdDxXE:e:M:m:qs:t:")) != -1) { + while ((ch = getopt(argc, argv, "klLcdDTxXE:e:M:m:qs:t:")) != -1) { switch (ch) { case 'E': fingerprint_hash = ssh_digest_alg_by_name(optarg); @@ -623,6 +658,9 @@ main(int argc, char **argv) case 'q': qflag = 1; break; + case 'T': + Tflag = 1; + break; default: usage(); ret = 1; @@ -648,6 +686,14 @@ main(int argc, char **argv) argc -= optind; argv += optind; + if (Tflag) { + if (argc <= 0) + fatal("no keys to test"); + for (r = i = 0; i < argc; i++) + r |= test_key(agent_fd, argv[i]); + ret = r == 0 ? 0 : 1; + goto done; + } if (pkcs11provider != NULL) { if (update_card(agent_fd, !deleting, pkcs11provider, qflag) == -1) |