summaryrefslogtreecommitdiff
path: root/sshconnect.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2009-12-29 21:42:53 +0000
committerColin Watson <cjwatson@debian.org>2009-12-29 21:42:53 +0000
commit87552344215a38d3a2b0d4d63dc151e05978bbe1 (patch)
tree9f4b96055e6ccaa915e8d59d9f2805e9e119371d /sshconnect.c
parenta25ec0b132c44c9e341e08464ff830de06b81126 (diff)
parentef94e5613d37bcbf880f21ee6094e4b1c7683a4c (diff)
import openssh-5.1p1-gsskex-cjwatson-20080722.patch
Diffstat (limited to 'sshconnect.c')
-rw-r--r--sshconnect.c154
1 files changed, 117 insertions, 37 deletions
diff --git a/sshconnect.c b/sshconnect.c
index a222233d0..ec8ba33e0 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshconnect.c,v 1.200 2006/10/10 10:12:45 markus Exp $ */ 1/* $OpenBSD: sshconnect.c,v 1.211 2008/07/01 07:24:22 dtucker Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -86,7 +86,10 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command)
86 char *command_string, *tmp; 86 char *command_string, *tmp;
87 int pin[2], pout[2]; 87 int pin[2], pout[2];
88 pid_t pid; 88 pid_t pid;
89 char strport[NI_MAXSERV]; 89 char *shell, strport[NI_MAXSERV];
90
91 if ((shell = getenv("SHELL")) == NULL)
92 shell = _PATH_BSHELL;
90 93
91 /* Convert the port number into a string. */ 94 /* Convert the port number into a string. */
92 snprintf(strport, sizeof strport, "%hu", port); 95 snprintf(strport, sizeof strport, "%hu", port);
@@ -132,7 +135,7 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command)
132 135
133 /* Stderr is left as it is so that error messages get 136 /* Stderr is left as it is so that error messages get
134 printed on the user's terminal. */ 137 printed on the user's terminal. */
135 argv[0] = _PATH_BSHELL; 138 argv[0] = shell;
136 argv[1] = "-c"; 139 argv[1] = "-c";
137 argv[2] = command_string; 140 argv[2] = command_string;
138 argv[3] = NULL; 141 argv[3] = NULL;
@@ -158,6 +161,8 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command)
158 161
159 /* Set the connection file descriptors. */ 162 /* Set the connection file descriptors. */
160 packet_set_connection(pout[0], pin[1]); 163 packet_set_connection(pout[0], pin[1]);
164 packet_set_timeout(options.server_alive_interval,
165 options.server_alive_count_max);
161 166
162 /* Indicate OK return */ 167 /* Indicate OK return */
163 return 0; 168 return 0;
@@ -201,10 +206,10 @@ ssh_create_socket(int privileged, struct addrinfo *ai)
201 hints.ai_socktype = ai->ai_socktype; 206 hints.ai_socktype = ai->ai_socktype;
202 hints.ai_protocol = ai->ai_protocol; 207 hints.ai_protocol = ai->ai_protocol;
203 hints.ai_flags = AI_PASSIVE; 208 hints.ai_flags = AI_PASSIVE;
204 gaierr = getaddrinfo(options.bind_address, "0", &hints, &res); 209 gaierr = getaddrinfo(options.bind_address, NULL, &hints, &res);
205 if (gaierr) { 210 if (gaierr) {
206 error("getaddrinfo: %s: %s", options.bind_address, 211 error("getaddrinfo: %s: %s", options.bind_address,
207 gai_strerror(gaierr)); 212 ssh_gai_strerror(gaierr));
208 close(sock); 213 close(sock);
209 return -1; 214 return -1;
210 } 215 }
@@ -220,30 +225,36 @@ ssh_create_socket(int privileged, struct addrinfo *ai)
220 225
221static int 226static int
222timeout_connect(int sockfd, const struct sockaddr *serv_addr, 227timeout_connect(int sockfd, const struct sockaddr *serv_addr,
223 socklen_t addrlen, int timeout) 228 socklen_t addrlen, int *timeoutp)
224{ 229{
225 fd_set *fdset; 230 fd_set *fdset;
226 struct timeval tv; 231 struct timeval tv, t_start;
227 socklen_t optlen; 232 socklen_t optlen;
228 int optval, rc, result = -1; 233 int optval, rc, result = -1;
229 234
230 if (timeout <= 0) 235 gettimeofday(&t_start, NULL);
231 return (connect(sockfd, serv_addr, addrlen)); 236
237 if (*timeoutp <= 0) {
238 result = connect(sockfd, serv_addr, addrlen);
239 goto done;
240 }
232 241
233 set_nonblock(sockfd); 242 set_nonblock(sockfd);
234 rc = connect(sockfd, serv_addr, addrlen); 243 rc = connect(sockfd, serv_addr, addrlen);
235 if (rc == 0) { 244 if (rc == 0) {
236 unset_nonblock(sockfd); 245 unset_nonblock(sockfd);
237 return (0); 246 result = 0;
247 goto done;
248 }
249 if (errno != EINPROGRESS) {
250 result = -1;
251 goto done;
238 } 252 }
239 if (errno != EINPROGRESS)
240 return (-1);
241 253
242 fdset = (fd_set *)xcalloc(howmany(sockfd + 1, NFDBITS), 254 fdset = (fd_set *)xcalloc(howmany(sockfd + 1, NFDBITS),
243 sizeof(fd_mask)); 255 sizeof(fd_mask));
244 FD_SET(sockfd, fdset); 256 FD_SET(sockfd, fdset);
245 tv.tv_sec = timeout; 257 ms_to_timeval(&tv, *timeoutp);
246 tv.tv_usec = 0;
247 258
248 for (;;) { 259 for (;;) {
249 rc = select(sockfd + 1, NULL, fdset, NULL, &tv); 260 rc = select(sockfd + 1, NULL, fdset, NULL, &tv);
@@ -282,6 +293,16 @@ timeout_connect(int sockfd, const struct sockaddr *serv_addr,
282 } 293 }
283 294
284 xfree(fdset); 295 xfree(fdset);
296
297 done:
298 if (result == 0 && *timeoutp > 0) {
299 ms_subtract_diff(&t_start, timeoutp);
300 if (*timeoutp <= 0) {
301 errno = ETIMEDOUT;
302 result = -1;
303 }
304 }
305
285 return (result); 306 return (result);
286} 307}
287 308
@@ -298,8 +319,8 @@ timeout_connect(int sockfd, const struct sockaddr *serv_addr,
298 */ 319 */
299int 320int
300ssh_connect(const char *host, struct sockaddr_storage * hostaddr, 321ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
301 u_short port, int family, int connection_attempts, 322 u_short port, int family, int connection_attempts, int *timeout_ms,
302 int needpriv, const char *proxy_command) 323 int want_keepalive, int needpriv, const char *proxy_command)
303{ 324{
304 int gaierr; 325 int gaierr;
305 int on = 1; 326 int on = 1;
@@ -320,8 +341,8 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
320 hints.ai_socktype = SOCK_STREAM; 341 hints.ai_socktype = SOCK_STREAM;
321 snprintf(strport, sizeof strport, "%u", port); 342 snprintf(strport, sizeof strport, "%u", port);
322 if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) 343 if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0)
323 fatal("%s: %.100s: %s", __progname, host, 344 fatal("%s: Could not resolve hostname %.100s: %s", __progname,
324 gai_strerror(gaierr)); 345 host, ssh_gai_strerror(gaierr));
325 346
326 for (attempt = 0; attempt < connection_attempts; attempt++) { 347 for (attempt = 0; attempt < connection_attempts; attempt++) {
327 if (attempt > 0) { 348 if (attempt > 0) {
@@ -352,7 +373,7 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
352 continue; 373 continue;
353 374
354 if (timeout_connect(sock, ai->ai_addr, ai->ai_addrlen, 375 if (timeout_connect(sock, ai->ai_addr, ai->ai_addrlen,
355 options.connection_timeout) >= 0) { 376 timeout_ms) >= 0) {
356 /* Successful connection. */ 377 /* Successful connection. */
357 memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen); 378 memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen);
358 break; 379 break;
@@ -379,13 +400,15 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
379 debug("Connection established."); 400 debug("Connection established.");
380 401
381 /* Set SO_KEEPALIVE if requested. */ 402 /* Set SO_KEEPALIVE if requested. */
382 if (options.tcp_keep_alive && 403 if (want_keepalive &&
383 setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, 404 setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on,
384 sizeof(on)) < 0) 405 sizeof(on)) < 0)
385 error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); 406 error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
386 407
387 /* Set the connection. */ 408 /* Set the connection. */
388 packet_set_connection(sock, sock); 409 packet_set_connection(sock, sock);
410 packet_set_timeout(options.server_alive_interval,
411 options.server_alive_count_max);
389 412
390 return 0; 413 return 0;
391} 414}
@@ -395,7 +418,7 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
395 * identification string. 418 * identification string.
396 */ 419 */
397static void 420static void
398ssh_exchange_identification(void) 421ssh_exchange_identification(int timeout_ms)
399{ 422{
400 char buf[256], remote_version[256]; /* must be same size! */ 423 char buf[256], remote_version[256]; /* must be same size! */
401 int remote_major, remote_minor, mismatch; 424 int remote_major, remote_minor, mismatch;
@@ -403,16 +426,44 @@ ssh_exchange_identification(void)
403 int connection_out = packet_get_connection_out(); 426 int connection_out = packet_get_connection_out();
404 int minor1 = PROTOCOL_MINOR_1; 427 int minor1 = PROTOCOL_MINOR_1;
405 u_int i, n; 428 u_int i, n;
429 size_t len;
430 int fdsetsz, remaining, rc;
431 struct timeval t_start, t_remaining;
432 fd_set *fdset;
433
434 fdsetsz = howmany(connection_in + 1, NFDBITS) * sizeof(fd_mask);
435 fdset = xcalloc(1, fdsetsz);
406 436
407 /* Read other side's version identification. */ 437 /* Read other side's version identification. */
438 remaining = timeout_ms;
408 for (n = 0;;) { 439 for (n = 0;;) {
409 for (i = 0; i < sizeof(buf) - 1; i++) { 440 for (i = 0; i < sizeof(buf) - 1; i++) {
410 size_t len = atomicio(read, connection_in, &buf[i], 1); 441 if (timeout_ms > 0) {
442 gettimeofday(&t_start, NULL);
443 ms_to_timeval(&t_remaining, remaining);
444 FD_SET(connection_in, fdset);
445 rc = select(connection_in + 1, fdset, NULL,
446 fdset, &t_remaining);
447 ms_subtract_diff(&t_start, &remaining);
448 if (rc == 0 || remaining <= 0)
449 fatal("Connection timed out during "
450 "banner exchange");
451 if (rc == -1) {
452 if (errno == EINTR)
453 continue;
454 fatal("ssh_exchange_identification: "
455 "select: %s", strerror(errno));
456 }
457 }
458
459 len = atomicio(read, connection_in, &buf[i], 1);
411 460
412 if (len != 1 && errno == EPIPE) 461 if (len != 1 && errno == EPIPE)
413 fatal("ssh_exchange_identification: Connection closed by remote host"); 462 fatal("ssh_exchange_identification: "
463 "Connection closed by remote host");
414 else if (len != 1) 464 else if (len != 1)
415 fatal("ssh_exchange_identification: read: %.100s", strerror(errno)); 465 fatal("ssh_exchange_identification: "
466 "read: %.100s", strerror(errno));
416 if (buf[i] == '\r') { 467 if (buf[i] == '\r') {
417 buf[i] = '\n'; 468 buf[i] = '\n';
418 buf[i + 1] = 0; 469 buf[i + 1] = 0;
@@ -423,7 +474,8 @@ ssh_exchange_identification(void)
423 break; 474 break;
424 } 475 }
425 if (++n > 65536) 476 if (++n > 65536)
426 fatal("ssh_exchange_identification: No banner received"); 477 fatal("ssh_exchange_identification: "
478 "No banner received");
427 } 479 }
428 buf[sizeof(buf) - 1] = 0; 480 buf[sizeof(buf) - 1] = 0;
429 if (strncmp(buf, "SSH-", 4) == 0) 481 if (strncmp(buf, "SSH-", 4) == 0)
@@ -431,6 +483,7 @@ ssh_exchange_identification(void)
431 debug("ssh_exchange_identification: %s", buf); 483 debug("ssh_exchange_identification: %s", buf);
432 } 484 }
433 server_version_string = xstrdup(buf); 485 server_version_string = xstrdup(buf);
486 xfree(fdset);
434 487
435 /* 488 /*
436 * Check that the versions match. In future this might accept 489 * Check that the versions match. In future this might accept
@@ -484,10 +537,10 @@ ssh_exchange_identification(void)
484 (options.protocol & SSH_PROTO_2) ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1, 537 (options.protocol & SSH_PROTO_2) ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
485 remote_major); 538 remote_major);
486 /* Send our own protocol version identification. */ 539 /* Send our own protocol version identification. */
487 snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", 540 snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s",
488 compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1, 541 compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
489 compat20 ? PROTOCOL_MINOR_2 : minor1, 542 compat20 ? PROTOCOL_MINOR_2 : minor1,
490 SSH_VERSION); 543 SSH_VERSION, compat20 ? "\r\n" : "\n");
491 if (atomicio(vwrite, connection_out, buf, strlen(buf)) != strlen(buf)) 544 if (atomicio(vwrite, connection_out, buf, strlen(buf)) != strlen(buf))
492 fatal("write: %.100s", strerror(errno)); 545 fatal("write: %.100s", strerror(errno));
493 client_version_string = xstrdup(buf); 546 client_version_string = xstrdup(buf);
@@ -536,14 +589,14 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
536 Key *file_key; 589 Key *file_key;
537 const char *type = key_type(host_key); 590 const char *type = key_type(host_key);
538 char *ip = NULL, *host = NULL; 591 char *ip = NULL, *host = NULL;
539 char hostline[1000], *hostp, *fp; 592 char hostline[1000], *hostp, *fp, *ra;
540 HostStatus host_status; 593 HostStatus host_status;
541 HostStatus ip_status; 594 HostStatus ip_status;
542 int r, local = 0, host_ip_differ = 0; 595 int r, local = 0, host_ip_differ = 0;
543 int salen; 596 int salen;
544 char ntop[NI_MAXHOST]; 597 char ntop[NI_MAXHOST];
545 char msg[1024]; 598 char msg[1024];
546 int len, host_line, ip_line; 599 int len, host_line, ip_line, cancelled_forwarding = 0;
547 const char *host_file = NULL, *ip_file = NULL; 600 const char *host_file = NULL, *ip_file = NULL;
548 601
549 /* 602 /*
@@ -590,6 +643,7 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
590 } else { 643 } else {
591 ip = xstrdup("<no hostip for proxy command>"); 644 ip = xstrdup("<no hostip for proxy command>");
592 } 645 }
646
593 /* 647 /*
594 * Turn off check_host_ip if the connection is to localhost, via proxy 648 * Turn off check_host_ip if the connection is to localhost, via proxy
595 * command or if we don't have a hostname to compare with 649 * command or if we don't have a hostname to compare with
@@ -674,6 +728,13 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
674 logit("Warning: Permanently added the %s host " 728 logit("Warning: Permanently added the %s host "
675 "key for IP address '%.128s' to the list " 729 "key for IP address '%.128s' to the list "
676 "of known hosts.", type, ip); 730 "of known hosts.", type, ip);
731 } else if (options.visual_host_key) {
732 fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
733 ra = key_fingerprint(host_key, SSH_FP_MD5,
734 SSH_FP_RANDOMART);
735 logit("Host key fingerprint is %s\n%s\n", fp, ra);
736 xfree(ra);
737 xfree(fp);
677 } 738 }
678 break; 739 break;
679 case HOST_NEW: 740 case HOST_NEW:
@@ -709,6 +770,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
709 snprintf(msg1, sizeof(msg1), "."); 770 snprintf(msg1, sizeof(msg1), ".");
710 /* The default */ 771 /* The default */
711 fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); 772 fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
773 ra = key_fingerprint(host_key, SSH_FP_MD5,
774 SSH_FP_RANDOMART);
712 msg2[0] = '\0'; 775 msg2[0] = '\0';
713 if (options.verify_host_key_dns) { 776 if (options.verify_host_key_dns) {
714 if (matching_host_key_dns) 777 if (matching_host_key_dns)
@@ -723,10 +786,14 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
723 snprintf(msg, sizeof(msg), 786 snprintf(msg, sizeof(msg),
724 "The authenticity of host '%.200s (%s)' can't be " 787 "The authenticity of host '%.200s (%s)' can't be "
725 "established%s\n" 788 "established%s\n"
726 "%s key fingerprint is %s.\n%s" 789 "%s key fingerprint is %s.%s%s\n%s"
727 "Are you sure you want to continue connecting " 790 "Are you sure you want to continue connecting "
728 "(yes/no)? ", 791 "(yes/no)? ",
729 host, ip, msg1, type, fp, msg2); 792 host, ip, msg1, type, fp,
793 options.visual_host_key ? "\n" : "",
794 options.visual_host_key ? ra : "",
795 msg2);
796 xfree(ra);
730 xfree(fp); 797 xfree(fp);
731 if (!confirm(msg)) 798 if (!confirm(msg))
732 goto fail; 799 goto fail;
@@ -779,7 +846,7 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
779 error("@ WARNING: POSSIBLE DNS SPOOFING DETECTED! @"); 846 error("@ WARNING: POSSIBLE DNS SPOOFING DETECTED! @");
780 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); 847 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
781 error("The %s host key for %s has changed,", type, host); 848 error("The %s host key for %s has changed,", type, host);
782 error("and the key for the according IP address %s", ip); 849 error("and the key for the corresponding IP address %s", ip);
783 error("%s. This could either mean that", key_msg); 850 error("%s. This could either mean that", key_msg);
784 error("DNS SPOOFING is happening or the IP address for the host"); 851 error("DNS SPOOFING is happening or the IP address for the host");
785 error("and its host key have changed at the same time."); 852 error("and its host key have changed at the same time.");
@@ -811,27 +878,32 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
811 error("Password authentication is disabled to avoid " 878 error("Password authentication is disabled to avoid "
812 "man-in-the-middle attacks."); 879 "man-in-the-middle attacks.");
813 options.password_authentication = 0; 880 options.password_authentication = 0;
881 cancelled_forwarding = 1;
814 } 882 }
815 if (options.kbd_interactive_authentication) { 883 if (options.kbd_interactive_authentication) {
816 error("Keyboard-interactive authentication is disabled" 884 error("Keyboard-interactive authentication is disabled"
817 " to avoid man-in-the-middle attacks."); 885 " to avoid man-in-the-middle attacks.");
818 options.kbd_interactive_authentication = 0; 886 options.kbd_interactive_authentication = 0;
819 options.challenge_response_authentication = 0; 887 options.challenge_response_authentication = 0;
888 cancelled_forwarding = 1;
820 } 889 }
821 if (options.challenge_response_authentication) { 890 if (options.challenge_response_authentication) {
822 error("Challenge/response authentication is disabled" 891 error("Challenge/response authentication is disabled"
823 " to avoid man-in-the-middle attacks."); 892 " to avoid man-in-the-middle attacks.");
824 options.challenge_response_authentication = 0; 893 options.challenge_response_authentication = 0;
894 cancelled_forwarding = 1;
825 } 895 }
826 if (options.forward_agent) { 896 if (options.forward_agent) {
827 error("Agent forwarding is disabled to avoid " 897 error("Agent forwarding is disabled to avoid "
828 "man-in-the-middle attacks."); 898 "man-in-the-middle attacks.");
829 options.forward_agent = 0; 899 options.forward_agent = 0;
900 cancelled_forwarding = 1;
830 } 901 }
831 if (options.forward_x11) { 902 if (options.forward_x11) {
832 error("X11 forwarding is disabled to avoid " 903 error("X11 forwarding is disabled to avoid "
833 "man-in-the-middle attacks."); 904 "man-in-the-middle attacks.");
834 options.forward_x11 = 0; 905 options.forward_x11 = 0;
906 cancelled_forwarding = 1;
835 } 907 }
836 if (options.num_local_forwards > 0 || 908 if (options.num_local_forwards > 0 ||
837 options.num_remote_forwards > 0) { 909 options.num_remote_forwards > 0) {
@@ -839,12 +911,18 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
839 "man-in-the-middle attacks."); 911 "man-in-the-middle attacks.");
840 options.num_local_forwards = 912 options.num_local_forwards =
841 options.num_remote_forwards = 0; 913 options.num_remote_forwards = 0;
914 cancelled_forwarding = 1;
842 } 915 }
843 if (options.tun_open != SSH_TUNMODE_NO) { 916 if (options.tun_open != SSH_TUNMODE_NO) {
844 error("Tunnel forwarding is disabled to avoid " 917 error("Tunnel forwarding is disabled to avoid "
845 "man-in-the-middle attacks."); 918 "man-in-the-middle attacks.");
846 options.tun_open = SSH_TUNMODE_NO; 919 options.tun_open = SSH_TUNMODE_NO;
920 cancelled_forwarding = 1;
847 } 921 }
922 if (options.exit_on_forward_failure && cancelled_forwarding)
923 fatal("Error: forwarding disabled due to host key "
924 "check failure");
925
848 /* 926 /*
849 * XXX Should permit the user to change to use the new id. 927 * XXX Should permit the user to change to use the new id.
850 * This could be done by converting the host key to an 928 * This could be done by converting the host key to an
@@ -943,7 +1021,7 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
943 */ 1021 */
944void 1022void
945ssh_login(Sensitive *sensitive, const char *orighost, 1023ssh_login(Sensitive *sensitive, const char *orighost,
946 struct sockaddr *hostaddr, struct passwd *pw) 1024 struct sockaddr *hostaddr, struct passwd *pw, int timeout_ms)
947{ 1025{
948 char *host, *cp; 1026 char *host, *cp;
949 char *server_user, *local_user; 1027 char *server_user, *local_user;
@@ -958,7 +1036,7 @@ ssh_login(Sensitive *sensitive, const char *orighost,
958 *cp = (char)tolower(*cp); 1036 *cp = (char)tolower(*cp);
959 1037
960 /* Exchange protocol version identification strings with the server. */ 1038 /* Exchange protocol version identification strings with the server. */
961 ssh_exchange_identification(); 1039 ssh_exchange_identification(timeout_ms);
962 1040
963 /* Put the connection into non-blocking mode. */ 1041 /* Put the connection into non-blocking mode. */
964 packet_set_nonblocking(); 1042 packet_set_nonblocking();
@@ -997,18 +1075,20 @@ static int
997show_key_from_file(const char *file, const char *host, int keytype) 1075show_key_from_file(const char *file, const char *host, int keytype)
998{ 1076{
999 Key *found; 1077 Key *found;
1000 char *fp; 1078 char *fp, *ra;
1001 int line, ret; 1079 int line, ret;
1002 1080
1003 found = key_new(keytype); 1081 found = key_new(keytype);
1004 if ((ret = lookup_key_in_hostfile_by_type(file, host, 1082 if ((ret = lookup_key_in_hostfile_by_type(file, host,
1005 keytype, found, &line))) { 1083 keytype, found, &line))) {
1006 fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); 1084 fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
1085 ra = key_fingerprint(found, SSH_FP_MD5, SSH_FP_RANDOMART);
1007 logit("WARNING: %s key found for host %s\n" 1086 logit("WARNING: %s key found for host %s\n"
1008 "in %s:%d\n" 1087 "in %s:%d\n"
1009 "%s key fingerprint %s.", 1088 "%s key fingerprint %s.\n%s\n",
1010 key_type(found), host, file, line, 1089 key_type(found), host, file, line,
1011 key_type(found), fp); 1090 key_type(found), fp, ra);
1091 xfree(ra);
1012 xfree(fp); 1092 xfree(fp);
1013 } 1093 }
1014 key_free(found); 1094 key_free(found);