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