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