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
19 #include "includes.h"
20 RCSID("$OpenBSD: sshconnect.c,v 1.135 2002/09/19 01:58:18 djm Exp $");
21
22 #include <openssl/bn.h>
23
24 #include "ssh.h"
25 #include "xmalloc.h"
26 #include "rsa.h"
27 #include "buffer.h"
28 #include "packet.h"
29 #include "uidswap.h"
30 #include "compat.h"
31 #include "key.h"
32 #include "sshconnect.h"
33 #include "hostfile.h"
34 #include "log.h"
35 #include "readconf.h"
36 #include "atomicio.h"
37 #include "misc.h"
38 #include "readpass.h"
39 #include <langinfo.h>
40 #include "engine.h"
41
42 char *client_version_string = NULL;
43 char *server_version_string = NULL;
44
45 /* import */
46 extern Options options;
47 extern char *__progname;
48 extern uid_t original_real_uid;
49 extern uid_t original_effective_uid;
50 extern pid_t proxy_command_pid;
51 extern ENGINE *e;
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
ssh_proxy_connect(const char * host,u_short port,const char * proxy_command)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
ssh_create_socket(int privileged,int family)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
timeout_connect(int sockfd,const struct sockaddr * serv_addr,socklen_t addrlen,int timeout)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
ssh_connect(const char * host,struct sockaddr_storage * hostaddr,ushort_t port,int family,int connection_attempts,int needpriv,const char * proxy_command)317 ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
318 ushort_t 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
ssh_exchange_identification(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
confirm(const char * prompt)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
check_host_key(char * host,struct sockaddr * hostaddr,Key * host_key,int validated,int readonly,const char * user_hostfile,const char * system_hostfile)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
verify_host_key(char * host,struct sockaddr * hostaddr,Key * host_key)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
accept_host_key(char * host,struct sockaddr * hostaddr,Key * host_key)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
ssh_login(Sensitive * sensitive,const char * orighost,struct sockaddr * hostaddr,char * pw_name)968 ssh_login(Sensitive *sensitive, const char *orighost,
969 struct sockaddr *hostaddr, char *pw_name)
970 {
971 char *host, *cp;
972 char *server_user, *local_user;
973
974 local_user = xstrdup(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 /*
987 * See comment at definition of will_daemonize for information why we
988 * don't support the PKCS#11 engine with protocol 1.
989 */
990 if (compat20 == 1 && options.use_openssl_engine == 1) {
991 /*
992 * If this fails then 'e' will be NULL which means we do not use
993 * the engine, as if UseOpenSSLEngine was set to "no". This is
994 * important in case we go to the background after the
995 * authentication.
996 */
997 e = pkcs11_engine_load(options.use_openssl_engine);
998 }
999
1000 /* Put the connection into non-blocking mode. */
1001 packet_set_nonblocking();
1002
1003 /* key exchange */
1004 /* authenticate user */
1005 if (compat20) {
1006 /*
1007 * Note that the host pointer is saved in ssh_kex2() for later
1008 * use during the key re-exchanges so we must not xfree() it.
1009 */
1010 ssh_kex2(host, hostaddr);
1011 ssh_userauth2(local_user, server_user, host, sensitive);
1012 } else {
1013 ssh_kex(host, hostaddr);
1014 ssh_userauth1(local_user, server_user, host, sensitive);
1015 }
1016
1017 xfree(local_user);
1018 }
1019
1020 void
ssh_put_password(char * password)1021 ssh_put_password(char *password)
1022 {
1023 int size;
1024 char *padded;
1025
1026 if (datafellows & SSH_BUG_PASSWORDPAD) {
1027 packet_put_cstring(password);
1028 return;
1029 }
1030 size = roundup(strlen(password) + 1, 32);
1031 padded = xmalloc(size);
1032 memset(padded, 0, size);
1033 strlcpy(padded, password, size);
1034 packet_put_string(padded, size);
1035 memset(padded, 0, size);
1036 xfree(padded);
1037 }
1038
1039 static int
show_key_from_file(const char * file,const char * host,int keytype)1040 show_key_from_file(const char *file, const char *host, int keytype)
1041 {
1042 Key *found;
1043 char *fp;
1044 int line, ret;
1045
1046 found = key_new(keytype);
1047 if ((ret = lookup_key_in_hostfile_by_type(file, host,
1048 keytype, found, &line))) {
1049 fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
1050 log("WARNING: %s key found for host %s\n"
1051 "in %s:%d\n"
1052 "%s key fingerprint %s.",
1053 key_type(found), host, file, line,
1054 key_type(found), fp);
1055 xfree(fp);
1056 }
1057 key_free(found);
1058 return (ret);
1059 }
1060
1061 /* print all known host keys for a given host, but skip keys of given type */
1062 static int
show_other_keys(const char * host,Key * key)1063 show_other_keys(const char *host, Key *key)
1064 {
1065 int type[] = { KEY_RSA1, KEY_RSA, KEY_DSA, -1};
1066 int i, found = 0;
1067
1068 for (i = 0; type[i] != -1; i++) {
1069 if (type[i] == key->type)
1070 continue;
1071 if (type[i] != KEY_RSA1 &&
1072 show_key_from_file(options.user_hostfile2, host, type[i])) {
1073 found = 1;
1074 continue;
1075 }
1076 if (type[i] != KEY_RSA1 &&
1077 show_key_from_file(options.system_hostfile2, host, type[i])) {
1078 found = 1;
1079 continue;
1080 }
1081 if (show_key_from_file(options.user_hostfile, host, type[i])) {
1082 found = 1;
1083 continue;
1084 }
1085 if (show_key_from_file(options.system_hostfile, host, type[i])) {
1086 found = 1;
1087 continue;
1088 }
1089 debug2("no key of type %d for host %s", type[i], host);
1090 }
1091 return (found);
1092 }
1093