summaryrefslogtreecommitdiff
path: root/sshconnect.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshconnect.c')
-rw-r--r--sshconnect.c163
1 files changed, 99 insertions, 64 deletions
diff --git a/sshconnect.c b/sshconnect.c
index 8a63ef22b..3c888e36a 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: sshconnect.c,v 1.200 2006/10/10 10:12:45 markus Exp $ */
1/* 2/*
2 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -13,12 +14,35 @@
13 */ 14 */
14 15
15#include "includes.h" 16#include "includes.h"
16RCSID("$OpenBSD: sshconnect.c,v 1.171 2005/12/06 22:38:27 reyk Exp $");
17 17
18#include <openssl/bn.h> 18#include <sys/types.h>
19#include <sys/wait.h>
20#include <sys/stat.h>
21#include <sys/socket.h>
22#ifdef HAVE_SYS_TIME_H
23# include <sys/time.h>
24#endif
25
26#include <netinet/in.h>
27#include <arpa/inet.h>
28
29#include <ctype.h>
30#include <errno.h>
31#include <netdb.h>
32#ifdef HAVE_PATHS_H
33#include <paths.h>
34#endif
35#include <pwd.h>
36#include <stdarg.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40#include <unistd.h>
19 41
20#include "ssh.h"
21#include "xmalloc.h" 42#include "xmalloc.h"
43#include "key.h"
44#include "hostfile.h"
45#include "ssh.h"
22#include "rsa.h" 46#include "rsa.h"
23#include "buffer.h" 47#include "buffer.h"
24#include "packet.h" 48#include "packet.h"
@@ -32,6 +56,7 @@ RCSID("$OpenBSD: sshconnect.c,v 1.171 2005/12/06 22:38:27 reyk Exp $");
32#include "atomicio.h" 56#include "atomicio.h"
33#include "misc.h" 57#include "misc.h"
34#include "dns.h" 58#include "dns.h"
59#include "version.h"
35 60
36char *client_version_string = NULL; 61char *client_version_string = NULL;
37char *server_version_string = NULL; 62char *server_version_string = NULL;
@@ -69,7 +94,6 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command)
69 int pin[2], pout[2]; 94 int pin[2], pout[2];
70 pid_t pid; 95 pid_t pid;
71 char strport[NI_MAXSERV]; 96 char strport[NI_MAXSERV];
72 size_t len;
73 97
74 /* Convert the port number into a string. */ 98 /* Convert the port number into a string. */
75 snprintf(strport, sizeof strport, "%hu", port); 99 snprintf(strport, sizeof strport, "%hu", port);
@@ -81,10 +105,7 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command)
81 * Use "exec" to avoid "sh -c" processes on some platforms 105 * Use "exec" to avoid "sh -c" processes on some platforms
82 * (e.g. Solaris) 106 * (e.g. Solaris)
83 */ 107 */
84 len = strlen(proxy_command) + 6; 108 xasprintf(&tmp, "exec %s", proxy_command);
85 tmp = xmalloc(len);
86 strlcpy(tmp, "exec ", len);
87 strlcat(tmp, proxy_command, len);
88 command_string = percent_expand(tmp, "h", host, 109 command_string = percent_expand(tmp, "h", host,
89 "p", strport, (char *)NULL); 110 "p", strport, (char *)NULL);
90 xfree(tmp); 111 xfree(tmp);
@@ -101,8 +122,7 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command)
101 char *argv[10]; 122 char *argv[10];
102 123
103 /* Child. Permanently give up superuser privileges. */ 124 /* Child. Permanently give up superuser privileges. */
104 seteuid(original_real_uid); 125 permanently_drop_suid(original_real_uid);
105 setuid(original_real_uid);
106 126
107 /* Redirect stdin and stdout. */ 127 /* Redirect stdin and stdout. */
108 close(pin[1]); 128 close(pin[1]);
@@ -212,7 +232,7 @@ timeout_connect(int sockfd, const struct sockaddr *serv_addr,
212 fd_set *fdset; 232 fd_set *fdset;
213 struct timeval tv; 233 struct timeval tv;
214 socklen_t optlen; 234 socklen_t optlen;
215 int fdsetsz, optval, rc, result = -1; 235 int optval, rc, result = -1;
216 236
217 if (timeout <= 0) 237 if (timeout <= 0)
218 return (connect(sockfd, serv_addr, addrlen)); 238 return (connect(sockfd, serv_addr, addrlen));
@@ -226,10 +246,8 @@ timeout_connect(int sockfd, const struct sockaddr *serv_addr,
226 if (errno != EINPROGRESS) 246 if (errno != EINPROGRESS)
227 return (-1); 247 return (-1);
228 248
229 fdsetsz = howmany(sockfd + 1, NFDBITS) * sizeof(fd_mask); 249 fdset = (fd_set *)xcalloc(howmany(sockfd + 1, NFDBITS),
230 fdset = (fd_set *)xmalloc(fdsetsz); 250 sizeof(fd_mask));
231
232 memset(fdset, 0, fdsetsz);
233 FD_SET(sockfd, fdset); 251 FD_SET(sockfd, fdset);
234 tv.tv_sec = timeout; 252 tv.tv_sec = timeout;
235 tv.tv_usec = 0; 253 tv.tv_usec = 0;
@@ -312,17 +330,16 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
312 fatal("%s: %.100s: %s", __progname, host, 330 fatal("%s: %.100s: %s", __progname, host,
313 gai_strerror(gaierr)); 331 gai_strerror(gaierr));
314 332
315 /* 333 for (attempt = 0; attempt < connection_attempts; attempt++) {
316 * Try to connect several times. On some machines, the first time 334 if (attempt > 0) {
317 * will sometimes fail. In general socket code appears to behave 335 /* Sleep a moment before retrying. */
318 * quite magically on many machines. 336 sleep(1);
319 */
320 for (attempt = 0; ;) {
321 if (attempt > 0)
322 debug("Trying again..."); 337 debug("Trying again...");
323 338 }
324 /* Loop through addresses for this host, and try each one in 339 /*
325 sequence until the connection succeeds. */ 340 * Loop through addresses for this host, and try each one in
341 * sequence until the connection succeeds.
342 */
326 for (ai = aitop; ai; ai = ai->ai_next) { 343 for (ai = aitop; ai; ai = ai->ai_next) {
327 if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) 344 if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
328 continue; 345 continue;
@@ -349,29 +366,18 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
349 } else { 366 } else {
350 debug("connect to address %s port %s: %s", 367 debug("connect to address %s port %s: %s",
351 ntop, strport, strerror(errno)); 368 ntop, strport, strerror(errno));
352 /*
353 * Close the failed socket; there appear to
354 * be some problems when reusing a socket for
355 * which connect() has already returned an
356 * error.
357 */
358 close(sock); 369 close(sock);
370 sock = -1;
359 } 371 }
360 } 372 }
361 if (ai) 373 if (sock != -1)
362 break; /* Successful connection. */ 374 break; /* Successful connection. */
363
364 attempt++;
365 if (attempt >= connection_attempts)
366 break;
367 /* Sleep a moment before retrying. */
368 sleep(1);
369 } 375 }
370 376
371 freeaddrinfo(aitop); 377 freeaddrinfo(aitop);
372 378
373 /* Return failure if we didn't get a successful connection. */ 379 /* Return failure if we didn't get a successful connection. */
374 if (attempt >= connection_attempts) { 380 if (sock == -1) {
375 error("ssh: connect to host %s port %s: %s", 381 error("ssh: connect to host %s port %s: %s",
376 host, strport, strerror(errno)); 382 host, strport, strerror(errno));
377 return (-1); 383 return (-1);
@@ -403,22 +409,23 @@ ssh_exchange_identification(void)
403 int connection_in = packet_get_connection_in(); 409 int connection_in = packet_get_connection_in();
404 int connection_out = packet_get_connection_out(); 410 int connection_out = packet_get_connection_out();
405 int minor1 = PROTOCOL_MINOR_1; 411 int minor1 = PROTOCOL_MINOR_1;
406 u_int i; 412 u_int i, n;
407 struct sigaction sa, osa; 413 struct sigaction sa, osa;
408 414
409 /* Read other side's version identification. 415 /* Read other side's version identification.
410 * If SetupTimeOut has been set, give up after 416 * If SetupTimeOut has been set, give up after the specified amount
411 * the specified amount of time 417 * of time.
412 */ 418 */
413 if(options.setuptimeout > 0){ 419 if (options.setuptimeout > 0) {
414 memset(&sa, 0, sizeof(sa)); 420 memset(&sa, 0, sizeof(sa));
415 sa.sa_handler = banner_alarm_catch; 421 sa.sa_handler = banner_alarm_catch;
416 /*throw away any pending alarms, since we'd block otherwise*/ 422 /* throw away any pending alarms, since we'd block otherwise */
417 alarm(0); 423 alarm(0);
418 sigaction(SIGALRM, &sa, &osa); 424 sigaction(SIGALRM, &sa, &osa);
419 alarm(options.setuptimeout); 425 alarm(options.setuptimeout);
420 } 426 }
421 for (;;) { 427 /* Read other side's version identification. */
428 for (n = 0;;) {
422 for (i = 0; i < sizeof(buf) - 1; ) { 429 for (i = 0; i < sizeof(buf) - 1; ) {
423 ssize_t len = read(connection_in, &buf[i], 1); 430 ssize_t len = read(connection_in, &buf[i], 1);
424 if (banner_timedout) 431 if (banner_timedout)
@@ -450,6 +457,8 @@ ssh_exchange_identification(void)
450 buf[i] = '\n'; 457 buf[i] = '\n';
451 buf[i + 1] = 0; /**XXX wait for \n */ 458 buf[i + 1] = 0; /**XXX wait for \n */
452 } 459 }
460 if (++n > 65536)
461 fatal("ssh_exchange_identification: No banner received");
453 i++; 462 i++;
454 } 463 }
455 buf[sizeof(buf) - 1] = 0; 464 buf[sizeof(buf) - 1] = 0;
@@ -464,7 +473,7 @@ ssh_exchange_identification(void)
464 */ 473 */
465 if (options.setuptimeout > 0) { 474 if (options.setuptimeout > 0) {
466 alarm(0); 475 alarm(0);
467 sigaction(SIGALRM,&osa,NULL); 476 sigaction(SIGALRM, &osa, NULL);
468 } 477 }
469 478
470 /* 479 /*
@@ -560,13 +569,17 @@ confirm(const char *prompt)
560 * check whether the supplied host key is valid, return -1 if the key 569 * check whether the supplied host key is valid, return -1 if the key
561 * is not valid. the user_hostfile will not be updated if 'readonly' is true. 570 * is not valid. the user_hostfile will not be updated if 'readonly' is true.
562 */ 571 */
572#define RDRW 0
573#define RDONLY 1
574#define ROQUIET 2
563static int 575static int
564check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, 576check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
565 int readonly, const char *user_hostfile, const char *system_hostfile) 577 Key *host_key, int readonly, const char *user_hostfile,
578 const char *system_hostfile)
566{ 579{
567 Key *file_key; 580 Key *file_key;
568 const char *type = key_type(host_key); 581 const char *type = key_type(host_key);
569 char *ip = NULL; 582 char *ip = NULL, *host = NULL;
570 char hostline[1000], *hostp, *fp; 583 char hostline[1000], *hostp, *fp;
571 HostStatus host_status; 584 HostStatus host_status;
572 HostStatus ip_status; 585 HostStatus ip_status;
@@ -617,7 +630,7 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
617 if (getnameinfo(hostaddr, salen, ntop, sizeof(ntop), 630 if (getnameinfo(hostaddr, salen, ntop, sizeof(ntop),
618 NULL, 0, NI_NUMERICHOST) != 0) 631 NULL, 0, NI_NUMERICHOST) != 0)
619 fatal("check_host_key: getnameinfo failed"); 632 fatal("check_host_key: getnameinfo failed");
620 ip = xstrdup(ntop); 633 ip = put_host_port(ntop, port);
621 } else { 634 } else {
622 ip = xstrdup("<no hostip for proxy command>"); 635 ip = xstrdup("<no hostip for proxy command>");
623 } 636 }
@@ -625,18 +638,21 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
625 * Turn off check_host_ip if the connection is to localhost, via proxy 638 * Turn off check_host_ip if the connection is to localhost, via proxy
626 * command or if we don't have a hostname to compare with 639 * command or if we don't have a hostname to compare with
627 */ 640 */
628 if (options.check_host_ip && 641 if (options.check_host_ip && (local ||
629 (local || strcmp(host, ip) == 0 || options.proxy_command != NULL)) 642 strcmp(hostname, ip) == 0 || options.proxy_command != NULL))
630 options.check_host_ip = 0; 643 options.check_host_ip = 0;
631 644
632 /* 645 /*
633 * Allow the user to record the key under a different name. This is 646 * Allow the user to record the key under a different name or
634 * useful for ssh tunneling over forwarded connections or if you run 647 * differentiate a non-standard port. This is useful for ssh
635 * multiple sshd's on different ports on the same machine. 648 * tunneling over forwarded connections or if you run multiple
649 * sshd's on different ports on the same machine.
636 */ 650 */
637 if (options.host_key_alias != NULL) { 651 if (options.host_key_alias != NULL) {
638 host = options.host_key_alias; 652 host = xstrdup(options.host_key_alias);
639 debug("using hostkeyalias: %s", host); 653 debug("using hostkeyalias: %s", host);
654 } else {
655 host = put_host_port(hostname, port);
640 } 656 }
641 657
642 /* 658 /*
@@ -705,6 +721,15 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
705 } 721 }
706 break; 722 break;
707 case HOST_NEW: 723 case HOST_NEW:
724 if (options.host_key_alias == NULL && port != 0 &&
725 port != SSH_DEFAULT_PORT) {
726 debug("checking without port identifier");
727 if (check_host_key(hostname, hostaddr, 0, host_key, 2,
728 user_hostfile, system_hostfile) == 0) {
729 debug("found matching key w/out port");
730 break;
731 }
732 }
708 if (readonly) 733 if (readonly)
709 goto fail; 734 goto fail;
710 /* The host is new. */ 735 /* The host is new. */
@@ -784,6 +809,8 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
784 "list of known hosts.", hostp, type); 809 "list of known hosts.", hostp, type);
785 break; 810 break;
786 case HOST_CHANGED: 811 case HOST_CHANGED:
812 if (readonly == ROQUIET)
813 goto fail;
787 if (options.check_host_ip && host_ip_differ) { 814 if (options.check_host_ip && host_ip_differ) {
788 char *key_msg; 815 char *key_msg;
789 if (ip_status == HOST_NEW) 816 if (ip_status == HOST_NEW)
@@ -822,7 +849,7 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
822 /* 849 /*
823 * If strict host key checking has not been requested, allow 850 * If strict host key checking has not been requested, allow
824 * the connection but without MITM-able authentication or 851 * the connection but without MITM-able authentication or
825 * agent forwarding. 852 * forwarding.
826 */ 853 */
827 if (options.password_authentication) { 854 if (options.password_authentication) {
828 error("Password authentication is disabled to avoid " 855 error("Password authentication is disabled to avoid "
@@ -857,6 +884,11 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
857 options.num_local_forwards = 884 options.num_local_forwards =
858 options.num_remote_forwards = 0; 885 options.num_remote_forwards = 0;
859 } 886 }
887 if (options.tun_open != SSH_TUNMODE_NO) {
888 error("Tunnel forwarding is disabled to avoid "
889 "man-in-the-middle attacks.");
890 options.tun_open = SSH_TUNMODE_NO;
891 }
860 /* 892 /*
861 * XXX Should permit the user to change to use the new id. 893 * XXX Should permit the user to change to use the new id.
862 * This could be done by converting the host key to an 894 * This could be done by converting the host key to an
@@ -898,10 +930,12 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
898 } 930 }
899 931
900 xfree(ip); 932 xfree(ip);
933 xfree(host);
901 return 0; 934 return 0;
902 935
903fail: 936fail:
904 xfree(ip); 937 xfree(ip);
938 xfree(host);
905 return -1; 939 return -1;
906} 940}
907 941
@@ -935,12 +969,13 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
935 /* return ok if the key can be found in an old keyfile */ 969 /* return ok if the key can be found in an old keyfile */
936 if (stat(options.system_hostfile2, &st) == 0 || 970 if (stat(options.system_hostfile2, &st) == 0 ||
937 stat(options.user_hostfile2, &st) == 0) { 971 stat(options.user_hostfile2, &st) == 0) {
938 if (check_host_key(host, hostaddr, host_key, /*readonly*/ 1, 972 if (check_host_key(host, hostaddr, options.port, host_key,
939 options.user_hostfile2, options.system_hostfile2) == 0) 973 RDONLY, options.user_hostfile2,
974 options.system_hostfile2) == 0)
940 return 0; 975 return 0;
941 } 976 }
942 return check_host_key(host, hostaddr, host_key, /*readonly*/ 0, 977 return check_host_key(host, hostaddr, options.port, host_key,
943 options.user_hostfile, options.system_hostfile); 978 RDRW, options.user_hostfile, options.system_hostfile);
944} 979}
945 980
946/* 981/*
@@ -964,7 +999,7 @@ ssh_login(Sensitive *sensitive, const char *orighost,
964 host = xstrdup(orighost); 999 host = xstrdup(orighost);
965 for (cp = host; *cp; cp++) 1000 for (cp = host; *cp; cp++)
966 if (isupper(*cp)) 1001 if (isupper(*cp))
967 *cp = tolower(*cp); 1002 *cp = (char)tolower(*cp);
968 1003
969 /* Exchange protocol version identification strings with the server. */ 1004 /* Exchange protocol version identification strings with the server. */
970 ssh_exchange_identification(); 1005 ssh_exchange_identification();
@@ -981,6 +1016,7 @@ ssh_login(Sensitive *sensitive, const char *orighost,
981 ssh_kex(host, hostaddr); 1016 ssh_kex(host, hostaddr);
982 ssh_userauth1(local_user, server_user, host, sensitive); 1017 ssh_userauth1(local_user, server_user, host, sensitive);
983 } 1018 }
1019 xfree(local_user);
984} 1020}
985 1021
986void 1022void
@@ -994,8 +1030,7 @@ ssh_put_password(char *password)
994 return; 1030 return;
995 } 1031 }
996 size = roundup(strlen(password) + 1, 32); 1032 size = roundup(strlen(password) + 1, 32);
997 padded = xmalloc(size); 1033 padded = xcalloc(1, size);
998 memset(padded, 0, size);
999 strlcpy(padded, password, size); 1034 strlcpy(padded, password, size);
1000 packet_put_string(padded, size); 1035 packet_put_string(padded, size);
1001 memset(padded, 0, size); 1036 memset(padded, 0, size);