diff options
Diffstat (limited to 'sshconnect.c')
-rw-r--r-- | sshconnect.c | 54 |
1 files changed, 43 insertions, 11 deletions
diff --git a/sshconnect.c b/sshconnect.c index dfeddd39e..e0d1a8c7e 100644 --- a/sshconnect.c +++ b/sshconnect.c | |||
@@ -51,6 +51,13 @@ extern pid_t proxy_command_pid; | |||
51 | #define INET6_ADDRSTRLEN 46 | 51 | #define INET6_ADDRSTRLEN 46 |
52 | #endif | 52 | #endif |
53 | 53 | ||
54 | static sig_atomic_t banner_timedout; | ||
55 | |||
56 | static void banner_alarm_catch (int signum) | ||
57 | { | ||
58 | banner_timedout = 1; | ||
59 | } | ||
60 | |||
54 | static int show_other_keys(const char *, Key *); | 61 | static int show_other_keys(const char *, Key *); |
55 | static void warn_changed_key(Key *); | 62 | static void warn_changed_key(Key *); |
56 | 63 | ||
@@ -158,7 +165,7 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command) | |||
158 | buffer_free(&command); | 165 | buffer_free(&command); |
159 | 166 | ||
160 | /* Set the connection file descriptors. */ | 167 | /* Set the connection file descriptors. */ |
161 | packet_set_connection(pout[0], pin[1]); | 168 | packet_set_connection(pout[0], pin[1], options.setuptimeout); |
162 | 169 | ||
163 | /* Indicate OK return */ | 170 | /* Indicate OK return */ |
164 | return 0; | 171 | return 0; |
@@ -423,7 +430,7 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr, | |||
423 | error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); | 430 | error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); |
424 | 431 | ||
425 | /* Set the connection. */ | 432 | /* Set the connection. */ |
426 | packet_set_connection(sock, sock); | 433 | packet_set_connection(sock, sock, options.setuptimeout); |
427 | 434 | ||
428 | return 0; | 435 | return 0; |
429 | } | 436 | } |
@@ -440,24 +447,41 @@ ssh_exchange_identification(void) | |||
440 | int connection_in = packet_get_connection_in(); | 447 | int connection_in = packet_get_connection_in(); |
441 | int connection_out = packet_get_connection_out(); | 448 | int connection_out = packet_get_connection_out(); |
442 | int minor1 = PROTOCOL_MINOR_1; | 449 | int minor1 = PROTOCOL_MINOR_1; |
450 | struct sigaction sa, osa; | ||
443 | 451 | ||
444 | /* Read other side\'s version identification. */ | 452 | /* Read other side's version identification. |
453 | * If SetupTimeOut has been set, give up after | ||
454 | * the specified amount of time | ||
455 | */ | ||
456 | if(options.setuptimeout > 0){ | ||
457 | memset(&sa, 0, sizeof(sa)); | ||
458 | sa.sa_handler = banner_alarm_catch; | ||
459 | /*throw away any pending alarms, since we'd block otherwise*/ | ||
460 | alarm(0); | ||
461 | sigaction(SIGALRM, &sa, &osa); | ||
462 | alarm(options.setuptimeout); | ||
463 | } | ||
445 | for (;;) { | 464 | for (;;) { |
446 | for (i = 0; i < sizeof(buf) - 1; i++) { | 465 | for (i = 0; i < sizeof(buf) - 1; ) { |
447 | int len = atomicio(read, connection_in, &buf[i], 1); | 466 | int len = read(connection_in, &buf[i], 1); |
448 | if (len < 0) | 467 | if (banner_timedout) |
468 | fatal("ssh_exchange_identification: Timeout waiting for version information."); | ||
469 | if (len < 0) { | ||
470 | if (errno == EINTR) | ||
471 | continue; | ||
449 | fatal("ssh_exchange_identification: read: %.100s", strerror(errno)); | 472 | fatal("ssh_exchange_identification: read: %.100s", strerror(errno)); |
473 | } | ||
450 | if (len != 1) | 474 | if (len != 1) |
451 | fatal("ssh_exchange_identification: Connection closed by remote host"); | 475 | fatal("ssh_exchange_identification: Connection closed by remote host"); |
452 | if (buf[i] == '\r') { | ||
453 | buf[i] = '\n'; | ||
454 | buf[i + 1] = 0; | ||
455 | continue; /**XXX wait for \n */ | ||
456 | } | ||
457 | if (buf[i] == '\n') { | 476 | if (buf[i] == '\n') { |
458 | buf[i + 1] = 0; | 477 | buf[i + 1] = 0; |
459 | break; | 478 | break; |
460 | } | 479 | } |
480 | if (buf[i] == '\r') { | ||
481 | buf[i] = '\n'; | ||
482 | buf[i + 1] = 0; /**XXX wait for \n */ | ||
483 | } | ||
484 | i++; | ||
461 | } | 485 | } |
462 | buf[sizeof(buf) - 1] = 0; | 486 | buf[sizeof(buf) - 1] = 0; |
463 | if (strncmp(buf, "SSH-", 4) == 0) | 487 | if (strncmp(buf, "SSH-", 4) == 0) |
@@ -466,6 +490,14 @@ ssh_exchange_identification(void) | |||
466 | } | 490 | } |
467 | server_version_string = xstrdup(buf); | 491 | server_version_string = xstrdup(buf); |
468 | 492 | ||
493 | /* If SetupTimeOut has been set, unset the alarm now, and | ||
494 | * put the correct handler for SIGALRM back. | ||
495 | */ | ||
496 | if (options.setuptimeout > 0) { | ||
497 | alarm(0); | ||
498 | sigaction(SIGALRM,&osa,NULL); | ||
499 | } | ||
500 | |||
469 | /* | 501 | /* |
470 | * Check that the versions match. In future this might accept | 502 | * Check that the versions match. In future this might accept |
471 | * several versions and set appropriate flags to handle them. | 503 | * several versions and set appropriate flags to handle them. |