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