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