sshconnect.c revision 1.24
1/* $NetBSD: sshconnect.c,v 1.24 2019/04/20 17:16:40 christos Exp $ */ 2/* $OpenBSD: sshconnect.c,v 1.314 2019/02/27 19:37:01 markus Exp $ */ 3/* 4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 5 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 6 * All rights reserved 7 * Code to connect to a remote host, and to perform the client side of the 8 * login (authentication) dialog. 9 * 10 * As far as I am concerned, the code I have written for this software 11 * can be used freely for any purpose. Any derived versions of this 12 * software must be clearly marked as such, and if the derived work is 13 * incompatible with the protocol description in the RFC file, it must be 14 * called by a name other than "ssh" or "Secure Shell". 15 */ 16 17#include "includes.h" 18__RCSID("$NetBSD: sshconnect.c,v 1.24 2019/04/20 17:16:40 christos Exp $"); 19 20#include <sys/param.h> /* roundup */ 21#include <sys/types.h> 22#include <sys/param.h> 23#include <sys/wait.h> 24#include <sys/stat.h> 25#include <sys/socket.h> 26#include <sys/time.h> 27 28#include <net/if.h> 29#include <netinet/in.h> 30#include <rpc/rpc.h> 31 32#include <ctype.h> 33#include <errno.h> 34#include <fcntl.h> 35#include <netdb.h> 36#include <paths.h> 37#include <signal.h> 38#include <pwd.h> 39#include <stdio.h> 40#include <stdlib.h> 41#include <string.h> 42#include <unistd.h> 43#include <ifaddrs.h> 44 45#include "xmalloc.h" 46#include "ssh.h" 47#include "sshbuf.h" 48#include "packet.h" 49#include "compat.h" 50#include "sshkey.h" 51#include "sshconnect.h" 52#include "hostfile.h" 53#include "log.h" 54#include "misc.h" 55#include "readconf.h" 56#include "atomicio.h" 57#include "dns.h" 58#include "monitor_fdpass.h" 59#include "ssh2.h" 60#include "version.h" 61#include "authfile.h" 62#include "ssherr.h" 63#include "authfd.h" 64#include "kex.h" 65 66struct sshkey *previous_host_key = NULL; 67 68static int matching_host_key_dns = 0; 69 70static pid_t proxy_command_pid = 0; 71 72/* import */ 73extern int debug_flag; 74extern Options options; 75extern char *__progname; 76 77static int show_other_keys(struct hostkeys *, struct sshkey *); 78static void warn_changed_key(struct sshkey *); 79 80/* Expand a proxy command */ 81static char * 82expand_proxy_command(const char *proxy_command, const char *user, 83 const char *host, int port) 84{ 85 char *tmp, *ret, strport[NI_MAXSERV]; 86 87 snprintf(strport, sizeof strport, "%d", port); 88 xasprintf(&tmp, "exec %s", proxy_command); 89 ret = percent_expand(tmp, "h", host, "p", strport, 90 "r", options.user, (char *)NULL); 91 free(tmp); 92 return ret; 93} 94 95static void 96stderr_null(void) 97{ 98 int devnull; 99 100 if ((devnull = open(_PATH_DEVNULL, O_WRONLY)) == -1) { 101 error("Can't open %s for stderr redirection: %s", 102 _PATH_DEVNULL, strerror(errno)); 103 return; 104 } 105 if (devnull == STDERR_FILENO) 106 return; 107 if (dup2(devnull, STDERR_FILENO) == -1) 108 error("Cannot redirect stderr to %s", _PATH_DEVNULL); 109 if (devnull > STDERR_FILENO) 110 close(devnull); 111} 112 113/* 114 * Connect to the given ssh server using a proxy command that passes a 115 * a connected fd back to us. 116 */ 117static int 118ssh_proxy_fdpass_connect(struct ssh *ssh, const char *host, u_short port, 119 const char *proxy_command) 120{ 121 char *command_string; 122 int sp[2], sock; 123 pid_t pid; 124 const char *shell; 125 126 if ((shell = getenv("SHELL")) == NULL) 127 shell = _PATH_BSHELL; 128 129 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) < 0) 130 fatal("Could not create socketpair to communicate with " 131 "proxy dialer: %.100s", strerror(errno)); 132 close(sp[1]); 133 134 command_string = expand_proxy_command(proxy_command, options.user, 135 host, port); 136 debug("Executing proxy dialer command: %.500s", command_string); 137 138 /* Fork and execute the proxy command. */ 139 if ((pid = fork()) == 0) { 140 char *argv[10]; 141 142 close(sp[1]); 143 /* Redirect stdin and stdout. */ 144 if (sp[0] != 0) { 145 if (dup2(sp[0], 0) < 0) 146 perror("dup2 stdin"); 147 } 148 if (sp[0] != 1) { 149 if (dup2(sp[0], 1) < 0) 150 perror("dup2 stdout"); 151 } 152 if (sp[0] >= 2) 153 close(sp[0]); 154 155 /* 156 * Stderr is left for non-ControlPersist connections is so 157 * error messages may be printed on the user's terminal. 158 */ 159 if (!debug_flag && options.control_path != NULL && 160 options.control_persist) 161 stderr_null(); 162 163 argv[0] = __UNCONST(shell); 164 argv[1] = __UNCONST("-c"); 165 argv[2] = command_string; 166 argv[3] = NULL; 167 168 /* 169 * Execute the proxy command. 170 * Note that we gave up any extra privileges above. 171 */ 172 execv(argv[0], argv); 173 perror(argv[0]); 174 exit(1); 175 } 176 /* Parent. */ 177 if (pid < 0) 178 fatal("fork failed: %.100s", strerror(errno)); 179 close(sp[0]); 180 free(command_string); 181 182 if ((sock = mm_receive_fd(sp[1])) == -1) 183 fatal("proxy dialer did not pass back a connection"); 184 close(sp[1]); 185 186 while (waitpid(pid, NULL, 0) == -1) 187 if (errno != EINTR) 188 fatal("Couldn't wait for child: %s", strerror(errno)); 189 190 /* Set the connection file descriptors. */ 191 if (ssh_packet_set_connection(ssh, sock, sock) == NULL) 192 return -1; /* ssh_packet_set_connection logs error */ 193 194 return 0; 195} 196 197/* 198 * Connect to the given ssh server using a proxy command. 199 */ 200static int 201ssh_proxy_connect(struct ssh *ssh, const char *host, u_short port, 202 const char *proxy_command) 203{ 204 char *command_string; 205 int pin[2], pout[2]; 206 pid_t pid; 207 char *shell; 208 209 if ((shell = getenv("SHELL")) == NULL || *shell == '\0') 210 shell = __UNCONST(_PATH_BSHELL); 211 212 /* Create pipes for communicating with the proxy. */ 213 if (pipe(pin) < 0 || pipe(pout) < 0) 214 fatal("Could not create pipes to communicate with the proxy: %.100s", 215 strerror(errno)); 216 217 command_string = expand_proxy_command(proxy_command, options.user, 218 host, port); 219 debug("Executing proxy command: %.500s", command_string); 220 221 /* Fork and execute the proxy command. */ 222 if ((pid = fork()) == 0) { 223 char *argv[10]; 224 225 /* Redirect stdin and stdout. */ 226 close(pin[1]); 227 if (pin[0] != 0) { 228 if (dup2(pin[0], 0) < 0) 229 perror("dup2 stdin"); 230 close(pin[0]); 231 } 232 close(pout[0]); 233 if (dup2(pout[1], 1) < 0) 234 perror("dup2 stdout"); 235 /* Cannot be 1 because pin allocated two descriptors. */ 236 close(pout[1]); 237 238 /* 239 * Stderr is left for non-ControlPersist connections is so 240 * error messages may be printed on the user's terminal. 241 */ 242 if (!debug_flag && options.control_path != NULL && 243 options.control_persist) 244 stderr_null(); 245 246 argv[0] = shell; 247 argv[1] = __UNCONST("-c"); 248 argv[2] = command_string; 249 argv[3] = NULL; 250 251 /* Execute the proxy command. Note that we gave up any 252 extra privileges above. */ 253 signal(SIGPIPE, SIG_DFL); 254 execv(argv[0], argv); 255 perror(argv[0]); 256 exit(1); 257 } 258 /* Parent. */ 259 if (pid < 0) 260 fatal("fork failed: %.100s", strerror(errno)); 261 else 262 proxy_command_pid = pid; /* save pid to clean up later */ 263 264 /* Close child side of the descriptors. */ 265 close(pin[0]); 266 close(pout[1]); 267 268 /* Free the command name. */ 269 free(command_string); 270 271 /* Set the connection file descriptors. */ 272 if (ssh_packet_set_connection(ssh, pout[0], pin[1]) == NULL) 273 return -1; /* ssh_packet_set_connection logs error */ 274 275 return 0; 276} 277 278void 279ssh_kill_proxy_command(void) 280{ 281 /* 282 * Send SIGHUP to proxy command if used. We don't wait() in 283 * case it hangs and instead rely on init to reap the child 284 */ 285 if (proxy_command_pid > 1) 286 kill(proxy_command_pid, SIGHUP); 287} 288 289/* 290 * Set TCP receive buffer if requested. 291 * Note: tuning needs to happen after the socket is 292 * created but before the connection happens 293 * so winscale is negotiated properly -cjr 294 */ 295static void 296ssh_set_socket_recvbuf(int sock) 297{ 298 void *buf = (void *)&options.tcp_rcv_buf; 299 int sz = sizeof(options.tcp_rcv_buf); 300 int socksize; 301 socklen_t socksizelen = sizeof(int); 302 303 debug("setsockopt Attempting to set SO_RCVBUF to %d", options.tcp_rcv_buf); 304 if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, buf, sz) >= 0) { 305 getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &socksize, &socksizelen); 306 debug("setsockopt SO_RCVBUF: %.100s %d", strerror(errno), socksize); 307 } 308 else 309 error("Couldn't set socket receive buffer to %d: %.100s", 310 options.tcp_rcv_buf, strerror(errno)); 311} 312 313/* 314 * Search a interface address list (returned from getifaddrs(3)) for an 315 * address that matches the desired address family on the specified interface. 316 * Returns 0 and fills in *resultp and *rlenp on success. Returns -1 on failure. 317 */ 318static int 319check_ifaddrs(const char *ifname, int af, const struct ifaddrs *ifaddrs, 320 struct sockaddr_storage *resultp, socklen_t *rlenp) 321{ 322 struct sockaddr_in6 *sa6; 323 struct sockaddr_in *sa; 324 struct in6_addr *v6addr; 325 const struct ifaddrs *ifa; 326 int allow_local; 327 328 /* 329 * Prefer addresses that are not loopback or linklocal, but use them 330 * if nothing else matches. 331 */ 332 for (allow_local = 0; allow_local < 2; allow_local++) { 333 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) { 334 if (ifa->ifa_addr == NULL || ifa->ifa_name == NULL || 335 (ifa->ifa_flags & IFF_UP) == 0 || 336 ifa->ifa_addr->sa_family != af || 337 strcmp(ifa->ifa_name, options.bind_interface) != 0) 338 continue; 339 switch (ifa->ifa_addr->sa_family) { 340 case AF_INET: 341 sa = (struct sockaddr_in *)ifa->ifa_addr; 342 if (!allow_local && sa->sin_addr.s_addr == 343 htonl(INADDR_LOOPBACK)) 344 continue; 345 if (*rlenp < sizeof(struct sockaddr_in)) { 346 error("%s: v4 addr doesn't fit", 347 __func__); 348 return -1; 349 } 350 *rlenp = sizeof(struct sockaddr_in); 351 memcpy(resultp, sa, *rlenp); 352 return 0; 353 case AF_INET6: 354 sa6 = (struct sockaddr_in6 *)ifa->ifa_addr; 355 v6addr = &sa6->sin6_addr; 356 if (!allow_local && 357 (IN6_IS_ADDR_LINKLOCAL(v6addr) || 358 IN6_IS_ADDR_LOOPBACK(v6addr))) 359 continue; 360 if (*rlenp < sizeof(struct sockaddr_in6)) { 361 error("%s: v6 addr doesn't fit", 362 __func__); 363 return -1; 364 } 365 *rlenp = sizeof(struct sockaddr_in6); 366 memcpy(resultp, sa6, *rlenp); 367 return 0; 368 } 369 } 370 } 371 return -1; 372} 373 374/* 375 * Creates a socket for use as the ssh connection. 376 */ 377static int 378ssh_create_socket(struct addrinfo *ai) 379{ 380 int sock, r; 381 struct sockaddr_storage bindaddr; 382 socklen_t bindaddrlen = 0; 383 struct addrinfo hints, *res = NULL; 384 struct ifaddrs *ifaddrs = NULL; 385 char ntop[NI_MAXHOST]; 386 387 sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); 388 if (sock < 0) { 389 error("socket: %s", strerror(errno)); 390 return -1; 391 } 392 fcntl(sock, F_SETFD, FD_CLOEXEC); 393 394 if (options.tcp_rcv_buf > 0) 395 ssh_set_socket_recvbuf(sock); 396 397 /* Bind the socket to an alternative local IP address */ 398 if (options.bind_address == NULL && options.bind_interface == NULL) 399 return sock; 400 401 if (options.bind_address != NULL) { 402 memset(&hints, 0, sizeof(hints)); 403 hints.ai_family = ai->ai_family; 404 hints.ai_socktype = ai->ai_socktype; 405 hints.ai_protocol = ai->ai_protocol; 406 hints.ai_flags = AI_PASSIVE; 407 if ((r = getaddrinfo(options.bind_address, NULL, 408 &hints, &res)) != 0) { 409 error("getaddrinfo: %s: %s", options.bind_address, 410 ssh_gai_strerror(r)); 411 goto fail; 412 } 413 if (res == NULL) { 414 error("getaddrinfo: no addrs"); 415 goto fail; 416 } 417 memcpy(&bindaddr, res->ai_addr, res->ai_addrlen); 418 bindaddrlen = res->ai_addrlen; 419 } else if (options.bind_interface != NULL) { 420 if ((r = getifaddrs(&ifaddrs)) != 0) { 421 error("getifaddrs: %s: %s", options.bind_interface, 422 strerror(errno)); 423 goto fail; 424 } 425 bindaddrlen = sizeof(bindaddr); 426 if (check_ifaddrs(options.bind_interface, ai->ai_family, 427 ifaddrs, &bindaddr, &bindaddrlen) != 0) { 428 logit("getifaddrs: %s: no suitable addresses", 429 options.bind_interface); 430 goto fail; 431 } 432 } 433 if ((r = getnameinfo((struct sockaddr *)&bindaddr, bindaddrlen, 434 ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST)) != 0) { 435 error("%s: getnameinfo failed: %s", __func__, 436 ssh_gai_strerror(r)); 437 goto fail; 438 } 439 if (bind(sock, (struct sockaddr *)&bindaddr, bindaddrlen) != 0) { 440 error("bind %s: %s", ntop, strerror(errno)); 441 goto fail; 442 } 443 debug("%s: bound to %s", __func__, ntop); 444 /* success */ 445 goto out; 446fail: 447 close(sock); 448 sock = -1; 449 out: 450 if (res != NULL) 451 freeaddrinfo(res); 452 if (ifaddrs != NULL) 453 freeifaddrs(ifaddrs); 454 return sock; 455} 456 457/* 458 * Opens a TCP/IP connection to the remote server on the given host. 459 * The address of the remote host will be returned in hostaddr. 460 * If port is 0, the default port will be used. 461 * Connection_attempts specifies the maximum number of tries (one per 462 * second). If proxy_command is non-NULL, it specifies the command (with %h 463 * and %p substituted for host and port, respectively) to use to contact 464 * the daemon. 465 */ 466static int 467ssh_connect_direct(struct ssh *ssh, const char *host, struct addrinfo *aitop, 468 struct sockaddr_storage *hostaddr, u_short port, int family, 469 int connection_attempts, int *timeout_ms, int want_keepalive) 470{ 471 int on = 1, saved_timeout_ms = *timeout_ms; 472 int oerrno, sock = -1, attempt; 473 char ntop[NI_MAXHOST], strport[NI_MAXSERV]; 474 struct addrinfo *ai; 475 476 debug2("%s", __func__); 477 memset(ntop, 0, sizeof(ntop)); 478 memset(strport, 0, sizeof(strport)); 479 480 for (attempt = 0; attempt < connection_attempts; attempt++) { 481 if (attempt > 0) { 482 /* Sleep a moment before retrying. */ 483 sleep(1); 484 debug("Trying again..."); 485 } 486 /* 487 * Loop through addresses for this host, and try each one in 488 * sequence until the connection succeeds. 489 */ 490 for (ai = aitop; ai; ai = ai->ai_next) { 491 if (ai->ai_family != AF_INET && 492 ai->ai_family != AF_INET6) { 493 errno = EAFNOSUPPORT; 494 continue; 495 } 496 if (getnameinfo(ai->ai_addr, ai->ai_addrlen, 497 ntop, sizeof(ntop), strport, sizeof(strport), 498 NI_NUMERICHOST|NI_NUMERICSERV) != 0) { 499 oerrno = errno; 500 error("%s: getnameinfo failed", __func__); 501 errno = oerrno; 502 continue; 503 } 504 debug("Connecting to %.200s [%.100s] port %s.", 505 host, ntop, strport); 506 507 /* Create a socket for connecting. */ 508 sock = ssh_create_socket(ai); 509 if (sock < 0) { 510 /* Any error is already output */ 511 errno = 0; 512 continue; 513 } 514 515 *timeout_ms = saved_timeout_ms; 516 if (timeout_connect(sock, ai->ai_addr, ai->ai_addrlen, 517 timeout_ms) >= 0) { 518 /* Successful connection. */ 519 memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen); 520 break; 521 } else { 522 oerrno = errno; 523 debug("connect to address %s port %s: %s", 524 ntop, strport, strerror(errno)); 525 close(sock); 526 sock = -1; 527 errno = oerrno; 528 } 529 } 530 if (sock != -1) 531 break; /* Successful connection. */ 532 } 533 534 /* Return failure if we didn't get a successful connection. */ 535 if (sock == -1) { 536 error("ssh: connect to host %s port %s: %s", 537 host, strport, errno == 0 ? "failure" : strerror(errno)); 538 return -1; 539 } 540 541 debug("Connection established."); 542 543 /* Set SO_KEEPALIVE if requested. */ 544 if (want_keepalive && 545 setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, 546 sizeof(on)) < 0) 547 error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); 548 549 /* Set the connection. */ 550 if (ssh_packet_set_connection(ssh, sock, sock) == NULL) 551 return -1; /* ssh_packet_set_connection logs error */ 552 553 return 0; 554} 555 556int 557ssh_connect(struct ssh *ssh, const char *host, struct addrinfo *addrs, 558 struct sockaddr_storage *hostaddr, u_short port, int family, 559 int connection_attempts, int *timeout_ms, int want_keepalive) 560{ 561 int in, out; 562 563 if (options.proxy_command == NULL) { 564 return ssh_connect_direct(ssh, host, addrs, hostaddr, port, 565 family, connection_attempts, timeout_ms, want_keepalive); 566 } else if (strcmp(options.proxy_command, "-") == 0) { 567 if ((in = dup(STDIN_FILENO)) < 0 || 568 (out = dup(STDOUT_FILENO)) < 0) { 569 if (in >= 0) 570 close(in); 571 error("%s: dup() in/out failed", __func__); 572 return -1; /* ssh_packet_set_connection logs error */ 573 } 574 if ((ssh_packet_set_connection(ssh, in, out)) == NULL) 575 return -1; /* ssh_packet_set_connection logs error */ 576 return 0; 577 } else if (options.proxy_use_fdpass) { 578 return ssh_proxy_fdpass_connect(ssh, host, port, 579 options.proxy_command); 580 } 581 return ssh_proxy_connect(ssh, host, port, options.proxy_command); 582} 583 584/* defaults to 'no' */ 585static int 586confirm(const char *prompt, const char *fingerprint) 587{ 588 const char *msg, *again = "Please type 'yes' or 'no': "; 589 const char *again_fp = "Please type 'yes', 'no' or the fingerprint: "; 590 char *p; 591 int ret = -1; 592 593 if (options.batch_mode) 594 return 0; 595 for (msg = prompt;;msg = fingerprint ? again_fp : again) { 596 p = read_passphrase(msg, RP_ECHO); 597 if (p == NULL) 598 return 0; 599 p[strcspn(p, "\n")] = '\0'; 600 if (p[0] == '\0' || strcasecmp(p, "no") == 0) 601 ret = 0; 602 else if (strcasecmp(p, "yes") == 0 || (fingerprint != NULL && 603 strcasecmp(p, fingerprint) == 0)) 604 ret = 1; 605 free(p); 606 if (ret != -1) 607 return ret; 608 } 609} 610 611static int 612check_host_cert(const char *host, const struct sshkey *key) 613{ 614 const char *reason; 615 int r; 616 617 if (sshkey_cert_check_authority(key, 1, 0, host, &reason) != 0) { 618 error("%s", reason); 619 return 0; 620 } 621 if (sshbuf_len(key->cert->critical) != 0) { 622 error("Certificate for %s contains unsupported " 623 "critical options(s)", host); 624 return 0; 625 } 626 if ((r = sshkey_check_cert_sigtype(key, 627 options.ca_sign_algorithms)) != 0) { 628 logit("%s: certificate signature algorithm %s: %s", __func__, 629 (key->cert == NULL || key->cert->signature_type == NULL) ? 630 "(null)" : key->cert->signature_type, ssh_err(r)); 631 return 0; 632 } 633 634 return 1; 635} 636 637static int 638sockaddr_is_local(struct sockaddr *hostaddr) 639{ 640 switch (hostaddr->sa_family) { 641 case AF_INET: 642 return (ntohl(((struct sockaddr_in *)hostaddr)-> 643 sin_addr.s_addr) >> 24) == IN_LOOPBACKNET; 644 case AF_INET6: 645 return IN6_IS_ADDR_LOOPBACK( 646 &(((struct sockaddr_in6 *)hostaddr)->sin6_addr)); 647 default: 648 return 0; 649 } 650} 651 652/* 653 * Prepare the hostname and ip address strings that are used to lookup 654 * host keys in known_hosts files. These may have a port number appended. 655 */ 656void 657get_hostfile_hostname_ipaddr(char *hostname, struct sockaddr *hostaddr, 658 u_short port, char **hostfile_hostname, char **hostfile_ipaddr) 659{ 660 char ntop[NI_MAXHOST]; 661 662 /* 663 * We don't have the remote ip-address for connections 664 * using a proxy command 665 */ 666 if (hostfile_ipaddr != NULL) { 667 if (options.proxy_command == NULL) { 668 if (getnameinfo(hostaddr, hostaddr->sa_len, 669 ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST) != 0) 670 fatal("%s: getnameinfo failed", __func__); 671 *hostfile_ipaddr = put_host_port(ntop, port); 672 } else { 673 *hostfile_ipaddr = xstrdup("<no hostip for proxy " 674 "command>"); 675 } 676 } 677 678 /* 679 * Allow the user to record the key under a different name or 680 * differentiate a non-standard port. This is useful for ssh 681 * tunneling over forwarded connections or if you run multiple 682 * sshd's on different ports on the same machine. 683 */ 684 if (hostfile_hostname != NULL) { 685 if (options.host_key_alias != NULL) { 686 *hostfile_hostname = xstrdup(options.host_key_alias); 687 debug("using hostkeyalias: %s", *hostfile_hostname); 688 } else { 689 *hostfile_hostname = put_host_port(hostname, port); 690 } 691 } 692} 693 694/* 695 * check whether the supplied host key is valid, return -1 if the key 696 * is not valid. user_hostfile[0] will not be updated if 'readonly' is true. 697 */ 698#define RDRW 0 699#define RDONLY 1 700#define ROQUIET 2 701static int 702check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, 703 struct sshkey *host_key, int readonly, 704 char **user_hostfiles, u_int num_user_hostfiles, 705 char **system_hostfiles, u_int num_system_hostfiles) 706{ 707 HostStatus host_status; 708 HostStatus ip_status; 709 struct sshkey *raw_key = NULL; 710 char *ip = NULL, *host = NULL; 711 char hostline[1000], *hostp, *fp, *ra; 712 char msg[1024]; 713 const char *type; 714 const struct hostkey_entry *host_found, *ip_found; 715 int len, cancelled_forwarding = 0, confirmed; 716 int local = sockaddr_is_local(hostaddr); 717 int r, want_cert = sshkey_is_cert(host_key), host_ip_differ = 0; 718 int hostkey_trusted = 0; /* Known or explicitly accepted by user */ 719 struct hostkeys *host_hostkeys, *ip_hostkeys; 720 u_int i; 721 722 /* 723 * Force accepting of the host key for loopback/localhost. The 724 * problem is that if the home directory is NFS-mounted to multiple 725 * machines, localhost will refer to a different machine in each of 726 * them, and the user will get bogus HOST_CHANGED warnings. This 727 * essentially disables host authentication for localhost; however, 728 * this is probably not a real problem. 729 */ 730 if (options.no_host_authentication_for_localhost == 1 && local && 731 options.host_key_alias == NULL) { 732 debug("Forcing accepting of host key for " 733 "loopback/localhost."); 734 return 0; 735 } 736 737 /* 738 * Prepare the hostname and address strings used for hostkey lookup. 739 * In some cases, these will have a port number appended. 740 */ 741 get_hostfile_hostname_ipaddr(hostname, hostaddr, port, &host, &ip); 742 743 /* 744 * Turn off check_host_ip if the connection is to localhost, via proxy 745 * command or if we don't have a hostname to compare with 746 */ 747 if (options.check_host_ip && (local || 748 strcmp(hostname, ip) == 0 || options.proxy_command != NULL)) 749 options.check_host_ip = 0; 750 751 host_hostkeys = init_hostkeys(); 752 for (i = 0; i < num_user_hostfiles; i++) 753 load_hostkeys(host_hostkeys, host, user_hostfiles[i]); 754 for (i = 0; i < num_system_hostfiles; i++) 755 load_hostkeys(host_hostkeys, host, system_hostfiles[i]); 756 757 ip_hostkeys = NULL; 758 if (!want_cert && options.check_host_ip) { 759 ip_hostkeys = init_hostkeys(); 760 for (i = 0; i < num_user_hostfiles; i++) 761 load_hostkeys(ip_hostkeys, ip, user_hostfiles[i]); 762 for (i = 0; i < num_system_hostfiles; i++) 763 load_hostkeys(ip_hostkeys, ip, system_hostfiles[i]); 764 } 765 766 retry: 767 /* Reload these as they may have changed on cert->key downgrade */ 768 want_cert = sshkey_is_cert(host_key); 769 type = sshkey_type(host_key); 770 771 /* 772 * Check if the host key is present in the user's list of known 773 * hosts or in the systemwide list. 774 */ 775 host_status = check_key_in_hostkeys(host_hostkeys, host_key, 776 &host_found); 777 778 /* 779 * Also perform check for the ip address, skip the check if we are 780 * localhost, looking for a certificate, or the hostname was an ip 781 * address to begin with. 782 */ 783 if (!want_cert && ip_hostkeys != NULL) { 784 ip_status = check_key_in_hostkeys(ip_hostkeys, host_key, 785 &ip_found); 786 if (host_status == HOST_CHANGED && 787 (ip_status != HOST_CHANGED || 788 (ip_found != NULL && 789 !sshkey_equal(ip_found->key, host_found->key)))) 790 host_ip_differ = 1; 791 } else 792 ip_status = host_status; 793 794 switch (host_status) { 795 case HOST_OK: 796 /* The host is known and the key matches. */ 797 debug("Host '%.200s' is known and matches the %s host %s.", 798 host, type, want_cert ? "certificate" : "key"); 799 debug("Found %s in %s:%lu", want_cert ? "CA key" : "key", 800 host_found->file, host_found->line); 801 if (want_cert && 802 !check_host_cert(options.host_key_alias == NULL ? 803 hostname : options.host_key_alias, host_key)) 804 goto fail; 805 if (options.check_host_ip && ip_status == HOST_NEW) { 806 if (readonly || want_cert) 807 logit("%s host key for IP address " 808 "'%.128s' not in list of known hosts.", 809 type, ip); 810 else if (!add_host_to_hostfile(user_hostfiles[0], ip, 811 host_key, options.hash_known_hosts)) 812 logit("Failed to add the %s host key for IP " 813 "address '%.128s' to the list of known " 814 "hosts (%.500s).", type, ip, 815 user_hostfiles[0]); 816 else 817 logit("Warning: Permanently added the %s host " 818 "key for IP address '%.128s' to the list " 819 "of known hosts.", type, ip); 820 } else if (options.visual_host_key) { 821 fp = sshkey_fingerprint(host_key, 822 options.fingerprint_hash, SSH_FP_DEFAULT); 823 ra = sshkey_fingerprint(host_key, 824 options.fingerprint_hash, SSH_FP_RANDOMART); 825 if (fp == NULL || ra == NULL) 826 fatal("%s: sshkey_fingerprint fail", __func__); 827 logit("Host key fingerprint is %s\n%s", fp, ra); 828 free(ra); 829 free(fp); 830 } 831 hostkey_trusted = 1; 832 break; 833 case HOST_NEW: 834 if (options.host_key_alias == NULL && port != 0 && 835 port != SSH_DEFAULT_PORT) { 836 debug("checking without port identifier"); 837 if (check_host_key(hostname, hostaddr, 0, host_key, 838 ROQUIET, user_hostfiles, num_user_hostfiles, 839 system_hostfiles, num_system_hostfiles) == 0) { 840 debug("found matching key w/out port"); 841 break; 842 } 843 } 844 if (readonly || want_cert) 845 goto fail; 846 /* The host is new. */ 847 if (options.strict_host_key_checking == 848 SSH_STRICT_HOSTKEY_YES) { 849 /* 850 * User has requested strict host key checking. We 851 * will not add the host key automatically. The only 852 * alternative left is to abort. 853 */ 854 error("No %s host key is known for %.200s and you " 855 "have requested strict checking.", type, host); 856 goto fail; 857 } else if (options.strict_host_key_checking == 858 SSH_STRICT_HOSTKEY_ASK) { 859 char msg1[1024], msg2[1024]; 860 861 if (show_other_keys(host_hostkeys, host_key)) 862 snprintf(msg1, sizeof(msg1), 863 "\nbut keys of different type are already" 864 " known for this host."); 865 else 866 snprintf(msg1, sizeof(msg1), "."); 867 /* The default */ 868 fp = sshkey_fingerprint(host_key, 869 options.fingerprint_hash, SSH_FP_DEFAULT); 870 ra = sshkey_fingerprint(host_key, 871 options.fingerprint_hash, SSH_FP_RANDOMART); 872 if (fp == NULL || ra == NULL) 873 fatal("%s: sshkey_fingerprint fail", __func__); 874 msg2[0] = '\0'; 875 if (options.verify_host_key_dns) { 876 if (matching_host_key_dns) 877 snprintf(msg2, sizeof(msg2), 878 "Matching host key fingerprint" 879 " found in DNS.\n"); 880 else 881 snprintf(msg2, sizeof(msg2), 882 "No matching host key fingerprint" 883 " found in DNS.\n"); 884 } 885 snprintf(msg, sizeof(msg), 886 "The authenticity of host '%.200s (%s)' can't be " 887 "established%s\n" 888 "%s key fingerprint is %s.%s%s\n%s" 889 "Are you sure you want to continue connecting " 890 "(yes/no/[fingerprint])? ", 891 host, ip, msg1, type, fp, 892 options.visual_host_key ? "\n" : "", 893 options.visual_host_key ? ra : "", 894 msg2); 895 free(ra); 896 confirmed = confirm(msg, fp); 897 free(fp); 898 if (!confirmed) 899 goto fail; 900 hostkey_trusted = 1; /* user explicitly confirmed */ 901 } 902 /* 903 * If in "new" or "off" strict mode, add the key automatically 904 * to the local known_hosts file. 905 */ 906 if (options.check_host_ip && ip_status == HOST_NEW) { 907 snprintf(hostline, sizeof(hostline), "%s,%s", host, ip); 908 hostp = hostline; 909 if (options.hash_known_hosts) { 910 /* Add hash of host and IP separately */ 911 r = add_host_to_hostfile(user_hostfiles[0], 912 host, host_key, options.hash_known_hosts) && 913 add_host_to_hostfile(user_hostfiles[0], ip, 914 host_key, options.hash_known_hosts); 915 } else { 916 /* Add unhashed "host,ip" */ 917 r = add_host_to_hostfile(user_hostfiles[0], 918 hostline, host_key, 919 options.hash_known_hosts); 920 } 921 } else { 922 r = add_host_to_hostfile(user_hostfiles[0], host, 923 host_key, options.hash_known_hosts); 924 hostp = host; 925 } 926 927 if (!r) 928 logit("Failed to add the host to the list of known " 929 "hosts (%.500s).", user_hostfiles[0]); 930 else 931 logit("Warning: Permanently added '%.200s' (%s) to the " 932 "list of known hosts.", hostp, type); 933 break; 934 case HOST_REVOKED: 935 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); 936 error("@ WARNING: REVOKED HOST KEY DETECTED! @"); 937 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); 938 error("The %s host key for %s is marked as revoked.", type, host); 939 error("This could mean that a stolen key is being used to"); 940 error("impersonate this host."); 941 942 /* 943 * If strict host key checking is in use, the user will have 944 * to edit the key manually and we can only abort. 945 */ 946 if (options.strict_host_key_checking != 947 SSH_STRICT_HOSTKEY_OFF) { 948 error("%s host key for %.200s was revoked and you have " 949 "requested strict checking.", type, host); 950 goto fail; 951 } 952 goto continue_unsafe; 953 954 case HOST_CHANGED: 955 if (want_cert) { 956 /* 957 * This is only a debug() since it is valid to have 958 * CAs with wildcard DNS matches that don't match 959 * all hosts that one might visit. 960 */ 961 debug("Host certificate authority does not " 962 "match %s in %s:%lu", CA_MARKER, 963 host_found->file, host_found->line); 964 goto fail; 965 } 966 if (readonly == ROQUIET) 967 goto fail; 968 if (options.check_host_ip && host_ip_differ) { 969 const char *key_msg; 970 if (ip_status == HOST_NEW) 971 key_msg = "is unknown"; 972 else if (ip_status == HOST_OK) 973 key_msg = "is unchanged"; 974 else 975 key_msg = "has a different value"; 976 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); 977 error("@ WARNING: POSSIBLE DNS SPOOFING DETECTED! @"); 978 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); 979 error("The %s host key for %s has changed,", type, host); 980 error("and the key for the corresponding IP address %s", ip); 981 error("%s. This could either mean that", key_msg); 982 error("DNS SPOOFING is happening or the IP address for the host"); 983 error("and its host key have changed at the same time."); 984 if (ip_status != HOST_NEW) 985 error("Offending key for IP in %s:%lu", 986 ip_found->file, ip_found->line); 987 } 988 /* The host key has changed. */ 989 warn_changed_key(host_key); 990 error("Add correct host key in %.100s to get rid of this message.", 991 user_hostfiles[0]); 992 error("Offending %s key in %s:%lu", 993 sshkey_type(host_found->key), 994 host_found->file, host_found->line); 995 996 /* 997 * If strict host key checking is in use, the user will have 998 * to edit the key manually and we can only abort. 999 */ 1000 if (options.strict_host_key_checking != 1001 SSH_STRICT_HOSTKEY_OFF) { 1002 error("%s host key for %.200s has changed and you have " 1003 "requested strict checking.", type, host); 1004 goto fail; 1005 } 1006 1007 continue_unsafe: 1008 /* 1009 * If strict host key checking has not been requested, allow 1010 * the connection but without MITM-able authentication or 1011 * forwarding. 1012 */ 1013 if (options.password_authentication) { 1014 error("Password authentication is disabled to avoid " 1015 "man-in-the-middle attacks."); 1016 options.password_authentication = 0; 1017 cancelled_forwarding = 1; 1018 } 1019 if (options.kbd_interactive_authentication) { 1020 error("Keyboard-interactive authentication is disabled" 1021 " to avoid man-in-the-middle attacks."); 1022 options.kbd_interactive_authentication = 0; 1023 options.challenge_response_authentication = 0; 1024 cancelled_forwarding = 1; 1025 } 1026 if (options.challenge_response_authentication) { 1027 error("Challenge/response authentication is disabled" 1028 " to avoid man-in-the-middle attacks."); 1029 options.challenge_response_authentication = 0; 1030 cancelled_forwarding = 1; 1031 } 1032 if (options.forward_agent) { 1033 error("Agent forwarding is disabled to avoid " 1034 "man-in-the-middle attacks."); 1035 options.forward_agent = 0; 1036 cancelled_forwarding = 1; 1037 } 1038 if (options.forward_x11) { 1039 error("X11 forwarding is disabled to avoid " 1040 "man-in-the-middle attacks."); 1041 options.forward_x11 = 0; 1042 cancelled_forwarding = 1; 1043 } 1044 if (options.num_local_forwards > 0 || 1045 options.num_remote_forwards > 0) { 1046 error("Port forwarding is disabled to avoid " 1047 "man-in-the-middle attacks."); 1048 options.num_local_forwards = 1049 options.num_remote_forwards = 0; 1050 cancelled_forwarding = 1; 1051 } 1052 if (options.tun_open != SSH_TUNMODE_NO) { 1053 error("Tunnel forwarding is disabled to avoid " 1054 "man-in-the-middle attacks."); 1055 options.tun_open = SSH_TUNMODE_NO; 1056 cancelled_forwarding = 1; 1057 } 1058 if (options.exit_on_forward_failure && cancelled_forwarding) 1059 fatal("Error: forwarding disabled due to host key " 1060 "check failure"); 1061 1062 /* 1063 * XXX Should permit the user to change to use the new id. 1064 * This could be done by converting the host key to an 1065 * identifying sentence, tell that the host identifies itself 1066 * by that sentence, and ask the user if he/she wishes to 1067 * accept the authentication. 1068 */ 1069 break; 1070 case HOST_FOUND: 1071 fatal("internal error"); 1072 break; 1073 } 1074 1075 if (options.check_host_ip && host_status != HOST_CHANGED && 1076 ip_status == HOST_CHANGED) { 1077 snprintf(msg, sizeof(msg), 1078 "Warning: the %s host key for '%.200s' " 1079 "differs from the key for the IP address '%.128s'" 1080 "\nOffending key for IP in %s:%lu", 1081 type, host, ip, ip_found->file, ip_found->line); 1082 if (host_status == HOST_OK) { 1083 len = strlen(msg); 1084 snprintf(msg + len, sizeof(msg) - len, 1085 "\nMatching host key in %s:%lu", 1086 host_found->file, host_found->line); 1087 } 1088 if (options.strict_host_key_checking == 1089 SSH_STRICT_HOSTKEY_ASK) { 1090 strlcat(msg, "\nAre you sure you want " 1091 "to continue connecting (yes/no)? ", sizeof(msg)); 1092 if (!confirm(msg, NULL)) 1093 goto fail; 1094 } else if (options.strict_host_key_checking != 1095 SSH_STRICT_HOSTKEY_OFF) { 1096 logit("%s", msg); 1097 error("Exiting, you have requested strict checking."); 1098 goto fail; 1099 } else { 1100 logit("%s", msg); 1101 } 1102 } 1103 1104 if (!hostkey_trusted && options.update_hostkeys) { 1105 debug("%s: hostkey not known or explicitly trusted: " 1106 "disabling UpdateHostkeys", __func__); 1107 options.update_hostkeys = 0; 1108 } 1109 1110 free(ip); 1111 free(host); 1112 if (host_hostkeys != NULL) 1113 free_hostkeys(host_hostkeys); 1114 if (ip_hostkeys != NULL) 1115 free_hostkeys(ip_hostkeys); 1116 return 0; 1117 1118fail: 1119 if (want_cert && host_status != HOST_REVOKED) { 1120 /* 1121 * No matching certificate. Downgrade cert to raw key and 1122 * search normally. 1123 */ 1124 debug("No matching CA found. Retry with plain key"); 1125 if ((r = sshkey_from_private(host_key, &raw_key)) != 0) 1126 fatal("%s: sshkey_from_private: %s", 1127 __func__, ssh_err(r)); 1128 if ((r = sshkey_drop_cert(raw_key)) != 0) 1129 fatal("Couldn't drop certificate: %s", ssh_err(r)); 1130 host_key = raw_key; 1131 goto retry; 1132 } 1133 sshkey_free(raw_key); 1134 free(ip); 1135 free(host); 1136 if (host_hostkeys != NULL) 1137 free_hostkeys(host_hostkeys); 1138 if (ip_hostkeys != NULL) 1139 free_hostkeys(ip_hostkeys); 1140 return -1; 1141} 1142 1143/* returns 0 if key verifies or -1 if key does NOT verify */ 1144int 1145verify_host_key(char *host, struct sockaddr *hostaddr, struct sshkey *host_key) 1146{ 1147 u_int i; 1148 int r = -1, flags = 0; 1149 char valid[64], *fp = NULL, *cafp = NULL; 1150 struct sshkey *plain = NULL; 1151 1152 if ((fp = sshkey_fingerprint(host_key, 1153 options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) { 1154 error("%s: fingerprint host key: %s", __func__, ssh_err(r)); 1155 r = -1; 1156 goto out; 1157 } 1158 1159 if (sshkey_is_cert(host_key)) { 1160 if ((cafp = sshkey_fingerprint(host_key->cert->signature_key, 1161 options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) { 1162 error("%s: fingerprint CA key: %s", 1163 __func__, ssh_err(r)); 1164 r = -1; 1165 goto out; 1166 } 1167 sshkey_format_cert_validity(host_key->cert, 1168 valid, sizeof(valid)); 1169 debug("Server host certificate: %s %s, serial %llu " 1170 "ID \"%s\" CA %s %s valid %s", 1171 sshkey_ssh_name(host_key), fp, 1172 (unsigned long long)host_key->cert->serial, 1173 host_key->cert->key_id, 1174 sshkey_ssh_name(host_key->cert->signature_key), cafp, 1175 valid); 1176 for (i = 0; i < host_key->cert->nprincipals; i++) { 1177 debug2("Server host certificate hostname: %s", 1178 host_key->cert->principals[i]); 1179 } 1180 } else { 1181 debug("Server host key: %s %s", sshkey_ssh_name(host_key), fp); 1182 } 1183 1184 if (sshkey_equal(previous_host_key, host_key)) { 1185 debug2("%s: server host key %s %s matches cached key", 1186 __func__, sshkey_type(host_key), fp); 1187 r = 0; 1188 goto out; 1189 } 1190 1191 /* Check in RevokedHostKeys file if specified */ 1192 if (options.revoked_host_keys != NULL) { 1193 r = sshkey_check_revoked(host_key, options.revoked_host_keys); 1194 switch (r) { 1195 case 0: 1196 break; /* not revoked */ 1197 case SSH_ERR_KEY_REVOKED: 1198 error("Host key %s %s revoked by file %s", 1199 sshkey_type(host_key), fp, 1200 options.revoked_host_keys); 1201 r = -1; 1202 goto out; 1203 default: 1204 error("Error checking host key %s %s in " 1205 "revoked keys file %s: %s", sshkey_type(host_key), 1206 fp, options.revoked_host_keys, ssh_err(r)); 1207 r = -1; 1208 goto out; 1209 } 1210 } 1211 1212 if (options.verify_host_key_dns) { 1213 /* 1214 * XXX certs are not yet supported for DNS, so downgrade 1215 * them and try the plain key. 1216 */ 1217 if ((r = sshkey_from_private(host_key, &plain)) != 0) 1218 goto out; 1219 if (sshkey_is_cert(plain)) 1220 sshkey_drop_cert(plain); 1221 if (verify_host_key_dns(host, hostaddr, plain, &flags) == 0) { 1222 if (flags & DNS_VERIFY_FOUND) { 1223 if (options.verify_host_key_dns == 1 && 1224 flags & DNS_VERIFY_MATCH && 1225 flags & DNS_VERIFY_SECURE) { 1226 r = 0; 1227 goto out; 1228 } 1229 if (flags & DNS_VERIFY_MATCH) { 1230 matching_host_key_dns = 1; 1231 } else { 1232 warn_changed_key(plain); 1233 error("Update the SSHFP RR in DNS " 1234 "with the new host key to get rid " 1235 "of this message."); 1236 } 1237 } 1238 } 1239 } 1240 r = check_host_key(host, hostaddr, options.port, host_key, RDRW, 1241 options.user_hostfiles, options.num_user_hostfiles, 1242 options.system_hostfiles, options.num_system_hostfiles); 1243 1244out: 1245 sshkey_free(plain); 1246 free(fp); 1247 free(cafp); 1248 if (r == 0 && host_key != NULL) { 1249 sshkey_free(previous_host_key); 1250 r = sshkey_from_private(host_key, &previous_host_key); 1251 } 1252 1253 return r; 1254} 1255 1256/* 1257 * Starts a dialog with the server, and authenticates the current user on the 1258 * server. This does not need any extra privileges. The basic connection 1259 * to the server must already have been established before this is called. 1260 * If login fails, this function prints an error and never returns. 1261 * This function does not require super-user privileges. 1262 */ 1263void 1264ssh_login(struct ssh *ssh, Sensitive *sensitive, const char *orighost, 1265 struct sockaddr *hostaddr, u_short port, struct passwd *pw, int timeout_ms) 1266{ 1267 char *host; 1268 char *server_user, *local_user; 1269 1270 local_user = xstrdup(pw->pw_name); 1271 server_user = options.user ? options.user : local_user; 1272 1273 /* Convert the user-supplied hostname into all lowercase. */ 1274 host = xstrdup(orighost); 1275 lowercase(host); 1276 1277 /* Exchange protocol version identification strings with the server. */ 1278 if (kex_exchange_identification(ssh, timeout_ms, NULL) != 0) 1279 cleanup_exit(255); /* error already logged */ 1280 1281 /* Put the connection into non-blocking mode. */ 1282 ssh_packet_set_nonblocking(ssh); 1283 1284 /* key exchange */ 1285 /* authenticate user */ 1286 debug("Authenticating to %s:%d as '%s'", host, port, server_user); 1287 ssh_kex2(ssh, host, hostaddr, port); 1288 ssh_userauth2(ssh, local_user, server_user, host, sensitive); 1289 free(local_user); 1290} 1291 1292/* print all known host keys for a given host, but skip keys of given type */ 1293static int 1294show_other_keys(struct hostkeys *hostkeys, struct sshkey *key) 1295{ 1296 int type[] = { 1297 KEY_RSA, 1298 KEY_DSA, 1299 KEY_ECDSA, 1300 KEY_ED25519, 1301 KEY_XMSS, 1302 -1 1303 }; 1304 int i, ret = 0; 1305 char *fp, *ra; 1306 const struct hostkey_entry *found; 1307 1308 for (i = 0; type[i] != -1; i++) { 1309 if (type[i] == key->type) 1310 continue; 1311 if (!lookup_key_in_hostkeys_by_type(hostkeys, type[i], &found)) 1312 continue; 1313 fp = sshkey_fingerprint(found->key, 1314 options.fingerprint_hash, SSH_FP_DEFAULT); 1315 ra = sshkey_fingerprint(found->key, 1316 options.fingerprint_hash, SSH_FP_RANDOMART); 1317 if (fp == NULL || ra == NULL) 1318 fatal("%s: sshkey_fingerprint fail", __func__); 1319 logit("WARNING: %s key found for host %s\n" 1320 "in %s:%lu\n" 1321 "%s key fingerprint %s.", 1322 sshkey_type(found->key), 1323 found->host, found->file, found->line, 1324 sshkey_type(found->key), fp); 1325 if (options.visual_host_key) 1326 logit("%s", ra); 1327 free(ra); 1328 free(fp); 1329 ret = 1; 1330 } 1331 return ret; 1332} 1333 1334static void 1335warn_changed_key(struct sshkey *host_key) 1336{ 1337 char *fp; 1338 1339 fp = sshkey_fingerprint(host_key, options.fingerprint_hash, 1340 SSH_FP_DEFAULT); 1341 if (fp == NULL) 1342 fatal("%s: sshkey_fingerprint fail", __func__); 1343 1344 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); 1345 error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @"); 1346 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); 1347 error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!"); 1348 error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!"); 1349 error("It is also possible that a host key has just been changed."); 1350 error("The fingerprint for the %s key sent by the remote host is\n%s.", 1351 sshkey_type(host_key), fp); 1352 error("Please contact your system administrator."); 1353 1354 free(fp); 1355} 1356 1357/* 1358 * Execute a local command 1359 */ 1360int 1361ssh_local_cmd(const char *args) 1362{ 1363 const char *shell; 1364 pid_t pid; 1365 int status; 1366 void (*osighand)(int); 1367 1368 if (!options.permit_local_command || 1369 args == NULL || !*args) 1370 return (1); 1371 1372 if ((shell = getenv("SHELL")) == NULL || *shell == '\0') 1373 shell = _PATH_BSHELL; 1374 1375 osighand = signal(SIGCHLD, SIG_DFL); 1376 pid = fork(); 1377 if (pid == 0) { 1378 signal(SIGPIPE, SIG_DFL); 1379 debug3("Executing %s -c \"%s\"", shell, args); 1380 execl(shell, shell, "-c", args, (char *)NULL); 1381 error("Couldn't execute %s -c \"%s\": %s", 1382 shell, args, strerror(errno)); 1383 _exit(1); 1384 } else if (pid == -1) 1385 fatal("fork failed: %.100s", strerror(errno)); 1386 while (waitpid(pid, &status, 0) == -1) 1387 if (errno != EINTR) 1388 fatal("Couldn't wait for child: %s", strerror(errno)); 1389 signal(SIGCHLD, osighand); 1390 1391 if (!WIFEXITED(status)) 1392 return (1); 1393 1394 return (WEXITSTATUS(status)); 1395} 1396 1397void 1398maybe_add_key_to_agent(char *authfile, const struct sshkey *private, 1399 char *comment, char *passphrase) 1400{ 1401 int auth_sock = -1, r; 1402 1403 if (options.add_keys_to_agent == 0) 1404 return; 1405 1406 if ((r = ssh_get_authentication_socket(&auth_sock)) != 0) { 1407 debug3("no authentication agent, not adding key"); 1408 return; 1409 } 1410 1411 if (options.add_keys_to_agent == 2 && 1412 !ask_permission("Add key %s (%s) to agent?", authfile, comment)) { 1413 debug3("user denied adding this key"); 1414 close(auth_sock); 1415 return; 1416 } 1417 1418 if ((r = ssh_add_identity_constrained(auth_sock, private, comment, 0, 1419 (options.add_keys_to_agent == 3), 0)) == 0) 1420 debug("identity added to agent: %s", authfile); 1421 else 1422 debug("could not add identity to agent: %s (%d)", authfile, r); 1423 close(auth_sock); 1424} 1425