diff options
Diffstat (limited to 'sshconnect.c')
-rw-r--r-- | sshconnect.c | 57 |
1 files changed, 50 insertions, 7 deletions
diff --git a/sshconnect.c b/sshconnect.c index 64ffec240..8a63ef22b 100644 --- a/sshconnect.c +++ b/sshconnect.c | |||
@@ -49,6 +49,13 @@ extern pid_t proxy_command_pid; | |||
49 | #define INET6_ADDRSTRLEN 46 | 49 | #define INET6_ADDRSTRLEN 46 |
50 | #endif | 50 | #endif |
51 | 51 | ||
52 | static sig_atomic_t banner_timedout; | ||
53 | |||
54 | static void banner_alarm_catch (int signum) | ||
55 | { | ||
56 | banner_timedout = 1; | ||
57 | } | ||
58 | |||
52 | static int show_other_keys(const char *, Key *); | 59 | static int show_other_keys(const char *, Key *); |
53 | static void warn_changed_key(Key *); | 60 | static void warn_changed_key(Key *); |
54 | 61 | ||
@@ -137,7 +144,7 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command) | |||
137 | xfree(command_string); | 144 | xfree(command_string); |
138 | 145 | ||
139 | /* Set the connection file descriptors. */ | 146 | /* Set the connection file descriptors. */ |
140 | packet_set_connection(pout[0], pin[1]); | 147 | packet_set_connection(pout[0], pin[1], options.setuptimeout); |
141 | 148 | ||
142 | /* Indicate OK return */ | 149 | /* Indicate OK return */ |
143 | return 0; | 150 | return 0; |
@@ -379,7 +386,7 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr, | |||
379 | error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); | 386 | error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); |
380 | 387 | ||
381 | /* Set the connection. */ | 388 | /* Set the connection. */ |
382 | packet_set_connection(sock, sock); | 389 | packet_set_connection(sock, sock, options.setuptimeout); |
383 | 390 | ||
384 | return 0; | 391 | return 0; |
385 | } | 392 | } |
@@ -397,16 +404,39 @@ ssh_exchange_identification(void) | |||
397 | int connection_out = packet_get_connection_out(); | 404 | int connection_out = packet_get_connection_out(); |
398 | int minor1 = PROTOCOL_MINOR_1; | 405 | int minor1 = PROTOCOL_MINOR_1; |
399 | u_int i; | 406 | u_int i; |
407 | struct sigaction sa, osa; | ||
400 | 408 | ||
401 | /* Read other side's version identification. */ | 409 | /* Read other side's version identification. |
410 | * If SetupTimeOut has been set, give up after | ||
411 | * the specified amount of time | ||
412 | */ | ||
413 | if(options.setuptimeout > 0){ | ||
414 | memset(&sa, 0, sizeof(sa)); | ||
415 | sa.sa_handler = banner_alarm_catch; | ||
416 | /*throw away any pending alarms, since we'd block otherwise*/ | ||
417 | alarm(0); | ||
418 | sigaction(SIGALRM, &sa, &osa); | ||
419 | alarm(options.setuptimeout); | ||
420 | } | ||
402 | for (;;) { | 421 | for (;;) { |
403 | for (i = 0; i < sizeof(buf) - 1; i++) { | 422 | for (i = 0; i < sizeof(buf) - 1; ) { |
404 | size_t len = atomicio(read, connection_in, &buf[i], 1); | 423 | ssize_t len = read(connection_in, &buf[i], 1); |
424 | if (banner_timedout) | ||
425 | fatal("ssh_exchange_identification: Timeout waiting for version information."); | ||
426 | if (len == 0) | ||
427 | errno = EPIPE; | ||
405 | 428 | ||
406 | if (len != 1 && errno == EPIPE) | 429 | if (len != 1 && errno == EPIPE) |
407 | fatal("ssh_exchange_identification: Connection closed by remote host"); | 430 | fatal("ssh_exchange_identification: Connection closed by remote host"); |
408 | else if (len != 1) | 431 | else if (len != 1) { |
432 | #ifdef EWOULDBLOCK | ||
433 | if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) | ||
434 | #else | ||
435 | if (errno == EINTR || errno == EAGAIN) | ||
436 | #endif | ||
437 | continue; | ||
409 | fatal("ssh_exchange_identification: read: %.100s", strerror(errno)); | 438 | fatal("ssh_exchange_identification: read: %.100s", strerror(errno)); |
439 | } | ||
410 | if (buf[i] == '\r') { | 440 | if (buf[i] == '\r') { |
411 | buf[i] = '\n'; | 441 | buf[i] = '\n'; |
412 | buf[i + 1] = 0; | 442 | buf[i + 1] = 0; |
@@ -416,6 +446,11 @@ ssh_exchange_identification(void) | |||
416 | buf[i + 1] = 0; | 446 | buf[i + 1] = 0; |
417 | break; | 447 | break; |
418 | } | 448 | } |
449 | if (buf[i] == '\r') { | ||
450 | buf[i] = '\n'; | ||
451 | buf[i + 1] = 0; /**XXX wait for \n */ | ||
452 | } | ||
453 | i++; | ||
419 | } | 454 | } |
420 | buf[sizeof(buf) - 1] = 0; | 455 | buf[sizeof(buf) - 1] = 0; |
421 | if (strncmp(buf, "SSH-", 4) == 0) | 456 | if (strncmp(buf, "SSH-", 4) == 0) |
@@ -424,6 +459,14 @@ ssh_exchange_identification(void) | |||
424 | } | 459 | } |
425 | server_version_string = xstrdup(buf); | 460 | server_version_string = xstrdup(buf); |
426 | 461 | ||
462 | /* If SetupTimeOut has been set, unset the alarm now, and | ||
463 | * put the correct handler for SIGALRM back. | ||
464 | */ | ||
465 | if (options.setuptimeout > 0) { | ||
466 | alarm(0); | ||
467 | sigaction(SIGALRM,&osa,NULL); | ||
468 | } | ||
469 | |||
427 | /* | 470 | /* |
428 | * Check that the versions match. In future this might accept | 471 | * Check that the versions match. In future this might accept |
429 | * several versions and set appropriate flags to handle them. | 472 | * several versions and set appropriate flags to handle them. |
@@ -479,7 +522,7 @@ ssh_exchange_identification(void) | |||
479 | snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", | 522 | snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", |
480 | compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1, | 523 | compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1, |
481 | compat20 ? PROTOCOL_MINOR_2 : minor1, | 524 | compat20 ? PROTOCOL_MINOR_2 : minor1, |
482 | SSH_VERSION); | 525 | SSH_RELEASE); |
483 | if (atomicio(vwrite, connection_out, buf, strlen(buf)) != strlen(buf)) | 526 | if (atomicio(vwrite, connection_out, buf, strlen(buf)) != strlen(buf)) |
484 | fatal("write: %.100s", strerror(errno)); | 527 | fatal("write: %.100s", strerror(errno)); |
485 | client_version_string = xstrdup(buf); | 528 | client_version_string = xstrdup(buf); |