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 11008e544..5158416f0 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; |
@@ -422,7 +429,7 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr, | |||
422 | error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); | 429 | error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); |
423 | 430 | ||
424 | /* Set the connection. */ | 431 | /* Set the connection. */ |
425 | packet_set_connection(sock, sock); | 432 | packet_set_connection(sock, sock, options.setuptimeout); |
426 | 433 | ||
427 | return 0; | 434 | return 0; |
428 | } | 435 | } |
@@ -439,24 +446,41 @@ ssh_exchange_identification(void) | |||
439 | int connection_in = packet_get_connection_in(); | 446 | int connection_in = packet_get_connection_in(); |
440 | int connection_out = packet_get_connection_out(); | 447 | int connection_out = packet_get_connection_out(); |
441 | int minor1 = PROTOCOL_MINOR_1; | 448 | int minor1 = PROTOCOL_MINOR_1; |
449 | struct sigaction sa, osa; | ||
442 | 450 | ||
443 | /* Read other side\'s version identification. */ | 451 | /* Read other side's version identification. |
452 | * If SetupTimeOut has been set, give up after | ||
453 | * the specified amount of time | ||
454 | */ | ||
455 | if(options.setuptimeout > 0){ | ||
456 | memset(&sa, 0, sizeof(sa)); | ||
457 | sa.sa_handler = banner_alarm_catch; | ||
458 | /*throw away any pending alarms, since we'd block otherwise*/ | ||
459 | alarm(0); | ||
460 | sigaction(SIGALRM, &sa, &osa); | ||
461 | alarm(options.setuptimeout); | ||
462 | } | ||
444 | for (;;) { | 463 | for (;;) { |
445 | for (i = 0; i < sizeof(buf) - 1; i++) { | 464 | for (i = 0; i < sizeof(buf) - 1; ) { |
446 | int len = atomicio(read, connection_in, &buf[i], 1); | 465 | int len = read(connection_in, &buf[i], 1); |
447 | if (len < 0) | 466 | if (banner_timedout) |
467 | fatal("ssh_exchange_identification: Timeout waiting for version information."); | ||
468 | if (len < 0) { | ||
469 | if (errno == EINTR) | ||
470 | continue; | ||
448 | fatal("ssh_exchange_identification: read: %.100s", strerror(errno)); | 471 | fatal("ssh_exchange_identification: read: %.100s", strerror(errno)); |
472 | } | ||
449 | if (len != 1) | 473 | if (len != 1) |
450 | fatal("ssh_exchange_identification: Connection closed by remote host"); | 474 | fatal("ssh_exchange_identification: Connection closed by remote host"); |
451 | if (buf[i] == '\r') { | ||
452 | buf[i] = '\n'; | ||
453 | buf[i + 1] = 0; | ||
454 | continue; /**XXX wait for \n */ | ||
455 | } | ||
456 | if (buf[i] == '\n') { | 475 | if (buf[i] == '\n') { |
457 | buf[i + 1] = 0; | 476 | buf[i + 1] = 0; |
458 | break; | 477 | break; |
459 | } | 478 | } |
479 | if (buf[i] == '\r') { | ||
480 | buf[i] = '\n'; | ||
481 | buf[i + 1] = 0; /**XXX wait for \n */ | ||
482 | } | ||
483 | i++; | ||
460 | } | 484 | } |
461 | buf[sizeof(buf) - 1] = 0; | 485 | buf[sizeof(buf) - 1] = 0; |
462 | if (strncmp(buf, "SSH-", 4) == 0) | 486 | if (strncmp(buf, "SSH-", 4) == 0) |
@@ -465,6 +489,14 @@ ssh_exchange_identification(void) | |||
465 | } | 489 | } |
466 | server_version_string = xstrdup(buf); | 490 | server_version_string = xstrdup(buf); |
467 | 491 | ||
492 | /* If SetupTimeOut has been set, unset the alarm now, and | ||
493 | * put the correct handler for SIGALRM back. | ||
494 | */ | ||
495 | if (options.setuptimeout > 0) { | ||
496 | alarm(0); | ||
497 | sigaction(SIGALRM,&osa,NULL); | ||
498 | } | ||
499 | |||
468 | /* | 500 | /* |
469 | * Check that the versions match. In future this might accept | 501 | * Check that the versions match. In future this might accept |
470 | * several versions and set appropriate flags to handle them. | 502 | * several versions and set appropriate flags to handle them. |