summaryrefslogtreecommitdiff
path: root/sshconnect.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshconnect.c')
-rw-r--r--sshconnect.c56
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
77static sig_atomic_t banner_timedout;
78
79static void banner_alarm_catch (int signum)
80{
81 banner_timedout = 1;
82}
83
77static int show_other_keys(const char *, Key *); 84static int show_other_keys(const char *, Key *);
78static void warn_changed_key(Key *); 85static 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);