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