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