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