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