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