diff options
Diffstat (limited to 'sshconnect.c')
-rw-r--r-- | sshconnect.c | 56 |
1 files changed, 50 insertions, 6 deletions
diff --git a/sshconnect.c b/sshconnect.c index a222233d0..3c888e36a 100644 --- a/sshconnect.c +++ b/sshconnect.c | |||
@@ -74,6 +74,13 @@ extern pid_t proxy_command_pid; | |||
74 | #define INET6_ADDRSTRLEN 46 | 74 | #define INET6_ADDRSTRLEN 46 |
75 | #endif | 75 | #endif |
76 | 76 | ||
77 | static sig_atomic_t banner_timedout; | ||
78 | |||
79 | static void banner_alarm_catch (int signum) | ||
80 | { | ||
81 | banner_timedout = 1; | ||
82 | } | ||
83 | |||
77 | static int show_other_keys(const char *, Key *); | 84 | static int show_other_keys(const char *, Key *); |
78 | static void warn_changed_key(Key *); | 85 | static void warn_changed_key(Key *); |
79 | 86 | ||
@@ -157,7 +164,7 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command) | |||
157 | xfree(command_string); | 164 | xfree(command_string); |
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; |
@@ -385,7 +392,7 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr, | |||
385 | error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); | 392 | error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); |
386 | 393 | ||
387 | /* Set the connection. */ | 394 | /* Set the connection. */ |
388 | packet_set_connection(sock, sock); | 395 | packet_set_connection(sock, sock, options.setuptimeout); |
389 | 396 | ||
390 | return 0; | 397 | return 0; |
391 | } | 398 | } |
@@ -403,16 +410,40 @@ ssh_exchange_identification(void) | |||
403 | int connection_out = packet_get_connection_out(); | 410 | int connection_out = packet_get_connection_out(); |
404 | int minor1 = PROTOCOL_MINOR_1; | 411 | int minor1 = PROTOCOL_MINOR_1; |
405 | u_int i, n; | 412 | u_int i, n; |
413 | struct sigaction sa, osa; | ||
406 | 414 | ||
415 | /* Read other side's version identification. | ||
416 | * If SetupTimeOut has been set, give up after the specified amount | ||
417 | * of time. | ||
418 | */ | ||
419 | if (options.setuptimeout > 0) { | ||
420 | memset(&sa, 0, sizeof(sa)); | ||
421 | sa.sa_handler = banner_alarm_catch; | ||
422 | /* throw away any pending alarms, since we'd block otherwise */ | ||
423 | alarm(0); | ||
424 | sigaction(SIGALRM, &sa, &osa); | ||
425 | alarm(options.setuptimeout); | ||
426 | } | ||
407 | /* Read other side's version identification. */ | 427 | /* Read other side's version identification. */ |
408 | for (n = 0;;) { | 428 | for (n = 0;;) { |
409 | for (i = 0; i < sizeof(buf) - 1; i++) { | 429 | for (i = 0; i < sizeof(buf) - 1; ) { |
410 | size_t len = atomicio(read, connection_in, &buf[i], 1); | 430 | ssize_t len = read(connection_in, &buf[i], 1); |
431 | if (banner_timedout) | ||
432 | fatal("ssh_exchange_identification: Timeout waiting for version information."); | ||
433 | if (len == 0) | ||
434 | errno = EPIPE; | ||
411 | 435 | ||
412 | if (len != 1 && errno == EPIPE) | 436 | if (len != 1 && errno == EPIPE) |
413 | fatal("ssh_exchange_identification: Connection closed by remote host"); | 437 | fatal("ssh_exchange_identification: Connection closed by remote host"); |
414 | else if (len != 1) | 438 | else if (len != 1) { |
439 | #ifdef EWOULDBLOCK | ||
440 | if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) | ||
441 | #else | ||
442 | if (errno == EINTR || errno == EAGAIN) | ||
443 | #endif | ||
444 | continue; | ||
415 | fatal("ssh_exchange_identification: read: %.100s", strerror(errno)); | 445 | fatal("ssh_exchange_identification: read: %.100s", strerror(errno)); |
446 | } | ||
416 | if (buf[i] == '\r') { | 447 | if (buf[i] == '\r') { |
417 | buf[i] = '\n'; | 448 | buf[i] = '\n'; |
418 | buf[i + 1] = 0; | 449 | buf[i + 1] = 0; |
@@ -422,8 +453,13 @@ ssh_exchange_identification(void) | |||
422 | buf[i + 1] = 0; | 453 | buf[i + 1] = 0; |
423 | break; | 454 | break; |
424 | } | 455 | } |
456 | if (buf[i] == '\r') { | ||
457 | buf[i] = '\n'; | ||
458 | buf[i + 1] = 0; /**XXX wait for \n */ | ||
459 | } | ||
425 | if (++n > 65536) | 460 | if (++n > 65536) |
426 | fatal("ssh_exchange_identification: No banner received"); | 461 | fatal("ssh_exchange_identification: No banner received"); |
462 | i++; | ||
427 | } | 463 | } |
428 | buf[sizeof(buf) - 1] = 0; | 464 | buf[sizeof(buf) - 1] = 0; |
429 | if (strncmp(buf, "SSH-", 4) == 0) | 465 | if (strncmp(buf, "SSH-", 4) == 0) |
@@ -432,6 +468,14 @@ ssh_exchange_identification(void) | |||
432 | } | 468 | } |
433 | server_version_string = xstrdup(buf); | 469 | server_version_string = xstrdup(buf); |
434 | 470 | ||
471 | /* If SetupTimeOut has been set, unset the alarm now, and | ||
472 | * put the correct handler for SIGALRM back. | ||
473 | */ | ||
474 | if (options.setuptimeout > 0) { | ||
475 | alarm(0); | ||
476 | sigaction(SIGALRM, &osa, NULL); | ||
477 | } | ||
478 | |||
435 | /* | 479 | /* |
436 | * Check that the versions match. In future this might accept | 480 | * Check that the versions match. In future this might accept |
437 | * several versions and set appropriate flags to handle them. | 481 | * several versions and set appropriate flags to handle them. |
@@ -487,7 +531,7 @@ ssh_exchange_identification(void) | |||
487 | snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", | 531 | snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", |
488 | compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1, | 532 | compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1, |
489 | compat20 ? PROTOCOL_MINOR_2 : minor1, | 533 | compat20 ? PROTOCOL_MINOR_2 : minor1, |
490 | SSH_VERSION); | 534 | SSH_RELEASE); |
491 | if (atomicio(vwrite, connection_out, buf, strlen(buf)) != strlen(buf)) | 535 | if (atomicio(vwrite, connection_out, buf, strlen(buf)) != strlen(buf)) |
492 | fatal("write: %.100s", strerror(errno)); | 536 | fatal("write: %.100s", strerror(errno)); |
493 | client_version_string = xstrdup(buf); | 537 | client_version_string = xstrdup(buf); |