summaryrefslogtreecommitdiff
path: root/ssh-keyscan.c
diff options
context:
space:
mode:
authormarkus@openbsd.org <markus@openbsd.org>2015-01-19 20:32:39 +0000
committerDamien Miller <djm@mindrot.org>2015-01-20 09:24:11 +1100
commit3f797653748e7c2b037dacb57574c01d9ef3b4d3 (patch)
tree8328e3436767e33e6274be3eaa31474da9792bd2 /ssh-keyscan.c
parentf582f0e917bb0017b00944783cd5f408bf4b0b5e (diff)
upstream commit
switch ssh-keyscan from setjmp to multiple ssh transport layer instances ok djm@
Diffstat (limited to 'ssh-keyscan.c')
-rw-r--r--ssh-keyscan.c149
1 files changed, 81 insertions, 68 deletions
diff --git a/ssh-keyscan.c b/ssh-keyscan.c
index 223ac58f1..e02a3bbb1 100644
--- a/ssh-keyscan.c
+++ b/ssh-keyscan.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-keyscan.c,v 1.94 2015/01/19 20:16:15 markus Exp $ */ 1/* $OpenBSD: ssh-keyscan.c,v 1.95 2015/01/19 20:32:39 markus Exp $ */
2/* 2/*
3 * Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>. 3 * Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>.
4 * 4 *
@@ -24,7 +24,6 @@
24 24
25#include <netdb.h> 25#include <netdb.h>
26#include <errno.h> 26#include <errno.h>
27#include <setjmp.h>
28#include <stdarg.h> 27#include <stdarg.h>
29#include <stdio.h> 28#include <stdio.h>
30#include <stdlib.h> 29#include <stdlib.h>
@@ -35,8 +34,8 @@
35#include "xmalloc.h" 34#include "xmalloc.h"
36#include "ssh.h" 35#include "ssh.h"
37#include "ssh1.h" 36#include "ssh1.h"
38#include "buffer.h" 37#include "sshbuf.h"
39#include "key.h" 38#include "sshkey.h"
40#include "cipher.h" 39#include "cipher.h"
41#include "kex.h" 40#include "kex.h"
42#include "compat.h" 41#include "compat.h"
@@ -47,6 +46,8 @@
47#include "atomicio.h" 46#include "atomicio.h"
48#include "misc.h" 47#include "misc.h"
49#include "hostfile.h" 48#include "hostfile.h"
49#include "ssherr.h"
50#include "ssh_api.h"
50 51
51/* Flag indicating whether IPv4 or IPv6. This can be set on the command line. 52/* Flag indicating whether IPv4 or IPv6. This can be set on the command line.
52 Default value is AF_UNSPEC means both IPv4 and IPv6. */ 53 Default value is AF_UNSPEC means both IPv4 and IPv6. */
@@ -76,9 +77,6 @@ extern char *__progname;
76fd_set *read_wait; 77fd_set *read_wait;
77size_t read_wait_nfdset; 78size_t read_wait_nfdset;
78int ncon; 79int ncon;
79int nonfatal_fatal = 0;
80jmp_buf kexjmp;
81Key *kexjmp_key;
82 80
83/* 81/*
84 * Keep a connection structure for each file descriptor. The state 82 * Keep a connection structure for each file descriptor. The state
@@ -95,12 +93,13 @@ typedef struct Connection {
95 int c_len; /* Total bytes which must be read. */ 93 int c_len; /* Total bytes which must be read. */
96 int c_off; /* Length of data read so far. */ 94 int c_off; /* Length of data read so far. */
97 int c_keytype; /* Only one of KT_RSA1, KT_DSA, or KT_RSA */ 95 int c_keytype; /* Only one of KT_RSA1, KT_DSA, or KT_RSA */
96 int c_done; /* SSH2 done */
98 char *c_namebase; /* Address to free for c_name and c_namelist */ 97 char *c_namebase; /* Address to free for c_name and c_namelist */
99 char *c_name; /* Hostname of connection for errors */ 98 char *c_name; /* Hostname of connection for errors */
100 char *c_namelist; /* Pointer to other possible addresses */ 99 char *c_namelist; /* Pointer to other possible addresses */
101 char *c_output_name; /* Hostname of connection for output */ 100 char *c_output_name; /* Hostname of connection for output */
102 char *c_data; /* Data read from this fd */ 101 char *c_data; /* Data read from this fd */
103 struct kex *c_kex; /* The key-exchange struct for ssh2 */ 102 struct ssh *c_ssh; /* SSH-connection */
104 struct timeval c_tv; /* Time at which connection gets aborted */ 103 struct timeval c_tv; /* Time at which connection gets aborted */
105 TAILQ_ENTRY(Connection) c_link; /* List of connections in timeout order. */ 104 TAILQ_ENTRY(Connection) c_link; /* List of connections in timeout order. */
106} con; 105} con;
@@ -108,6 +107,8 @@ typedef struct Connection {
108TAILQ_HEAD(conlist, Connection) tq; /* Timeout Queue */ 107TAILQ_HEAD(conlist, Connection) tq; /* Timeout Queue */
109con *fdcon; 108con *fdcon;
110 109
110static void keyprint(con *c, struct sshkey *key);
111
111static int 112static int
112fdlim_get(int hard) 113fdlim_get(int hard)
113{ 114{
@@ -185,46 +186,61 @@ strnnsep(char **stringp, char *delim)
185} 186}
186 187
187#ifdef WITH_SSH1 188#ifdef WITH_SSH1
188static Key * 189static struct sshkey *
189keygrab_ssh1(con *c) 190keygrab_ssh1(con *c)
190{ 191{
191 static Key *rsa; 192 static struct sshkey *rsa;
192 static Buffer msg; 193 static struct sshbuf *msg;
194 int r;
195 u_char type;
193 196
194 if (rsa == NULL) { 197 if (rsa == NULL) {
195 buffer_init(&msg); 198 if ((rsa = sshkey_new(KEY_RSA1)) == NULL) {
196 rsa = key_new(KEY_RSA1); 199 error("%s: sshkey_new failed", __func__);
200 return NULL;
201 }
202 if ((msg = sshbuf_new()) == NULL)
203 fatal("%s: sshbuf_new failed", __func__);
197 } 204 }
198 buffer_append(&msg, c->c_data, c->c_plen); 205 if ((r = sshbuf_put(msg, c->c_data, c->c_plen)) != 0 ||
199 buffer_consume(&msg, 8 - (c->c_plen & 7)); /* padding */ 206 (r = sshbuf_consume(msg, 8 - (c->c_plen & 7))) != 0 || /* padding */
200 if (buffer_get_char(&msg) != (int) SSH_SMSG_PUBLIC_KEY) { 207 (r = sshbuf_get_u8(msg, &type)) != 0)
208 goto buf_err;
209 if (type != (int) SSH_SMSG_PUBLIC_KEY) {
201 error("%s: invalid packet type", c->c_name); 210 error("%s: invalid packet type", c->c_name);
202 buffer_clear(&msg); 211 sshbuf_reset(msg);
212 return NULL;
213 }
214 if ((r = sshbuf_consume(msg, 8)) != 0 || /* cookie */
215 /* server key */
216 (r = sshbuf_get_u32(msg, NULL)) != 0 ||
217 (r = sshbuf_get_bignum1(msg, NULL)) != 0 ||
218 (r = sshbuf_get_bignum1(msg, NULL)) != 0 ||
219 /* host key */
220 (r = sshbuf_get_u32(msg, NULL)) != 0 ||
221 (r = sshbuf_get_bignum1(msg, rsa->rsa->e)) != 0 ||
222 (r = sshbuf_get_bignum1(msg, rsa->rsa->n)) != 0) {
223 buf_err:
224 error("%s: buffer error: %s", __func__, ssh_err(r));
225 sshbuf_reset(msg);
203 return NULL; 226 return NULL;
204 } 227 }
205 buffer_consume(&msg, 8); /* cookie */
206
207 /* server key */
208 (void) buffer_get_int(&msg);
209 buffer_get_bignum(&msg, rsa->rsa->e);
210 buffer_get_bignum(&msg, rsa->rsa->n);
211
212 /* host key */
213 (void) buffer_get_int(&msg);
214 buffer_get_bignum(&msg, rsa->rsa->e);
215 buffer_get_bignum(&msg, rsa->rsa->n);
216 228
217 buffer_clear(&msg); 229 sshbuf_reset(msg);
218 230
219 return (rsa); 231 return (rsa);
220} 232}
221#endif 233#endif
222 234
223static int 235static int
224hostjump(Key *hostkey, struct ssh *ssh) 236key_print_wrapper(struct sshkey *hostkey, struct ssh *ssh)
225{ 237{
226 kexjmp_key = hostkey; 238 con *c;
227 longjmp(kexjmp, 1); 239
240 if ((c = ssh_get_app_data(ssh)) != NULL)
241 keyprint(c, hostkey);
242 /* always abort key exchange */
243 return -1;
228} 244}
229 245
230static int 246static int
@@ -243,48 +259,41 @@ ssh2_capable(int remote_major, int remote_minor)
243 return 0; 259 return 0;
244} 260}
245 261
246static Key * 262static void
247keygrab_ssh2(con *c) 263keygrab_ssh2(con *c)
248{ 264{
249 char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; 265 char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
250 int r, j; 266 int r;
251 267
252 packet_set_connection(c->c_fd, c->c_fd);
253 enable_compat20(); 268 enable_compat20();
254 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = 269 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
255 c->c_keytype == KT_DSA ? "ssh-dss" : 270 c->c_keytype == KT_DSA ? "ssh-dss" :
256 (c->c_keytype == KT_RSA ? "ssh-rsa" : 271 (c->c_keytype == KT_RSA ? "ssh-rsa" :
257 (c->c_keytype == KT_ED25519 ? "ssh-ed25519" : 272 (c->c_keytype == KT_ED25519 ? "ssh-ed25519" :
258 "ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521")); 273 "ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521"));
259 if ((r = kex_setup(active_state, myproposal)) < 0) 274 if ((r = kex_setup(c->c_ssh, myproposal)) != 0) {
260 fatal("%s: kex_setup: %s", __func__, ssh_err(r)); 275 free(c->c_ssh);
261 c->c_kex = active_state->kex; 276 fprintf(stderr, "kex_setup: %s\n", ssh_err(r));
262#ifdef WITH_OPENSSL
263 c->c_kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
264 c->c_kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
265 c->c_kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
266 c->c_kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
267 c->c_kex->kex[KEX_ECDH_SHA2] = kexecdh_client;
268#endif
269 c->c_kex->kex[KEX_C25519_SHA256] = kexc25519_client;
270 c->c_kex->verify_host_key = hostjump;
271
272 if (!(j = setjmp(kexjmp))) {
273 nonfatal_fatal = 1;
274 dispatch_run(DISPATCH_BLOCK, &c->c_kex->done, active_state);
275 fprintf(stderr, "Impossible! dispatch_run() returned!\n");
276 exit(1); 277 exit(1);
277 } 278 }
278 nonfatal_fatal = 0; 279#ifdef WITH_OPENSSL
279 free(c->c_kex); 280 c->c_ssh->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
280 c->c_kex = NULL; 281 c->c_ssh->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
281 packet_close(); 282 c->c_ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
282 283 c->c_ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
283 return j < 0? NULL : kexjmp_key; 284 c->c_ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_client;
285#endif
286 c->c_ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_client;
287 ssh_set_verify_host_key_callback(c->c_ssh, key_print_wrapper);
288 /*
289 * do the key-exchange until an error occurs or until
290 * the key_print_wrapper() callback sets c_done.
291 */
292 ssh_dispatch_run(c->c_ssh, DISPATCH_BLOCK, &c->c_done, c->c_ssh);
284} 293}
285 294
286static void 295static void
287keyprint(con *c, Key *key) 296keyprint(con *c, struct sshkey *key)
288{ 297{
289 char *host = c->c_output_name ? c->c_output_name : c->c_name; 298 char *host = c->c_output_name ? c->c_output_name : c->c_name;
290 299
@@ -294,7 +303,7 @@ keyprint(con *c, Key *key)
294 fatal("host_hash failed"); 303 fatal("host_hash failed");
295 304
296 fprintf(stdout, "%s ", host); 305 fprintf(stdout, "%s ", host);
297 key_write(key, stdout); 306 sshkey_write(key, stdout);
298 fputs("\n", stdout); 307 fputs("\n", stdout);
299} 308}
300 309
@@ -382,6 +391,11 @@ confree(int s)
382 free(fdcon[s].c_data); 391 free(fdcon[s].c_data);
383 fdcon[s].c_status = CS_UNUSED; 392 fdcon[s].c_status = CS_UNUSED;
384 fdcon[s].c_keytype = 0; 393 fdcon[s].c_keytype = 0;
394 if (fdcon[s].c_ssh) {
395 ssh_packet_close(fdcon[s].c_ssh);
396 free(fdcon[s].c_ssh);
397 fdcon[s].c_ssh = NULL;
398 }
385 TAILQ_REMOVE(&tq, &fdcon[s], c_link); 399 TAILQ_REMOVE(&tq, &fdcon[s], c_link);
386 FD_CLR(s, read_wait); 400 FD_CLR(s, read_wait);
387 ncon--; 401 ncon--;
@@ -449,11 +463,13 @@ congreet(int s)
449 return; 463 return;
450 } 464 }
451 *cp = '\0'; 465 *cp = '\0';
466 c->c_ssh = ssh_packet_set_connection(NULL, s, s);
467 ssh_set_app_data(c->c_ssh, c); /* back link */
452 if (sscanf(buf, "SSH-%d.%d-%[^\n]\n", 468 if (sscanf(buf, "SSH-%d.%d-%[^\n]\n",
453 &remote_major, &remote_minor, remote_version) == 3) 469 &remote_major, &remote_minor, remote_version) == 3)
454 compat_datafellows(remote_version); 470 c->c_ssh->compat = compat_datafellows(remote_version);
455 else 471 else
456 datafellows = 0; 472 c->c_ssh->compat = 0;
457 if (c->c_keytype != KT_RSA1) { 473 if (c->c_keytype != KT_RSA1) {
458 if (!ssh2_capable(remote_major, remote_minor)) { 474 if (!ssh2_capable(remote_major, remote_minor)) {
459 debug("%s doesn't support ssh2", c->c_name); 475 debug("%s doesn't support ssh2", c->c_name);
@@ -480,7 +496,7 @@ congreet(int s)
480 return; 496 return;
481 } 497 }
482 if (c->c_keytype != KT_RSA1) { 498 if (c->c_keytype != KT_RSA1) {
483 keyprint(c, keygrab_ssh2(c)); 499 keygrab_ssh2(c);
484 confree(s); 500 confree(s);
485 return; 501 return;
486 } 502 }
@@ -606,10 +622,7 @@ fatal(const char *fmt,...)
606 va_start(args, fmt); 622 va_start(args, fmt);
607 do_log(SYSLOG_LEVEL_FATAL, fmt, args); 623 do_log(SYSLOG_LEVEL_FATAL, fmt, args);
608 va_end(args); 624 va_end(args);
609 if (nonfatal_fatal) 625 exit(255);
610 longjmp(kexjmp, -1);
611 else
612 exit(255);
613} 626}
614 627
615static void 628static void
@@ -682,7 +695,7 @@ main(int argc, char **argv)
682 get_keytypes = 0; 695 get_keytypes = 0;
683 tname = strtok(optarg, ","); 696 tname = strtok(optarg, ",");
684 while (tname) { 697 while (tname) {
685 int type = key_type_from_name(tname); 698 int type = sshkey_type_from_name(tname);
686 switch (type) { 699 switch (type) {
687 case KEY_RSA1: 700 case KEY_RSA1:
688 get_keytypes |= KT_RSA1; 701 get_keytypes |= KT_RSA1;