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
This commit is contained in:
djm@openbsd.org 2019-01-20 22:03:29 +00:00 committed by Damien Miller
parent a36b0b14a1
commit aa22c20e0c
2 changed files with 60 additions and 6 deletions

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: ssh-add.1,v 1.66 2017/08/29 13:05:58 jmc Exp $ .\" $OpenBSD: ssh-add.1,v 1.67 2019/01/20 22:03:29 djm Exp $
.\" .\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi> .\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland .\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -35,7 +35,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\" .\"
.Dd $Mdocdate: August 29 2017 $ .Dd $Mdocdate: January 20 2019 $
.Dt SSH-ADD 1 .Dt SSH-ADD 1
.Os .Os
.Sh NAME .Sh NAME
@ -43,7 +43,7 @@
.Nd adds private key identities to the authentication agent .Nd adds private key identities to the authentication agent
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm ssh-add .Nm ssh-add
.Op Fl cDdkLlqXx .Op Fl cDdkLlqTXx
.Op Fl E Ar fingerprint_hash .Op Fl E Ar fingerprint_hash
.Op Fl t Ar life .Op Fl t Ar life
.Op Ar .Op Ar
@ -51,6 +51,10 @@
.Fl s Ar pkcs11 .Fl s Ar pkcs11
.Nm ssh-add .Nm ssh-add
.Fl e Ar pkcs11 .Fl e Ar pkcs11
.Nm ssh-add
.Fl T
.Ar pubkey
.Op Ar ...
.Sh DESCRIPTION .Sh DESCRIPTION
.Nm .Nm
adds private key identities to the authentication agent, adds private key identities to the authentication agent,
@ -131,6 +135,10 @@ Be quiet after a successful operation.
.It Fl s Ar pkcs11 .It Fl s Ar pkcs11
Add keys provided by the PKCS#11 shared library Add keys provided by the PKCS#11 shared library
.Ar pkcs11 . .Ar pkcs11 .
.It Fl T Ar pubkey Op Ar ...
Tests whether the private keys that correspond to the specified
.Ar pubkey
files are usable by performing sign and verify operations on each.
.It Fl t Ar life .It Fl t Ar life
Set a maximum lifetime when adding identities to an agent. Set a maximum lifetime when adding identities to an agent.
The lifetime may be specified in seconds or in a time format The lifetime may be specified in seconds or in a time format

View File

@ -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> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -417,6 +417,40 @@ update_card(int agent_fd, int add, const char *id, int qflag)
return ret; return ret;
} }
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 static int
list_identities(int agent_fd, int do_fp) list_identities(int agent_fd, int do_fp)
{ {
@ -524,6 +558,7 @@ usage(void)
fprintf(stderr, " -X Unlock agent.\n"); fprintf(stderr, " -X Unlock agent.\n");
fprintf(stderr, " -s pkcs11 Add keys from PKCS#11 provider.\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, " -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"); fprintf(stderr, " -q Be quiet after a successful operation.\n");
} }
@ -535,7 +570,7 @@ main(int argc, char **argv)
int agent_fd; int agent_fd;
char *pkcs11provider = NULL; char *pkcs11provider = NULL;
int r, i, ch, deleting = 0, ret = 0, key_only = 0; 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 */ ssh_malloc_init(); /* must be called before any mallocs */
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ /* 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); 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) { switch (ch) {
case 'E': case 'E':
fingerprint_hash = ssh_digest_alg_by_name(optarg); fingerprint_hash = ssh_digest_alg_by_name(optarg);
@ -623,6 +658,9 @@ main(int argc, char **argv)
case 'q': case 'q':
qflag = 1; qflag = 1;
break; break;
case 'T':
Tflag = 1;
break;
default: default:
usage(); usage();
ret = 1; ret = 1;
@ -648,6 +686,14 @@ main(int argc, char **argv)
argc -= optind; argc -= optind;
argv += 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 (pkcs11provider != NULL) {
if (update_card(agent_fd, !deleting, pkcs11provider, if (update_card(agent_fd, !deleting, pkcs11provider,
qflag) == -1) qflag) == -1)