Home | History | Annotate | Download | only in ssh
      1 /*
      2  * Author: Tatu Ylonen <ylo (at) cs.hut.fi>
      3  * Copyright (c) 1995 Tatu Ylonen <ylo (at) cs.hut.fi>, Espoo, Finland
      4  *                    All rights reserved
      5  * Code to connect to a remote host, and to perform the client side of the
      6  * login (authentication) dialog.
      7  *
      8  * As far as I am concerned, the code I have written for this software
      9  * can be used freely for any purpose.  Any derived versions of this
     10  * software must be clearly marked as such, and if the derived work is
     11  * incompatible with the protocol description in the RFC file, it must be
     12  * called by a name other than "ssh" or "Secure Shell".
     13  */
     14 /*
     15  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
     16  * Use is subject to license terms.
     17  */
     18 
     19 #include "includes.h"
     20 RCSID("$OpenBSD: sshconnect.c,v 1.135 2002/09/19 01:58:18 djm Exp $");
     21 
     22 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     23 
     24 #include <openssl/bn.h>
     25 
     26 #include "ssh.h"
     27 #include "xmalloc.h"
     28 #include "rsa.h"
     29 #include "buffer.h"
     30 #include "packet.h"
     31 #include "uidswap.h"
     32 #include "compat.h"
     33 #include "key.h"
     34 #include "sshconnect.h"
     35 #include "hostfile.h"
     36 #include "log.h"
     37 #include "readconf.h"
     38 #include "atomicio.h"
     39 #include "misc.h"
     40 #include "readpass.h"
     41 #include <langinfo.h>
     42 
     43 char *client_version_string = NULL;
     44 char *server_version_string = NULL;
     45 
     46 /* import */
     47 extern Options options;
     48 extern char *__progname;
     49 extern uid_t original_real_uid;
     50 extern uid_t original_effective_uid;
     51 extern pid_t proxy_command_pid;
     52 
     53 #ifndef INET6_ADDRSTRLEN		/* for non IPv6 machines */
     54 #define INET6_ADDRSTRLEN 46
     55 #endif
     56 
     57 static int show_other_keys(const char *, Key *);
     58 
     59 /*
     60  * Connect to the given ssh server using a proxy command.
     61  */
     62 static int
     63 ssh_proxy_connect(const char *host, u_short port, const char *proxy_command)
     64 {
     65 	Buffer command;
     66 	const char *cp;
     67 	char *command_string;
     68 	int pin[2], pout[2];
     69 	pid_t pid;
     70 	char strport[NI_MAXSERV];
     71 
     72 	/* Convert the port number into a string. */
     73 	snprintf(strport, sizeof strport, "%hu", port);
     74 
     75 	/*
     76 	 * Build the final command string in the buffer by making the
     77 	 * appropriate substitutions to the given proxy command.
     78 	 *
     79 	 * Use "exec" to avoid "sh -c" processes on some platforms
     80 	 * (e.g. Solaris)
     81 	 */
     82 	buffer_init(&command);
     83 
     84 #define EXECLEN (sizeof ("exec") - 1)
     85 	for (cp = proxy_command; *cp && isspace(*cp) ; cp++)
     86 		;
     87 	if (strncmp(cp, "exec", EXECLEN) != 0 ||
     88 	    (strlen(cp) >= EXECLEN && !isspace(*(cp + EXECLEN))))
     89 		buffer_append(&command, "exec ", EXECLEN + 1);
     90 #undef EXECLEN
     91 
     92 	for (cp = proxy_command; *cp; cp++) {
     93 		if (cp[0] == '%' && cp[1] == '%') {
     94 			buffer_append(&command, "%", 1);
     95 			cp++;
     96 			continue;
     97 		}
     98 		if (cp[0] == '%' && cp[1] == 'h') {
     99 			buffer_append(&command, host, strlen(host));
    100 			cp++;
    101 			continue;
    102 		}
    103 		if (cp[0] == '%' && cp[1] == 'p') {
    104 			buffer_append(&command, strport, strlen(strport));
    105 			cp++;
    106 			continue;
    107 		}
    108 		buffer_append(&command, cp, 1);
    109 	}
    110 	buffer_append(&command, "\0", 1);
    111 
    112 	/* Get the final command string. */
    113 	command_string = buffer_ptr(&command);
    114 
    115 	/* Create pipes for communicating with the proxy. */
    116 	if (pipe(pin) < 0 || pipe(pout) < 0)
    117 		fatal("Could not create pipes to communicate with the proxy: %.100s",
    118 		    strerror(errno));
    119 
    120 	debug("Executing proxy command: %.500s", command_string);
    121 
    122 	/* Fork and execute the proxy command. */
    123 	if ((pid = fork()) == 0) {
    124 		char *argv[10];
    125 
    126 		/* Child.  Permanently give up superuser privileges. */
    127 		seteuid(original_real_uid);
    128 		setuid(original_real_uid);
    129 
    130 		/* Redirect stdin and stdout. */
    131 		close(pin[1]);
    132 		if (pin[0] != 0) {
    133 			if (dup2(pin[0], 0) < 0)
    134 				perror("dup2 stdin");
    135 			close(pin[0]);
    136 		}
    137 		close(pout[0]);
    138 		if (dup2(pout[1], 1) < 0)
    139 			perror("dup2 stdout");
    140 		/* Cannot be 1 because pin allocated two descriptors. */
    141 		close(pout[1]);
    142 
    143 		/* Stderr is left as it is so that error messages get
    144 		   printed on the user's terminal. */
    145 		argv[0] = _PATH_BSHELL;
    146 		argv[1] = "-c";
    147 		argv[2] = command_string;
    148 		argv[3] = NULL;
    149 
    150 		/* Execute the proxy command.  Note that we gave up any
    151 		   extra privileges above. */
    152 		execv(argv[0], argv);
    153 		perror(argv[0]);
    154 		exit(1);
    155 	}
    156 	/* Parent. */
    157 	if (pid < 0)
    158 		fatal("fork failed: %.100s", strerror(errno));
    159 	else
    160 		proxy_command_pid = pid; /* save pid to clean up later */
    161 
    162 	/* Close child side of the descriptors. */
    163 	close(pin[0]);
    164 	close(pout[1]);
    165 
    166 	/* Free the command name. */
    167 	buffer_free(&command);
    168 
    169 	/* Set the connection file descriptors. */
    170 	packet_set_connection(pout[0], pin[1]);
    171 
    172 	/* Indicate OK return */
    173 	return 0;
    174 }
    175 
    176 /*
    177  * Creates a (possibly privileged) socket for use as the ssh connection.
    178  */
    179 static int
    180 ssh_create_socket(int privileged, int family)
    181 {
    182 	int sock, gaierr;
    183 	struct addrinfo hints, *res;
    184 
    185 	/*
    186 	 * If we are running as root and want to connect to a privileged
    187 	 * port, bind our own socket to a privileged port.
    188 	 */
    189 	if (privileged) {
    190 		int p = IPPORT_RESERVED - 1;
    191 		PRIV_START;
    192 		sock = rresvport_af(&p, family);
    193 		PRIV_END;
    194 		if (sock < 0)
    195 			error("rresvport: af=%d %.100s", family, strerror(errno));
    196 		else
    197 			debug("Allocated local port %d.", p);
    198 		return sock;
    199 	}
    200 	sock = socket(family, SOCK_STREAM, 0);
    201 	if (sock < 0)
    202 		error("socket: %.100s", strerror(errno));
    203 
    204 	/* Bind the socket to an alternative local IP address */
    205 	if (options.bind_address == NULL)
    206 		return sock;
    207 
    208 	memset(&hints, 0, sizeof(hints));
    209 	hints.ai_family = family;
    210 	hints.ai_socktype = SOCK_STREAM;
    211 	hints.ai_flags = AI_PASSIVE;
    212 	gaierr = getaddrinfo(options.bind_address, "0", &hints, &res);
    213 	if (gaierr) {
    214 		error("getaddrinfo: %s: %s", options.bind_address,
    215 		    gai_strerror(gaierr));
    216 		close(sock);
    217 		return -1;
    218 	}
    219 	if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) {
    220 		error("bind: %s: %s", options.bind_address, strerror(errno));
    221 		close(sock);
    222 		freeaddrinfo(res);
    223 		return -1;
    224 	}
    225 	freeaddrinfo(res);
    226 	return sock;
    227 }
    228 
    229 /*
    230  * Connect with timeout. Implements ConnectTimeout option.
    231  */
    232 static int
    233 timeout_connect(int sockfd, const struct sockaddr *serv_addr,
    234     socklen_t addrlen, int timeout)
    235 {
    236 	fd_set *fdset;
    237 	struct timeval tv;
    238 	socklen_t optlen;
    239 	int optval, rc, result = -1;
    240 
    241 	if (timeout <= 0)
    242 		return (connect(sockfd, serv_addr, addrlen));
    243 
    244 	set_nonblock(sockfd);
    245 	rc = connect(sockfd, serv_addr, addrlen);
    246 	if (rc == 0) {
    247 		unset_nonblock(sockfd);
    248 		return (0);
    249 	}
    250 	if (errno != EINPROGRESS)
    251 		return (-1);
    252 
    253 	fdset = (fd_set *)xcalloc(howmany(sockfd + 1, NFDBITS),
    254 	    sizeof(fd_mask));
    255 	FD_SET(sockfd, fdset);
    256 	tv.tv_sec = timeout;
    257 	tv.tv_usec = 0;
    258 
    259 	for (;;) {
    260 		rc = select(sockfd + 1, NULL, fdset, NULL, &tv);
    261 		if (rc != -1 || errno != EINTR)
    262 			break;
    263 	}
    264 
    265 	switch (rc) {
    266 	case 0:
    267 		/* Timed out */
    268 		errno = ETIMEDOUT;
    269 		break;
    270 	case -1:
    271 		/* Select error */
    272 		debug("select: %s", strerror(errno));
    273 		break;
    274 	case 1:
    275 		/* Completed or failed */
    276 		optval = 0;
    277 		optlen = sizeof(optval);
    278 		if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval,
    279 		    &optlen) == -1) {
    280 			debug("getsockopt: %s", strerror(errno));
    281 			break;
    282 		}
    283 		if (optval != 0) {
    284 			errno = optval;
    285 			break;
    286 		}
    287 		result = 0;
    288 		unset_nonblock(sockfd);
    289 		break;
    290 	default:
    291 		/* Should not occur */
    292 		fatal("Bogus return (%d) from select()", rc);
    293 	}
    294 
    295 	xfree(fdset);
    296 	return (result);
    297 }
    298 
    299 /*
    300  * Opens a TCP/IP connection to the remote server on the given host.
    301  * The address of the remote host will be returned in hostaddr.
    302  * If port is 0, the default port will be used.  If needpriv is true,
    303  * a privileged port will be allocated to make the connection.
    304  * This requires super-user privileges if needpriv is true.
    305  * Connection_attempts specifies the maximum number of tries (one per
    306  * second).  If proxy_command is non-NULL, it specifies the command (with %h
    307  * and %p substituted for host and port, respectively) to use to contact
    308  * the daemon.
    309  * Return values:
    310  *    0 for OK
    311  *    ECONNREFUSED if we got a "Connection Refused" by the peer on any address
    312  *    ECONNABORTED if we failed without a "Connection refused"
    313  * Suitable error messages for the connection failure will already have been
    314  * printed.
    315  */
    316 int
    317 ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
    318     u_short port, int family, int connection_attempts,
    319     int needpriv, const char *proxy_command)
    320 {
    321 	int gaierr;
    322 	int on = 1;
    323 	int sock = -1, attempt;
    324 	char ntop[NI_MAXHOST], strport[NI_MAXSERV];
    325 	struct addrinfo hints, *ai, *aitop;
    326 	struct servent *sp;
    327 	/*
    328 	 * Did we get only other errors than "Connection refused" (which
    329 	 * should block fallback to rsh and similar), or did we get at least
    330 	 * one "Connection refused"?
    331 	 */
    332 	int full_failure = 1;
    333 
    334 	debug("ssh_connect: needpriv %d", needpriv);
    335 
    336 	/* Get default port if port has not been set. */
    337 	if (port == 0) {
    338 		sp = getservbyname(SSH_SERVICE_NAME, "tcp");
    339 		if (sp)
    340 			port = ntohs(sp->s_port);
    341 		else
    342 			port = SSH_DEFAULT_PORT;
    343 	}
    344 	/* If a proxy command is given, connect using it. */
    345 	if (proxy_command != NULL)
    346 		return ssh_proxy_connect(host, port, proxy_command);
    347 
    348 	/* No proxy command. */
    349 
    350 	memset(&hints, 0, sizeof(hints));
    351 	hints.ai_family = family;
    352 	hints.ai_socktype = SOCK_STREAM;
    353 	snprintf(strport, sizeof strport, "%u", port);
    354 	if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0)
    355 		fatal("%s: %.100s: %s", __progname, host,
    356 		    gai_strerror(gaierr));
    357 
    358 	/*
    359 	 * Try to connect several times.  On some machines, the first time
    360 	 * will sometimes fail.  In general socket code appears to behave
    361 	 * quite magically on many machines.
    362 		 */
    363 	for (attempt = 0; ;) {
    364 		if (attempt > 0)
    365 			debug("Trying again...");
    366 
    367 		/* Loop through addresses for this host, and try each one in
    368 		   sequence until the connection succeeds. */
    369 		for (ai = aitop; ai; ai = ai->ai_next) {
    370 			if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
    371 				continue;
    372 			if (getnameinfo(ai->ai_addr, ai->ai_addrlen,
    373 			    ntop, sizeof(ntop), strport, sizeof(strport),
    374 			    NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
    375 				error("ssh_connect: getnameinfo failed");
    376 				continue;
    377 			}
    378 			debug("Connecting to %.200s [%.100s] port %s.",
    379 				host, ntop, strport);
    380 
    381 			/* Create a socket for connecting. */
    382 			sock = ssh_create_socket(needpriv, ai->ai_family);
    383 			if (sock < 0)
    384 				/* Any error is already output */
    385 				continue;
    386 
    387 			if (timeout_connect(sock, ai->ai_addr, ai->ai_addrlen,
    388 			    options.connection_timeout) >= 0) {
    389 				/* Successful connection. */
    390 				memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen);
    391 				break;
    392 			} else {
    393 				if (errno == ECONNREFUSED)
    394 					full_failure = 0;
    395 				debug("connect to address %s port %s: %s",
    396 				    ntop, strport, strerror(errno));
    397 				/*
    398 				 * Close the failed socket; there appear to
    399 				 * be some problems when reusing a socket for
    400 				 * which connect() has already returned an
    401 				 * error.
    402 				 */
    403 				close(sock);
    404 			}
    405 		}
    406 		if (ai)
    407 			break;	/* Successful connection. */
    408 
    409 		attempt++;
    410 		if (attempt >= connection_attempts)
    411 			break;
    412 		/* Sleep a moment before retrying. */
    413 		sleep(1);
    414 	}
    415 
    416 	freeaddrinfo(aitop);
    417 
    418 	/* Return failure if we didn't get a successful connection. */
    419 	if (attempt >= connection_attempts) {
    420 		log("ssh: connect to host %s port %s: %s",
    421 		    host, strport, strerror(errno));
    422 		return full_failure ? ECONNABORTED : ECONNREFUSED;
    423 	}
    424 
    425 	debug("Connection established.");
    426 
    427 	/* Set keepalives if requested. */
    428 	if (options.keepalives &&
    429 	    setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on,
    430 	    sizeof(on)) < 0)
    431 		debug2("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
    432 
    433 	/* Set the connection. */
    434 	packet_set_connection(sock, sock);
    435 
    436 	return 0;
    437 }
    438 
    439 /*
    440  * Waits for the server identification string, and sends our own
    441  * identification string.
    442  */
    443 static void
    444 ssh_exchange_identification(void)
    445 {
    446 	char buf[256], remote_version[256];	/* must be same size! */
    447 	int remote_major, remote_minor, i, mismatch;
    448 	int connection_in = packet_get_connection_in();
    449 	int connection_out = packet_get_connection_out();
    450 	int minor1 = PROTOCOL_MINOR_1;
    451 
    452 	/* Read other side\'s version identification. */
    453 	for (;;) {
    454 		for (i = 0; i < sizeof(buf) - 1; i++) {
    455 			int len = atomicio(read, connection_in, &buf[i], 1);
    456 			if (len < 0)
    457 				fatal("ssh_exchange_identification: read: %.100s", strerror(errno));
    458 			if (len != 1)
    459 				fatal("ssh_exchange_identification: Connection closed by remote host");
    460 			if (buf[i] == '\r') {
    461 				buf[i] = '\n';
    462 				buf[i + 1] = 0;
    463 				continue;		/**XXX wait for \n */
    464 			}
    465 			if (buf[i] == '\n') {
    466 				buf[i + 1] = 0;
    467 				break;
    468 			}
    469 		}
    470 		buf[sizeof(buf) - 1] = 0;
    471 		if (strncmp(buf, "SSH-", 4) == 0)
    472 			break;
    473 		debug("ssh_exchange_identification: %s", buf);
    474 	}
    475 	server_version_string = xstrdup(buf);
    476 
    477 	/*
    478 	 * Check that the versions match.  In future this might accept
    479 	 * several versions and set appropriate flags to handle them.
    480 	 */
    481 	if (sscanf(server_version_string, "SSH-%d.%d-%[^\n]\n",
    482 	    &remote_major, &remote_minor, remote_version) != 3)
    483 		fatal("Bad remote protocol version identification: '%.100s'", buf);
    484 	debug("Remote protocol version %d.%d, remote software version %.100s",
    485 	    remote_major, remote_minor, remote_version);
    486 
    487 	compat_datafellows(remote_version);
    488 	mismatch = 0;
    489 
    490 	switch (remote_major) {
    491 	case 1:
    492 		if (remote_minor == 99 &&
    493 		    (options.protocol & SSH_PROTO_2) &&
    494 		    !(options.protocol & SSH_PROTO_1_PREFERRED)) {
    495 			enable_compat20();
    496 			break;
    497 		}
    498 		if (!(options.protocol & SSH_PROTO_1)) {
    499 			mismatch = 1;
    500 			break;
    501 		}
    502 		if (remote_minor < 3) {
    503 			fatal("Remote machine has too old SSH software version.");
    504 		} else if (remote_minor == 3 || remote_minor == 4) {
    505 			/* We speak 1.3, too. */
    506 			enable_compat13();
    507 			minor1 = 3;
    508 			if (options.forward_agent) {
    509 				log("Agent forwarding disabled for protocol 1.3");
    510 				options.forward_agent = 0;
    511 			}
    512 		}
    513 		break;
    514 	case 2:
    515 		if (options.protocol & SSH_PROTO_2) {
    516 			enable_compat20();
    517 			break;
    518 		}
    519 		/* FALLTHROUGH */
    520 	default:
    521 		mismatch = 1;
    522 		break;
    523 	}
    524 	if (mismatch)
    525 		fatal("Protocol major versions differ: %d vs. %d",
    526 		    (options.protocol & SSH_PROTO_2) ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
    527 		    remote_major);
    528 	/* Send our own protocol version identification. */
    529 	snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n",
    530 	    compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
    531 	    compat20 ? PROTOCOL_MINOR_2 : minor1,
    532 	    SSH_VERSION);
    533 	if (atomicio(write, connection_out, buf, strlen(buf)) != strlen(buf))
    534 		fatal("write: %.100s", strerror(errno));
    535 	client_version_string = xstrdup(buf);
    536 	chop(client_version_string);
    537 	chop(server_version_string);
    538 	debug("Local version string %.100s", client_version_string);
    539 }
    540 
    541 /* defaults to 'no' */
    542 static int
    543 confirm(const char *prompt)
    544 {
    545 	const char *msg;
    546 	char *p, *again = NULL;
    547 	int n, ret = -1;
    548 
    549 	if (options.batch_mode)
    550 		return 0;
    551 	n = snprintf(NULL, 0, gettext("Please type '%s' or '%s': "),
    552 		nl_langinfo(YESSTR), nl_langinfo(NOSTR));
    553 	again = xmalloc(n + 1);
    554 	(void) snprintf(again, n + 1, gettext("Please type '%s' or '%s': "),
    555 		    nl_langinfo(YESSTR), nl_langinfo(NOSTR));
    556 
    557 	for (msg = prompt;;msg = again) {
    558 		p = read_passphrase(msg, RP_ECHO);
    559 		if (p == NULL ||
    560 		    (p[0] == '\0') || (p[0] == '\n') ||
    561 		    strcasecmp(p, nl_langinfo(NOSTR)) == 0)
    562 			ret = 0;
    563 		if (p && strcasecmp(p, nl_langinfo(YESSTR)) == 0)
    564 			ret = 1;
    565 		if (p)
    566 			xfree(p);
    567 		if (ret != -1)
    568 			return ret;
    569 	}
    570 }
    571 
    572 /*
    573  * check whether the supplied host key is valid, return -1 if the key
    574  * is not valid. the user_hostfile will not be updated if 'readonly' is true.
    575  */
    576 static int
    577 check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, int
    578 	validated, int readonly, const char *user_hostfile, const char
    579 	*system_hostfile)
    580 {
    581 	Key *file_key;
    582 	char *type = key_type(host_key);
    583 	char *ip = NULL;
    584 	char hostline[1000], *hostp, *fp;
    585 	HostStatus host_status;
    586 	HostStatus ip_status;
    587 	int r, local = 0, host_ip_differ = 0;
    588 	int salen;
    589 	char ntop[NI_MAXHOST];
    590 	char msg[1024];
    591 	int len, host_line, ip_line, has_keys;
    592 	const char *host_file = NULL, *ip_file = NULL;
    593 
    594 	/*
    595 	 * Force accepting of the host key for loopback/localhost. The
    596 	 * problem is that if the home directory is NFS-mounted to multiple
    597 	 * machines, localhost will refer to a different machine in each of
    598 	 * them, and the user will get bogus HOST_CHANGED warnings.  This
    599 	 * essentially disables host authentication for localhost; however,
    600 	 * this is probably not a real problem.
    601 	 */
    602 	/**  hostaddr == 0! */
    603 	switch (hostaddr->sa_family) {
    604 	case AF_INET:
    605 		/* LINTED */
    606 		local = (ntohl(((struct sockaddr_in *)hostaddr)->
    607 		   sin_addr.s_addr) >> 24) == IN_LOOPBACKNET;
    608 		salen = sizeof(struct sockaddr_in);
    609 		break;
    610 	case AF_INET6:
    611 		/* LINTED */
    612 		local = IN6_IS_ADDR_LOOPBACK(
    613 		    &(((struct sockaddr_in6 *)hostaddr)->sin6_addr));
    614 		salen = sizeof(struct sockaddr_in6);
    615 		break;
    616 	default:
    617 		local = 0;
    618 		salen = sizeof(struct sockaddr_storage);
    619 		break;
    620 	}
    621 	if (options.no_host_authentication_for_localhost == 1 && local &&
    622 	    options.host_key_alias == NULL) {
    623 		debug("Forcing accepting of host key for "
    624 		    "loopback/localhost.");
    625 		return 0;
    626 	}
    627 
    628 	/*
    629 	 * We don't have the remote ip-address for connections
    630 	 * using a proxy command
    631 	 */
    632 	if (options.proxy_command == NULL) {
    633 		if (getnameinfo(hostaddr, salen, ntop, sizeof(ntop),
    634 		    NULL, 0, NI_NUMERICHOST) != 0)
    635 			fatal("check_host_key: getnameinfo failed");
    636 		ip = xstrdup(ntop);
    637 	} else {
    638 		ip = xstrdup("<no hostip for proxy command>");
    639 	}
    640 	/*
    641 	 * Turn off check_host_ip if the connection is to localhost, via proxy
    642 	 * command or if we don't have a hostname to compare with
    643 	 */
    644 	if (options.check_host_ip &&
    645 	    (local || strcmp(host, ip) == 0 || options.proxy_command != NULL))
    646 		options.check_host_ip = 0;
    647 
    648 	/*
    649 	 * Allow the user to record the key under a different name. This is
    650 	 * useful for ssh tunneling over forwarded connections or if you run
    651 	 * multiple sshd's on different ports on the same machine.
    652 	 */
    653 	if (options.host_key_alias != NULL) {
    654 		host = options.host_key_alias;
    655 		debug("using hostkeyalias: %s", host);
    656 	}
    657 
    658 	/*
    659 	 * Store the host key from the known host file in here so that we can
    660 	 * compare it with the key for the IP address.
    661 	 */
    662 	file_key = key_new(host_key->type);
    663 
    664 	/*
    665 	 * Check if the host key is present in the user's list of known
    666 	 * hosts or in the systemwide list.
    667 	 */
    668 	host_file = user_hostfile;
    669 	host_status = check_host_in_hostfile(host_file, host, host_key,
    670 	    file_key, &host_line);
    671 	if (host_status == HOST_NEW) {
    672 		host_file = system_hostfile;
    673 		host_status = check_host_in_hostfile(host_file, host, host_key,
    674 		    file_key, &host_line);
    675 	}
    676 	/*
    677 	 * Also perform check for the ip address, skip the check if we are
    678 	 * localhost or the hostname was an ip address to begin with
    679 	 */
    680 	if (options.check_host_ip) {
    681 		Key *ip_key = key_new(host_key->type);
    682 
    683 		ip_file = user_hostfile;
    684 		ip_status = check_host_in_hostfile(ip_file, ip, host_key,
    685 		    ip_key, &ip_line);
    686 		if (ip_status == HOST_NEW) {
    687 			ip_file = system_hostfile;
    688 			ip_status = check_host_in_hostfile(ip_file, ip,
    689 			    host_key, ip_key, &ip_line);
    690 		}
    691 		if (host_status == HOST_CHANGED &&
    692 		    (ip_status != HOST_CHANGED || !key_equal(ip_key, file_key)))
    693 			host_ip_differ = 1;
    694 
    695 		key_free(ip_key);
    696 	} else
    697 		ip_status = host_status;
    698 
    699 	key_free(file_key);
    700 
    701 	switch (host_status) {
    702 	case HOST_OK:
    703 		/* The host is known and the key matches. */
    704 		if (validated)
    705 			debug("Host '%.200s' is known and matches the %s host key.",
    706 			    host, type);
    707 		else
    708 			debug("Host '%.200s' is known and matches the %s host "
    709 				"key.", host, type);
    710 		debug("Found key in %s:%d", host_file, host_line);
    711 		if (options.check_host_ip && ip_status == HOST_NEW) {
    712 			if (readonly)
    713 				log("%s host key for IP address "
    714 				    "'%.128s' not in list of known hosts.",
    715 				    type, ip);
    716 			else if (!add_host_to_hostfile(user_hostfile, ip,
    717 			    host_key, options.hash_known_hosts))
    718 				log("Failed to add the %s host key for IP "
    719 				    "address '%.128s' to the list of known "
    720 				    "hosts (%.30s).", type, ip, user_hostfile);
    721 			else
    722 				log("Warning: Permanently added the %s host "
    723 				    "key for IP address '%.128s' to the list "
    724 				    "of known hosts.", type, ip);
    725 		}
    726 		break;
    727 	case HOST_NEW:
    728 		if (readonly)
    729 			goto fail;
    730 		/* The host is new. */
    731 		if (!validated && options.strict_host_key_checking == 1) {
    732 			/*
    733 			 * User has requested strict host key checking.  We
    734 			 * will not add the host key automatically.  The only
    735 			 * alternative left is to abort.
    736 			 */
    737 			error("No %s host key is known for %.200s and you "
    738 			    "have requested strict checking.", type, host);
    739 			goto fail;
    740 		} else if (!validated &&
    741 			    options.strict_host_key_checking == 2) {
    742 			has_keys = show_other_keys(host, host_key);
    743 			/* The default */
    744 			fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
    745 			snprintf(msg, sizeof(msg),
    746 			    gettext("The authenticity of host '%.200s (%s)' "
    747 			    "can't be established%s\n%s key fingerprint "
    748 			    "is %s.\n"
    749 			    "Are you sure you want to continue connecting "
    750 			    "(%s/%s)? "),
    751 			     host, ip,
    752 			     has_keys ? gettext(",\nbut keys of different type "
    753 				    "are already known for this host.") : ".",
    754 			     type, fp, nl_langinfo(YESSTR), nl_langinfo(NOSTR));
    755 			xfree(fp);
    756 			if (!confirm(msg))
    757 				goto fail;
    758 		}
    759 		/*
    760 		 * If not in strict mode, add the key automatically to the
    761 		 * local known_hosts file.
    762 		 */
    763 		if (options.check_host_ip && ip_status == HOST_NEW) {
    764 			snprintf(hostline, sizeof(hostline), "%s,%s",
    765 			    host, ip);
    766 			hostp = hostline;
    767 			if (options.hash_known_hosts) {
    768 				/* Add hash of host and IP separately */
    769 				r = add_host_to_hostfile(user_hostfile, host,
    770 				    host_key, options.hash_known_hosts) &&
    771 				    add_host_to_hostfile(user_hostfile, ip,
    772 				    host_key, options.hash_known_hosts);
    773 			} else {
    774 				/* Add unhashed "host,ip" */
    775 				r = add_host_to_hostfile(user_hostfile,
    776 				    hostline, host_key,
    777 				    options.hash_known_hosts);
    778 			}
    779 		} else {
    780 			r = add_host_to_hostfile(user_hostfile, host, host_key,
    781 			    options.hash_known_hosts);
    782 			hostp = host;
    783 		}
    784 
    785 		if (!r)
    786 			log("Failed to add the host to the list of known "
    787 			    "hosts (%.500s).", user_hostfile);
    788 		else
    789 			log("Warning: Permanently added '%.200s' (%s) to the "
    790 			    "list of known hosts.", hostp, type);
    791 		break;
    792 	case HOST_CHANGED:
    793 		if (validated) {
    794 			log("Warning: The host key for host %s has changed; "
    795 				"please update your known hosts file(s) "
    796 				"(%s:%d)", host, host_file, host_line);
    797 			if (options.check_host_ip && host_ip_differ) {
    798 				log("Warning: The host key for host %s has "
    799 					"changed; please update your known "
    800 					"hosts file(s) (%s:%d)", ip, host_file,
    801 					host_line);
    802 
    803 			}
    804 			break;
    805 		}
    806 		if (options.check_host_ip && host_ip_differ) {
    807 			char *msg;
    808 			if (ip_status == HOST_NEW)
    809 				msg = "is unknown";
    810 			else if (ip_status == HOST_OK)
    811 				msg = "is unchanged";
    812 			else
    813 				msg = "has a different value";
    814 			error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
    815 			      "@       WARNING: POSSIBLE DNS SPOOFING DETECTED!          @\n"
    816 			      "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
    817 			      "The %s host key for %s has changed,\n"
    818 			      "and the key for the according IP address %s\n"
    819 			      "%s. This could either mean that\n"
    820 			      "DNS SPOOFING is happening or the IP address for the host\n"
    821 			      "and its host key have changed at the same time.\n",
    822 			      type, host, ip, msg);
    823 			if (ip_status != HOST_NEW)
    824 				error("Offending key for IP in %s:%d", ip_file, ip_line);
    825 		}
    826 		/* The host key has changed. */
    827 		fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
    828 		error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
    829 		      "@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @\n"
    830 		      "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
    831 		      "IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!\n"
    832 		      "Someone could be eavesdropping on you right now (man-in-the-middle attack)!\n"
    833 		      "It is also possible that the %s host key has just been changed.\n"
    834 		      "The fingerprint for the %s key sent by the remote host is\n%s.\n"
    835 		      "Please contact your system administrator.\n"
    836 		      "Add correct host key in %.100s to get rid of this message.\n"
    837 		      "Offending key in %s:%d\n",
    838 		      type, type, fp, user_hostfile, host_file, host_line);
    839 		xfree(fp);
    840 
    841 		/*
    842 		 * If strict host key checking is in use, the user will have
    843 		 * to edit the key manually and we can only abort.
    844 		 */
    845 		if (options.strict_host_key_checking) {
    846 			error("%s host key for %.200s has changed and you have "
    847 			    "requested strict checking.", type, host);
    848 			goto fail;
    849 		}
    850 
    851 		/*
    852 		 * If strict host key checking has not been requested, allow
    853 		 * the connection but without password authentication or
    854 		 * agent forwarding.
    855 		 */
    856 		if (options.password_authentication) {
    857 			error("Password authentication is disabled to avoid "
    858 			    "man-in-the-middle attacks.");
    859 			options.password_authentication = 0;
    860 		}
    861 		if (options.forward_agent) {
    862 			error("Agent forwarding is disabled to avoid "
    863 			    "man-in-the-middle attacks.");
    864 			options.forward_agent = 0;
    865 		}
    866 		if (options.forward_x11) {
    867 			error("X11 forwarding is disabled to avoid "
    868 			    "man-in-the-middle attacks.");
    869 			options.forward_x11 = 0;
    870 		}
    871 		if (options.num_local_forwards > 0 ||
    872 		    options.num_remote_forwards > 0) {
    873 			error("Port forwarding is disabled to avoid "
    874 			    "man-in-the-middle attacks.");
    875 			options.num_local_forwards =
    876 			    options.num_remote_forwards = 0;
    877 		}
    878 		/*
    879 		 * XXX Should permit the user to change to use the new id.
    880 		 * This could be done by converting the host key to an
    881 		 * identifying sentence, tell that the host identifies itself
    882 		 * by that sentence, and ask the user if he/she whishes to
    883 		 * accept the authentication.
    884 		 */
    885 		break;
    886 	case HOST_FOUND:
    887 		fatal("internal error");
    888 		break;
    889 	}
    890 
    891 	if (options.check_host_ip && host_status != HOST_CHANGED &&
    892 	    ip_status == HOST_CHANGED) {
    893 		snprintf(msg, sizeof(msg),
    894 		    gettext("Warning: the %s host key for '%.200s' "
    895 			    "differs from the key for the IP address '%.128s'"
    896 			    "\nOffending key for IP in %s:%d"),
    897 		    type, host, ip, ip_file, ip_line);
    898 		if (host_status == HOST_OK) {
    899 			len = strlen(msg);
    900 			snprintf(msg + len, sizeof(msg) - len,
    901 			    "\nMatching host key in %s:%d",
    902 			    host_file, host_line);
    903 		}
    904 		if (!validated && options.strict_host_key_checking == 1) {
    905 			log(msg);
    906 			error("Exiting, you have requested strict checking.");
    907 			goto fail;
    908 		} else if (!validated &&
    909 			    options.strict_host_key_checking == 2) {
    910 			snprintf(msg + strlen(msg), sizeof(msg) - strlen(msg),
    911 				gettext("\nAre you sure you want to continue "
    912 					"connecting (%s/%s)"),
    913 				nl_langinfo(YESSTR), nl_langinfo(NOSTR));
    914 			if (!confirm(msg))
    915 				goto fail;
    916 		} else {
    917 			log(msg);
    918 		}
    919 	}
    920 
    921 	xfree(ip);
    922 	return 0;
    923 
    924 fail:
    925 	xfree(ip);
    926 	return -1;
    927 }
    928 
    929 int
    930 verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
    931 {
    932 	struct stat st;
    933 
    934 	/* return ok if the key can be found in an old keyfile */
    935 	if (stat(options.system_hostfile2, &st) == 0 ||
    936 	    stat(options.user_hostfile2, &st) == 0) {
    937 		if (check_host_key(host, hostaddr, host_key, 0, /*readonly*/ 1,
    938 		    options.user_hostfile2, options.system_hostfile2) == 0)
    939 			return 0;
    940 	}
    941 	return check_host_key(host, hostaddr, host_key, 0, /*readonly*/ 0,
    942 	    options.user_hostfile, options.system_hostfile);
    943 }
    944 
    945 int
    946 accept_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
    947 {
    948 	struct stat st;
    949 
    950 	/* return ok if the key can be found in an old keyfile */
    951 	if (stat(options.system_hostfile2, &st) == 0 ||
    952 	    stat(options.user_hostfile2, &st) == 0) {
    953 		if (check_host_key(host, hostaddr, host_key, 1, /*readonly*/ 1,
    954 		    options.user_hostfile2, options.system_hostfile2) == 0)
    955 			return 0;
    956 	}
    957 	return check_host_key(host, hostaddr, host_key, 1, /*readonly*/ 0,
    958 	    options.user_hostfile, options.system_hostfile);
    959 }
    960 /*
    961  * Starts a dialog with the server, and authenticates the current user on the
    962  * server.  This does not need any extra privileges.  The basic connection
    963  * to the server must already have been established before this is called.
    964  * If login fails, this function prints an error and never returns.
    965  * This function does not require super-user privileges.
    966  */
    967 void
    968 ssh_login(Sensitive *sensitive, const char *orighost,
    969     struct sockaddr *hostaddr, struct passwd *pw)
    970 {
    971 	char *host, *cp;
    972 	char *server_user, *local_user;
    973 
    974 	local_user = xstrdup(pw->pw_name);
    975 	server_user = options.user ? options.user : local_user;
    976 
    977 	/* Convert the user-supplied hostname into all lowercase. */
    978 	host = xstrdup(orighost);
    979 	for (cp = host; *cp; cp++)
    980 		if (isupper(*cp))
    981 			*cp = tolower(*cp);
    982 
    983 	/* Exchange protocol version identification strings with the server. */
    984 	ssh_exchange_identification();
    985 
    986 	/* Put the connection into non-blocking mode. */
    987 	packet_set_nonblocking();
    988 
    989 	/* key exchange */
    990 	/* authenticate user */
    991 	if (compat20) {
    992 		ssh_kex2(host, hostaddr);
    993 		ssh_userauth2(local_user, server_user, host, sensitive);
    994 	} else {
    995 		ssh_kex(host, hostaddr);
    996 		ssh_userauth1(local_user, server_user, host, sensitive);
    997 	}
    998 }
    999 
   1000 void
   1001 ssh_put_password(char *password)
   1002 {
   1003 	int size;
   1004 	char *padded;
   1005 
   1006 	if (datafellows & SSH_BUG_PASSWORDPAD) {
   1007 		packet_put_cstring(password);
   1008 		return;
   1009 	}
   1010 	size = roundup(strlen(password) + 1, 32);
   1011 	padded = xmalloc(size);
   1012 	memset(padded, 0, size);
   1013 	strlcpy(padded, password, size);
   1014 	packet_put_string(padded, size);
   1015 	memset(padded, 0, size);
   1016 	xfree(padded);
   1017 }
   1018 
   1019 static int
   1020 show_key_from_file(const char *file, const char *host, int keytype)
   1021 {
   1022 	Key *found;
   1023 	char *fp;
   1024 	int line, ret;
   1025 
   1026 	found = key_new(keytype);
   1027 	if ((ret = lookup_key_in_hostfile_by_type(file, host,
   1028 	    keytype, found, &line))) {
   1029 		fp