Annotation of src/usr.bin/ssh/sshconnect.c, Revision 1.38
1.1 deraadt 1: /*
2:
3: sshconnect.c
4:
5: Author: Tatu Ylonen <ylo@cs.hut.fi>
6:
7: Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8: All rights reserved
9:
10: Created: Sat Mar 18 22:15:47 1995 ylo
11:
12: Code to connect to a remote host, and to perform the client side of the
13: login (authentication) dialog.
14:
15: */
16:
17: #include "includes.h"
1.38 ! markus 18: RCSID("$Id: sshconnect.c,v 1.37 1999/11/22 21:52:42 markus Exp $");
1.1 deraadt 19:
1.3 provos 20: #include <ssl/bn.h>
1.1 deraadt 21: #include "xmalloc.h"
22: #include "rsa.h"
23: #include "ssh.h"
24: #include "packet.h"
25: #include "authfd.h"
26: #include "cipher.h"
27: #include "mpaux.h"
28: #include "uidswap.h"
1.21 markus 29: #include "compat.h"
1.27 markus 30: #include "readconf.h"
1.34 markus 31: #include "fingerprint.h"
1.1 deraadt 32:
1.24 deraadt 33: #include <ssl/md5.h>
1.10 deraadt 34:
1.1 deraadt 35: /* Session id for the current session. */
36: unsigned char session_id[16];
37:
38: /* Connect to the given ssh server using a proxy command. */
39:
1.3 provos 40: int
41: ssh_proxy_connect(const char *host, int port, uid_t original_real_uid,
42: const char *proxy_command)
1.1 deraadt 43: {
1.38 ! markus 44: Buffer command;
! 45: const char *cp;
! 46: char *command_string;
! 47: int pin[2], pout[2];
! 48: int pid;
! 49: char portstring[100];
! 50:
! 51: /* Convert the port number into a string. */
! 52: snprintf(portstring, sizeof portstring, "%d", port);
! 53:
! 54: /* Build the final command string in the buffer by making the
! 55: appropriate substitutions to the given proxy command. */
! 56: buffer_init(&command);
! 57: for (cp = proxy_command; *cp; cp++) {
! 58: if (cp[0] == '%' && cp[1] == '%') {
! 59: buffer_append(&command, "%", 1);
! 60: cp++;
! 61: continue;
! 62: }
! 63: if (cp[0] == '%' && cp[1] == 'h') {
! 64: buffer_append(&command, host, strlen(host));
! 65: cp++;
! 66: continue;
! 67: }
! 68: if (cp[0] == '%' && cp[1] == 'p') {
! 69: buffer_append(&command, portstring, strlen(portstring));
! 70: cp++;
! 71: continue;
! 72: }
! 73: buffer_append(&command, cp, 1);
! 74: }
! 75: buffer_append(&command, "\0", 1);
! 76:
! 77: /* Get the final command string. */
! 78: command_string = buffer_ptr(&command);
! 79:
! 80: /* Create pipes for communicating with the proxy. */
! 81: if (pipe(pin) < 0 || pipe(pout) < 0)
! 82: fatal("Could not create pipes to communicate with the proxy: %.100s",
! 83: strerror(errno));
! 84:
! 85: debug("Executing proxy command: %.500s", command_string);
! 86:
! 87: /* Fork and execute the proxy command. */
! 88: if ((pid = fork()) == 0) {
! 89: char *argv[10];
! 90:
! 91: /* Child. Permanently give up superuser privileges. */
! 92: permanently_set_uid(original_real_uid);
! 93:
! 94: /* Redirect stdin and stdout. */
! 95: close(pin[1]);
! 96: if (pin[0] != 0) {
! 97: if (dup2(pin[0], 0) < 0)
! 98: perror("dup2 stdin");
! 99: close(pin[0]);
! 100: }
! 101: close(pout[0]);
! 102: if (dup2(pout[1], 1) < 0)
! 103: perror("dup2 stdout");
! 104: /* Cannot be 1 because pin allocated two descriptors. */
! 105: close(pout[1]);
! 106:
! 107: /* Stderr is left as it is so that error messages get
! 108: printed on the user's terminal. */
! 109: argv[0] = "/bin/sh";
! 110: argv[1] = "-c";
! 111: argv[2] = command_string;
! 112: argv[3] = NULL;
! 113:
! 114: /* Execute the proxy command. Note that we gave up any
! 115: extra privileges above. */
! 116: execv("/bin/sh", argv);
! 117: perror("/bin/sh");
! 118: exit(1);
! 119: }
! 120: /* Parent. */
! 121: if (pid < 0)
! 122: fatal("fork failed: %.100s", strerror(errno));
! 123:
! 124: /* Close child side of the descriptors. */
! 125: close(pin[0]);
! 126: close(pout[1]);
! 127:
! 128: /* Free the command name. */
! 129: buffer_free(&command);
! 130:
! 131: /* Set the connection file descriptors. */
! 132: packet_set_connection(pout[0], pin[1]);
1.1 deraadt 133:
1.38 ! markus 134: return 1;
1.1 deraadt 135: }
136:
137: /* Creates a (possibly privileged) socket for use as the ssh connection. */
138:
1.38 ! markus 139: int
! 140: ssh_create_socket(uid_t original_real_uid, int privileged)
1.1 deraadt 141: {
1.38 ! markus 142: int sock;
1.1 deraadt 143:
1.38 ! markus 144: /* If we are running as root and want to connect to a privileged
! 145: port, bind our own socket to a privileged port. */
! 146: if (privileged) {
! 147: int p = IPPORT_RESERVED - 1;
! 148:
! 149: sock = rresvport(&p);
! 150: if (sock < 0)
! 151: fatal("rresvport: %.100s", strerror(errno));
! 152: debug("Allocated local port %d.", p);
! 153: } else {
! 154: /* Just create an ordinary socket on arbitrary port. We
! 155: use the user's uid to create the socket. */
! 156: temporarily_use_uid(original_real_uid);
! 157: sock = socket(AF_INET, SOCK_STREAM, 0);
! 158: if (sock < 0)
! 159: fatal("socket: %.100s", strerror(errno));
! 160: restore_uid();
! 161: }
! 162: return sock;
1.1 deraadt 163: }
164:
165: /* Opens a TCP/IP connection to the remote server on the given host. If
166: port is 0, the default port will be used. If anonymous is zero,
1.38 ! markus 167: a privileged port will be allocated to make the connection.
! 168: This requires super-user privileges if anonymous is false.
1.1 deraadt 169: Connection_attempts specifies the maximum number of tries (one per
1.38 ! markus 170: second). If proxy_command is non-NULL, it specifies the command (with %h
1.1 deraadt 171: and %p substituted for host and port, respectively) to use to contact
172: the daemon. */
173:
1.38 ! markus 174: int
! 175: ssh_connect(const char *host, struct sockaddr_in * hostaddr,
! 176: int port, int connection_attempts,
! 177: int anonymous, uid_t original_real_uid,
! 178: const char *proxy_command)
1.1 deraadt 179: {
1.38 ! markus 180: int sock = -1, attempt, i;
! 181: int on = 1;
! 182: struct servent *sp;
! 183: struct hostent *hp;
! 184: struct linger linger;
! 185:
! 186: debug("ssh_connect: getuid %d geteuid %d anon %d",
! 187: (int) getuid(), (int) geteuid(), anonymous);
! 188:
! 189: /* Get default port if port has not been set. */
! 190: if (port == 0) {
! 191: sp = getservbyname(SSH_SERVICE_NAME, "tcp");
! 192: if (sp)
! 193: port = ntohs(sp->s_port);
! 194: else
! 195: port = SSH_DEFAULT_PORT;
! 196: }
! 197: /* If a proxy command is given, connect using it. */
! 198: if (proxy_command != NULL)
! 199: return ssh_proxy_connect(host, port, original_real_uid, proxy_command);
! 200:
! 201: /* No proxy command. */
! 202:
! 203: /* No host lookup made yet. */
! 204: hp = NULL;
! 205:
! 206: /* Try to connect several times. On some machines, the first time
! 207: will sometimes fail. In general socket code appears to behave
! 208: quite magically on many machines. */
! 209: for (attempt = 0; attempt < connection_attempts; attempt++) {
! 210: if (attempt > 0)
! 211: debug("Trying again...");
! 212:
! 213: /* Try to parse the host name as a numeric inet address. */
! 214: memset(hostaddr, 0, sizeof(hostaddr));
! 215: hostaddr->sin_family = AF_INET;
! 216: hostaddr->sin_port = htons(port);
! 217: hostaddr->sin_addr.s_addr = inet_addr(host);
! 218: if ((hostaddr->sin_addr.s_addr & 0xffffffff) != 0xffffffff) {
! 219: /* Valid numeric IP address */
! 220: debug("Connecting to %.100s port %d.",
! 221: inet_ntoa(hostaddr->sin_addr), port);
! 222:
! 223: /* Create a socket. */
! 224: sock = ssh_create_socket(original_real_uid,
! 225: !anonymous && geteuid() == 0 &&
! 226: port < IPPORT_RESERVED);
! 227:
! 228: /* Connect to the host. We use the user's uid in
! 229: the hope that it will help with the problems of
! 230: tcp_wrappers showing the remote uid as root. */
! 231: temporarily_use_uid(original_real_uid);
! 232: if (connect(sock, (struct sockaddr *) hostaddr, sizeof(*hostaddr))
! 233: >= 0) {
! 234: /* Successful connect. */
! 235: restore_uid();
! 236: break;
! 237: }
! 238: debug("connect: %.100s", strerror(errno));
! 239: restore_uid();
! 240:
! 241: /* Destroy the failed socket. */
! 242: shutdown(sock, SHUT_RDWR);
! 243: close(sock);
! 244: } else {
! 245: /* Not a valid numeric inet address. */
! 246: /* Map host name to an address. */
! 247: if (!hp)
! 248: hp = gethostbyname(host);
! 249: if (!hp)
! 250: fatal("Bad host name: %.100s", host);
! 251: if (!hp->h_addr_list[0])
! 252: fatal("Host does not have an IP address: %.100s", host);
! 253:
! 254: /* Loop through addresses for this host, and try
! 255: each one in sequence until the connection
! 256: succeeds. */
! 257: for (i = 0; hp->h_addr_list[i]; i++) {
! 258: /* Set the address to connect to. */
! 259: hostaddr->sin_family = hp->h_addrtype;
! 260: memcpy(&hostaddr->sin_addr, hp->h_addr_list[i],
! 261: sizeof(hostaddr->sin_addr));
! 262:
! 263: debug("Connecting to %.200s [%.100s] port %d.",
! 264: host, inet_ntoa(hostaddr->sin_addr), port);
! 265:
! 266: /* Create a socket for connecting. */
! 267: sock = ssh_create_socket(original_real_uid,
! 268: !anonymous && geteuid() == 0 &&
! 269: port < IPPORT_RESERVED);
! 270:
! 271: /* Connect to the host. We use the user's uid in the hope that
! 272: it will help with tcp_wrappers showing the remote uid as root. */
! 273: temporarily_use_uid(original_real_uid);
! 274: if (connect(sock, (struct sockaddr *) hostaddr,
! 275: sizeof(*hostaddr)) >= 0) {
! 276: /* Successful connection. */
! 277: restore_uid();
! 278: break;
! 279: }
! 280: debug("connect: %.100s", strerror(errno));
! 281: restore_uid();
! 282:
! 283: /* Close the failed socket; there appear to be some problems when
! 284: reusing a socket for which connect() has already returned an error. */
! 285: shutdown(sock, SHUT_RDWR);
! 286: close(sock);
! 287: }
! 288: if (hp->h_addr_list[i])
! 289: break; /* Successful connection. */
! 290: }
1.1 deraadt 291:
1.38 ! markus 292: /* Sleep a moment before retrying. */
! 293: sleep(1);
! 294: }
! 295: /* Return failure if we didn't get a successful connection. */
! 296: if (attempt >= connection_attempts)
! 297: return 0;
! 298:
! 299: debug("Connection established.");
! 300:
! 301: /* Set socket options. We would like the socket to disappear as
! 302: soon as it has been closed for whatever reason. */
! 303: /* setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on,
! 304: sizeof(on)); */
! 305: setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void *) &on, sizeof(on));
! 306: linger.l_onoff = 1;
! 307: linger.l_linger = 5;
! 308: setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *) &linger, sizeof(linger));
! 309:
! 310: /* Set the connection. */
! 311: packet_set_connection(sock, sock);
1.1 deraadt 312:
1.38 ! markus 313: return 1;
1.1 deraadt 314: }
315:
316: /* Checks if the user has an authentication agent, and if so, tries to
317: authenticate using the agent. */
318:
1.3 provos 319: int
320: try_agent_authentication()
1.1 deraadt 321: {
1.38 ! markus 322: int status, type;
! 323: char *comment;
! 324: AuthenticationConnection *auth;
! 325: unsigned char response[16];
! 326: unsigned int i;
! 327: BIGNUM *e, *n, *challenge;
! 328:
! 329: /* Get connection to the agent. */
! 330: auth = ssh_get_authentication_connection();
! 331: if (!auth)
! 332: return 0;
! 333:
! 334: e = BN_new();
! 335: n = BN_new();
! 336: challenge = BN_new();
! 337:
! 338: /* Loop through identities served by the agent. */
! 339: for (status = ssh_get_first_identity(auth, e, n, &comment);
! 340: status;
! 341: status = ssh_get_next_identity(auth, e, n, &comment)) {
! 342: int plen, clen;
! 343:
! 344: /* Try this identity. */
! 345: debug("Trying RSA authentication via agent with '%.100s'", comment);
! 346: xfree(comment);
! 347:
! 348: /* Tell the server that we are willing to authenticate using this key. */
! 349: packet_start(SSH_CMSG_AUTH_RSA);
! 350: packet_put_bignum(n);
! 351: packet_send();
! 352: packet_write_wait();
! 353:
! 354: /* Wait for server's response. */
! 355: type = packet_read(&plen);
! 356:
! 357: /* The server sends failure if it doesn\'t like our key or
! 358: does not support RSA authentication. */
! 359: if (type == SSH_SMSG_FAILURE) {
! 360: debug("Server refused our key.");
! 361: continue;
! 362: }
! 363: /* Otherwise it should have sent a challenge. */
! 364: if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)
! 365: packet_disconnect("Protocol error during RSA authentication: %d",
! 366: type);
! 367:
! 368: packet_get_bignum(challenge, &clen);
! 369:
! 370: packet_integrity_check(plen, clen, type);
! 371:
! 372: debug("Received RSA challenge from server.");
! 373:
! 374: /* Ask the agent to decrypt the challenge. */
! 375: if (!ssh_decrypt_challenge(auth, e, n, challenge,
! 376: session_id, 1, response)) {
! 377: /* The agent failed to authenticate this identifier although it
! 378: advertised it supports this. Just return a wrong value. */
! 379: log("Authentication agent failed to decrypt challenge.");
! 380: memset(response, 0, sizeof(response));
! 381: }
! 382: debug("Sending response to RSA challenge.");
1.1 deraadt 383:
1.38 ! markus 384: /* Send the decrypted challenge back to the server. */
! 385: packet_start(SSH_CMSG_AUTH_RSA_RESPONSE);
! 386: for (i = 0; i < 16; i++)
! 387: packet_put_char(response[i]);
! 388: packet_send();
! 389: packet_write_wait();
! 390:
! 391: /* Wait for response from the server. */
! 392: type = packet_read(&plen);
! 393:
! 394: /* The server returns success if it accepted the authentication. */
! 395: if (type == SSH_SMSG_SUCCESS) {
! 396: debug("RSA authentication accepted by server.");
! 397: BN_clear_free(e);
! 398: BN_clear_free(n);
! 399: BN_clear_free(challenge);
! 400: return 1;
! 401: }
! 402: /* Otherwise it should return failure. */
! 403: if (type != SSH_SMSG_FAILURE)
! 404: packet_disconnect("Protocol error waiting RSA auth response: %d",
! 405: type);
! 406: }
! 407:
! 408: BN_clear_free(e);
! 409: BN_clear_free(n);
! 410: BN_clear_free(challenge);
! 411:
! 412: debug("RSA authentication using agent refused.");
! 413: return 0;
1.1 deraadt 414: }
415:
416: /* Computes the proper response to a RSA challenge, and sends the response to
417: the server. */
418:
1.3 provos 419: void
1.38 ! markus 420: respond_to_rsa_challenge(BIGNUM * challenge, RSA * prv)
1.1 deraadt 421: {
1.38 ! markus 422: unsigned char buf[32], response[16];
! 423: MD5_CTX md;
! 424: int i, len;
! 425:
! 426: /* Decrypt the challenge using the private key. */
! 427: rsa_private_decrypt(challenge, challenge, prv);
! 428:
! 429: /* Compute the response. */
! 430: /* The response is MD5 of decrypted challenge plus session id. */
! 431: len = BN_num_bytes(challenge);
! 432: if (len <= 0 || len > sizeof(buf))
! 433: packet_disconnect("respond_to_rsa_challenge: bad challenge length %d",
! 434: len);
! 435:
! 436: memset(buf, 0, sizeof(buf));
! 437: BN_bn2bin(challenge, buf + sizeof(buf) - len);
! 438: MD5_Init(&md);
! 439: MD5_Update(&md, buf, 32);
! 440: MD5_Update(&md, session_id, 16);
! 441: MD5_Final(response, &md);
! 442:
! 443: debug("Sending response to host key RSA challenge.");
! 444:
! 445: /* Send the response back to the server. */
! 446: packet_start(SSH_CMSG_AUTH_RSA_RESPONSE);
! 447: for (i = 0; i < 16; i++)
! 448: packet_put_char(response[i]);
! 449: packet_send();
! 450: packet_write_wait();
! 451:
! 452: memset(buf, 0, sizeof(buf));
! 453: memset(response, 0, sizeof(response));
! 454: memset(&md, 0, sizeof(md));
1.1 deraadt 455: }
456:
457: /* Checks if the user has authentication file, and if so, tries to authenticate
458: the user using it. */
459:
1.3 provos 460: int
1.38 ! markus 461: try_rsa_authentication(struct passwd * pw, const char *authfile)
1.1 deraadt 462: {
1.38 ! markus 463: extern Options options;
! 464: BIGNUM *challenge;
! 465: RSA *private_key;
! 466: RSA *public_key;
! 467: char *passphrase, *comment;
! 468: int type, i;
! 469: int plen, clen;
! 470:
! 471: /* Try to load identification for the authentication key. */
! 472: public_key = RSA_new();
! 473: if (!load_public_key(authfile, public_key, &comment)) {
! 474: RSA_free(public_key);
! 475: return 0; /* Could not load it. Fail. */
! 476: }
! 477: debug("Trying RSA authentication with key '%.100s'", comment);
! 478:
! 479: /* Tell the server that we are willing to authenticate using this key. */
! 480: packet_start(SSH_CMSG_AUTH_RSA);
! 481: packet_put_bignum(public_key->n);
! 482: packet_send();
! 483: packet_write_wait();
! 484:
! 485: /* We no longer need the public key. */
! 486: RSA_free(public_key);
! 487:
! 488: /* Wait for server's response. */
! 489: type = packet_read(&plen);
! 490:
! 491: /* The server responds with failure if it doesn\'t like our key or
! 492: doesn\'t support RSA authentication. */
! 493: if (type == SSH_SMSG_FAILURE) {
! 494: debug("Server refused our key.");
! 495: xfree(comment);
! 496: return 0; /* Server refuses to authenticate with
! 497: this key. */
! 498: }
! 499: /* Otherwise, the server should respond with a challenge. */
! 500: if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)
! 501: packet_disconnect("Protocol error during RSA authentication: %d", type);
! 502:
! 503: /* Get the challenge from the packet. */
! 504: challenge = BN_new();
! 505: packet_get_bignum(challenge, &clen);
! 506:
! 507: packet_integrity_check(plen, clen, type);
! 508:
! 509: debug("Received RSA challenge from server.");
! 510:
! 511: private_key = RSA_new();
! 512: /* Load the private key. Try first with empty passphrase; if it
! 513: fails, ask for a passphrase. */
! 514: if (!load_private_key(authfile, "", private_key, NULL)) {
! 515: char buf[300];
! 516: snprintf(buf, sizeof buf, "Enter passphrase for RSA key '%.100s': ",
! 517: comment);
! 518: if (!options.batch_mode)
! 519: passphrase = read_passphrase(buf, 0);
! 520: else {
! 521: debug("Will not query passphrase for %.100s in batch mode.",
! 522: comment);
! 523: passphrase = xstrdup("");
! 524: }
! 525:
! 526: /* Load the authentication file using the pasphrase. */
! 527: if (!load_private_key(authfile, passphrase, private_key, NULL)) {
! 528: memset(passphrase, 0, strlen(passphrase));
! 529: xfree(passphrase);
! 530: error("Bad passphrase.");
! 531:
! 532: /* Send a dummy response packet to avoid protocol error. */
! 533: packet_start(SSH_CMSG_AUTH_RSA_RESPONSE);
! 534: for (i = 0; i < 16; i++)
! 535: packet_put_char(0);
! 536: packet_send();
! 537: packet_write_wait();
! 538:
! 539: /* Expect the server to reject it... */
! 540: packet_read_expect(&plen, SSH_SMSG_FAILURE);
! 541: xfree(comment);
! 542: return 0;
! 543: }
! 544: /* Destroy the passphrase. */
! 545: memset(passphrase, 0, strlen(passphrase));
! 546: xfree(passphrase);
! 547: }
! 548: /* We no longer need the comment. */
! 549: xfree(comment);
! 550:
! 551: /* Compute and send a response to the challenge. */
! 552: respond_to_rsa_challenge(challenge, private_key);
! 553:
! 554: /* Destroy the private key. */
! 555: RSA_free(private_key);
! 556:
! 557: /* We no longer need the challenge. */
! 558: BN_clear_free(challenge);
! 559:
! 560: /* Wait for response from the server. */
! 561: type = packet_read(&plen);
! 562: if (type == SSH_SMSG_SUCCESS) {
! 563: debug("RSA authentication accepted by server.");
! 564: return 1;
! 565: }
! 566: if (type != SSH_SMSG_FAILURE)
! 567: packet_disconnect("Protocol error waiting RSA auth response: %d", type);
! 568: debug("RSA authentication refused.");
! 569: return 0;
1.1 deraadt 570: }
571:
572: /* Tries to authenticate the user using combined rhosts or /etc/hosts.equiv
573: authentication and RSA host authentication. */
574:
1.3 provos 575: int
1.38 ! markus 576: try_rhosts_rsa_authentication(const char *local_user, RSA * host_key)
1.1 deraadt 577: {
1.38 ! markus 578: int type;
! 579: BIGNUM *challenge;
! 580: int plen, clen;
! 581:
! 582: debug("Trying rhosts or /etc/hosts.equiv with RSA host authentication.");
! 583:
! 584: /* Tell the server that we are willing to authenticate using this key. */
! 585: packet_start(SSH_CMSG_AUTH_RHOSTS_RSA);
! 586: packet_put_string(local_user, strlen(local_user));
! 587: packet_put_int(BN_num_bits(host_key->n));
! 588: packet_put_bignum(host_key->e);
! 589: packet_put_bignum(host_key->n);
! 590: packet_send();
! 591: packet_write_wait();
! 592:
! 593: /* Wait for server's response. */
! 594: type = packet_read(&plen);
! 595:
! 596: /* The server responds with failure if it doesn't admit our
! 597: .rhosts authentication or doesn't know our host key. */
! 598: if (type == SSH_SMSG_FAILURE) {
! 599: debug("Server refused our rhosts authentication or host key.");
! 600: return 0;
! 601: }
! 602: /* Otherwise, the server should respond with a challenge. */
! 603: if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)
! 604: packet_disconnect("Protocol error during RSA authentication: %d", type);
! 605:
! 606: /* Get the challenge from the packet. */
! 607: challenge = BN_new();
! 608: packet_get_bignum(challenge, &clen);
! 609:
! 610: packet_integrity_check(plen, clen, type);
! 611:
! 612: debug("Received RSA challenge for host key from server.");
! 613:
! 614: /* Compute a response to the challenge. */
! 615: respond_to_rsa_challenge(challenge, host_key);
! 616:
! 617: /* We no longer need the challenge. */
! 618: BN_clear_free(challenge);
! 619:
! 620: /* Wait for response from the server. */
! 621: type = packet_read(&plen);
! 622: if (type == SSH_SMSG_SUCCESS) {
! 623: debug("Rhosts or /etc/hosts.equiv with RSA host authentication accepted by server.");
! 624: return 1;
! 625: }
! 626: if (type != SSH_SMSG_FAILURE)
! 627: packet_disconnect("Protocol error waiting RSA auth response: %d", type);
! 628: debug("Rhosts or /etc/hosts.equiv with RSA host authentication refused.");
! 629: return 0;
1.1 deraadt 630: }
631:
632: #ifdef KRB4
1.38 ! markus 633: int
! 634: try_kerberos_authentication()
1.1 deraadt 635: {
1.38 ! markus 636: KTEXT_ST auth; /* Kerberos data */
! 637: char *reply;
! 638: char inst[INST_SZ];
! 639: char *realm;
! 640: CREDENTIALS cred;
! 641: int r, type, plen;
! 642: Key_schedule schedule;
! 643: u_long checksum, cksum;
! 644: MSG_DAT msg_data;
! 645: struct sockaddr_in local, foreign;
! 646: struct stat st;
! 647:
! 648: /* Don't do anything if we don't have any tickets. */
! 649: if (stat(tkt_string(), &st) < 0)
! 650: return 0;
! 651:
! 652: strncpy(inst, (char *) krb_get_phost(get_canonical_hostname()), INST_SZ);
! 653:
! 654: realm = (char *) krb_realmofhost(get_canonical_hostname());
! 655: if (!realm) {
! 656: debug("Kerberos V4: no realm for %s", get_canonical_hostname());
! 657: return 0;
! 658: }
! 659: /* This can really be anything. */
! 660: checksum = (u_long) getpid();
! 661:
! 662: r = krb_mk_req(&auth, KRB4_SERVICE_NAME, inst, realm, checksum);
! 663: if (r != KSUCCESS) {
! 664: debug("Kerberos V4 krb_mk_req failed: %s", krb_err_txt[r]);
! 665: return 0;
! 666: }
! 667: /* Get session key to decrypt the server's reply with. */
! 668: r = krb_get_cred(KRB4_SERVICE_NAME, inst, realm, &cred);
! 669: if (r != KSUCCESS) {
! 670: debug("get_cred failed: %s", krb_err_txt[r]);
! 671: return 0;
! 672: }
! 673: des_key_sched((des_cblock *) cred.session, schedule);
! 674:
! 675: /* Send authentication info to server. */
! 676: packet_start(SSH_CMSG_AUTH_KERBEROS);
! 677: packet_put_string((char *) auth.dat, auth.length);
! 678: packet_send();
! 679: packet_write_wait();
! 680:
! 681: /* Zero the buffer. */
! 682: (void) memset(auth.dat, 0, MAX_KTXT_LEN);
! 683:
! 684: r = sizeof(local);
! 685: memset(&local, 0, sizeof(local));
! 686: if (getsockname(packet_get_connection_in(),
! 687: (struct sockaddr *) & local, &r) < 0)
! 688: debug("getsockname failed: %s", strerror(errno));
! 689:
! 690: r = sizeof(foreign);
! 691: memset(&foreign, 0, sizeof(foreign));
! 692: if (getpeername(packet_get_connection_in(),
! 693: (struct sockaddr *) & foreign, &r) < 0) {
! 694: debug("getpeername failed: %s", strerror(errno));
! 695: fatal_cleanup();
! 696: }
! 697: /* Get server reply. */
! 698: type = packet_read(&plen);
! 699: switch (type) {
! 700: case SSH_SMSG_FAILURE:
! 701: /* Should really be SSH_SMSG_AUTH_KERBEROS_FAILURE */
! 702: debug("Kerberos V4 authentication failed.");
! 703: return 0;
! 704: break;
! 705:
! 706: case SSH_SMSG_AUTH_KERBEROS_RESPONSE:
! 707: /* SSH_SMSG_AUTH_KERBEROS_SUCCESS */
! 708: debug("Kerberos V4 authentication accepted.");
! 709:
! 710: /* Get server's response. */
! 711: reply = packet_get_string((unsigned int *) &auth.length);
! 712: memcpy(auth.dat, reply, auth.length);
! 713: xfree(reply);
! 714:
! 715: packet_integrity_check(plen, 4 + auth.length, type);
! 716:
! 717: /* If his response isn't properly encrypted with the
! 718: session key, and the decrypted checksum fails to match,
! 719: he's bogus. Bail out. */
! 720: r = krb_rd_priv(auth.dat, auth.length, schedule, &cred.session,
! 721: &foreign, &local, &msg_data);
! 722: if (r != KSUCCESS) {
! 723: debug("Kerberos V4 krb_rd_priv failed: %s", krb_err_txt[r]);
! 724: packet_disconnect("Kerberos V4 challenge failed!");
! 725: }
! 726: /* Fetch the (incremented) checksum that we supplied in the request. */
! 727: (void) memcpy((char *) &cksum, (char *) msg_data.app_data, sizeof(cksum));
! 728: cksum = ntohl(cksum);
! 729:
! 730: /* If it matches, we're golden. */
! 731: if (cksum == checksum + 1) {
! 732: debug("Kerberos V4 challenge successful.");
! 733: return 1;
! 734: } else
! 735: packet_disconnect("Kerberos V4 challenge failed!");
! 736: break;
! 737:
! 738: default:
! 739: packet_disconnect("Protocol error on Kerberos V4 response: %d", type);
! 740: }
! 741: return 0;
1.1 deraadt 742: }
1.38 ! markus 743:
1.1 deraadt 744: #endif /* KRB4 */
745:
746: #ifdef AFS
1.38 ! markus 747: int
! 748: send_kerberos_tgt()
1.1 deraadt 749: {
1.38 ! markus 750: CREDENTIALS *creds;
! 751: char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ];
! 752: int r, type, plen;
! 753: unsigned char buffer[8192];
! 754: struct stat st;
! 755:
! 756: /* Don't do anything if we don't have any tickets. */
! 757: if (stat(tkt_string(), &st) < 0)
! 758: return 0;
! 759:
! 760: creds = xmalloc(sizeof(*creds));
! 761:
! 762: if ((r = krb_get_tf_fullname(TKT_FILE, pname, pinst, prealm)) != KSUCCESS) {
! 763: debug("Kerberos V4 tf_fullname failed: %s", krb_err_txt[r]);
! 764: return 0;
! 765: }
! 766: if ((r = krb_get_cred("krbtgt", prealm, prealm, creds)) != GC_OK) {
! 767: debug("Kerberos V4 get_cred failed: %s", krb_err_txt[r]);
! 768: return 0;
! 769: }
! 770: if (time(0) > krb_life_to_time(creds->issue_date, creds->lifetime)) {
! 771: debug("Kerberos V4 ticket expired: %s", TKT_FILE);
! 772: return 0;
! 773: }
! 774: creds_to_radix(creds, buffer);
! 775: xfree(creds);
! 776:
! 777: packet_start(SSH_CMSG_HAVE_KERBEROS_TGT);
! 778: packet_put_string((char *) buffer, strlen(buffer));
! 779: packet_send();
! 780: packet_write_wait();
! 781:
! 782: type = packet_read(&plen);
1.1 deraadt 783:
1.38 ! markus 784: if (type == SSH_SMSG_FAILURE)
! 785: debug("Kerberos TGT for realm %s rejected.", prealm);
! 786: else if (type != SSH_SMSG_SUCCESS)
! 787: packet_disconnect("Protocol error on Kerberos TGT response: %d", type);
! 788:
! 789: return 1;
1.1 deraadt 790: }
791:
1.38 ! markus 792: void
! 793: send_afs_tokens(void)
1.1 deraadt 794: {
1.38 ! markus 795: CREDENTIALS creds;
! 796: struct ViceIoctl parms;
! 797: struct ClearToken ct;
! 798: int i, type, len, plen;
! 799: char buf[2048], *p, *server_cell;
! 800: unsigned char buffer[8192];
! 801:
! 802: /* Move over ktc_GetToken, here's something leaner. */
! 803: for (i = 0; i < 100; i++) { /* just in case */
! 804: parms.in = (char *) &i;
! 805: parms.in_size = sizeof(i);
! 806: parms.out = buf;
! 807: parms.out_size = sizeof(buf);
! 808: if (k_pioctl(0, VIOCGETTOK, &parms, 0) != 0)
! 809: break;
! 810: p = buf;
! 811:
! 812: /* Get secret token. */
! 813: memcpy(&creds.ticket_st.length, p, sizeof(unsigned int));
! 814: if (creds.ticket_st.length > MAX_KTXT_LEN)
! 815: break;
! 816: p += sizeof(unsigned int);
! 817: memcpy(creds.ticket_st.dat, p, creds.ticket_st.length);
! 818: p += creds.ticket_st.length;
! 819:
! 820: /* Get clear token. */
! 821: memcpy(&len, p, sizeof(len));
! 822: if (len != sizeof(struct ClearToken))
! 823: break;
! 824: p += sizeof(len);
! 825: memcpy(&ct, p, len);
! 826: p += len;
! 827: p += sizeof(len); /* primary flag */
! 828: server_cell = p;
! 829:
! 830: /* Flesh out our credentials. */
! 831: strlcpy(creds.service, "afs", sizeof creds.service);
! 832: creds.instance[0] = '\0';
! 833: strlcpy(creds.realm, server_cell, REALM_SZ);
! 834: memcpy(creds.session, ct.HandShakeKey, DES_KEY_SZ);
! 835: creds.issue_date = ct.BeginTimestamp;
! 836: creds.lifetime = krb_time_to_life(creds.issue_date, ct.EndTimestamp);
! 837: creds.kvno = ct.AuthHandle;
! 838: snprintf(creds.pname, sizeof(creds.pname), "AFS ID %d", ct.ViceId);
! 839: creds.pinst[0] = '\0';
! 840:
! 841: /* Encode token, ship it off. */
! 842: if (!creds_to_radix(&creds, buffer))
! 843: break;
! 844: packet_start(SSH_CMSG_HAVE_AFS_TOKEN);
! 845: packet_put_string((char *) buffer, strlen(buffer));
! 846: packet_send();
! 847: packet_write_wait();
! 848:
! 849: /* Roger, Roger. Clearance, Clarence. What's your vector,
! 850: Victor? */
! 851: type = packet_read(&plen);
! 852:
! 853: if (type == SSH_SMSG_FAILURE)
! 854: debug("AFS token for cell %s rejected.", server_cell);
! 855: else if (type != SSH_SMSG_SUCCESS)
! 856: packet_disconnect("Protocol error on AFS token response: %d", type);
! 857: }
1.1 deraadt 858: }
1.38 ! markus 859:
1.1 deraadt 860: #endif /* AFS */
861:
1.38 ! markus 862: /* Waits for the server identification string, and sends our own
! 863: identification string. */
1.1 deraadt 864:
1.38 ! markus 865: void
! 866: ssh_exchange_identification()
1.1 deraadt 867: {
1.38 ! markus 868: char buf[256], remote_version[256]; /* must be same size! */
! 869: int remote_major, remote_minor, i;
! 870: int connection_in = packet_get_connection_in();
! 871: int connection_out = packet_get_connection_out();
! 872: extern Options options;
! 873:
! 874: /* Read other side\'s version identification. */
! 875: for (i = 0; i < sizeof(buf) - 1; i++) {
! 876: if (read(connection_in, &buf[i], 1) != 1)
! 877: fatal("ssh_exchange_identification: read: %.100s", strerror(errno));
! 878: if (buf[i] == '\r') {
! 879: buf[i] = '\n';
! 880: buf[i + 1] = 0;
! 881: break;
! 882: }
! 883: if (buf[i] == '\n') {
! 884: buf[i + 1] = 0;
! 885: break;
! 886: }
! 887: }
! 888: buf[sizeof(buf) - 1] = 0;
! 889:
! 890: /* Check that the versions match. In future this might accept
! 891: several versions and set appropriate flags to handle them. */
! 892: if (sscanf(buf, "SSH-%d.%d-%[^\n]\n", &remote_major, &remote_minor,
! 893: remote_version) != 3)
! 894: fatal("Bad remote protocol version identification: '%.100s'", buf);
! 895: debug("Remote protocol version %d.%d, remote software version %.100s",
! 896: remote_major, remote_minor, remote_version);
! 897:
! 898: /* Check if the remote protocol version is too old. */
! 899: if (remote_major == 1 && remote_minor < 3)
! 900: fatal("Remote machine has too old SSH software version.");
! 901:
! 902: /* We speak 1.3, too. */
! 903: if (remote_major == 1 && remote_minor == 3) {
! 904: enable_compat13();
! 905: if (options.forward_agent && strcmp(remote_version, SSH_VERSION) != 0) {
! 906: log("Agent forwarding disabled, remote version '%s' is not compatible.",
! 907: remote_version);
! 908: options.forward_agent = 0;
! 909: }
! 910: }
1.1 deraadt 911: #if 0
1.38 ! markus 912: /* Removed for now, to permit compatibility with latter versions.
! 913: The server will reject our version and disconnect if it doesn't
! 914: support it. */
! 915: if (remote_major != PROTOCOL_MAJOR)
! 916: fatal("Protocol major versions differ: %d vs. %d",
! 917: PROTOCOL_MAJOR, remote_major);
1.1 deraadt 918: #endif
919:
1.38 ! markus 920: /* Send our own protocol version identification. */
! 921: snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n",
! 922: PROTOCOL_MAJOR, PROTOCOL_MINOR, SSH_VERSION);
! 923: if (write(connection_out, buf, strlen(buf)) != strlen(buf))
! 924: fatal("write: %.100s", strerror(errno));
1.1 deraadt 925: }
926:
927: int ssh_cipher_default = SSH_CIPHER_3DES;
928:
1.38 ! markus 929: int
! 930: read_yes_or_no(const char *prompt, int defval)
1.1 deraadt 931: {
1.38 ! markus 932: char buf[1024];
! 933: FILE *f;
! 934: int retval = -1;
! 935:
! 936: if (isatty(0))
! 937: f = stdin;
! 938: else
! 939: f = fopen("/dev/tty", "rw");
! 940:
! 941: if (f == NULL)
! 942: return 0;
! 943:
! 944: fflush(stdout);
! 945:
! 946: while (1) {
! 947: fprintf(stderr, "%s", prompt);
! 948: if (fgets(buf, sizeof(buf), f) == NULL) {
! 949: /* Print a newline (the prompt probably didn\'t have one). */
! 950: fprintf(stderr, "\n");
! 951: strlcpy(buf, "no", sizeof buf);
! 952: }
! 953: /* Remove newline from response. */
! 954: if (strchr(buf, '\n'))
! 955: *strchr(buf, '\n') = 0;
! 956:
! 957: if (buf[0] == 0)
! 958: retval = defval;
! 959: if (strcmp(buf, "yes") == 0)
! 960: retval = 1;
! 961: if (strcmp(buf, "no") == 0)
! 962: retval = 0;
! 963:
! 964: if (retval != -1) {
! 965: if (f != stdin)
! 966: fclose(f);
! 967: return retval;
! 968: }
1.1 deraadt 969: }
970: }
971:
972: /* Starts a dialog with the server, and authenticates the current user on the
973: server. This does not need any extra privileges. The basic connection
1.38 ! markus 974: to the server must already have been established before this is called.
1.1 deraadt 975: User is the remote user; if it is NULL, the current local user name will
976: be used. Anonymous indicates that no rhosts authentication will be used.
1.38 ! markus 977: If login fails, this function prints an error and never returns.
1.1 deraadt 978: This function does not require super-user privileges. */
979:
1.38 ! markus 980: void
! 981: ssh_login(int host_key_valid,
! 982: RSA *own_host_key,
! 983: const char *orighost,
! 984: struct sockaddr_in *hostaddr,
! 985: uid_t original_real_uid)
1.1 deraadt 986: {
1.38 ! markus 987: extern Options options;
! 988: int i, type;
! 989: char *password;
! 990: struct passwd *pw;
! 991: BIGNUM *key;
! 992: RSA *host_key, *file_key;
! 993: RSA *public_key;
! 994: int bits, rbits;
! 995: unsigned char session_key[SSH_SESSION_KEY_LENGTH];
! 996: const char *server_user, *local_user;
! 997: char *cp, *host, *ip = NULL;
! 998: char hostline[1000], *hostp;
! 999: unsigned char check_bytes[8];
! 1000: unsigned int supported_ciphers, supported_authentications, protocol_flags;
! 1001: HostStatus host_status;
! 1002: HostStatus ip_status;
! 1003: int host_ip_differ = 0;
! 1004: int local = (ntohl(hostaddr->sin_addr.s_addr) >> 24) == IN_LOOPBACKNET;
! 1005: int payload_len, clen, sum_len = 0;
! 1006: u_int32_t rand = 0;
! 1007:
! 1008: if (options.check_host_ip)
! 1009: ip = xstrdup(inet_ntoa(hostaddr->sin_addr));
! 1010:
! 1011: /* Convert the user-supplied hostname into all lowercase. */
! 1012: host = xstrdup(orighost);
! 1013: for (cp = host; *cp; cp++)
! 1014: if (isupper(*cp))
! 1015: *cp = tolower(*cp);
! 1016:
! 1017: /* Exchange protocol version identification strings with the server. */
! 1018: ssh_exchange_identification();
! 1019:
! 1020: /* Put the connection into non-blocking mode. */
! 1021: packet_set_nonblocking();
! 1022:
! 1023: /* Get local user name. Use it as server user if no user name was given. */
! 1024: pw = getpwuid(original_real_uid);
! 1025: if (!pw)
! 1026: fatal("User id %d not found from user database.", original_real_uid);
! 1027: local_user = xstrdup(pw->pw_name);
! 1028: server_user = options.user ? options.user : local_user;
! 1029:
! 1030: debug("Waiting for server public key.");
! 1031:
! 1032: /* Wait for a public key packet from the server. */
! 1033: packet_read_expect(&payload_len, SSH_SMSG_PUBLIC_KEY);
! 1034:
! 1035: /* Get check bytes from the packet. */
! 1036: for (i = 0; i < 8; i++)
! 1037: check_bytes[i] = packet_get_char();
! 1038:
! 1039: /* Get the public key. */
! 1040: public_key = RSA_new();
! 1041: bits = packet_get_int();/* bits */
! 1042: public_key->e = BN_new();
! 1043: packet_get_bignum(public_key->e, &clen);
! 1044: sum_len += clen;
! 1045: public_key->n = BN_new();
! 1046: packet_get_bignum(public_key->n, &clen);
! 1047: sum_len += clen;
! 1048:
! 1049: rbits = BN_num_bits(public_key->n);
! 1050: if (bits != rbits) {
! 1051: log("Warning: Server lies about size of server public key: "
! 1052: "actual size is %d bits vs. announced %d.", rbits, bits);
! 1053: log("Warning: This may be due to an old implementation of ssh.");
! 1054: }
! 1055: /* Get the host key. */
! 1056: host_key = RSA_new();
! 1057: bits = packet_get_int();/* bits */
! 1058: host_key->e = BN_new();
! 1059: packet_get_bignum(host_key->e, &clen);
! 1060: sum_len += clen;
! 1061: host_key->n = BN_new();
! 1062: packet_get_bignum(host_key->n, &clen);
! 1063: sum_len += clen;
! 1064:
! 1065: rbits = BN_num_bits(host_key->n);
! 1066: if (bits != rbits) {
! 1067: log("Warning: Server lies about size of server host key: "
! 1068: "actual size is %d bits vs. announced %d.", rbits, bits);
! 1069: log("Warning: This may be due to an old implementation of ssh.");
! 1070: }
! 1071: /* Store the host key from the known host file in here so that we
! 1072: can compare it with the key for the IP address. */
! 1073: file_key = RSA_new();
! 1074: file_key->n = BN_new();
! 1075: file_key->e = BN_new();
! 1076:
! 1077: /* Get protocol flags. */
! 1078: protocol_flags = packet_get_int();
! 1079: packet_set_protocol_flags(protocol_flags);
! 1080:
! 1081: /* Get supported cipher types. */
! 1082: supported_ciphers = packet_get_int();
! 1083:
! 1084: /* Get supported authentication types. */
! 1085: supported_authentications = packet_get_int();
! 1086:
! 1087: debug("Received server public key (%d bits) and host key (%d bits).",
! 1088: BN_num_bits(public_key->n), BN_num_bits(host_key->n));
! 1089:
! 1090: packet_integrity_check(payload_len,
! 1091: 8 + 4 + sum_len + 0 + 4 + 0 + 0 + 4 + 4 + 4,
! 1092: SSH_SMSG_PUBLIC_KEY);
! 1093:
! 1094: /* Compute the session id. */
! 1095: compute_session_id(session_id, check_bytes, host_key->n, public_key->n);
! 1096:
! 1097: /* Check if the host key is present in the user\'s list of known
! 1098: hosts or in the systemwide list. */
! 1099: host_status = check_host_in_hostfile(options.user_hostfile, host,
! 1100: host_key->e, host_key->n,
! 1101: file_key->e, file_key->n);
! 1102: if (host_status == HOST_NEW)
! 1103: host_status = check_host_in_hostfile(options.system_hostfile, host,
! 1104: host_key->e, host_key->n,
! 1105: file_key->e, file_key->n);
! 1106: /* Force accepting of the host key for localhost and 127.0.0.1.
! 1107: The problem is that if the home directory is NFS-mounted to
! 1108: multiple machines, localhost will refer to a different machine
! 1109: in each of them, and the user will get bogus HOST_CHANGED
! 1110: warnings. This essentially disables host authentication for
! 1111: localhost; however, this is probably not a real problem. */
! 1112: if (local) {
! 1113: debug("Forcing accepting of host key for localhost.");
! 1114: host_status = HOST_OK;
! 1115: }
! 1116: /* Also perform check for the ip address, skip the check if we are
! 1117: localhost or the hostname was an ip address to begin with */
! 1118: if (options.check_host_ip && !local && strcmp(host, ip)) {
! 1119: RSA *ip_key = RSA_new();
! 1120: ip_key->n = BN_new();
! 1121: ip_key->e = BN_new();
! 1122: ip_status = check_host_in_hostfile(options.user_hostfile, ip,
! 1123: host_key->e, host_key->n,
! 1124: ip_key->e, ip_key->n);
! 1125:
! 1126: if (ip_status == HOST_NEW)
! 1127: ip_status = check_host_in_hostfile(options.system_hostfile, ip,
! 1128: host_key->e, host_key->n,
! 1129: ip_key->e, ip_key->n);
! 1130: if (host_status == HOST_CHANGED &&
! 1131: (ip_status != HOST_CHANGED ||
! 1132: (BN_cmp(ip_key->e, file_key->e) || BN_cmp(ip_key->n, file_key->n))))
! 1133: host_ip_differ = 1;
! 1134:
! 1135: RSA_free(ip_key);
! 1136: } else
! 1137: ip_status = host_status;
! 1138:
! 1139: RSA_free(file_key);
! 1140:
! 1141: switch (host_status) {
! 1142: case HOST_OK:
! 1143: /* The host is known and the key matches. */
! 1144: debug("Host '%.200s' is known and matches the host key.", host);
! 1145: if (options.check_host_ip) {
! 1146: if (ip_status == HOST_NEW) {
! 1147: if (!add_host_to_hostfile(options.user_hostfile, ip,
! 1148: host_key->e, host_key->n))
! 1149: log("Failed to add the host key for IP address '%.30s' to the list of known hosts (%.30s).",
! 1150: ip, options.user_hostfile);
! 1151: else
! 1152: log("Warning: Permanently added host key for IP address '%.30s' to the list of known hosts.",
! 1153: ip);
! 1154: } else if (ip_status != HOST_OK)
! 1155: log("Warning: the host key for '%.200s' differs from the key for the IP address '%.30s'",
! 1156: host, ip);
! 1157: }
! 1158: break;
! 1159: case HOST_NEW:
! 1160: /* The host is new. */
! 1161: if (options.strict_host_key_checking == 1) {
! 1162: /* User has requested strict host key checking. We will not add the host key
! 1163: automatically. The only alternative left is to abort. */
! 1164: fatal("No host key is known for %.200s and you have requested strict checking.", host);
! 1165: } else if (options.strict_host_key_checking == 2) {
! 1166: /* The default */
! 1167: char prompt[1024];
! 1168: char *fp = fingerprint(host_key->e, host_key->n);
! 1169: snprintf(prompt, sizeof(prompt),
! 1170: "The authenticity of host '%.200s' can't be established.\n"
! 1171: "Key fingerprint is %d %s.\n"
! 1172: "Are you sure you want to continue connecting (yes/no)? ",
! 1173: host, BN_num_bits(host_key->n), fp);
! 1174: if (!read_yes_or_no(prompt, -1))
! 1175: fatal("Aborted by user!\n");
! 1176: }
! 1177: if (options.check_host_ip && ip_status == HOST_NEW && strcmp(host, ip)) {
! 1178: snprintf(hostline, sizeof(hostline), "%s,%s", host, ip);
! 1179: hostp = hostline;
! 1180: } else
! 1181: hostp = host;
! 1182:
! 1183: /* If not in strict mode, add the key automatically to the local known_hosts file. */
! 1184: if (!add_host_to_hostfile(options.user_hostfile, hostp,
! 1185: host_key->e, host_key->n))
! 1186: log("Failed to add the host to the list of known hosts (%.500s).",
! 1187: options.user_hostfile);
! 1188: else
! 1189: log("Warning: Permanently added '%.200s' to the list of known hosts.",
! 1190: hostp);
! 1191: break;
! 1192: case HOST_CHANGED:
! 1193: if (options.check_host_ip && host_ip_differ) {
! 1194: char *msg;
! 1195: if (ip_status == HOST_NEW)
! 1196: msg = "is unknown";
! 1197: else if (ip_status == HOST_OK)
! 1198: msg = "is unchanged";
! 1199: else
! 1200: msg = "has a different value";
! 1201: error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
! 1202: error("@ WARNING: POSSIBLE DNS SPOOFING DETECTED! @");
! 1203: error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
! 1204: error("The host key for %s has changed,", host);
! 1205: error("and the key for the according IP address %s", ip);
! 1206: error("%s. This could either mean that", msg);
! 1207: error("DNS SPOOFING is happening or the IP address for the host");
! 1208: error("and its host key have changed at the same time");
! 1209: }
! 1210: /* The host key has changed. */
! 1211: error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
! 1212: error("@ WARNING: HOST IDENTIFICATION HAS CHANGED! @");
! 1213: error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
! 1214: error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!");
! 1215: error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!");
! 1216: error("It is also possible that the host key has just been changed.");
! 1217: error("Please contact your system administrator.");
! 1218: error("Add correct host key in %.100s to get rid of this message.",
! 1219: options.user_hostfile);
! 1220:
! 1221: /* If strict host key checking is in use, the user will
! 1222: have to edit the key manually and we can only abort. */
! 1223: if (options.strict_host_key_checking)
! 1224: fatal("Host key for %.200s has changed and you have requested strict checking.", host);
! 1225:
! 1226: /* If strict host key checking has not been requested, allow the connection
! 1227: but without password authentication or agent forwarding. */
! 1228: if (options.password_authentication) {
! 1229: error("Password authentication is disabled to avoid trojan horses.");
! 1230: options.password_authentication = 0;
! 1231: }
! 1232: if (options.forward_agent) {
! 1233: error("Agent forwarding is disabled to avoid trojan horses.");
! 1234: options.forward_agent = 0;
! 1235: }
! 1236: /* XXX Should permit the user to change to use the new id.
! 1237: This could be done by converting the host key to an
! 1238: identifying sentence, tell that the host identifies
! 1239: itself by that sentence, and ask the user if he/she
! 1240: whishes to accept the authentication. */
! 1241: break;
! 1242: }
! 1243:
! 1244: if (options.check_host_ip)
! 1245: xfree(ip);
! 1246:
! 1247: /* Generate a session key. */
! 1248: arc4random_stir();
! 1249:
! 1250: /* Generate an encryption key for the session. The key is a 256
! 1251: bit random number, interpreted as a 32-byte key, with the least
! 1252: significant 8 bits being the first byte of the key. */
! 1253: for (i = 0; i < 32; i++) {
! 1254: if (i % 4 == 0)
! 1255: rand = arc4random();
! 1256: session_key[i] = rand & 0xff;
! 1257: rand >>= 8;
! 1258: }
! 1259:
! 1260: /* According to the protocol spec, the first byte of the session
! 1261: key is the highest byte of the integer. The session key is
! 1262: xored with the first 16 bytes of the session id. */
! 1263: key = BN_new();
! 1264: BN_set_word(key, 0);
! 1265: for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++) {
! 1266: BN_lshift(key, key, 8);
! 1267: if (i < 16)
! 1268: BN_add_word(key, session_key[i] ^ session_id[i]);
! 1269: else
! 1270: BN_add_word(key, session_key[i]);
! 1271: }
! 1272:
! 1273: /* Encrypt the integer using the public key and host key of the
! 1274: server (key with smaller modulus first). */
! 1275: if (BN_cmp(public_key->n, host_key->n) < 0) {
! 1276: /* Public key has smaller modulus. */
! 1277: if (BN_num_bits(host_key->n) <
! 1278: BN_num_bits(public_key->n) + SSH_KEY_BITS_RESERVED) {
! 1279: fatal("respond_to_rsa_challenge: host_key %d < public_key %d + "
! 1280: "SSH_KEY_BITS_RESERVED %d",
! 1281: BN_num_bits(host_key->n),
! 1282: BN_num_bits(public_key->n),
! 1283: SSH_KEY_BITS_RESERVED);
! 1284: }
! 1285: rsa_public_encrypt(key, key, public_key);
! 1286: rsa_public_encrypt(key, key, host_key);
! 1287: } else {
! 1288: /* Host key has smaller modulus (or they are equal). */
! 1289: if (BN_num_bits(public_key->n) <
! 1290: BN_num_bits(host_key->n) + SSH_KEY_BITS_RESERVED) {
! 1291: fatal("respond_to_rsa_challenge: public_key %d < host_key %d + "
! 1292: "SSH_KEY_BITS_RESERVED %d",
! 1293: BN_num_bits(public_key->n),
! 1294: BN_num_bits(host_key->n),
! 1295: SSH_KEY_BITS_RESERVED);
! 1296: }
! 1297: rsa_public_encrypt(key, key, host_key);
! 1298: rsa_public_encrypt(key, key, public_key);
! 1299: }
! 1300:
! 1301: if (options.cipher == SSH_CIPHER_NOT_SET) {
! 1302: if (cipher_mask() & supported_ciphers & (1 << ssh_cipher_default))
! 1303: options.cipher = ssh_cipher_default;
! 1304: else {
! 1305: debug("Cipher %s not supported, using %.100s instead.",
! 1306: cipher_name(ssh_cipher_default),
! 1307: cipher_name(SSH_FALLBACK_CIPHER));
! 1308: options.cipher = SSH_FALLBACK_CIPHER;
! 1309: }
! 1310: }
! 1311: /* Check that the selected cipher is supported. */
! 1312: if (!(supported_ciphers & (1 << options.cipher)))
! 1313: fatal("Selected cipher type %.100s not supported by server.",
! 1314: cipher_name(options.cipher));
! 1315:
! 1316: debug("Encryption type: %.100s", cipher_name(options.cipher));
! 1317:
! 1318: /* Send the encrypted session key to the server. */
! 1319: packet_start(SSH_CMSG_SESSION_KEY);
! 1320: packet_put_char(options.cipher);
! 1321:
! 1322: /* Send the check bytes back to the server. */
! 1323: for (i = 0; i < 8; i++)
! 1324: packet_put_char(check_bytes[i]);
! 1325:
! 1326: /* Send the encrypted encryption key. */
! 1327: packet_put_bignum(key);
! 1328:
! 1329: /* Send protocol flags. */
! 1330: packet_put_int(SSH_PROTOFLAG_SCREEN_NUMBER | SSH_PROTOFLAG_HOST_IN_FWD_OPEN);
! 1331:
! 1332: /* Send the packet now. */
! 1333: packet_send();
! 1334: packet_write_wait();
! 1335:
! 1336: /* Destroy the session key integer and the public keys since we no longer need them. */
! 1337: BN_clear_free(key);
! 1338: RSA_free(public_key);
! 1339: RSA_free(host_key);
! 1340:
! 1341: debug("Sent encrypted session key.");
! 1342:
! 1343: /* Set the encryption key. */
! 1344: packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH, options.cipher);
! 1345:
! 1346: /* We will no longer need the session key here. Destroy any extra copies. */
! 1347: memset(session_key, 0, sizeof(session_key));
! 1348:
! 1349: /* Expect a success message from the server. Note that this
! 1350: message will be received in encrypted form. */
! 1351: packet_read_expect(&payload_len, SSH_SMSG_SUCCESS);
! 1352:
! 1353: debug("Received encrypted confirmation.");
! 1354:
! 1355: /* Send the name of the user to log in as on the server. */
! 1356: packet_start(SSH_CMSG_USER);
! 1357: packet_put_string(server_user, strlen(server_user));
1.16 dugsong 1358: packet_send();
1359: packet_write_wait();
1.38 ! markus 1360:
! 1361: /* The server should respond with success if no authentication is
! 1362: needed (the user has no password). Otherwise the server
! 1363: responds with failure. */
1.16 dugsong 1364: type = packet_read(&payload_len);
1.38 ! markus 1365:
! 1366: /* check whether the connection was accepted without authentication. */
1.16 dugsong 1367: if (type == SSH_SMSG_SUCCESS)
1.38 ! markus 1368: return;
1.16 dugsong 1369: if (type != SSH_SMSG_FAILURE)
1.38 ! markus 1370: packet_disconnect("Protocol error: got %d in response to SSH_CMSG_USER",
! 1371: type);
! 1372:
! 1373: #ifdef AFS
! 1374: /* Try Kerberos tgt passing if the server supports it. */
! 1375: if ((supported_authentications & (1 << SSH_PASS_KERBEROS_TGT)) &&
! 1376: options.kerberos_tgt_passing) {
! 1377: if (options.cipher == SSH_CIPHER_NONE)
! 1378: log("WARNING: Encryption is disabled! Ticket will be transmitted in the clear!");
! 1379: (void) send_kerberos_tgt();
! 1380: }
! 1381: /* Try AFS token passing if the server supports it. */
! 1382: if ((supported_authentications & (1 << SSH_PASS_AFS_TOKEN)) &&
! 1383: options.afs_token_passing && k_hasafs()) {
! 1384: if (options.cipher == SSH_CIPHER_NONE)
! 1385: log("WARNING: Encryption is disabled! Token will be transmitted in the clear!");
! 1386: send_afs_tokens();
! 1387: }
! 1388: #endif /* AFS */
! 1389:
! 1390: #ifdef KRB4
! 1391: if ((supported_authentications & (1 << SSH_AUTH_KERBEROS)) &&
! 1392: options.kerberos_authentication) {
! 1393: debug("Trying Kerberos authentication.");
! 1394: if (try_kerberos_authentication()) {
! 1395: /* The server should respond with success or failure. */
! 1396: type = packet_read(&payload_len);
! 1397: if (type == SSH_SMSG_SUCCESS)
! 1398: return;
! 1399: if (type != SSH_SMSG_FAILURE)
! 1400: packet_disconnect("Protocol error: got %d in response to Kerberos auth", type);
! 1401: }
! 1402: }
! 1403: #endif /* KRB4 */
! 1404:
! 1405: /* Use rhosts authentication if running in privileged socket and
! 1406: we do not wish to remain anonymous. */
! 1407: if ((supported_authentications & (1 << SSH_AUTH_RHOSTS)) &&
! 1408: options.rhosts_authentication) {
! 1409: debug("Trying rhosts authentication.");
! 1410: packet_start(SSH_CMSG_AUTH_RHOSTS);
! 1411: packet_put_string(local_user, strlen(local_user));
! 1412: packet_send();
! 1413: packet_write_wait();
! 1414:
! 1415: /* The server should respond with success or failure. */
! 1416: type = packet_read(&payload_len);
! 1417: if (type == SSH_SMSG_SUCCESS)
! 1418: return;
! 1419: if (type != SSH_SMSG_FAILURE)
! 1420: packet_disconnect("Protocol error: got %d in response to rhosts auth",
! 1421: type);
! 1422: }
! 1423: /* Try .rhosts or /etc/hosts.equiv authentication with RSA host
! 1424: authentication. */
! 1425: if ((supported_authentications & (1 << SSH_AUTH_RHOSTS_RSA)) &&
! 1426: options.rhosts_rsa_authentication && host_key_valid) {
! 1427: if (try_rhosts_rsa_authentication(local_user, own_host_key))
! 1428: return;
! 1429: }
! 1430: /* Try RSA authentication if the server supports it. */
! 1431: if ((supported_authentications & (1 << SSH_AUTH_RSA)) &&
! 1432: options.rsa_authentication) {
! 1433: /* Try RSA authentication using the authentication agent.
! 1434: The agent is tried first because no passphrase is
! 1435: needed for it, whereas identity files may require
! 1436: passphrases. */
! 1437: if (try_agent_authentication())
! 1438: return;
! 1439:
! 1440: /* Try RSA authentication for each identity. */
! 1441: for (i = 0; i < options.num_identity_files; i++)
! 1442: if (try_rsa_authentication(pw, options.identity_files[i]))
! 1443: return;
! 1444: }
! 1445: /* Try skey authentication if the server supports it. */
! 1446: if ((supported_authentications & (1 << SSH_AUTH_TIS)) &&
! 1447: options.skey_authentication && !options.batch_mode) {
! 1448: debug("Doing skey authentication.");
! 1449:
! 1450: /* request a challenge */
! 1451: packet_start(SSH_CMSG_AUTH_TIS);
! 1452: packet_send();
! 1453: packet_write_wait();
! 1454:
! 1455: type = packet_read(&payload_len);
! 1456: if (type != SSH_SMSG_FAILURE &&
! 1457: type != SSH_SMSG_AUTH_TIS_CHALLENGE) {
! 1458: packet_disconnect("Protocol error: got %d in response "
! 1459: "to skey auth", type);
! 1460: }
! 1461: if (type != SSH_SMSG_AUTH_TIS_CHALLENGE) {
! 1462: debug("No challenge for skey authentication.");
! 1463: } else {
! 1464: char *challenge, *response;
! 1465: challenge = packet_get_string(&payload_len);
! 1466: if (options.cipher == SSH_CIPHER_NONE)
! 1467: log("WARNING: Encryption is disabled! "
! 1468: "Reponse will be transmitted in clear text.");
! 1469: fprintf(stderr, "%s\n", challenge);
! 1470: fflush(stderr);
! 1471: for (i = 0; i < options.number_of_password_prompts; i++) {
! 1472: if (i != 0)
! 1473: error("Permission denied, please try again.");
! 1474: response = read_passphrase("Response: ", 0);
! 1475: packet_start(SSH_CMSG_AUTH_TIS_RESPONSE);
! 1476: packet_put_string(response, strlen(response));
! 1477: memset(response, 0, strlen(response));
! 1478: xfree(response);
! 1479: packet_send();
! 1480: packet_write_wait();
! 1481: type = packet_read(&payload_len);
! 1482: if (type == SSH_SMSG_SUCCESS)
! 1483: return;
! 1484: if (type != SSH_SMSG_FAILURE)
! 1485: packet_disconnect("Protocol error: got %d in response "
! 1486: "to skey auth", type);
! 1487: }
! 1488: }
! 1489: }
! 1490: /* Try password authentication if the server supports it. */
! 1491: if ((supported_authentications & (1 << SSH_AUTH_PASSWORD)) &&
! 1492: options.password_authentication && !options.batch_mode) {
! 1493: char prompt[80];
! 1494: snprintf(prompt, sizeof(prompt), "%.30s@%.30s's password: ",
! 1495: server_user, host);
! 1496: debug("Doing password authentication.");
! 1497: if (options.cipher == SSH_CIPHER_NONE)
! 1498: log("WARNING: Encryption is disabled! Password will be transmitted in clear text.");
! 1499: for (i = 0; i < options.number_of_password_prompts; i++) {
! 1500: if (i != 0)
! 1501: error("Permission denied, please try again.");
! 1502: password = read_passphrase(prompt, 0);
! 1503: packet_start(SSH_CMSG_AUTH_PASSWORD);
! 1504: packet_put_string(password, strlen(password));
! 1505: memset(password, 0, strlen(password));
! 1506: xfree(password);
! 1507: packet_send();
! 1508: packet_write_wait();
! 1509:
! 1510: type = packet_read(&payload_len);
! 1511: if (type == SSH_SMSG_SUCCESS)
! 1512: return;
! 1513: if (type != SSH_SMSG_FAILURE)
! 1514: packet_disconnect("Protocol error: got %d in response to passwd auth", type);
! 1515: }
! 1516: }
! 1517: /* All authentication methods have failed. Exit with an error message. */
! 1518: fatal("Permission denied.");
! 1519: /* NOTREACHED */
1.1 deraadt 1520: }