summaryrefslogtreecommitdiffstats
path: root/crypto/openssh/ssh-keysign.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/openssh/ssh-keysign.c')
-rw-r--r--crypto/openssh/ssh-keysign.c161
1 files changed, 99 insertions, 62 deletions
diff --git a/crypto/openssh/ssh-keysign.c b/crypto/openssh/ssh-keysign.c
index 6bde8ad..1dca3e2 100644
--- a/crypto/openssh/ssh-keysign.c
+++ b/crypto/openssh/ssh-keysign.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-keysign.c,v 1.39 2013/12/06 13:39:49 markus Exp $ */
+/* $OpenBSD: ssh-keysign.c,v 1.49 2015/07/03 03:56:25 djm Exp $ */
/*
* Copyright (c) 2002 Markus Friedl. All rights reserved.
*
@@ -35,23 +35,29 @@
#include <string.h>
#include <unistd.h>
+#ifdef WITH_OPENSSL
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/rsa.h>
+#endif
#include "xmalloc.h"
#include "log.h"
-#include "key.h"
+#include "sshkey.h"
#include "ssh.h"
#include "ssh2.h"
#include "misc.h"
-#include "buffer.h"
+#include "sshbuf.h"
#include "authfile.h"
#include "msg.h"
#include "canohost.h"
#include "pathnames.h"
#include "readconf.h"
#include "uidswap.h"
+#include "sshkey.h"
+#include "ssherr.h"
+
+struct ssh *active_state = NULL; /* XXX needed for linking */
/* XXX readconf.c needs these */
uid_t original_real_uid;
@@ -59,62 +65,73 @@ uid_t original_real_uid;
extern char *__progname;
static int
-valid_request(struct passwd *pw, char *host, Key **ret, u_char *data,
- u_int datalen)
+valid_request(struct passwd *pw, char *host, struct sshkey **ret,
+ u_char *data, size_t datalen)
{
- Buffer b;
- Key *key = NULL;
- u_char *pkblob;
- u_int blen, len;
- char *pkalg, *p;
- int pktype, fail;
-
+ struct sshbuf *b;
+ struct sshkey *key = NULL;
+ u_char type, *pkblob;
+ char *p;
+ size_t blen, len;
+ char *pkalg, *luser;
+ int r, pktype, fail;
+
+ if (ret != NULL)
+ *ret = NULL;
fail = 0;
- buffer_init(&b);
- buffer_append(&b, data, datalen);
+ if ((b = sshbuf_from(data, datalen)) == NULL)
+ fatal("%s: sshbuf_from failed", __func__);
/* session id, currently limited to SHA1 (20 bytes) or SHA256 (32) */
- p = buffer_get_string(&b, &len);
+ if ((r = sshbuf_get_string(b, NULL, &len)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (len != 20 && len != 32)
fail++;
- free(p);
- if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
+ if ((r = sshbuf_get_u8(b, &type)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ if (type != SSH2_MSG_USERAUTH_REQUEST)
fail++;
/* server user */
- buffer_skip_string(&b);
+ if ((r = sshbuf_skip_string(b)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
/* service */
- p = buffer_get_string(&b, NULL);
+ if ((r = sshbuf_get_cstring(b, &p, NULL)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (strcmp("ssh-connection", p) != 0)
fail++;
free(p);
/* method */
- p = buffer_get_string(&b, NULL);
+ if ((r = sshbuf_get_cstring(b, &p, NULL)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (strcmp("hostbased", p) != 0)
fail++;
free(p);
/* pubkey */
- pkalg = buffer_get_string(&b, NULL);
- pkblob = buffer_get_string(&b, &blen);
+ if ((r = sshbuf_get_cstring(b, &pkalg, NULL)) != 0 ||
+ (r = sshbuf_get_string(b, &pkblob, &blen)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
- pktype = key_type_from_name(pkalg);
+ pktype = sshkey_type_from_name(pkalg);
if (pktype == KEY_UNSPEC)
fail++;
- else if ((key = key_from_blob(pkblob, blen)) == NULL)
+ else if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) {
+ error("%s: bad key blob: %s", __func__, ssh_err(r));
fail++;
- else if (key->type != pktype)
+ } else if (key->type != pktype)
fail++;
free(pkalg);
free(pkblob);
/* client host name, handle trailing dot */
- p = buffer_get_string(&b, &len);
- debug2("valid_request: check expect chost %s got %s", host, p);
+ if ((r = sshbuf_get_cstring(b, &p, &len)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ debug2("%s: check expect chost %s got %s", __func__, host, p);
if (strlen(host) != len - 1)
fail++;
else if (p[len - 1] != '.')
@@ -124,22 +141,23 @@ valid_request(struct passwd *pw, char *host, Key **ret, u_char *data,
free(p);
/* local user */
- p = buffer_get_string(&b, NULL);
+ if ((r = sshbuf_get_cstring(b, &luser, NULL)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
- if (strcmp(pw->pw_name, p) != 0)
+ if (strcmp(pw->pw_name, luser) != 0)
fail++;
- free(p);
+ free(luser);
/* end of message */
- if (buffer_len(&b) != 0)
+ if (sshbuf_len(b) != 0)
fail++;
- buffer_free(&b);
+ sshbuf_free(b);
- debug3("valid_request: fail %d", fail);
+ debug3("%s: fail %d", __func__, fail);
if (fail && key != NULL)
- key_free(key);
- else
+ sshkey_free(key);
+ else if (ret != NULL)
*ret = key;
return (fail ? -1 : 0);
@@ -148,16 +166,18 @@ valid_request(struct passwd *pw, char *host, Key **ret, u_char *data,
int
main(int argc, char **argv)
{
- Buffer b;
+ struct sshbuf *b;
Options options;
#define NUM_KEYTYPES 4
- Key *keys[NUM_KEYTYPES], *key = NULL;
+ struct sshkey *keys[NUM_KEYTYPES], *key = NULL;
struct passwd *pw;
- int key_fd[NUM_KEYTYPES], i, found, version = 2, fd;
- u_char *signature, *data;
- char *host;
- u_int slen, dlen;
+ int r, key_fd[NUM_KEYTYPES], i, found, version = 2, fd;
+ u_char *signature, *data, rver;
+ char *host, *fp;
+ size_t slen, dlen;
+#ifdef WITH_OPENSSL
u_int32_t rnd[256];
+#endif
/* Ensure that stdin and stdout are connected */
if ((fd = open(_PATH_DEVNULL, O_RDWR)) < 2)
@@ -167,6 +187,7 @@ main(int argc, char **argv)
close(fd);
i = 0;
+ /* XXX This really needs to read sshd_config for the paths */
key_fd[i++] = open(_PATH_HOST_DSA_KEY_FILE, O_RDONLY);
key_fd[i++] = open(_PATH_HOST_ECDSA_KEY_FILE, O_RDONLY);
key_fd[i++] = open(_PATH_HOST_ED25519_KEY_FILE, O_RDONLY);
@@ -187,7 +208,7 @@ main(int argc, char **argv)
/* verify that ssh-keysign is enabled by the admin */
initialize_options(&options);
- (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, "", &options, 0);
+ (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, "", "", &options, 0);
fill_default_options(&options);
if (options.enable_ssh_keysign != 1)
fatal("ssh-keysign not enabled in %s",
@@ -200,37 +221,47 @@ main(int argc, char **argv)
if (found == 0)
fatal("could not open any host key");
+#ifdef WITH_OPENSSL
OpenSSL_add_all_algorithms();
- for (i = 0; i < 256; i++)
- rnd[i] = arc4random();
+ arc4random_buf(rnd, sizeof(rnd));
RAND_seed(rnd, sizeof(rnd));
+#endif
found = 0;
for (i = 0; i < NUM_KEYTYPES; i++) {
keys[i] = NULL;
if (key_fd[i] == -1)
continue;
- keys[i] = key_load_private_pem(key_fd[i], KEY_UNSPEC,
- NULL, NULL);
+ r = sshkey_load_private_type_fd(key_fd[i], KEY_UNSPEC,
+ NULL, &key, NULL);
close(key_fd[i]);
- if (keys[i] != NULL)
+ if (r != 0)
+ debug("parse key %d: %s", i, ssh_err(r));
+ else if (key != NULL) {
+ keys[i] = key;
found = 1;
+ }
}
if (!found)
fatal("no hostkey found");
- buffer_init(&b);
- if (ssh_msg_recv(STDIN_FILENO, &b) < 0)
+ if ((b = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if (ssh_msg_recv(STDIN_FILENO, b) < 0)
fatal("ssh_msg_recv failed");
- if (buffer_get_char(&b) != version)
- fatal("bad version");
- fd = buffer_get_int(&b);
- if ((fd == STDIN_FILENO) || (fd == STDOUT_FILENO))
+ if ((r = sshbuf_get_u8(b, &rver)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ if (rver != version)
+ fatal("bad version: received %d, expected %d", rver, version);
+ if ((r = sshbuf_get_u32(b, (u_int *)&fd)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ if (fd < 0 || fd == STDIN_FILENO || fd == STDOUT_FILENO)
fatal("bad fd");
if ((host = get_local_name(fd)) == NULL)
fatal("cannot get local name for fd");
- data = buffer_get_string(&b, &dlen);
+ if ((r = sshbuf_get_string(b, &data, &dlen)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (valid_request(pw, host, &key, data, dlen) < 0)
fatal("not a valid request");
free(host);
@@ -238,22 +269,28 @@ main(int argc, char **argv)
found = 0;
for (i = 0; i < NUM_KEYTYPES; i++) {
if (keys[i] != NULL &&
- key_equal_public(key, keys[i])) {
+ sshkey_equal_public(key, keys[i])) {
found = 1;
break;
}
}
- if (!found)
- fatal("no matching hostkey found");
+ if (!found) {
+ if ((fp = sshkey_fingerprint(key, options.fingerprint_hash,
+ SSH_FP_DEFAULT)) == NULL)
+ fatal("%s: sshkey_fingerprint failed", __func__);
+ fatal("no matching hostkey found for key %s %s",
+ sshkey_type(key), fp ? fp : "");
+ }
- if (key_sign(keys[i], &signature, &slen, data, dlen) != 0)
- fatal("key_sign failed");
+ if ((r = sshkey_sign(keys[i], &signature, &slen, data, dlen, 0)) != 0)
+ fatal("sshkey_sign failed: %s", ssh_err(r));
free(data);
/* send reply */
- buffer_clear(&b);
- buffer_put_string(&b, signature, slen);
- if (ssh_msg_send(STDOUT_FILENO, version, &b) == -1)
+ sshbuf_reset(b);
+ if ((r = sshbuf_put_string(b, signature, slen)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ if (ssh_msg_send(STDOUT_FILENO, version, b) == -1)
fatal("ssh_msg_send failed");
return (0);
OpenPOWER on IntegriCloud