|
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-75
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_verbose = 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 */ |
|
|
70 |
/* and the maximum time to wait for kex data from the remote server.*/ |
| 67 |
int timeout = 5; |
71 |
int timeout = 5; |
| 68 |
|
72 |
|
| 69 |
int maxfd; |
73 |
int maxfd; |
| 70 |
#define MAXCON (maxfd - 10) |
74 |
#define MAXCON (maxfd - 10) |
| 71 |
|
75 |
|
| 72 |
extern char *__progname; |
76 |
extern char *__progname; |
|
|
77 |
extern int connclosed; |
| 78 |
extern int conntimedout; |
| 73 |
fd_set *read_wait; |
79 |
fd_set *read_wait; |
| 74 |
size_t read_wait_nfdset; |
80 |
size_t read_wait_nfdset; |
| 75 |
int ncon; |
81 |
int ncon; |
|
Lines 243-249
Link Here
|
| 243 |
{ |
249 |
{ |
| 244 |
int j; |
250 |
int j; |
| 245 |
|
251 |
|
|
|
252 |
/* |
| 253 |
* New fd and socket. Clear the possibly cached IP-address of the |
| 254 |
* remote host (kex.c:canonical_host_ip) of the previous socket. Also |
| 255 |
* clear the packet_read_seqnr() "Connection closed ..." and "Connection |
| 256 |
* to ... timed out ..." flags (called by dispatch_run()). |
| 257 |
*/ |
| 258 |
clear_cached_addr(); |
| 259 |
connclosed = 0; |
| 260 |
conntimedout = 0; |
| 261 |
|
| 246 |
packet_set_connection(c->c_fd, c->c_fd); |
262 |
packet_set_connection(c->c_fd, c->c_fd); |
|
|
263 |
/* |
| 264 |
* Use our "timeout" value to set the maximum allowed wait time for data |
| 265 |
* to become available in the `packet.c:packet_read_seqnr()' function. |
| 266 |
*/ |
| 267 |
packet_set_timeout(timeout, 1); |
| 268 |
|
| 247 |
enable_compat20(); |
269 |
enable_compat20(); |
| 248 |
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = c->c_keytype == KT_DSA? |
270 |
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = c->c_keytype == KT_DSA? |
| 249 |
"ssh-dss" : (c->c_keytype == KT_RSA ? "ssh-rsa" : |
271 |
"ssh-dss" : (c->c_keytype == KT_RSA ? "ssh-rsa" : |
|
Lines 296-303
Link Here
|
| 296 |
memset(&hints, 0, sizeof(hints)); |
318 |
memset(&hints, 0, sizeof(hints)); |
| 297 |
hints.ai_family = IPv4or6; |
319 |
hints.ai_family = IPv4or6; |
| 298 |
hints.ai_socktype = SOCK_STREAM; |
320 |
hints.ai_socktype = SOCK_STREAM; |
| 299 |
if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) |
321 |
if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) { |
| 300 |
fatal("getaddrinfo %s: %s", host, ssh_gai_strerror(gaierr)); |
322 |
error("getaddrinfo %s: %s", host, ssh_gai_strerror(gaierr)); |
|
|
323 |
s = -1; |
| 324 |
return s; |
| 325 |
} |
| 301 |
for (ai = aitop; ai; ai = ai->ai_next) { |
326 |
for (ai = aitop; ai; ai = ai->ai_next) { |
| 302 |
s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); |
327 |
s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); |
| 303 |
if (s < 0) { |
328 |
if (s < 0) { |
|
Lines 388-395
Link Here
|
| 388 |
{ |
413 |
{ |
| 389 |
con *c = &fdcon[s]; |
414 |
con *c = &fdcon[s]; |
| 390 |
int ret; |
415 |
int ret; |
|
|
416 |
char *name; |
| 391 |
|
417 |
|
| 392 |
ret = conalloc(c->c_namelist, c->c_output_name, c->c_keytype); |
418 |
/* |
|
|
419 |
* If "connclosed" isn't set, do the next host from c->c_namelist. Else, |
| 420 |
* restore the original string in c->c_namebase and redo the current |
| 421 |
* host. |
| 422 |
*/ |
| 423 |
name = c->c_namelist; /* do next in list ?? */ |
| 424 |
if (connclosed != 0) { /* nope so */ |
| 425 |
if (name && *name != '\0') /* restore separator, if any */ |
| 426 |
*(name - 1) = ','; /* and */ |
| 427 |
name = c->c_namebase; /* redo current */ |
| 428 |
} |
| 429 |
ret = conalloc(name, c->c_output_name, c->c_keytype); |
| 393 |
confree(s); |
430 |
confree(s); |
| 394 |
return (ret); |
431 |
return (ret); |
| 395 |
} |
432 |
} |
|
Lines 422-427
Link Here
|
| 422 |
error("%s: Connection closed by remote host", c->c_name); |
459 |
error("%s: Connection closed by remote host", c->c_name); |
| 423 |
break; |
460 |
break; |
| 424 |
case ECONNREFUSED: |
461 |
case ECONNREFUSED: |
|
|
462 |
if (log_verbose) |
| 463 |
error("%s: Connection refused by remote host", c->c_name); |
| 425 |
break; |
464 |
break; |
| 426 |
default: |
465 |
default: |
| 427 |
error("read (%s): %s", c->c_name, strerror(errno)); |
466 |
error("read (%s): %s", c->c_name, strerror(errno)); |
|
Lines 443-456
Link Here
|
| 443 |
datafellows = 0; |
482 |
datafellows = 0; |
| 444 |
if (c->c_keytype != KT_RSA1) { |
483 |
if (c->c_keytype != KT_RSA1) { |
| 445 |
if (!ssh2_capable(remote_major, remote_minor)) { |
484 |
if (!ssh2_capable(remote_major, remote_minor)) { |
|
|
485 |
if (log_verbose) |
| 486 |
logit("%s doesn't support ssh2", c->c_name); |
| 487 |
else |
| 446 |
debug("%s doesn't support ssh2", c->c_name); |
488 |
debug("%s doesn't support ssh2", c->c_name); |
| 447 |
confree(s); |
489 |
confree(s); |
| 448 |
return; |
490 |
return; |
| 449 |
} |
491 |
} |
| 450 |
} else if (remote_major != 1) { |
492 |
} else if (remote_major != 1) { |
|
|
493 |
if (log_verbose) |
| 494 |
logit("%s doesn't support ssh1", c->c_name); |
| 495 |
else |
| 451 |
debug("%s doesn't support ssh1", c->c_name); |
496 |
debug("%s doesn't support ssh1", c->c_name); |
| 452 |
confree(s); |
497 |
confree(s); |
| 453 |
return; |
498 |
return; |
| 454 |
} |
499 |
} |
| 455 |
fprintf(stderr, "# %s %s\n", c->c_name, chop(buf)); |
500 |
fprintf(stderr, "# %s %s\n", c->c_name, chop(buf)); |
| 456 |
n = snprintf(buf, sizeof buf, "SSH-%d.%d-OpenSSH-keyscan\r\n", |
501 |
n = snprintf(buf, sizeof buf, "SSH-%d.%d-OpenSSH-keyscan\r\n", |
|
Lines 466-478
Link Here
|
| 466 |
confree(s); |
511 |
confree(s); |
| 467 |
return; |
512 |
return; |
| 468 |
} |
513 |
} |
|
|
514 |
/* |
| 515 |
* Read and print one of the ssh2 keys for this host. |
| 516 |
*/ |
| 469 |
if (c->c_keytype != KT_RSA1) { |
517 |
if (c->c_keytype != KT_RSA1) { |
| 470 |
keyprint(c, keygrab_ssh2(c)); |
518 |
keyprint(c, keygrab_ssh2(c)); |
| 471 |
confree(s); |
519 |
confree(s); |
| 472 |
return; |
520 |
return; |
| 473 |
} |
521 |
} |
|
|
522 |
/* |
| 523 |
* Continue the process of getting the ssh1 key. |
| 524 |
*/ |
| 474 |
c->c_status = CS_SIZE; |
525 |
c->c_status = CS_SIZE; |
| 475 |
contouch(s); |
526 |
contouch(s); |
|
|
527 |
return; |
| 528 |
|
| 476 |
} |
529 |
} |
| 477 |
|
530 |
|
| 478 |
static void |
531 |
static void |
|
Lines 520-526
Link Here
|
| 520 |
struct timeval seltime, now; |
573 |
struct timeval seltime, now; |
| 521 |
fd_set *r, *e; |
574 |
fd_set *r, *e; |
| 522 |
con *c; |
575 |
con *c; |
| 523 |
int i; |
576 |
int i, s; |
| 524 |
|
577 |
|
| 525 |
gettimeofday(&now, NULL); |
578 |
gettimeofday(&now, NULL); |
| 526 |
c = TAILQ_FIRST(&tq); |
579 |
c = TAILQ_FIRST(&tq); |
|
Lines 550-569
Link Here
|
| 550 |
if (FD_ISSET(i, e)) { |
603 |
if (FD_ISSET(i, e)) { |
| 551 |
error("%s: exception!", fdcon[i].c_name); |
604 |
error("%s: exception!", fdcon[i].c_name); |
| 552 |
confree(i); |
605 |
confree(i); |
| 553 |
} else if (FD_ISSET(i, r)) |
606 |
} else if (FD_ISSET(i, r)) { |
| 554 |
conread(i); |
607 |
conread(i); |
|
|
608 |
/* |
| 609 |
* Break if the read attempt in the `packet.c:packet_read_seqnr()' |
| 610 |
* function failed because our "local" timeout was exceeded or because |
| 611 |
* the remote host closed the connection before the packet data read |
| 612 |
* was complete. The remote closure probably occurred because the |
| 613 |
* LoginGraceTime was exceeded on the remote `sshd' server. |
| 614 |
*/ |
| 615 |
if (conntimedout || connclosed) |
| 616 |
break; |
| 617 |
} |
| 555 |
} |
618 |
} |
| 556 |
xfree(r); |
619 |
xfree(r); |
| 557 |
xfree(e); |
620 |
xfree(e); |
| 558 |
|
621 |
|
|
|
622 |
/* |
| 623 |
* If we have the "conntimedout" condition, the read attempt failed |
| 624 |
* because the "local" timeout (set by the `packet_set_timeout()' |
| 625 |
* function call) was exceeded. Give all hosts that currently have a |
| 626 |
* "fdcon[s]" entry a fresh timeout. |
| 627 |
*/ |
| 628 |
i = -1; |
| 559 |
c = TAILQ_FIRST(&tq); |
629 |
c = TAILQ_FIRST(&tq); |
| 560 |
while (c && (c->c_tv.tv_sec < now.tv_sec || |
630 |
|
| 561 |
(c->c_tv.tv_sec == now.tv_sec && c->c_tv.tv_usec < now.tv_usec))) { |
631 |
if (conntimedout) { |
| 562 |
int s = c->c_fd; |
632 |
while (c) { |
|
|
633 |
s = c->c_fd; |
| 634 |
/* |
| 635 |
* If i >= 0, fdcon[i] should be the first entry "touch"ed by |
| 636 |
* the call to contouch() below. |
| 637 |
*/ |
| 638 |
if (s == i) |
| 639 |
break; |
| 640 |
/* |
| 641 |
* Save fd of first "touch"ed entry. If we encounter it again, we'll |
| 642 |
* know that we've cycled through all of the original queue. |
| 643 |
*/ |
| 644 |
contouch(s); /* a fresh timeout for fdcon[s] */ |
| 645 |
if (i < 0) |
| 646 |
i = s; |
| 647 |
|
| 648 |
c = TAILQ_NEXT(c, c_link); |
| 649 |
} |
| 650 |
|
| 651 |
conntimedout = 0; |
| 652 |
|
| 653 |
return; |
| 654 |
} |
| 655 |
|
| 656 |
/* |
| 657 |
* If we have the "connclosed" condition, the read failed because the |
| 658 |
* remote server closed the connection before sending the key. All hosts |
| 659 |
* that currently have a viable "fdcon[s]" entry will be recycled below |
| 660 |
* to negate the time used waiting for the server to respond. This is |
| 661 |
* a very kludgy way to do this and should be necessary only if the |
| 662 |
* "local" timeout value exceeds the remote servers LoginGraceTime or |
| 663 |
* if there are a lot of very slow servers out there. |
| 664 |
* |
| 665 |
* Loop through the remaining open TAILQ entries. The loop covers two |
| 666 |
* conditions: all entries for"connclosed" (described above) and the per |
| 667 |
* entry timeout that occurs while waiting for the remote server to send |
| 668 |
* its return greeting. |
| 669 |
*/ |
| 670 |
while (c && (connclosed || |
| 671 |
(c->c_tv.tv_sec < now.tv_sec || |
| 672 |
(c->c_tv.tv_sec == now.tv_sec && |
| 673 |
c->c_tv.tv_usec < now.tv_usec)))) { |
| 674 |
s = c->c_fd; |
| 675 |
/* |
| 676 |
* If i >= 0, fdcon[i] should be the first of any new allocations that |
| 677 |
* were made as a result of the call(s) to conrecycle() below. |
| 678 |
*/ |
| 679 |
if (s == i) |
| 680 |
break; |
| 681 |
|
| 682 |
/* |
| 683 |
* If requested and if not recycling because of "connclosed", list this |
| 684 |
* host as a connection time out. |
| 685 |
*/ |
| 686 |
if (log_verbose && connclosed == 0) |
| 687 |
logit("%s: Connection timed out.", c->c_name); |
| 688 |
|
| 689 |
/* |
| 690 |
* Save fd of first new allocation. If we encounter it again, we'll |
| 691 |
* know that we've cycled through all of the original queue. |
| 692 |
*/ |
| 693 |
s = conrecycle(s); |
| 694 |
if (i < 0) |
| 695 |
i = s; |
| 563 |
|
696 |
|
| 564 |
c = TAILQ_NEXT(c, c_link); |
697 |
c = TAILQ_NEXT(c, c_link); |
| 565 |
conrecycle(s); |
|
|
| 566 |
} |
698 |
} |
|
|
699 |
connclosed = 0; |
| 567 |
} |
700 |
} |
| 568 |
|
701 |
|
| 569 |
static void |
702 |
static void |
|
Lines 583-588
Link Here
|
| 583 |
} |
716 |
} |
| 584 |
} |
717 |
} |
| 585 |
|
718 |
|
|
|
719 |
/* |
| 720 |
* Convert general remote aborts to continues while the `dispatch_run()' |
| 721 |
* function is being executed. |
| 722 |
*/ |
| 723 |
void |
| 724 |
cleanup_exit(int i) |
| 725 |
{ |
| 726 |
if (nonfatal_fatal) |
| 727 |
longjmp(kexjmp, -1); |
| 728 |
else |
| 729 |
exit(i); |
| 730 |
} |
| 731 |
|
| 586 |
void |
732 |
void |
| 587 |
fatal(const char *fmt,...) |
733 |
fatal(const char *fmt,...) |
| 588 |
{ |
734 |
{ |
|
Lines 601-607
Link Here
|
| 601 |
usage(void) |
747 |
usage(void) |
| 602 |
{ |
748 |
{ |
| 603 |
fprintf(stderr, |
749 |
fprintf(stderr, |
| 604 |
"usage: %s [-46Hv] [-f file] [-p port] [-T timeout] [-t type]\n" |
750 |
"usage: %s [-46HLv] [-f file] [-p port] [-T timeout] [-t type]\n" |
| 605 |
"\t\t [host | addrlist namelist] ...\n", |
751 |
"\t\t [host | addrlist namelist] ...\n", |
| 606 |
__progname); |
752 |
__progname); |
| 607 |
exit(1); |
753 |
exit(1); |
|
Lines 630-640
Link Here
|
| 630 |
if (argc <= 1) |
776 |
if (argc <= 1) |
| 631 |
usage(); |
777 |
usage(); |
| 632 |
|
778 |
|
| 633 |
while ((opt = getopt(argc, argv, "Hv46p:T:t:f:")) != -1) { |
779 |
while ((opt = getopt(argc, argv, "HLv46p:T:t:f:")) != -1) { |
| 634 |
switch (opt) { |
780 |
switch (opt) { |
| 635 |
case 'H': |
781 |
case 'H': |
| 636 |
hash_hosts = 1; |
782 |
hash_hosts = 1; |
| 637 |
break; |
783 |
break; |
|
|
784 |
case 'L': |
| 785 |
log_verbose = 1; |
| 786 |
break; |
| 638 |
case 'p': |
787 |
case 'p': |
| 639 |
ssh_port = a2port(optarg); |
788 |
ssh_port = a2port(optarg); |
| 640 |
if (ssh_port <= 0) { |
789 |
if (ssh_port <= 0) { |
|
Lines 715-721
Link Here
|
| 715 |
fdlim_set(maxfd); |
864 |
fdlim_set(maxfd); |
| 716 |
fdcon = xcalloc(maxfd, sizeof(con)); |
865 |
fdcon = xcalloc(maxfd, sizeof(con)); |
| 717 |
|
866 |
|
| 718 |
read_wait_nfdset = howmany(maxfd, NFDBITS); |
867 |
read_wait_nfdset = howmany(maxfd + 1, NFDBITS); |
| 719 |
read_wait = xcalloc(read_wait_nfdset, sizeof(fd_mask)); |
868 |
read_wait = xcalloc(read_wait_nfdset, sizeof(fd_mask)); |
| 720 |
|
869 |
|
| 721 |
for (j = 0; j < fopt_count; j++) { |
870 |
for (j = 0; j < fopt_count; j++) { |