mirror of
https://github.com/PowerShell/openssh-portable.git
synced 2025-07-31 01:35:11 +02:00
upstream commit
switch ssh-keyscan from setjmp to multiple ssh transport layer instances ok djm@
This commit is contained in:
parent
f582f0e917
commit
3f79765374
149
ssh-keyscan.c
149
ssh-keyscan.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: ssh-keyscan.c,v 1.94 2015/01/19 20:16:15 markus Exp $ */
|
/* $OpenBSD: ssh-keyscan.c,v 1.95 2015/01/19 20:32:39 markus Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>.
|
* Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>.
|
||||||
*
|
*
|
||||||
@ -24,7 +24,6 @@
|
|||||||
|
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <setjmp.h>
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -35,8 +34,8 @@
|
|||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
#include "ssh1.h"
|
#include "ssh1.h"
|
||||||
#include "buffer.h"
|
#include "sshbuf.h"
|
||||||
#include "key.h"
|
#include "sshkey.h"
|
||||||
#include "cipher.h"
|
#include "cipher.h"
|
||||||
#include "kex.h"
|
#include "kex.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
@ -47,6 +46,8 @@
|
|||||||
#include "atomicio.h"
|
#include "atomicio.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "hostfile.h"
|
#include "hostfile.h"
|
||||||
|
#include "ssherr.h"
|
||||||
|
#include "ssh_api.h"
|
||||||
|
|
||||||
/* Flag indicating whether IPv4 or IPv6. This can be set on the command line.
|
/* Flag indicating whether IPv4 or IPv6. This can be set on the command line.
|
||||||
Default value is AF_UNSPEC means both IPv4 and IPv6. */
|
Default value is AF_UNSPEC means both IPv4 and IPv6. */
|
||||||
@ -76,9 +77,6 @@ extern char *__progname;
|
|||||||
fd_set *read_wait;
|
fd_set *read_wait;
|
||||||
size_t read_wait_nfdset;
|
size_t read_wait_nfdset;
|
||||||
int ncon;
|
int ncon;
|
||||||
int nonfatal_fatal = 0;
|
|
||||||
jmp_buf kexjmp;
|
|
||||||
Key *kexjmp_key;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Keep a connection structure for each file descriptor. The state
|
* Keep a connection structure for each file descriptor. The state
|
||||||
@ -95,12 +93,13 @@ typedef struct Connection {
|
|||||||
int c_len; /* Total bytes which must be read. */
|
int c_len; /* Total bytes which must be read. */
|
||||||
int c_off; /* Length of data read so far. */
|
int c_off; /* Length of data read so far. */
|
||||||
int c_keytype; /* Only one of KT_RSA1, KT_DSA, or KT_RSA */
|
int c_keytype; /* Only one of KT_RSA1, KT_DSA, or KT_RSA */
|
||||||
|
int c_done; /* SSH2 done */
|
||||||
char *c_namebase; /* Address to free for c_name and c_namelist */
|
char *c_namebase; /* Address to free for c_name and c_namelist */
|
||||||
char *c_name; /* Hostname of connection for errors */
|
char *c_name; /* Hostname of connection for errors */
|
||||||
char *c_namelist; /* Pointer to other possible addresses */
|
char *c_namelist; /* Pointer to other possible addresses */
|
||||||
char *c_output_name; /* Hostname of connection for output */
|
char *c_output_name; /* Hostname of connection for output */
|
||||||
char *c_data; /* Data read from this fd */
|
char *c_data; /* Data read from this fd */
|
||||||
struct kex *c_kex; /* The key-exchange struct for ssh2 */
|
struct ssh *c_ssh; /* SSH-connection */
|
||||||
struct timeval c_tv; /* Time at which connection gets aborted */
|
struct timeval c_tv; /* Time at which connection gets aborted */
|
||||||
TAILQ_ENTRY(Connection) c_link; /* List of connections in timeout order. */
|
TAILQ_ENTRY(Connection) c_link; /* List of connections in timeout order. */
|
||||||
} con;
|
} con;
|
||||||
@ -108,6 +107,8 @@ typedef struct Connection {
|
|||||||
TAILQ_HEAD(conlist, Connection) tq; /* Timeout Queue */
|
TAILQ_HEAD(conlist, Connection) tq; /* Timeout Queue */
|
||||||
con *fdcon;
|
con *fdcon;
|
||||||
|
|
||||||
|
static void keyprint(con *c, struct sshkey *key);
|
||||||
|
|
||||||
static int
|
static int
|
||||||
fdlim_get(int hard)
|
fdlim_get(int hard)
|
||||||
{
|
{
|
||||||
@ -185,46 +186,61 @@ strnnsep(char **stringp, char *delim)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_SSH1
|
#ifdef WITH_SSH1
|
||||||
static Key *
|
static struct sshkey *
|
||||||
keygrab_ssh1(con *c)
|
keygrab_ssh1(con *c)
|
||||||
{
|
{
|
||||||
static Key *rsa;
|
static struct sshkey *rsa;
|
||||||
static Buffer msg;
|
static struct sshbuf *msg;
|
||||||
|
int r;
|
||||||
|
u_char type;
|
||||||
|
|
||||||
if (rsa == NULL) {
|
if (rsa == NULL) {
|
||||||
buffer_init(&msg);
|
if ((rsa = sshkey_new(KEY_RSA1)) == NULL) {
|
||||||
rsa = key_new(KEY_RSA1);
|
error("%s: sshkey_new failed", __func__);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if ((msg = sshbuf_new()) == NULL)
|
||||||
|
fatal("%s: sshbuf_new failed", __func__);
|
||||||
}
|
}
|
||||||
buffer_append(&msg, c->c_data, c->c_plen);
|
if ((r = sshbuf_put(msg, c->c_data, c->c_plen)) != 0 ||
|
||||||
buffer_consume(&msg, 8 - (c->c_plen & 7)); /* padding */
|
(r = sshbuf_consume(msg, 8 - (c->c_plen & 7))) != 0 || /* padding */
|
||||||
if (buffer_get_char(&msg) != (int) SSH_SMSG_PUBLIC_KEY) {
|
(r = sshbuf_get_u8(msg, &type)) != 0)
|
||||||
|
goto buf_err;
|
||||||
|
if (type != (int) SSH_SMSG_PUBLIC_KEY) {
|
||||||
error("%s: invalid packet type", c->c_name);
|
error("%s: invalid packet type", c->c_name);
|
||||||
buffer_clear(&msg);
|
sshbuf_reset(msg);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if ((r = sshbuf_consume(msg, 8)) != 0 || /* cookie */
|
||||||
|
/* server key */
|
||||||
|
(r = sshbuf_get_u32(msg, NULL)) != 0 ||
|
||||||
|
(r = sshbuf_get_bignum1(msg, NULL)) != 0 ||
|
||||||
|
(r = sshbuf_get_bignum1(msg, NULL)) != 0 ||
|
||||||
|
/* host key */
|
||||||
|
(r = sshbuf_get_u32(msg, NULL)) != 0 ||
|
||||||
|
(r = sshbuf_get_bignum1(msg, rsa->rsa->e)) != 0 ||
|
||||||
|
(r = sshbuf_get_bignum1(msg, rsa->rsa->n)) != 0) {
|
||||||
|
buf_err:
|
||||||
|
error("%s: buffer error: %s", __func__, ssh_err(r));
|
||||||
|
sshbuf_reset(msg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
buffer_consume(&msg, 8); /* cookie */
|
|
||||||
|
|
||||||
/* server key */
|
sshbuf_reset(msg);
|
||||||
(void) buffer_get_int(&msg);
|
|
||||||
buffer_get_bignum(&msg, rsa->rsa->e);
|
|
||||||
buffer_get_bignum(&msg, rsa->rsa->n);
|
|
||||||
|
|
||||||
/* host key */
|
|
||||||
(void) buffer_get_int(&msg);
|
|
||||||
buffer_get_bignum(&msg, rsa->rsa->e);
|
|
||||||
buffer_get_bignum(&msg, rsa->rsa->n);
|
|
||||||
|
|
||||||
buffer_clear(&msg);
|
|
||||||
|
|
||||||
return (rsa);
|
return (rsa);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int
|
static int
|
||||||
hostjump(Key *hostkey, struct ssh *ssh)
|
key_print_wrapper(struct sshkey *hostkey, struct ssh *ssh)
|
||||||
{
|
{
|
||||||
kexjmp_key = hostkey;
|
con *c;
|
||||||
longjmp(kexjmp, 1);
|
|
||||||
|
if ((c = ssh_get_app_data(ssh)) != NULL)
|
||||||
|
keyprint(c, hostkey);
|
||||||
|
/* always abort key exchange */
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -243,48 +259,41 @@ ssh2_capable(int remote_major, int remote_minor)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Key *
|
static void
|
||||||
keygrab_ssh2(con *c)
|
keygrab_ssh2(con *c)
|
||||||
{
|
{
|
||||||
char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
|
char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
|
||||||
int r, j;
|
int r;
|
||||||
|
|
||||||
packet_set_connection(c->c_fd, c->c_fd);
|
|
||||||
enable_compat20();
|
enable_compat20();
|
||||||
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
|
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
|
||||||
c->c_keytype == KT_DSA ? "ssh-dss" :
|
c->c_keytype == KT_DSA ? "ssh-dss" :
|
||||||
(c->c_keytype == KT_RSA ? "ssh-rsa" :
|
(c->c_keytype == KT_RSA ? "ssh-rsa" :
|
||||||
(c->c_keytype == KT_ED25519 ? "ssh-ed25519" :
|
(c->c_keytype == KT_ED25519 ? "ssh-ed25519" :
|
||||||
"ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521"));
|
"ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521"));
|
||||||
if ((r = kex_setup(active_state, myproposal)) < 0)
|
if ((r = kex_setup(c->c_ssh, myproposal)) != 0) {
|
||||||
fatal("%s: kex_setup: %s", __func__, ssh_err(r));
|
free(c->c_ssh);
|
||||||
c->c_kex = active_state->kex;
|
fprintf(stderr, "kex_setup: %s\n", ssh_err(r));
|
||||||
#ifdef WITH_OPENSSL
|
|
||||||
c->c_kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
|
|
||||||
c->c_kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
|
|
||||||
c->c_kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
|
|
||||||
c->c_kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
|
|
||||||
c->c_kex->kex[KEX_ECDH_SHA2] = kexecdh_client;
|
|
||||||
#endif
|
|
||||||
c->c_kex->kex[KEX_C25519_SHA256] = kexc25519_client;
|
|
||||||
c->c_kex->verify_host_key = hostjump;
|
|
||||||
|
|
||||||
if (!(j = setjmp(kexjmp))) {
|
|
||||||
nonfatal_fatal = 1;
|
|
||||||
dispatch_run(DISPATCH_BLOCK, &c->c_kex->done, active_state);
|
|
||||||
fprintf(stderr, "Impossible! dispatch_run() returned!\n");
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
nonfatal_fatal = 0;
|
#ifdef WITH_OPENSSL
|
||||||
free(c->c_kex);
|
c->c_ssh->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
|
||||||
c->c_kex = NULL;
|
c->c_ssh->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
|
||||||
packet_close();
|
c->c_ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
|
||||||
|
c->c_ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
|
||||||
return j < 0? NULL : kexjmp_key;
|
c->c_ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_client;
|
||||||
|
#endif
|
||||||
|
c->c_ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_client;
|
||||||
|
ssh_set_verify_host_key_callback(c->c_ssh, key_print_wrapper);
|
||||||
|
/*
|
||||||
|
* do the key-exchange until an error occurs or until
|
||||||
|
* the key_print_wrapper() callback sets c_done.
|
||||||
|
*/
|
||||||
|
ssh_dispatch_run(c->c_ssh, DISPATCH_BLOCK, &c->c_done, c->c_ssh);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
keyprint(con *c, Key *key)
|
keyprint(con *c, struct sshkey *key)
|
||||||
{
|
{
|
||||||
char *host = c->c_output_name ? c->c_output_name : c->c_name;
|
char *host = c->c_output_name ? c->c_output_name : c->c_name;
|
||||||
|
|
||||||
@ -294,7 +303,7 @@ keyprint(con *c, Key *key)
|
|||||||
fatal("host_hash failed");
|
fatal("host_hash failed");
|
||||||
|
|
||||||
fprintf(stdout, "%s ", host);
|
fprintf(stdout, "%s ", host);
|
||||||
key_write(key, stdout);
|
sshkey_write(key, stdout);
|
||||||
fputs("\n", stdout);
|
fputs("\n", stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -382,6 +391,11 @@ confree(int s)
|
|||||||
free(fdcon[s].c_data);
|
free(fdcon[s].c_data);
|
||||||
fdcon[s].c_status = CS_UNUSED;
|
fdcon[s].c_status = CS_UNUSED;
|
||||||
fdcon[s].c_keytype = 0;
|
fdcon[s].c_keytype = 0;
|
||||||
|
if (fdcon[s].c_ssh) {
|
||||||
|
ssh_packet_close(fdcon[s].c_ssh);
|
||||||
|
free(fdcon[s].c_ssh);
|
||||||
|
fdcon[s].c_ssh = NULL;
|
||||||
|
}
|
||||||
TAILQ_REMOVE(&tq, &fdcon[s], c_link);
|
TAILQ_REMOVE(&tq, &fdcon[s], c_link);
|
||||||
FD_CLR(s, read_wait);
|
FD_CLR(s, read_wait);
|
||||||
ncon--;
|
ncon--;
|
||||||
@ -449,11 +463,13 @@ congreet(int s)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*cp = '\0';
|
*cp = '\0';
|
||||||
|
c->c_ssh = ssh_packet_set_connection(NULL, s, s);
|
||||||
|
ssh_set_app_data(c->c_ssh, c); /* back link */
|
||||||
if (sscanf(buf, "SSH-%d.%d-%[^\n]\n",
|
if (sscanf(buf, "SSH-%d.%d-%[^\n]\n",
|
||||||
&remote_major, &remote_minor, remote_version) == 3)
|
&remote_major, &remote_minor, remote_version) == 3)
|
||||||
compat_datafellows(remote_version);
|
c->c_ssh->compat = compat_datafellows(remote_version);
|
||||||
else
|
else
|
||||||
datafellows = 0;
|
c->c_ssh->compat = 0;
|
||||||
if (c->c_keytype != KT_RSA1) {
|
if (c->c_keytype != KT_RSA1) {
|
||||||
if (!ssh2_capable(remote_major, remote_minor)) {
|
if (!ssh2_capable(remote_major, remote_minor)) {
|
||||||
debug("%s doesn't support ssh2", c->c_name);
|
debug("%s doesn't support ssh2", c->c_name);
|
||||||
@ -480,7 +496,7 @@ congreet(int s)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (c->c_keytype != KT_RSA1) {
|
if (c->c_keytype != KT_RSA1) {
|
||||||
keyprint(c, keygrab_ssh2(c));
|
keygrab_ssh2(c);
|
||||||
confree(s);
|
confree(s);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -606,10 +622,7 @@ fatal(const char *fmt,...)
|
|||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
do_log(SYSLOG_LEVEL_FATAL, fmt, args);
|
do_log(SYSLOG_LEVEL_FATAL, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
if (nonfatal_fatal)
|
exit(255);
|
||||||
longjmp(kexjmp, -1);
|
|
||||||
else
|
|
||||||
exit(255);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -682,7 +695,7 @@ main(int argc, char **argv)
|
|||||||
get_keytypes = 0;
|
get_keytypes = 0;
|
||||||
tname = strtok(optarg, ",");
|
tname = strtok(optarg, ",");
|
||||||
while (tname) {
|
while (tname) {
|
||||||
int type = key_type_from_name(tname);
|
int type = sshkey_type_from_name(tname);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case KEY_RSA1:
|
case KEY_RSA1:
|
||||||
get_keytypes |= KT_RSA1;
|
get_keytypes |= KT_RSA1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user