|
Lines 45-50
Link Here
|
| 45 |
#include "atomicio.h" |
45 |
#include "atomicio.h" |
| 46 |
#include "misc.h" |
46 |
#include "misc.h" |
| 47 |
#include "hostfile.h" |
47 |
#include "hostfile.h" |
|
|
48 |
#include "canohost.h" |
| 48 |
|
49 |
|
| 49 |
/* Flag indicating whether IPv4 or IPv6. This can be set on the command line. |
50 |
/* Flag indicating whether IPv4 or IPv6. This can be set on the command line. |
| 50 |
Default value is AF_UNSPEC means both IPv4 and IPv6. */ |
51 |
Default value is AF_UNSPEC means both IPv4 and IPv6. */ |
|
Lines 61-66
Link Here
|
| 61 |
|
62 |
|
| 62 |
int hash_hosts = 0; /* Hash hostname on output */ |
63 |
int hash_hosts = 0; /* Hash hostname on output */ |
| 63 |
|
64 |
|
|
|
65 |
int log_all_failures = 0; /* list all hosts checked */ |
| 66 |
|
| 64 |
#define MAXMAXFD 256 |
67 |
#define MAXMAXFD 256 |
| 65 |
|
68 |
|
| 66 |
/* The number of seconds after which to give up on a TCP connection */ |
69 |
/* The number of seconds after which to give up on a TCP connection */ |
|
Lines 70-75
Link Here
|
| 70 |
#define MAXCON (maxfd - 10) |
73 |
#define MAXCON (maxfd - 10) |
| 71 |
|
74 |
|
| 72 |
extern char *__progname; |
75 |
extern char *__progname; |
|
|
76 |
extern int connclosed; |
| 73 |
fd_set *read_wait; |
77 |
fd_set *read_wait; |
| 74 |
size_t read_wait_nfdset; |
78 |
size_t read_wait_nfdset; |
| 75 |
int ncon; |
79 |
int ncon; |
|
Lines 92-97
Link Here
|
| 92 |
int c_len; /* Total bytes which must be read. */ |
96 |
int c_len; /* Total bytes which must be read. */ |
| 93 |
int c_off; /* Length of data read so far. */ |
97 |
int c_off; /* Length of data read so far. */ |
| 94 |
int c_keytype; /* Only one of KT_RSA1, KT_DSA, or KT_RSA */ |
98 |
int c_keytype; /* Only one of KT_RSA1, KT_DSA, or KT_RSA */ |
|
|
99 |
int c_connclosed; /* = 1 if previous closed connection */ |
| 95 |
char *c_namebase; /* Address to free for c_name and c_namelist */ |
100 |
char *c_namebase; /* Address to free for c_name and c_namelist */ |
| 96 |
char *c_name; /* Hostname of connection for errors */ |
101 |
char *c_name; /* Hostname of connection for errors */ |
| 97 |
char *c_namelist; /* Pointer to other possible addresses */ |
102 |
char *c_namelist; /* Pointer to other possible addresses */ |
|
Lines 243-248
Link Here
|
| 243 |
{ |
248 |
{ |
| 244 |
int j; |
249 |
int j; |
| 245 |
|
250 |
|
|
|
251 |
/* |
| 252 |
* New fd and socket. Clear the possibly cached IP-address of the |
| 253 |
* remote host (kex.c:canonical_host_ip) of the previous socket. Also |
| 254 |
* ensure that the packet_read_seqnr():Connection closed ..." flag is |
| 255 |
* clear (called by dispatch_run()). |
| 256 |
*/ |
| 257 |
clear_cached_addr(); |
| 258 |
connclosed = 0; |
| 259 |
|
| 246 |
packet_set_connection(c->c_fd, c->c_fd); |
260 |
packet_set_connection(c->c_fd, c->c_fd); |
| 247 |
enable_compat20(); |
261 |
enable_compat20(); |
| 248 |
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = c->c_keytype == KT_DSA? |
262 |
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = c->c_keytype == KT_DSA? |
|
Lines 296-303
Link Here
|
| 296 |
memset(&hints, 0, sizeof(hints)); |
310 |
memset(&hints, 0, sizeof(hints)); |
| 297 |
hints.ai_family = IPv4or6; |
311 |
hints.ai_family = IPv4or6; |
| 298 |
hints.ai_socktype = SOCK_STREAM; |
312 |
hints.ai_socktype = SOCK_STREAM; |
| 299 |
if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) |
313 |
if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) { |
| 300 |
fatal("getaddrinfo %s: %s", host, ssh_gai_strerror(gaierr)); |
314 |
error("getaddrinfo %s: %s", host, ssh_gai_strerror(gaierr)); |
|
|
315 |
s = -1; |
| 316 |
return s; |
| 317 |
} |
| 301 |
for (ai = aitop; ai; ai = ai->ai_next) { |
318 |
for (ai = aitop; ai; ai = ai->ai_next) { |
| 302 |
s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); |
319 |
s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); |
| 303 |
if (s < 0) { |
320 |
if (s < 0) { |
|
Lines 349-354
Link Here
|
| 349 |
fdcon[s].c_len = 4; |
366 |
fdcon[s].c_len = 4; |
| 350 |
fdcon[s].c_off = 0; |
367 |
fdcon[s].c_off = 0; |
| 351 |
fdcon[s].c_keytype = keytype; |
368 |
fdcon[s].c_keytype = keytype; |
|
|
369 |
fdcon[s].c_connclosed = 0; |
| 352 |
gettimeofday(&fdcon[s].c_tv, NULL); |
370 |
gettimeofday(&fdcon[s].c_tv, NULL); |
| 353 |
fdcon[s].c_tv.tv_sec += timeout; |
371 |
fdcon[s].c_tv.tv_sec += timeout; |
| 354 |
TAILQ_INSERT_TAIL(&tq, &fdcon[s], c_link); |
372 |
TAILQ_INSERT_TAIL(&tq, &fdcon[s], c_link); |
|
Lines 388-396
Link Here
|
| 388 |
{ |
406 |
{ |
| 389 |
con *c = &fdcon[s]; |
407 |
con *c = &fdcon[s]; |
| 390 |
int ret; |
408 |
int ret; |
|
|
409 |
char *name; |
| 391 |
|
410 |
|
| 392 |
ret = conalloc(c->c_namelist, c->c_output_name, c->c_keytype); |
411 |
/* |
|
|
412 |
* If "connclosed" isn't set, do the next host from c->c_namelist. Else, |
| 413 |
* restore the original string in c->c_namebase and redo the current |
| 414 |
* host. |
| 415 |
*/ |
| 416 |
name = c->c_namelist; /* do next in list ?? */ |
| 417 |
if (connclosed != 0) { |
| 418 |
if (name && *name != '\0') /* restore separator, if any */ |
| 419 |
*(--name) = ','; |
| 420 |
name = c->c_namebase; /* redo current */ |
| 421 |
} |
| 422 |
ret = conalloc(name, c->c_output_name, c->c_keytype); |
| 393 |
confree(s); |
423 |
confree(s); |
|
|
424 |
if (ret >= 0 && connclosed == s) |
| 425 |
fdcon[ret].c_connclosed = 1; /* flag once */ |
| 394 |
return (ret); |
426 |
return (ret); |
| 395 |
} |
427 |
} |
| 396 |
|
428 |
|
|
Lines 422-427
Link Here
|
| 422 |
error("%s: Connection closed by remote host", c->c_name); |
454 |
error("%s: Connection closed by remote host", c->c_name); |
| 423 |
break; |
455 |
break; |
| 424 |
case ECONNREFUSED: |
456 |
case ECONNREFUSED: |
|
|
457 |
if (log_all_failures) |
| 458 |
error("%s: Connection refused by remote host", c->c_name); |
| 425 |
break; |
459 |
break; |
| 426 |
default: |
460 |
default: |
| 427 |
error("read (%s): %s", c->c_name, strerror(errno)); |
461 |
error("read (%s): %s", c->c_name, strerror(errno)); |
|
Lines 443-456
Link Here
|
| 443 |
datafellows = 0; |
477 |
datafellows = 0; |
| 444 |
if (c->c_keytype != KT_RSA1) { |
478 |
if (c->c_keytype != KT_RSA1) { |
| 445 |
if (!ssh2_capable(remote_major, remote_minor)) { |
479 |
if (!ssh2_capable(remote_major, remote_minor)) { |
|
|
480 |
if (log_all_failures) |
| 481 |
logit("%s doesn't support ssh2", c->c_name); |
| 482 |
else |
| 446 |
debug("%s doesn't support ssh2", c->c_name); |
483 |
debug("%s doesn't support ssh2", c->c_name); |
| 447 |
confree(s); |
484 |
confree(s); |
| 448 |
return; |
485 |
return; |
| 449 |
} |
486 |
} |
| 450 |
} else if (remote_major != 1) { |
487 |
} else if (remote_major != 1) { |
|
|
488 |
if (log_all_failures) |
| 489 |
logit("%s doesn't support ssh1", c->c_name); |
| 490 |
else |
| 451 |
debug("%s doesn't support ssh1", c->c_name); |
491 |
debug("%s doesn't support ssh1", c->c_name); |
| 452 |
confree(s); |
492 |
confree(s); |
| 453 |
return; |
493 |
return; |
| 454 |
} |
494 |
} |
| 455 |
fprintf(stderr, "# %s %s\n", c->c_name, chop(buf)); |
495 |
fprintf(stderr, "# %s %s\n", c->c_name, chop(buf)); |
| 456 |
n = snprintf(buf, sizeof buf, "SSH-%d.%d-OpenSSH-keyscan\r\n", |
496 |
n = snprintf(buf, sizeof buf, "SSH-%d.%d-OpenSSH-keyscan\r\n", |
|
Lines 466-478
Link Here
|
| 466 |
confree(s); |
506 |
confree(s); |
| 467 |
return; |
507 |
return; |
| 468 |
} |
508 |
} |
| 469 |
if (c->c_keytype != KT_RSA1) { |
509 |
if (c->c_keytype == KT_RSA1) { |
| 470 |
keyprint(c, keygrab_ssh2(c)); |
510 |
c->c_status = CS_SIZE; |
| 471 |
confree(s); |
511 |
contouch(s); |
| 472 |
return; |
512 |
return; |
| 473 |
} |
513 |
} |
| 474 |
c->c_status = CS_SIZE; |
514 |
/* |
| 475 |
contouch(s); |
515 |
* Read and print one of the ssh2 keys for this host. |
|
|
516 |
*/ |
| 517 |
keyprint(c, keygrab_ssh2(c)); |
| 518 |
|
| 519 |
/* |
| 520 |
* We're done with this host if the `packet.c:packet_read_seqnr()' |
| 521 |
* function was able to complete its data read. |
| 522 |
*/ |
| 523 |
if (connclosed == 0) { |
| 524 |
confree(s); |
| 525 |
} |
| 526 |
/* |
| 527 |
* We're also done with this host if the `packet.c:packet_read_seqnr()' |
| 528 |
* function received an EOF while attempting to read data (probably |
| 529 |
* caused by the LoginGraceTime being exceeded on the host) and if this |
| 530 |
* is the second time this has occurred for this host. |
| 531 |
*/ |
| 532 |
else if (c->c_connclosed) { |
| 533 |
confree(s); |
| 534 |
connclosed = -1; /* conrecycle other active sockets */ |
| 535 |
} |
| 536 |
/* |
| 537 |
* Else, give this host one and only one more chance with this key. We |
| 538 |
* don't know if this timeout was caused because of slow responses by |
| 539 |
* previous hosts or the host itself (or both (:@{)). This host and all |
| 540 |
* other hosts that currently have open sockets will be `conrecycled()'. |
| 541 |
*/ |
| 542 |
else { |
| 543 |
connclosed = s; |
| 544 |
} |
| 476 |
} |
545 |
} |
| 477 |
|
546 |
|
| 478 |
static void |
547 |
static void |
|
Lines 550-569
Link Here
|
| 550 |
if (FD_ISSET(i, e)) { |
619 |
if (FD_ISSET(i, e)) { |
| 551 |
error("%s: exception!", fdcon[i].c_name); |
620 |
error("%s: exception!", fdcon[i].c_name); |
| 552 |
confree(i); |
621 |
confree(i); |
| 553 |
} else if (FD_ISSET(i, r)) |
622 |
} else if (FD_ISSET(i, r)) { |
| 554 |
conread(i); |
623 |
conread(i); |
|
|
624 |
/* |
| 625 |
* Break if the read attempt in the `packet.c:packet_read_seqnr()' |
| 626 |
* function failed because the remote host closed the connection before |
| 627 |
* the packet data read was complete. The closure probably occurred |
| 628 |
* because the LoginGraceTime was exceeded on the remote `sshd' server. |
| 629 |
* All hosts that currently have a viable "fdcon[s]" entry will be |
| 630 |
* recycled below to negate the time used waiting for the current |
| 631 |
* "fdcon[i]"th host to respond. This is a very kludgy way to do this. |
| 632 |
*/ |
| 633 |
if (connclosed) |
| 634 |
break; |
| 635 |
} |
| 555 |
} |
636 |
} |
| 556 |
xfree(r); |
637 |
xfree(r); |
| 557 |
xfree(e); |
638 |
xfree(e); |
| 558 |
|
639 |
|
| 559 |
c = TAILQ_FIRST(&tq); |
640 |
c = TAILQ_FIRST(&tq); |
| 560 |
while (c && (c->c_tv.tv_sec < now.tv_sec || |
641 |
i = -1; |
| 561 |
(c->c_tv.tv_sec == now.tv_sec && c->c_tv.tv_usec < now.tv_usec))) { |
642 |
while (c && (connclosed || |
|
|
643 |
(c->c_tv.tv_sec < now.tv_sec || |
| 644 |
(c->c_tv.tv_sec == now.tv_sec && |
| 645 |
c->c_tv.tv_usec < now.tv_usec)))) { |
| 562 |
int s = c->c_fd; |
646 |
int s = c->c_fd; |
| 563 |
|
647 |
|
|
|
648 |
/* |
| 649 |
* If requested and if not recycling because of "connclosed", list this |
| 650 |
* host as a connection time out. |
| 651 |
*/ |
| 652 |
if (log_all_failures && connclosed == 0) |
| 653 |
logit("%s: Connection timed out.", c->c_name); |
| 654 |
/* |
| 655 |
* If i >= 0, fdcon[i] should be the first of any new allocations that |
| 656 |
* were made as a result of the call(s) to conrecycle(). |
| 657 |
*/ |
| 658 |
if (s == i) |
| 659 |
break; |
| 564 |
c = TAILQ_NEXT(c, c_link); |
660 |
c = TAILQ_NEXT(c, c_link); |
| 565 |
conrecycle(s); |
661 |
s = conrecycle(s); |
|
|
662 |
/* |
| 663 |
* Save fd of first new allocation. If we encounter it again, we'll |
| 664 |
* know that we've cycled through all of the original queue. |
| 665 |
*/ |
| 666 |
if (i < 0) |
| 667 |
i = s; |
| 566 |
} |
668 |
} |
|
|
669 |
connclosed = 0; |
| 567 |
} |
670 |
} |
| 568 |
|
671 |
|
| 569 |
static void |
672 |
static void |
|
Lines 583-588
Link Here
|
| 583 |
} |
686 |
} |
| 584 |
} |
687 |
} |
| 585 |
|
688 |
|
|
|
689 |
/* |
| 690 |
* Convert general remote aborts to continues for ssh-keyscan while |
| 691 |
* executing the `dispatch_run()' function. |
| 692 |
*/ |
| 693 |
void |
| 694 |
cleanup_exit(int i) |
| 695 |
{ |
| 696 |
if (nonfatal_fatal) |
| 697 |
longjmp(kexjmp, -1); |
| 698 |
else |
| 699 |
exit(i); |
| 700 |
} |
| 701 |
|
| 586 |
void |
702 |
void |
| 587 |
fatal(const char *fmt,...) |
703 |
fatal(const char *fmt,...) |
| 588 |
{ |
704 |
{ |
|
Lines 630-640
Link Here
|
| 630 |
if (argc <= 1) |
746 |
if (argc <= 1) |
| 631 |
usage(); |
747 |
usage(); |
| 632 |
|
748 |
|
| 633 |
while ((opt = getopt(argc, argv, "Hv46p:T:t:f:")) != -1) { |
749 |
while ((opt = getopt(argc, argv, "HLv46p:T:t:f:")) != -1) { |
| 634 |
switch (opt) { |
750 |
switch (opt) { |
| 635 |
case 'H': |
751 |
case 'H': |
| 636 |
hash_hosts = 1; |
752 |
hash_hosts = 1; |
| 637 |
break; |
753 |
break; |
|
|
754 |
case 'L': |
| 755 |
log_all_failures = 1; |
| 756 |
break; |
| 638 |
case 'p': |
757 |
case 'p': |
| 639 |
ssh_port = a2port(optarg); |
758 |
ssh_port = a2port(optarg); |
| 640 |
if (ssh_port <= 0) { |
759 |
if (ssh_port <= 0) { |
|
Lines 715-721
Link Here
|
| 715 |
fdlim_set(maxfd); |
834 |
fdlim_set(maxfd); |
| 716 |
fdcon = xcalloc(maxfd, sizeof(con)); |
835 |
fdcon = xcalloc(maxfd, sizeof(con)); |
| 717 |
|
836 |
|
| 718 |
read_wait_nfdset = howmany(maxfd, NFDBITS); |
837 |
read_wait_nfdset = howmany(maxfd + 1, NFDBITS); |
| 719 |
read_wait = xcalloc(read_wait_nfdset, sizeof(fd_mask)); |
838 |
read_wait = xcalloc(read_wait_nfdset, sizeof(fd_mask)); |
| 720 |
|
839 |
|
| 721 |
for (j = 0; j < fopt_count; j++) { |
840 |
for (j = 0; j < fopt_count; j++) { |