|
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 70-75
Link Here
|
| 70 |
#define MAXCON (maxfd - 10) |
71 |
#define MAXCON (maxfd - 10) |
| 71 |
|
72 |
|
| 72 |
extern char *__progname; |
73 |
extern char *__progname; |
|
|
74 |
extern int connclosed; |
| 73 |
fd_set *read_wait; |
75 |
fd_set *read_wait; |
| 74 |
size_t read_wait_nfdset; |
76 |
size_t read_wait_nfdset; |
| 75 |
int ncon; |
77 |
int ncon; |
|
Lines 92-97
Link Here
|
| 92 |
int c_len; /* Total bytes which must be read. */ |
94 |
int c_len; /* Total bytes which must be read. */ |
| 93 |
int c_off; /* Length of data read so far. */ |
95 |
int c_off; /* Length of data read so far. */ |
| 94 |
int c_keytype; /* Only one of KT_RSA1, KT_DSA, or KT_RSA */ |
96 |
int c_keytype; /* Only one of KT_RSA1, KT_DSA, or KT_RSA */ |
|
|
97 |
int c_connclosed; /* = 1 if previous closed connection */ |
| 95 |
char *c_namebase; /* Address to free for c_name and c_namelist */ |
98 |
char *c_namebase; /* Address to free for c_name and c_namelist */ |
| 96 |
char *c_name; /* Hostname of connection for errors */ |
99 |
char *c_name; /* Hostname of connection for errors */ |
| 97 |
char *c_namelist; /* Pointer to other possible addresses */ |
100 |
char *c_namelist; /* Pointer to other possible addresses */ |
|
Lines 243-248
Link Here
|
| 243 |
{ |
246 |
{ |
| 244 |
int j; |
247 |
int j; |
| 245 |
|
248 |
|
|
|
249 |
/* |
| 250 |
* New fd and socket. Clear the possibly cached IP-address of the |
| 251 |
* remote host (kex.c:canonical_host_ip) of the previous socket. Also |
| 252 |
* ensure that the packet_read_seqnr():Connection closed ..." flag is |
| 253 |
* clear (called by dispatch_run()). |
| 254 |
*/ |
| 255 |
clear_cached_addr(); |
| 256 |
connclosed = 0; |
| 257 |
|
| 246 |
packet_set_connection(c->c_fd, c->c_fd); |
258 |
packet_set_connection(c->c_fd, c->c_fd); |
| 247 |
enable_compat20(); |
259 |
enable_compat20(); |
| 248 |
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = c->c_keytype == KT_DSA? |
260 |
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = c->c_keytype == KT_DSA? |
|
Lines 296-303
Link Here
|
| 296 |
memset(&hints, 0, sizeof(hints)); |
308 |
memset(&hints, 0, sizeof(hints)); |
| 297 |
hints.ai_family = IPv4or6; |
309 |
hints.ai_family = IPv4or6; |
| 298 |
hints.ai_socktype = SOCK_STREAM; |
310 |
hints.ai_socktype = SOCK_STREAM; |
| 299 |
if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) |
311 |
if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) { |
| 300 |
fatal("getaddrinfo %s: %s", host, ssh_gai_strerror(gaierr)); |
312 |
error("getaddrinfo %s: %s", host, ssh_gai_strerror(gaierr)); |
|
|
313 |
s = -1; |
| 314 |
return s; |
| 315 |
} |
| 301 |
for (ai = aitop; ai; ai = ai->ai_next) { |
316 |
for (ai = aitop; ai; ai = ai->ai_next) { |
| 302 |
s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); |
317 |
s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); |
| 303 |
if (s < 0) { |
318 |
if (s < 0) { |
|
Lines 349-354
Link Here
|
| 349 |
fdcon[s].c_len = 4; |
364 |
fdcon[s].c_len = 4; |
| 350 |
fdcon[s].c_off = 0; |
365 |
fdcon[s].c_off = 0; |
| 351 |
fdcon[s].c_keytype = keytype; |
366 |
fdcon[s].c_keytype = keytype; |
|
|
367 |
fdcon[s].c_connclosed = 0; |
| 352 |
gettimeofday(&fdcon[s].c_tv, NULL); |
368 |
gettimeofday(&fdcon[s].c_tv, NULL); |
| 353 |
fdcon[s].c_tv.tv_sec += timeout; |
369 |
fdcon[s].c_tv.tv_sec += timeout; |
| 354 |
TAILQ_INSERT_TAIL(&tq, &fdcon[s], c_link); |
370 |
TAILQ_INSERT_TAIL(&tq, &fdcon[s], c_link); |
|
Lines 388-396
Link Here
|
| 388 |
{ |
404 |
{ |
| 389 |
con *c = &fdcon[s]; |
405 |
con *c = &fdcon[s]; |
| 390 |
int ret; |
406 |
int ret; |
|
|
407 |
char *name; |
| 391 |
|
408 |
|
| 392 |
ret = conalloc(c->c_namelist, c->c_output_name, c->c_keytype); |
409 |
/* |
|
|
410 |
* If "connclosed" isn't set, do the next host from c->c_namelist. Else, |
| 411 |
* restore the original string in c->c_namebase and redo the current |
| 412 |
* host. |
| 413 |
*/ |
| 414 |
name = c->c_namelist; /* do next in list ?? */ |
| 415 |
if (connclosed != 0) { |
| 416 |
if (name && *name != '\0') /* restore separator, if any */ |
| 417 |
*(--name) = ','; |
| 418 |
name = c->c_namebase; /* redo current */ |
| 419 |
} |
| 420 |
ret = conalloc(name, c->c_output_name, c->c_keytype); |
| 393 |
confree(s); |
421 |
confree(s); |
|
|
422 |
if (ret >= 0 && connclosed == s) |
| 423 |
fdcon[ret].c_connclosed = 1; /* flag once */ |
| 394 |
return (ret); |
424 |
return (ret); |
| 395 |
} |
425 |
} |
| 396 |
|
426 |
|
|
Lines 466-478
Link Here
|
| 466 |
confree(s); |
496 |
confree(s); |
| 467 |
return; |
497 |
return; |
| 468 |
} |
498 |
} |
| 469 |
if (c->c_keytype != KT_RSA1) { |
499 |
if (c->c_keytype == KT_RSA1) { |
| 470 |
keyprint(c, keygrab_ssh2(c)); |
500 |
c->c_status = CS_SIZE; |
| 471 |
confree(s); |
501 |
contouch(s); |
| 472 |
return; |
502 |
return; |
| 473 |
} |
503 |
} |
| 474 |
c->c_status = CS_SIZE; |
504 |
/* |
| 475 |
contouch(s); |
505 |
* Read and print one of the ssh2 keys for this host. |
|
|
506 |
*/ |
| 507 |
keyprint(c, keygrab_ssh2(c)); |
| 508 |
|
| 509 |
/* |
| 510 |
* We're done with this host if the `packet_read_seqnr()' function was |
| 511 |
* able to complete its data read. |
| 512 |
*/ |
| 513 |
if (connclosed == 0) { |
| 514 |
confree(s); |
| 515 |
} |
| 516 |
/* |
| 517 |
* We're also done with this host if the `packet.c:packet_read_seqnr()' |
| 518 |
* function received an EOF while attempting to read data (probably |
| 519 |
* caused by the LoginGraceTime being exceeded on the host) and if this |
| 520 |
* is the second time this has occurred for this host. |
| 521 |
*/ |
| 522 |
else if (c->c_connclosed) { |
| 523 |
confree(s); |
| 524 |
connclosed = -1; /* conrecycle other active sockets */ |
| 525 |
} |
| 526 |
/* |
| 527 |
* Else, give this host one and only one more chance with this key. We |
| 528 |
* don't know if this timeout was caused because of slow responses by |
| 529 |
* previous hosts or the host itself (or both (:@{)). This host and all |
| 530 |
* other hosts that currently have open sockets will be `conrecycled()'. |
| 531 |
*/ |
| 532 |
else { |
| 533 |
connclosed = s; |
| 534 |
} |
| 476 |
} |
535 |
} |
| 477 |
|
536 |
|
| 478 |
static void |
537 |
static void |
|
Lines 550-569
Link Here
|
| 550 |
if (FD_ISSET(i, e)) { |
609 |
if (FD_ISSET(i, e)) { |
| 551 |
error("%s: exception!", fdcon[i].c_name); |
610 |
error("%s: exception!", fdcon[i].c_name); |
| 552 |
confree(i); |
611 |
confree(i); |
| 553 |
} else if (FD_ISSET(i, r)) |
612 |
} else if (FD_ISSET(i, r)) { |
| 554 |
conread(i); |
613 |
conread(i); |
|
|
614 |
/* |
| 615 |
* Break if the read attempt in the `packet_read_seqnr()' function |
| 616 |
* failed because the remote host closed the connection before the |
| 617 |
* packet data read was complete. The closure probably occurred because |
| 618 |
* the LoginGraceTime was exceeded on the remote `sshd' server. All |
| 619 |
* hosts that currently have a viable "fdcon[s]" entry will be recycled |
| 620 |
* below to negate the time used waiting for the current "fdcon[i]"th |
| 621 |
* host to respond. This is really a kludgy way to do this. |
| 622 |
*/ |
| 623 |
if (connclosed) |
| 624 |
break; |
| 625 |
} |
| 555 |
} |
626 |
} |
| 556 |
xfree(r); |
627 |
xfree(r); |
| 557 |
xfree(e); |
628 |
xfree(e); |
| 558 |
|
629 |
|
| 559 |
c = TAILQ_FIRST(&tq); |
630 |
c = TAILQ_FIRST(&tq); |
| 560 |
while (c && (c->c_tv.tv_sec < now.tv_sec || |
631 |
i = -1; |
| 561 |
(c->c_tv.tv_sec == now.tv_sec && c->c_tv.tv_usec < now.tv_usec))) { |
632 |
while (c && (connclosed || |
|
|
633 |
(c->c_tv.tv_sec < now.tv_sec || |
| 634 |
(c->c_tv.tv_sec == now.tv_sec && |
| 635 |
c->c_tv.tv_usec < now.tv_usec)))) { |
| 562 |
int s = c->c_fd; |
636 |
int s = c->c_fd; |
| 563 |
|
637 |
|
|
|
638 |
/* |
| 639 |
* If i >= 0, fdcon[i] should be the first of any new allocations that |
| 640 |
* were made as a result of the call(s) to conrecycle(). |
| 641 |
*/ |
| 642 |
if (s == i) |
| 643 |
break; |
| 564 |
c = TAILQ_NEXT(c, c_link); |
644 |
c = TAILQ_NEXT(c, c_link); |
| 565 |
conrecycle(s); |
645 |
s = conrecycle(s); |
|
|
646 |
/* |
| 647 |
* Save fd of first new allocation. If we encounter it again, we'll |
| 648 |
* know that we've cycled through all of the original queue. |
| 649 |
*/ |
| 650 |
if (i < 0) |
| 651 |
i = s; |
| 566 |
} |
652 |
} |
|
|
653 |
connclosed = 0; |
| 567 |
} |
654 |
} |
| 568 |
|
655 |
|
| 569 |
static void |
656 |
static void |
|
Lines 583-588
Link Here
|
| 583 |
} |
670 |
} |
| 584 |
} |
671 |
} |
| 585 |
|
672 |
|
|
|
673 |
/* |
| 674 |
* Convert general remote aborts to continues for ssh-keyscan while |
| 675 |
* executing the `dispatch_run()' function. |
| 676 |
*/ |
| 677 |
void |
| 678 |
cleanup_exit(int i) |
| 679 |
{ |
| 680 |
if (nonfatal_fatal) |
| 681 |
longjmp(kexjmp, -1); |
| 682 |
else |
| 683 |
exit(i); |
| 684 |
} |
| 685 |
|
| 586 |
void |
686 |
void |
| 587 |
fatal(const char *fmt,...) |
687 |
fatal(const char *fmt,...) |
| 588 |
{ |
688 |
{ |
|
Lines 715-721
Link Here
|
| 715 |
fdlim_set(maxfd); |
815 |
fdlim_set(maxfd); |
| 716 |
fdcon = xcalloc(maxfd, sizeof(con)); |
816 |
fdcon = xcalloc(maxfd, sizeof(con)); |
| 717 |
|
817 |
|
| 718 |
read_wait_nfdset = howmany(maxfd, NFDBITS); |
818 |
read_wait_nfdset = howmany(maxfd + 1, NFDBITS); |
| 719 |
read_wait = xcalloc(read_wait_nfdset, sizeof(fd_mask)); |
819 |
read_wait = xcalloc(read_wait_nfdset, sizeof(fd_mask)); |
| 720 |
|
820 |
|
| 721 |
for (j = 0; j < fopt_count; j++) { |
821 |
for (j = 0; j < fopt_count; j++) { |