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