[BACK]Return to sshconnect.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

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: }