summaryrefslogtreecommitdiff
path: root/sshconnect.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshconnect.c')
-rw-r--r--sshconnect.c57
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
52static sig_atomic_t banner_timedout;
53
54static void banner_alarm_catch (int signum)
55{
56 banner_timedout = 1;
57}
58
52static int show_other_keys(const char *, Key *); 59static int show_other_keys(const char *, Key *);
53static void warn_changed_key(Key *); 60static 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);