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