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.126 2002/06/23 03:30:17 deraadt Exp $"); 17 RCSID("$FreeBSD$"); 18 19 #include <openssl/bn.h> 20 21 #include "ssh.h" 22 #include "xmalloc.h" 23 #include "rsa.h" 24 #include "buffer.h" 25 #include "packet.h" 26 #include "uidswap.h" 27 #include "compat.h" 28 #include "key.h" 29 #include "sshconnect.h" 30 #include "hostfile.h" 31 #include "log.h" 32 #include "readconf.h" 33 #include "atomicio.h" 34 #include "misc.h" 35 #include "readpass.h" 36 37 char *client_version_string = NULL; 38 char *server_version_string = NULL; 39 40 /* import */ 41 extern Options options; 42 extern char *__progname; 43 extern uid_t original_real_uid; 44 extern uid_t original_effective_uid; 45 46 #ifndef INET6_ADDRSTRLEN /* for non IPv6 machines */ 47 #define INET6_ADDRSTRLEN 46 48 #endif 49 50 static const char * 51 sockaddr_ntop(struct sockaddr *sa, socklen_t salen) 52 { 53 static char addrbuf[NI_MAXHOST]; 54 55 if (getnameinfo(sa, salen, addrbuf, sizeof(addrbuf), NULL, 0, 56 NI_NUMERICHOST) != 0) 57 fatal("sockaddr_ntop: getnameinfo NI_NUMERICHOST failed"); 58 return addrbuf; 59 } 60 61 /* 62 * Connect to the given ssh server using a proxy command. 63 */ 64 static int 65 ssh_proxy_connect(const char *host, u_short port, const char *proxy_command) 66 { 67 Buffer command; 68 const char *cp; 69 char *command_string; 70 int pin[2], pout[2]; 71 pid_t pid; 72 char strport[NI_MAXSERV]; 73 74 /* Convert the port number into a string. */ 75 snprintf(strport, sizeof strport, "%hu", port); 76 77 /* Build the final command string in the buffer by making the 78 appropriate substitutions to the given proxy command. */ 79 buffer_init(&command); 80 for (cp = proxy_command; *cp; cp++) { 81 if (cp[0] == '%' && cp[1] == '%') { 82 buffer_append(&command, "%", 1); 83 cp++; 84 continue; 85 } 86 if (cp[0] == '%' && cp[1] == 'h') { 87 buffer_append(&command, host, strlen(host)); 88 cp++; 89 continue; 90 } 91 if (cp[0] == '%' && cp[1] == 'p') { 92 buffer_append(&command, strport, strlen(strport)); 93 cp++; 94 continue; 95 } 96 buffer_append(&command, cp, 1); 97 } 98 buffer_append(&command, "\0", 1); 99 100 /* Get the final command string. */ 101 command_string = buffer_ptr(&command); 102 103 /* Create pipes for communicating with the proxy. */ 104 if (pipe(pin) < 0 || pipe(pout) < 0) 105 fatal("Could not create pipes to communicate with the proxy: %.100s", 106 strerror(errno)); 107 108 debug("Executing proxy command: %.500s", command_string); 109 110 /* Fork and execute the proxy command. */ 111 if ((pid = fork()) == 0) { 112 char *argv[10]; 113 114 /* Child. Permanently give up superuser privileges. */ 115 seteuid(original_real_uid); 116 setuid(original_real_uid); 117 118 /* Redirect stdin and stdout. */ 119 close(pin[1]); 120 if (pin[0] != 0) { 121 if (dup2(pin[0], 0) < 0) 122 perror("dup2 stdin"); 123 close(pin[0]); 124 } 125 close(pout[0]); 126 if (dup2(pout[1], 1) < 0) 127 perror("dup2 stdout"); 128 /* Cannot be 1 because pin allocated two descriptors. */ 129 close(pout[1]); 130 131 /* Stderr is left as it is so that error messages get 132 printed on the user's terminal. */ 133 argv[0] = _PATH_BSHELL; 134 argv[1] = "-c"; 135 argv[2] = command_string; 136 argv[3] = NULL; 137 138 /* Execute the proxy command. Note that we gave up any 139 extra privileges above. */ 140 execv(argv[0], argv); 141 perror(argv[0]); 142 exit(1); 143 } 144 /* Parent. */ 145 if (pid < 0) 146 fatal("fork failed: %.100s", strerror(errno)); 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 linger linger; 243 struct servent *sp; 244 /* 245 * Did we get only other errors than "Connection refused" (which 246 * should block fallback to rsh and similar), or did we get at least 247 * one "Connection refused"? 248 */ 249 int full_failure = 1; 250 251 debug("ssh_connect: needpriv %d", needpriv); 252 253 /* Get default port if port has not been set. */ 254 if (port == 0) { 255 sp = getservbyname(SSH_SERVICE_NAME, "tcp"); 256 if (sp) 257 port = ntohs(sp->s_port); 258 else 259 port = SSH_DEFAULT_PORT; 260 } 261 /* If a proxy command is given, connect using it. */ 262 if (proxy_command != NULL) 263 return ssh_proxy_connect(host, port, proxy_command); 264 265 /* No proxy command. */ 266 267 memset(&hints, 0, sizeof(hints)); 268 hints.ai_family = family; 269 hints.ai_socktype = SOCK_STREAM; 270 snprintf(strport, sizeof strport, "%u", port); 271 if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) 272 fatal("%s: %.100s: %s", __progname, host, 273 gai_strerror(gaierr)); 274 275 /* 276 * Try to connect several times. On some machines, the first time 277 * will sometimes fail. In general socket code appears to behave 278 * quite magically on many machines. 279 */ 280 for (attempt = 0; ;) { 281 if (attempt > 0) 282 debug("Trying again..."); 283 284 /* Loop through addresses for this host, and try each one in 285 sequence until the connection succeeds. */ 286 for (ai = aitop; ai; ai = ai->ai_next) { 287 if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) 288 continue; 289 if (getnameinfo(ai->ai_addr, ai->ai_addrlen, 290 ntop, sizeof(ntop), strport, sizeof(strport), 291 NI_NUMERICHOST|NI_NUMERICSERV) != 0) { 292 error("ssh_connect: getnameinfo failed"); 293 continue; 294 } 295 debug("Connecting to %.200s [%.100s] port %s.", 296 host, ntop, strport); 297 298 /* Create a socket for connecting. */ 299 sock = ssh_create_socket(needpriv, ai->ai_family); 300 if (sock < 0) 301 /* Any error is already output */ 302 continue; 303 304 if (connect(sock, ai->ai_addr, ai->ai_addrlen) >= 0) { 305 /* Successful connection. */ 306 memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen); 307 break; 308 } else { 309 if (errno == ECONNREFUSED) 310 full_failure = 0; 311 log("ssh: connect to address %s port %s: %s", 312 sockaddr_ntop(ai->ai_addr, ai->ai_addrlen), 313 strport, strerror(errno)); 314 /* 315 * Close the failed socket; there appear to 316 * be some problems when reusing a socket for 317 * which connect() has already returned an 318 * error. 319 */ 320 close(sock); 321 } 322 } 323 if (ai) 324 break; /* Successful connection. */ 325 326 attempt++; 327 if (attempt >= connection_attempts) 328 break; 329 /* Sleep a moment before retrying. */ 330 sleep(1); 331 } 332 333 freeaddrinfo(aitop); 334 335 /* Return failure if we didn't get a successful connection. */ 336 if (attempt >= connection_attempts) 337 return full_failure ? ECONNABORTED : ECONNREFUSED; 338 339 debug("Connection established."); 340 341 /* 342 * Set socket options. We would like the socket to disappear as soon 343 * as it has been closed for whatever reason. 344 */ 345 /* setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)); */ 346 linger.l_onoff = 1; 347 linger.l_linger = 5; 348 setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *)&linger, sizeof(linger)); 349 350 /* Set keepalives if requested. */ 351 if (options.keepalives && 352 setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, 353 sizeof(on)) < 0) 354 error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); 355 356 /* Set the connection. */ 357 packet_set_connection(sock, sock); 358 359 return 0; 360 } 361 362 /* 363 * Waits for the server identification string, and sends our own 364 * identification string. 365 */ 366 static void 367 ssh_exchange_identification(void) 368 { 369 char buf[256], remote_version[256]; /* must be same size! */ 370 int remote_major, remote_minor, i, mismatch; 371 int connection_in = packet_get_connection_in(); 372 int connection_out = packet_get_connection_out(); 373 int minor1 = PROTOCOL_MINOR_1; 374 375 /* Read other side\'s version identification. */ 376 for (;;) { 377 for (i = 0; i < sizeof(buf) - 1; i++) { 378 int len = atomicio(read, connection_in, &buf[i], 1); 379 if (len < 0) 380 fatal("ssh_exchange_identification: read: %.100s", strerror(errno)); 381 if (len != 1) 382 fatal("ssh_exchange_identification: Connection closed by remote host"); 383 if (buf[i] == '\r') { 384 buf[i] = '\n'; 385 buf[i + 1] = 0; 386 continue; /**XXX wait for \n */ 387 } 388 if (buf[i] == '\n') { 389 buf[i + 1] = 0; 390 break; 391 } 392 } 393 buf[sizeof(buf) - 1] = 0; 394 if (strncmp(buf, "SSH-", 4) == 0) 395 break; 396 debug("ssh_exchange_identification: %s", buf); 397 } 398 server_version_string = xstrdup(buf); 399 400 /* 401 * Check that the versions match. In future this might accept 402 * several versions and set appropriate flags to handle them. 403 */ 404 if (sscanf(server_version_string, "SSH-%d.%d-%[^\n]\n", 405 &remote_major, &remote_minor, remote_version) != 3) 406 fatal("Bad remote protocol version identification: '%.100s'", buf); 407 debug("Remote protocol version %d.%d, remote software version %.100s", 408 remote_major, remote_minor, remote_version); 409 410 compat_datafellows(remote_version); 411 mismatch = 0; 412 413 switch (remote_major) { 414 case 1: 415 if (remote_minor == 99 && 416 (options.protocol & SSH_PROTO_2) && 417 !(options.protocol & SSH_PROTO_1_PREFERRED)) { 418 enable_compat20(); 419 break; 420 } 421 if (!(options.protocol & SSH_PROTO_1)) { 422 mismatch = 1; 423 break; 424 } 425 if (remote_minor < 3) { 426 fatal("Remote machine has too old SSH software version."); 427 } else if (remote_minor == 3 || remote_minor == 4) { 428 /* We speak 1.3, too. */ 429 enable_compat13(); 430 minor1 = 3; 431 if (options.forward_agent) { 432 log("Agent forwarding disabled for protocol 1.3"); 433 options.forward_agent = 0; 434 } 435 } 436 break; 437 case 2: 438 if (options.protocol & SSH_PROTO_2) { 439 enable_compat20(); 440 break; 441 } 442 /* FALLTHROUGH */ 443 default: 444 mismatch = 1; 445 break; 446 } 447 if (mismatch) 448 fatal("Protocol major versions differ: %d vs. %d", 449 (options.protocol & SSH_PROTO_2) ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1, 450 remote_major); 451 /* Send our own protocol version identification. */ 452 snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", 453 compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1, 454 compat20 ? PROTOCOL_MINOR_2 : minor1, 455 SSH_VERSION); 456 if (atomicio(write, connection_out, buf, strlen(buf)) != strlen(buf)) 457 fatal("write: %.100s", strerror(errno)); 458 client_version_string = xstrdup(buf); 459 chop(client_version_string); 460 chop(server_version_string); 461 debug("Local version string %.100s", client_version_string); 462 } 463 464 /* defaults to 'no' */ 465 static int 466 confirm(const char *prompt) 467 { 468 const char *msg, *again = "Please type 'yes' or 'no': "; 469 char *p; 470 int ret = -1; 471 472 if (options.batch_mode) 473 return 0; 474 for (msg = prompt;;msg = again) { 475 p = read_passphrase(msg, RP_ECHO); 476 if (p == NULL || 477 (p[0] == '\0') || (p[0] == '\n') || 478 strncasecmp(p, "no", 2) == 0) 479 ret = 0; 480 if (strncasecmp(p, "yes", 3) == 0) 481 ret = 1; 482 if (p) 483 xfree(p); 484 if (ret != -1) 485 return ret; 486 } 487 } 488 489 /* 490 * check whether the supplied host key is valid, return -1 if the key 491 * is not valid. the user_hostfile will not be updated if 'readonly' is true. 492 */ 493 static int 494 check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, 495 int readonly, const char *user_hostfile, const char *system_hostfile) 496 { 497 Key *file_key; 498 char *type = key_type(host_key); 499 char *ip = NULL; 500 char hostline[1000], *hostp, *fp; 501 HostStatus host_status; 502 HostStatus ip_status; 503 int local = 0, host_ip_differ = 0; 504 int salen; 505 char ntop[NI_MAXHOST]; 506 char msg[1024]; 507 int len, host_line, ip_line; 508 const char *host_file = NULL, *ip_file = NULL; 509 510 /* 511 * Force accepting of the host key for loopback/localhost. The 512 * problem is that if the home directory is NFS-mounted to multiple 513 * machines, localhost will refer to a different machine in each of 514 * them, and the user will get bogus HOST_CHANGED warnings. This 515 * essentially disables host authentication for localhost; however, 516 * this is probably not a real problem. 517 */ 518 /** hostaddr == 0! */ 519 switch (hostaddr->sa_family) { 520 case AF_INET: 521 local = (ntohl(((struct sockaddr_in *)hostaddr)-> 522 sin_addr.s_addr) >> 24) == IN_LOOPBACKNET; 523 salen = sizeof(struct sockaddr_in); 524 break; 525 case AF_INET6: 526 local = IN6_IS_ADDR_LOOPBACK( 527 &(((struct sockaddr_in6 *)hostaddr)->sin6_addr)); 528 salen = sizeof(struct sockaddr_in6); 529 break; 530 default: 531 local = 0; 532 salen = sizeof(struct sockaddr_storage); 533 break; 534 } 535 if (options.no_host_authentication_for_localhost == 1 && local && 536 options.host_key_alias == NULL) { 537 debug("Forcing accepting of host key for " 538 "loopback/localhost."); 539 return 0; 540 } 541 542 /* 543 * We don't have the remote ip-address for connections 544 * using a proxy command 545 */ 546 if (options.proxy_command == NULL) { 547 if (getnameinfo(hostaddr, salen, ntop, sizeof(ntop), 548 NULL, 0, NI_NUMERICHOST) != 0) 549 fatal("check_host_key: getnameinfo failed"); 550 ip = xstrdup(ntop); 551 } else { 552 ip = xstrdup("<no hostip for proxy command>"); 553 } 554 /* 555 * Turn off check_host_ip if the connection is to localhost, via proxy 556 * command or if we don't have a hostname to compare with 557 */ 558 if (options.check_host_ip && 559 (local || strcmp(host, ip) == 0 || options.proxy_command != NULL)) 560 options.check_host_ip = 0; 561 562 /* 563 * Allow the user to record the key under a different name. This is 564 * useful for ssh tunneling over forwarded connections or if you run 565 * multiple sshd's on different ports on the same machine. 566 */ 567 if (options.host_key_alias != NULL) { 568 host = options.host_key_alias; 569 debug("using hostkeyalias: %s", host); 570 } 571 572 /* 573 * Store the host key from the known host file in here so that we can 574 * compare it with the key for the IP address. 575 */ 576 file_key = key_new(host_key->type); 577 578 /* 579 * Check if the host key is present in the user\'s list of known 580 * hosts or in the systemwide list. 581 */ 582 host_file = user_hostfile; 583 host_status = check_host_in_hostfile(host_file, host, host_key, 584 file_key, &host_line); 585 if (host_status == HOST_NEW) { 586 host_file = system_hostfile; 587 host_status = check_host_in_hostfile(host_file, host, host_key, 588 file_key, &host_line); 589 } 590 /* 591 * Also perform check for the ip address, skip the check if we are 592 * localhost or the hostname was an ip address to begin with 593 */ 594 if (options.check_host_ip) { 595 Key *ip_key = key_new(host_key->type); 596 597 ip_file = user_hostfile; 598 ip_status = check_host_in_hostfile(ip_file, ip, host_key, 599 ip_key, &ip_line); 600 if (ip_status == HOST_NEW) { 601 ip_file = system_hostfile; 602 ip_status = check_host_in_hostfile(ip_file, ip, 603 host_key, ip_key, &ip_line); 604 } 605 if (host_status == HOST_CHANGED && 606 (ip_status != HOST_CHANGED || !key_equal(ip_key, file_key))) 607 host_ip_differ = 1; 608 609 key_free(ip_key); 610 } else 611 ip_status = host_status; 612 613 key_free(file_key); 614 615 switch (host_status) { 616 case HOST_OK: 617 /* The host is known and the key matches. */ 618 debug("Host '%.200s' is known and matches the %s host key.", 619 host, type); 620 debug("Found key in %s:%d", host_file, host_line); 621 if (options.check_host_ip && ip_status == HOST_NEW) { 622 if (readonly) 623 log("%s host key for IP address " 624 "'%.128s' not in list of known hosts.", 625 type, ip); 626 else if (!add_host_to_hostfile(user_hostfile, ip, 627 host_key)) 628 log("Failed to add the %s host key for IP " 629 "address '%.128s' to the list of known " 630 "hosts (%.30s).", type, ip, user_hostfile); 631 else 632 log("Warning: Permanently added the %s host " 633 "key for IP address '%.128s' to the list " 634 "of known hosts.", type, ip); 635 } 636 break; 637 case HOST_NEW: 638 if (readonly) 639 goto fail; 640 /* The host is new. */ 641 if (options.strict_host_key_checking == 1) { 642 /* 643 * User has requested strict host key checking. We 644 * will not add the host key automatically. The only 645 * alternative left is to abort. 646 */ 647 error("No %s host key is known for %.200s and you " 648 "have requested strict checking.", type, host); 649 goto fail; 650 } else if (options.strict_host_key_checking == 2) { 651 /* The default */ 652 fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); 653 snprintf(msg, sizeof(msg), 654 "The authenticity of host '%.200s (%s)' can't be " 655 "established.\n" 656 "%s key fingerprint is %s.\n" 657 "Are you sure you want to continue connecting " 658 "(yes/no)? ", host, ip, type, fp); 659 xfree(fp); 660 if (!confirm(msg)) 661 goto fail; 662 } 663 if (options.check_host_ip && ip_status == HOST_NEW) { 664 snprintf(hostline, sizeof(hostline), "%s,%s", host, ip); 665 hostp = hostline; 666 } else 667 hostp = host; 668 669 /* 670 * If not in strict mode, add the key automatically to the 671 * local known_hosts file. 672 */ 673 if (!add_host_to_hostfile(user_hostfile, hostp, host_key)) 674 log("Failed to add the host to the list of known " 675 "hosts (%.500s).", user_hostfile); 676 else 677 log("Warning: Permanently added '%.200s' (%s) to the " 678 "list of known hosts.", hostp, type); 679 break; 680 case HOST_CHANGED: 681 if (options.check_host_ip && host_ip_differ) { 682 char *msg; 683 if (ip_status == HOST_NEW) 684 msg = "is unknown"; 685 else if (ip_status == HOST_OK) 686 msg = "is unchanged"; 687 else 688 msg = "has a different value"; 689 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); 690 error("@ WARNING: POSSIBLE DNS SPOOFING DETECTED! @"); 691 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); 692 error("The %s host key for %s has changed,", type, host); 693 error("and the key for the according IP address %s", ip); 694 error("%s. This could either mean that", msg); 695 error("DNS SPOOFING is happening or the IP address for the host"); 696 error("and its host key have changed at the same time."); 697 if (ip_status != HOST_NEW) 698 error("Offending key for IP in %s:%d", ip_file, ip_line); 699 } 700 /* The host key has changed. */ 701 fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); 702 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); 703 error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @"); 704 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); 705 error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!"); 706 error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!"); 707 error("It is also possible that the %s host key has just been changed.", type); 708 error("The fingerprint for the %s key sent by the remote host is\n%s.", 709 type, fp); 710 error("Please contact your system administrator."); 711 error("Add correct host key in %.100s to get rid of this message.", 712 user_hostfile); 713 error("Offending key in %s:%d", host_file, host_line); 714 xfree(fp); 715 716 /* 717 * If strict host key checking is in use, the user will have 718 * to edit the key manually and we can only abort. 719 */ 720 if (options.strict_host_key_checking) { 721 error("%s host key for %.200s has changed and you have " 722 "requested strict checking.", type, host); 723 goto fail; 724 } 725 726 /* 727 * If strict host key checking has not been requested, allow 728 * the connection but without password authentication or 729 * agent forwarding. 730 */ 731 if (options.password_authentication) { 732 error("Password authentication is disabled to avoid " 733 "man-in-the-middle attacks."); 734 options.password_authentication = 0; 735 } 736 if (options.forward_agent) { 737 error("Agent forwarding is disabled to avoid " 738 "man-in-the-middle attacks."); 739 options.forward_agent = 0; 740 } 741 if (options.forward_x11) { 742 error("X11 forwarding is disabled to avoid " 743 "man-in-the-middle attacks."); 744 options.forward_x11 = 0; 745 } 746 if (options.num_local_forwards > 0 || 747 options.num_remote_forwards > 0) { 748 error("Port forwarding is disabled to avoid " 749 "man-in-the-middle attacks."); 750 options.num_local_forwards = 751 options.num_remote_forwards = 0; 752 } 753 /* 754 * XXX Should permit the user to change to use the new id. 755 * This could be done by converting the host key to an 756 * identifying sentence, tell that the host identifies itself 757 * by that sentence, and ask the user if he/she whishes to 758 * accept the authentication. 759 */ 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