mirror of
git://anongit.mindrot.org/openssh.git
synced 2025-02-16 22:06:55 +00:00
upstream: use ssh-sk-helper for all security key signing operations
This extracts and refactors the client interface for ssh-sk-helper from ssh-agent and generalises it for use by the other programs. This means that most OpenSSH tools no longer need to link against libfido2 or directly interact with /dev/uhid* requested by, feedback and ok markus@ OpenBSD-Commit-ID: 1abcd3aea9a7460eccfbf8ca154cdfa62f1dc93f
This commit is contained in:
parent
c33d46868c
commit
b52ec0ba39
160
ssh-agent.c
160
ssh-agent.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: ssh-agent.c,v 1.250 2019/11/19 16:02:32 jmc Exp $ */
|
||||
/* $OpenBSD: ssh-agent.c,v 1.251 2019/12/13 19:09:10 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -90,7 +90,7 @@
|
||||
#include "ssherr.h"
|
||||
#include "pathnames.h"
|
||||
#include "ssh-pkcs11.h"
|
||||
#include "ssh-sk.h"
|
||||
#include "sk-api.h"
|
||||
|
||||
#ifndef DEFAULT_PROVIDER_WHITELIST
|
||||
# define DEFAULT_PROVIDER_WHITELIST "/usr/lib*/*,/usr/local/lib*/*"
|
||||
@ -282,130 +282,6 @@ agent_decode_alg(struct sshkey *key, u_int flags)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
provider_sign(const char *provider, struct sshkey *key,
|
||||
u_char **sigp, size_t *lenp,
|
||||
const u_char *data, size_t datalen,
|
||||
const char *alg, u_int compat)
|
||||
{
|
||||
int status, pair[2], r = SSH_ERR_INTERNAL_ERROR;
|
||||
pid_t pid;
|
||||
char *helper, *verbosity = NULL, *fp = NULL;
|
||||
struct sshbuf *kbuf, *req, *resp;
|
||||
u_char version;
|
||||
struct notifier_ctx *notifier = NULL;
|
||||
|
||||
debug3("%s: start for provider %s", __func__, provider);
|
||||
|
||||
*sigp = NULL;
|
||||
*lenp = 0;
|
||||
|
||||
helper = getenv("SSH_SK_HELPER");
|
||||
if (helper == NULL || strlen(helper) == 0)
|
||||
helper = _PATH_SSH_SK_HELPER;
|
||||
if (log_level_get() >= SYSLOG_LEVEL_DEBUG1)
|
||||
verbosity = "-vvv";
|
||||
|
||||
/* Start helper */
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) {
|
||||
error("socketpair: %s", strerror(errno));
|
||||
return SSH_ERR_SYSTEM_ERROR;
|
||||
}
|
||||
if ((pid = fork()) == -1) {
|
||||
error("fork: %s", strerror(errno));
|
||||
close(pair[0]);
|
||||
close(pair[1]);
|
||||
return SSH_ERR_SYSTEM_ERROR;
|
||||
}
|
||||
if (pid == 0) {
|
||||
if ((dup2(pair[1], STDIN_FILENO) == -1) ||
|
||||
(dup2(pair[1], STDOUT_FILENO) == -1))
|
||||
fatal("%s: dup2: %s", __func__, ssh_err(r));
|
||||
close(pair[0]);
|
||||
close(pair[1]);
|
||||
closefrom(STDERR_FILENO + 1);
|
||||
debug("%s: starting %s %s", __func__, helper,
|
||||
verbosity == NULL ? "" : verbosity);
|
||||
execlp(helper, helper, verbosity, (char *)NULL);
|
||||
fatal("%s: execlp: %s", __func__, strerror(errno));
|
||||
}
|
||||
close(pair[1]);
|
||||
|
||||
if ((kbuf = sshbuf_new()) == NULL ||
|
||||
(req = sshbuf_new()) == NULL ||
|
||||
(resp = sshbuf_new()) == NULL)
|
||||
fatal("%s: sshbuf_new failed", __func__);
|
||||
|
||||
if ((r = sshkey_private_serialize(key, kbuf)) != 0 ||
|
||||
(r = sshbuf_put_stringb(req, kbuf)) != 0 ||
|
||||
(r = sshbuf_put_cstring(req, provider)) != 0 ||
|
||||
(r = sshbuf_put_string(req, data, datalen)) != 0 ||
|
||||
(r = sshbuf_put_u32(req, compat)) != 0)
|
||||
fatal("%s: compose: %s", __func__, ssh_err(r));
|
||||
|
||||
if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT,
|
||||
SSH_FP_DEFAULT)) == NULL)
|
||||
fatal("%s: sshkey_fingerprint failed", __func__);
|
||||
notifier = notify_start(0,
|
||||
"Confirm user presence for key %s %s", sshkey_type(key), fp);
|
||||
|
||||
if ((r = ssh_msg_send(pair[0], SSH_SK_HELPER_VERSION, req)) != 0) {
|
||||
error("%s: send: %s", __func__, ssh_err(r));
|
||||
goto out;
|
||||
}
|
||||
if ((r = ssh_msg_recv(pair[0], resp)) != 0) {
|
||||
error("%s: receive: %s", __func__, ssh_err(r));
|
||||
goto out;
|
||||
}
|
||||
if ((r = sshbuf_get_u8(resp, &version)) != 0) {
|
||||
error("%s: parse version: %s", __func__, ssh_err(r));
|
||||
goto out;
|
||||
}
|
||||
if (version != SSH_SK_HELPER_VERSION) {
|
||||
error("%s: unsupported version: got %u, expected %u",
|
||||
__func__, version, SSH_SK_HELPER_VERSION);
|
||||
r = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
if ((r = sshbuf_get_string(resp, sigp, lenp)) != 0) {
|
||||
error("%s: parse signature: %s", __func__, ssh_err(r));
|
||||
r = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
if (sshbuf_len(resp) != 0) {
|
||||
error("%s: trailing data in response", __func__);
|
||||
r = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
/* success */
|
||||
r = 0;
|
||||
out:
|
||||
while (waitpid(pid, &status, 0) == -1) {
|
||||
if (errno != EINTR)
|
||||
fatal("%s: waitpid: %s", __func__, ssh_err(r));
|
||||
}
|
||||
notify_complete(notifier);
|
||||
if (!WIFEXITED(status)) {
|
||||
error("%s: helper %s exited abnormally", __func__, helper);
|
||||
if (r == 0)
|
||||
r = SSH_ERR_SYSTEM_ERROR;
|
||||
} else if (WEXITSTATUS(status) != 0) {
|
||||
error("%s: helper %s exited with non-zero exit status",
|
||||
__func__, helper);
|
||||
if (r == 0)
|
||||
r = SSH_ERR_SYSTEM_ERROR;
|
||||
}
|
||||
if (r != 0) {
|
||||
freezero(*sigp, *lenp);
|
||||
*sigp = NULL;
|
||||
*lenp = 0;
|
||||
}
|
||||
sshbuf_free(kbuf);
|
||||
sshbuf_free(req);
|
||||
sshbuf_free(resp);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* ssh2 only */
|
||||
static void
|
||||
process_sign_request2(SocketEntry *e)
|
||||
@ -415,9 +291,11 @@ process_sign_request2(SocketEntry *e)
|
||||
size_t dlen, slen = 0;
|
||||
u_int compat = 0, flags;
|
||||
int r, ok = -1;
|
||||
char *fp = NULL;
|
||||
struct sshbuf *msg;
|
||||
struct sshkey *key = NULL;
|
||||
struct identity *id;
|
||||
struct notifier_ctx *notifier = NULL;
|
||||
|
||||
if ((msg = sshbuf_new()) == NULL)
|
||||
fatal("%s: sshbuf_new failed", __func__);
|
||||
@ -436,25 +314,27 @@ process_sign_request2(SocketEntry *e)
|
||||
verbose("%s: user refused key", __func__);
|
||||
goto send;
|
||||
}
|
||||
if (id->sk_provider != NULL) {
|
||||
if ((r = provider_sign(id->sk_provider, id->key, &signature,
|
||||
&slen, data, dlen, agent_decode_alg(key, flags),
|
||||
compat)) != 0) {
|
||||
error("%s: sign: %s", __func__, ssh_err(r));
|
||||
goto send;
|
||||
}
|
||||
} else {
|
||||
if ((r = sshkey_sign(id->key, &signature, &slen,
|
||||
data, dlen, agent_decode_alg(key, flags),
|
||||
NULL, compat)) != 0) {
|
||||
error("%s: sshkey_sign: %s", __func__, ssh_err(r));
|
||||
goto send;
|
||||
}
|
||||
if (sshkey_is_sk(id->key) &&
|
||||
(id->key->sk_flags & SSH_SK_USER_PRESENCE_REQD)) {
|
||||
if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT,
|
||||
SSH_FP_DEFAULT)) == NULL)
|
||||
fatal("%s: fingerprint failed", __func__);
|
||||
notifier = notify_start(0,
|
||||
"Confirm user presence for key %s %s",
|
||||
sshkey_type(id->key), fp);
|
||||
}
|
||||
if ((r = sshkey_sign(id->key, &signature, &slen,
|
||||
data, dlen, agent_decode_alg(key, flags),
|
||||
id->sk_provider, compat)) != 0) {
|
||||
error("%s: sshkey_sign: %s", __func__, ssh_err(r));
|
||||
goto send;
|
||||
}
|
||||
/* Success */
|
||||
ok = 0;
|
||||
send:
|
||||
notify_complete(notifier);
|
||||
sshkey_free(key);
|
||||
free(fp);
|
||||
if (ok == 0) {
|
||||
if ((r = sshbuf_put_u8(msg, SSH2_AGENT_SIGN_RESPONSE)) != 0 ||
|
||||
(r = sshbuf_put_string(msg, signature, slen)) != 0)
|
||||
|
4
ssh-sk.c
4
ssh-sk.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: ssh-sk.c,v 1.17 2019/11/27 22:32:11 djm Exp $ */
|
||||
/* $OpenBSD: ssh-sk.c,v 1.18 2019/12/13 19:09:10 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2019 Google LLC
|
||||
*
|
||||
@ -464,7 +464,7 @@ sshsk_ed25519_sig(struct sk_sign_response *resp, struct sshbuf *sig)
|
||||
}
|
||||
|
||||
int
|
||||
sshsk_sign(const char *provider_path, const struct sshkey *key,
|
||||
sshsk_sign(const char *provider_path, struct sshkey *key,
|
||||
u_char **sigp, size_t *lenp, const u_char *data, size_t datalen,
|
||||
u_int compat)
|
||||
{
|
||||
|
7
ssh-sk.h
7
ssh-sk.h
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: ssh-sk.h,v 1.5 2019/11/12 19:31:45 markus Exp $ */
|
||||
/* $OpenBSD: ssh-sk.h,v 1.6 2019/12/13 19:09:10 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2019 Google LLC
|
||||
*
|
||||
@ -21,9 +21,6 @@
|
||||
struct sshbuf;
|
||||
struct sshkey;
|
||||
|
||||
/* Version of protocol between ssh-agent and ssh-sk-helper */
|
||||
#define SSH_SK_HELPER_VERSION 1
|
||||
|
||||
/*
|
||||
* Enroll (generate) a new security-key hosted private key of given type
|
||||
* via the specified provider middleware.
|
||||
@ -44,7 +41,7 @@ int sshsk_enroll(int type, const char *provider_path, const char *application,
|
||||
*
|
||||
* Returns 0 on success or a ssherr.h error code on failure.
|
||||
*/
|
||||
int sshsk_sign(const char *provider_path, const struct sshkey *key,
|
||||
int sshsk_sign(const char *provider_path, struct sshkey *key,
|
||||
u_char **sigp, size_t *lenp, const u_char *data, size_t datalen,
|
||||
u_int compat);
|
||||
|
||||
|
15
sshkey.c
15
sshkey.c
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: sshkey.c,v 1.96 2019/11/25 00:51:37 djm Exp $ */
|
||||
/* $OpenBSD: sshkey.c,v 1.97 2019/12/13 19:09:10 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||
* Copyright (c) 2008 Alexander von Gernler. All rights reserved.
|
||||
@ -2750,13 +2750,6 @@ sshkey_sign(struct sshkey *key,
|
||||
case KEY_ECDSA:
|
||||
r = ssh_ecdsa_sign(key, sigp, lenp, data, datalen, compat);
|
||||
break;
|
||||
# ifdef ENABLE_SK
|
||||
case KEY_ECDSA_SK_CERT:
|
||||
case KEY_ECDSA_SK:
|
||||
r = sshsk_sign(sk_provider, key, sigp, lenp, data, datalen,
|
||||
compat);
|
||||
break;
|
||||
# endif /* ENABLE_SK */
|
||||
# endif /* OPENSSL_HAS_ECC */
|
||||
case KEY_RSA_CERT:
|
||||
case KEY_RSA:
|
||||
@ -2770,8 +2763,10 @@ sshkey_sign(struct sshkey *key,
|
||||
#ifdef ENABLE_SK
|
||||
case KEY_ED25519_SK:
|
||||
case KEY_ED25519_SK_CERT:
|
||||
r = sshsk_sign(sk_provider, key, sigp, lenp, data, datalen,
|
||||
compat);
|
||||
case KEY_ECDSA_SK_CERT:
|
||||
case KEY_ECDSA_SK:
|
||||
r = sshsk_sign(sk_provider, key, sigp, lenp, data,
|
||||
datalen, compat);
|
||||
break;
|
||||
#endif /* ENABLE_SK */
|
||||
#ifdef WITH_XMSS
|
||||
|
5
sshkey.h
5
sshkey.h
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: sshkey.h,v 1.40 2019/11/25 00:51:37 djm Exp $ */
|
||||
/* $OpenBSD: sshkey.h,v 1.41 2019/12/13 19:09:10 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||
@ -51,6 +51,9 @@
|
||||
#define SSH_RSA_MINIMUM_MODULUS_SIZE 1024
|
||||
#define SSH_KEY_MAX_SIGN_DATA_SIZE (1 << 20)
|
||||
|
||||
/* Version of protocol expected from ssh-sk-helper */
|
||||
#define SSH_SK_HELPER_VERSION 1
|
||||
|
||||
struct sshbuf;
|
||||
|
||||
/* Key types */
|
||||
|
Loading…
Reference in New Issue
Block a user