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