summaryrefslogtreecommitdiff
path: root/ssh-agent.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2019-12-13 19:09:10 +0000
committerDamien Miller <djm@mindrot.org>2019-12-14 07:17:44 +1100
commitb52ec0ba3983859514aa7b57d6100fa9759fe696 (patch)
tree262c9a2ebc4e6972594f45ea75fc15e8ae3bfefb /ssh-agent.c
parentc33d46868c3d88e04a92610cdb429094aeeb5847 (diff)
downloadopenssh-git-b52ec0ba3983859514aa7b57d6100fa9759fe696.tar.gz
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
Diffstat (limited to 'ssh-agent.c')
-rw-r--r--ssh-agent.c160
1 files changed, 20 insertions, 140 deletions
diff --git a/ssh-agent.c b/ssh-agent.c
index 1d4b779f..09d12dc3 100644
--- a/ssh-agent.c
+++ b/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)