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