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