mirror of
git://anongit.mindrot.org/openssh.git
synced 2025-01-08 18:49:50 +00:00
upstream: ssh-add support for U2F/FIDO keys
OpenBSD-Commit-ID: 7f88a5181c982687afedf3130c6ab2bba60f7644
This commit is contained in:
parent
b9dd14d309
commit
486164d060
13
ssh-add.1
13
ssh-add.1
@ -1,4 +1,4 @@
|
|||||||
.\" $OpenBSD: ssh-add.1,v 1.69 2019/01/21 12:53:35 djm Exp $
|
.\" $OpenBSD: ssh-add.1,v 1.70 2019/10/31 21:19:56 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: January 21 2019 $
|
.Dd $Mdocdate: October 31 2019 $
|
||||||
.Dt SSH-ADD 1
|
.Dt SSH-ADD 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -46,6 +46,7 @@
|
|||||||
.Op Fl cDdkLlqvXx
|
.Op Fl cDdkLlqvXx
|
||||||
.Op Fl E Ar fingerprint_hash
|
.Op Fl E Ar fingerprint_hash
|
||||||
.Op Fl t Ar life
|
.Op Fl t Ar life
|
||||||
|
.Op Fl S Ar provider
|
||||||
.Op Ar
|
.Op Ar
|
||||||
.Nm ssh-add
|
.Nm ssh-add
|
||||||
.Fl s Ar pkcs11
|
.Fl s Ar pkcs11
|
||||||
@ -134,6 +135,11 @@ 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 S Ar provider
|
||||||
|
Specifies a path to a security key provider library that will be used when
|
||||||
|
adding any security key-hosted keys, overriding the default of using the
|
||||||
|
.Ev "SSH_SK_PROVIDER"
|
||||||
|
environment variable to specify a provider.
|
||||||
.It Fl T Ar pubkey ...
|
.It Fl T Ar pubkey ...
|
||||||
Tests whether the private keys that correspond to the specified
|
Tests whether the private keys that correspond to the specified
|
||||||
.Ar pubkey
|
.Ar pubkey
|
||||||
@ -189,6 +195,9 @@ to make this work.)
|
|||||||
Identifies the path of a
|
Identifies the path of a
|
||||||
.Ux Ns -domain
|
.Ux Ns -domain
|
||||||
socket used to communicate with the agent.
|
socket used to communicate with the agent.
|
||||||
|
.It Ev SSH_SK_PROVIDER
|
||||||
|
Specifies the path to a security key provider library used to interact with
|
||||||
|
hardware security keys.
|
||||||
.El
|
.El
|
||||||
.Sh FILES
|
.Sh FILES
|
||||||
.Bl -tag -width Ds
|
.Bl -tag -width Ds
|
||||||
|
37
ssh-add.c
37
ssh-add.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: ssh-add.c,v 1.142 2019/10/31 21:19:15 djm Exp $ */
|
/* $OpenBSD: ssh-add.c,v 1.143 2019/10/31 21:19:56 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
|
||||||
@ -77,6 +77,7 @@ static char *default_files[] = {
|
|||||||
_PATH_SSH_CLIENT_ID_DSA,
|
_PATH_SSH_CLIENT_ID_DSA,
|
||||||
#ifdef OPENSSL_HAS_ECC
|
#ifdef OPENSSL_HAS_ECC
|
||||||
_PATH_SSH_CLIENT_ID_ECDSA,
|
_PATH_SSH_CLIENT_ID_ECDSA,
|
||||||
|
_PATH_SSH_CLIENT_ID_ECDSA_SK,
|
||||||
#endif
|
#endif
|
||||||
#endif /* WITH_OPENSSL */
|
#endif /* WITH_OPENSSL */
|
||||||
_PATH_SSH_CLIENT_ID_ED25519,
|
_PATH_SSH_CLIENT_ID_ED25519,
|
||||||
@ -191,7 +192,8 @@ delete_all(int agent_fd, int qflag)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
add_file(int agent_fd, const char *filename, int key_only, int qflag)
|
add_file(int agent_fd, const char *filename, int key_only, int qflag,
|
||||||
|
const char *skprovider)
|
||||||
{
|
{
|
||||||
struct sshkey *private, *cert;
|
struct sshkey *private, *cert;
|
||||||
char *comment = NULL;
|
char *comment = NULL;
|
||||||
@ -310,8 +312,16 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag)
|
|||||||
ssh_free_identitylist(idlist);
|
ssh_free_identitylist(idlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sshkey_type_plain(private->type) != KEY_ECDSA_SK)
|
||||||
|
skprovider = NULL; /* Don't send constraint for other keys */
|
||||||
|
else if (skprovider == NULL) {
|
||||||
|
fprintf(stderr, "Cannot load security key %s without "
|
||||||
|
"provider\n", filename);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if ((r = ssh_add_identity_constrained(agent_fd, private, comment,
|
if ((r = ssh_add_identity_constrained(agent_fd, private, comment,
|
||||||
lifetime, confirm, maxsign, NULL)) == 0) {
|
lifetime, confirm, maxsign, skprovider)) == 0) {
|
||||||
ret = 0;
|
ret = 0;
|
||||||
if (!qflag) {
|
if (!qflag) {
|
||||||
fprintf(stderr, "Identity added: %s (%s)\n",
|
fprintf(stderr, "Identity added: %s (%s)\n",
|
||||||
@ -364,7 +374,7 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag)
|
|||||||
sshkey_free(cert);
|
sshkey_free(cert);
|
||||||
|
|
||||||
if ((r = ssh_add_identity_constrained(agent_fd, private, comment,
|
if ((r = ssh_add_identity_constrained(agent_fd, private, comment,
|
||||||
lifetime, confirm, maxsign, NULL)) != 0) {
|
lifetime, confirm, maxsign, skprovider)) != 0) {
|
||||||
error("Certificate %s (%s) add failed: %s", certpath,
|
error("Certificate %s (%s) add failed: %s", certpath,
|
||||||
private->cert->key_id, ssh_err(r));
|
private->cert->key_id, ssh_err(r));
|
||||||
goto out;
|
goto out;
|
||||||
@ -529,13 +539,14 @@ lock_agent(int agent_fd, int lock)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
do_file(int agent_fd, int deleting, int key_only, char *file, int qflag)
|
do_file(int agent_fd, int deleting, int key_only, char *file, int qflag,
|
||||||
|
const char *skprovider)
|
||||||
{
|
{
|
||||||
if (deleting) {
|
if (deleting) {
|
||||||
if (delete_file(agent_fd, file, key_only, qflag) == -1)
|
if (delete_file(agent_fd, file, key_only, qflag) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
if (add_file(agent_fd, file, key_only, qflag) == -1)
|
if (add_file(agent_fd, file, key_only, qflag, skprovider) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -561,6 +572,7 @@ usage(void)
|
|||||||
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, " -T pubkey Test if ssh-agent can access matching private key.\n");
|
||||||
|
fprintf(stderr, " -S provider Specify security key provider.\n");
|
||||||
fprintf(stderr, " -q Be quiet after a successful operation.\n");
|
fprintf(stderr, " -q Be quiet after a successful operation.\n");
|
||||||
fprintf(stderr, " -v Be more verbose.\n");
|
fprintf(stderr, " -v Be more verbose.\n");
|
||||||
}
|
}
|
||||||
@ -571,7 +583,7 @@ main(int argc, char **argv)
|
|||||||
extern char *optarg;
|
extern char *optarg;
|
||||||
extern int optind;
|
extern int optind;
|
||||||
int agent_fd;
|
int agent_fd;
|
||||||
char *pkcs11provider = NULL;
|
char *pkcs11provider = NULL, *skprovider = 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, Tflag = 0;
|
int xflag = 0, lflag = 0, Dflag = 0, qflag = 0, Tflag = 0;
|
||||||
SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
|
SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
|
||||||
@ -600,7 +612,9 @@ main(int argc, char **argv)
|
|||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((ch = getopt(argc, argv, "vklLcdDTxXE:e:M:m:qs:t:")) != -1) {
|
skprovider = getenv("SSH_SK_PROVIDER");
|
||||||
|
|
||||||
|
while ((ch = getopt(argc, argv, "vklLcdDTxXE:e:M:m:qs:S:t:")) != -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'v':
|
case 'v':
|
||||||
if (log_level == SYSLOG_LEVEL_INFO)
|
if (log_level == SYSLOG_LEVEL_INFO)
|
||||||
@ -656,6 +670,9 @@ main(int argc, char **argv)
|
|||||||
case 's':
|
case 's':
|
||||||
pkcs11provider = optarg;
|
pkcs11provider = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 'S':
|
||||||
|
skprovider = optarg;
|
||||||
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
deleting = 1;
|
deleting = 1;
|
||||||
pkcs11provider = optarg;
|
pkcs11provider = optarg;
|
||||||
@ -732,7 +749,7 @@ main(int argc, char **argv)
|
|||||||
if (stat(buf, &st) == -1)
|
if (stat(buf, &st) == -1)
|
||||||
continue;
|
continue;
|
||||||
if (do_file(agent_fd, deleting, key_only, buf,
|
if (do_file(agent_fd, deleting, key_only, buf,
|
||||||
qflag) == -1)
|
qflag, skprovider) == -1)
|
||||||
ret = 1;
|
ret = 1;
|
||||||
else
|
else
|
||||||
count++;
|
count++;
|
||||||
@ -742,7 +759,7 @@ main(int argc, char **argv)
|
|||||||
} else {
|
} else {
|
||||||
for (i = 0; i < argc; i++) {
|
for (i = 0; i < argc; i++) {
|
||||||
if (do_file(agent_fd, deleting, key_only,
|
if (do_file(agent_fd, deleting, key_only,
|
||||||
argv[i], qflag) == -1)
|
argv[i], qflag, skprovider) == -1)
|
||||||
ret = 1;
|
ret = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user