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