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

Annotation of src/usr.bin/ssh/ssh.c, Revision 1.31

1.1       deraadt     1: /*
                      2:
                      3: ssh.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 16:36:11 1995 ylo
                     11:
                     12: Ssh client program.  This program can be used to log into a remote machine.
                     13: The software supports strong authentication, encryption, and forwarding
                     14: of X11, TCP/IP, and authentication connections.
                     15:
1.2       provos     16: Modified to work with SSL by Niels Provos <provos@citi.umich.edu> in Canada.
                     17:
1.1       deraadt    18: */
                     19:
                     20: #include "includes.h"
1.31    ! markus     21: RCSID("$Id: ssh.c,v 1.30 1999/11/15 21:05:03 markus Exp $");
1.1       deraadt    22:
                     23: #include "xmalloc.h"
                     24: #include "ssh.h"
                     25: #include "packet.h"
                     26: #include "buffer.h"
                     27: #include "authfd.h"
                     28: #include "readconf.h"
                     29: #include "uidswap.h"
                     30:
1.31    ! markus     31: /* Flag indicating whether debug mode is on.  This can be set on the command line. */
1.1       deraadt    32: int debug_flag = 0;
                     33:
1.31    ! markus     34: /* Flag indicating whether to allocate a pseudo tty.  This can be set on the command
        !            35:    line, and is automatically set if no command is given on the command line. */
1.1       deraadt    36: int tty_flag = 0;
                     37:
                     38: /* Flag indicating that nothing should be read from stdin.  This can be set
                     39:    on the command line. */
                     40: int stdin_null_flag = 0;
                     41:
                     42: /* Flag indicating that ssh should fork after authentication.  This is useful
                     43:    so that the pasphrase can be entered manually, and then ssh goes to the
                     44:    background. */
                     45: int fork_after_authentication_flag = 0;
                     46:
                     47: /* General data structure for command line options and options configurable
                     48:    in configuration files.  See readconf.h. */
                     49: Options options;
                     50:
                     51: /* Name of the host we are connecting to.  This is the name given on the
                     52:    command line, or the HostName specified for the user-supplied name
                     53:    in a configuration file. */
                     54: char *host;
                     55:
1.22      provos     56: /* socket address the host resolves to */
                     57: struct sockaddr_in hostaddr;
                     58:
1.1       deraadt    59: /* Flag to indicate that we have received a window change signal which has
                     60:    not yet been processed.  This will cause a message indicating the new
                     61:    window size to be sent to the server a little later.  This is volatile
                     62:    because this is updated in a signal handler. */
                     63: volatile int received_window_change_signal = 0;
                     64:
                     65: /* Value of argv[0] (set in the main program). */
                     66: char *av0;
                     67:
                     68: /* Flag indicating whether we have a valid host private key loaded. */
                     69: int host_private_key_loaded = 0;
                     70:
                     71: /* Host private key. */
1.2       provos     72: RSA *host_private_key = NULL;
1.1       deraadt    73:
1.10      dugsong    74: /* Original real UID. */
                     75: uid_t original_real_uid;
1.1       deraadt    76:
                     77: /* Prints a help message to the user.  This function never returns. */
                     78:
1.2       provos     79: void
                     80: usage()
1.1       deraadt    81: {
1.31    ! markus     82:        fprintf(stderr, "Usage: %s [options] host [command]\n", av0);
        !            83:        fprintf(stderr, "Options:\n");
        !            84:        fprintf(stderr, "  -l user     Log in using this user name.\n");
        !            85:        fprintf(stderr, "  -n          Redirect input from /dev/null.\n");
        !            86:        fprintf(stderr, "  -a          Disable authentication agent forwarding.\n");
1.9       dugsong    87: #ifdef AFS
1.31    ! markus     88:        fprintf(stderr, "  -k          Disable Kerberos ticket and AFS token forwarding.\n");
        !            89: #endif                         /* AFS */
        !            90:        fprintf(stderr, "  -x          Disable X11 connection forwarding.\n");
        !            91:        fprintf(stderr, "  -i file     Identity for RSA authentication (default: ~/.ssh/identity).\n");
        !            92:        fprintf(stderr, "  -t          Tty; allocate a tty even if command is given.\n");
        !            93:        fprintf(stderr, "  -v          Verbose; display verbose debugging messages.\n");
        !            94:        fprintf(stderr, "  -V          Display version number only.\n");
        !            95:        fprintf(stderr, "  -P          Don't allocate a privileged port.\n");
        !            96:        fprintf(stderr, "  -q          Quiet; don't display any warning messages.\n");
        !            97:        fprintf(stderr, "  -f          Fork into background after authentication.\n");
        !            98:        fprintf(stderr, "  -e char     Set escape character; ``none'' = disable (default: ~).\n");
        !            99:
        !           100:        fprintf(stderr, "  -c cipher   Select encryption algorithm: "
        !           101:                        "``3des'', "
        !           102:                        "``blowfish''\n");
        !           103:        fprintf(stderr, "  -p port     Connect to this port.  Server must be on the same port.\n");
        !           104:        fprintf(stderr, "  -L listen-port:host:port   Forward local port to remote address\n");
        !           105:        fprintf(stderr, "  -R listen-port:host:port   Forward remote port to local address\n");
        !           106:        fprintf(stderr, "              These cause %s to listen for connections on a port, and\n", av0);
        !           107:        fprintf(stderr, "              forward them to the other side by connecting to host:port.\n");
        !           108:        fprintf(stderr, "  -C          Enable compression.\n");
        !           109:        fprintf(stderr, "  -g          Allow remote hosts to connect to forwarded ports.\n");
        !           110:        fprintf(stderr, "  -o 'option' Process the option as if it was read from a configuration file.\n");
        !           111:        exit(1);
1.1       deraadt   112: }
                    113:
                    114: /* Connects to the given host using rsh (or prints an error message and exits
                    115:    if rsh is not available).  This function never returns. */
                    116:
1.2       provos    117: void
1.31    ! markus    118: rsh_connect(char *host, char *user, Buffer * command)
1.1       deraadt   119: {
1.31    ! markus    120:        char *args[10];
        !           121:        int i;
        !           122:
        !           123:        log("Using rsh.  WARNING: Connection will not be encrypted.");
        !           124:        /* Build argument list for rsh. */
        !           125:        i = 0;
        !           126:        args[i++] = _PATH_RSH;
        !           127:        /* host may have to come after user on some systems */
        !           128:        args[i++] = host;
        !           129:        if (user) {
        !           130:                args[i++] = "-l";
        !           131:                args[i++] = user;
        !           132:        }
        !           133:        if (buffer_len(command) > 0) {
        !           134:                buffer_append(command, "\0", 1);
        !           135:                args[i++] = buffer_ptr(command);
        !           136:        }
        !           137:        args[i++] = NULL;
        !           138:        if (debug_flag) {
        !           139:                for (i = 0; args[i]; i++) {
        !           140:                        if (i != 0)
        !           141:                                fprintf(stderr, " ");
        !           142:                        fprintf(stderr, "%s", args[i]);
        !           143:                }
        !           144:                fprintf(stderr, "\n");
        !           145:        }
        !           146:        execv(_PATH_RSH, args);
        !           147:        perror(_PATH_RSH);
        !           148:        exit(1);
1.1       deraadt   149: }
                    150:
                    151: /* Main program for the ssh client. */
1.11      deraadt   152:
1.2       provos    153: int
                    154: main(int ac, char **av)
1.1       deraadt   155: {
1.31    ! markus    156:        int i, opt, optind, type, exit_status, ok, fwd_port, fwd_host_port,
        !           157:         authfd;
        !           158:        char *optarg, *cp, buf[256];
        !           159:        Buffer command;
        !           160:        struct winsize ws;
        !           161:        struct stat st;
        !           162:        struct passwd *pw, pwcopy;
        !           163:        int interactive = 0, dummy;
        !           164:        uid_t original_effective_uid;
        !           165:        int plen;
        !           166:
        !           167:        /* Save the original real uid.  It will be needed later
        !           168:           (uid-swapping may clobber the real uid).  */
        !           169:        original_real_uid = getuid();
        !           170:        original_effective_uid = geteuid();
        !           171:
        !           172:        /* If we are installed setuid root be careful to not drop core. */
        !           173:        if (original_real_uid != original_effective_uid) {
        !           174:                struct rlimit rlim;
        !           175:                rlim.rlim_cur = rlim.rlim_max = 0;
        !           176:                if (setrlimit(RLIMIT_CORE, &rlim) < 0)
        !           177:                        fatal("setrlimit failed: %.100s", strerror(errno));
1.1       deraadt   178:        }
1.31    ! markus    179:        /* Use uid-swapping to give up root privileges for the duration of
        !           180:           option processing.  We will re-instantiate the rights when we
        !           181:           are ready to create the privileged port, and will permanently
        !           182:           drop them when the port has been created (actually, when the
        !           183:           connection has been made, as we may need to create the port
        !           184:           several times). */
        !           185:        temporarily_use_uid(original_real_uid);
        !           186:
        !           187:        /* Set our umask to something reasonable, as some files are
        !           188:           created with the default umask.  This will make them
        !           189:           world-readable but writable only by the owner, which is ok for
        !           190:           all files for which we don't set the modes explicitly. */
        !           191:        umask(022);
        !           192:
        !           193:        /* Save our own name. */
        !           194:        av0 = av[0];
        !           195:
        !           196:        /* Initialize option structure to indicate that no values have been set. */
        !           197:        initialize_options(&options);
        !           198:
        !           199:        /* Parse command-line arguments. */
        !           200:        host = NULL;
        !           201:
        !           202:        /* If program name is not one of the standard names, use it as host name. */
        !           203:        if (strchr(av0, '/'))
        !           204:                cp = strrchr(av0, '/') + 1;
        !           205:        else
        !           206:                cp = av0;
        !           207:        if (strcmp(cp, "rsh") != 0 && strcmp(cp, "ssh") != 0 &&
        !           208:            strcmp(cp, "rlogin") != 0 && strcmp(cp, "slogin") != 0)
        !           209:                host = cp;
        !           210:
        !           211:        for (optind = 1; optind < ac; optind++) {
        !           212:                if (av[optind][0] != '-') {
        !           213:                        if (host)
        !           214:                                break;
        !           215:                        if ((cp = strchr(av[optind], '@'))) {
        !           216:                                options.user = av[optind];
        !           217:                                *cp = '\0';
        !           218:                                host = ++cp;
        !           219:                        } else
        !           220:                                host = av[optind];
        !           221:                        continue;
        !           222:                }
        !           223:                opt = av[optind][1];
        !           224:                if (!opt)
        !           225:                        usage();
        !           226:                if (strchr("eilcpLRo", opt)) {  /* options with arguments */
        !           227:                        optarg = av[optind] + 2;
        !           228:                        if (strcmp(optarg, "") == 0) {
        !           229:                                if (optind >= ac - 1)
        !           230:                                        usage();
        !           231:                                optarg = av[++optind];
        !           232:                        }
        !           233:                } else {
        !           234:                        if (av[optind][2])
        !           235:                                usage();
        !           236:                        optarg = NULL;
        !           237:                }
        !           238:                switch (opt) {
        !           239:                case 'n':
        !           240:                        stdin_null_flag = 1;
        !           241:                        break;
        !           242:
        !           243:                case 'f':
        !           244:                        fork_after_authentication_flag = 1;
        !           245:                        stdin_null_flag = 1;
        !           246:                        break;
        !           247:
        !           248:                case 'x':
        !           249:                        options.forward_x11 = 0;
        !           250:                        break;
        !           251:
        !           252:                case 'X':
        !           253:                        options.forward_x11 = 1;
        !           254:                        break;
        !           255:
        !           256:                case 'g':
        !           257:                        options.gateway_ports = 1;
        !           258:                        break;
        !           259:
        !           260:                case 'P':
        !           261:                        options.use_privileged_port = 0;
        !           262:                        break;
        !           263:
        !           264:                case 'a':
        !           265:                        options.forward_agent = 0;
        !           266:                        break;
1.9       dugsong   267: #ifdef AFS
1.31    ! markus    268:                case 'k':
        !           269:                        options.kerberos_tgt_passing = 0;
        !           270:                        options.afs_token_passing = 0;
        !           271:                        break;
1.1       deraadt   272: #endif
1.31    ! markus    273:                case 'i':
        !           274:                        if (stat(optarg, &st) < 0) {
        !           275:                                fprintf(stderr, "Warning: Identity file %s does not exist.\n",
        !           276:                                        optarg);
        !           277:                                break;
        !           278:                        }
        !           279:                        if (options.num_identity_files >= SSH_MAX_IDENTITY_FILES)
        !           280:                                fatal("Too many identity files specified (max %d)",
        !           281:                                      SSH_MAX_IDENTITY_FILES);
        !           282:                        options.identity_files[options.num_identity_files++] =
        !           283:                                xstrdup(optarg);
        !           284:                        break;
        !           285:
        !           286:                case 't':
        !           287:                        tty_flag = 1;
        !           288:                        break;
        !           289:
        !           290:                case 'v':
        !           291:                case 'V':
        !           292:                        fprintf(stderr, "SSH Version %s, protocol version %d.%d.\n",
        !           293:                            SSH_VERSION, PROTOCOL_MAJOR, PROTOCOL_MINOR);
        !           294:                        fprintf(stderr, "Compiled with SSL.\n");
        !           295:                        if (opt == 'V')
        !           296:                                exit(0);
        !           297:                        debug_flag = 1;
        !           298:                        options.log_level = SYSLOG_LEVEL_DEBUG;
        !           299:                        break;
        !           300:
        !           301:                case 'q':
        !           302:                        options.log_level = SYSLOG_LEVEL_QUIET;
        !           303:                        break;
        !           304:
        !           305:                case 'e':
        !           306:                        if (optarg[0] == '^' && optarg[2] == 0 &&
        !           307:                            (unsigned char) optarg[1] >= 64 && (unsigned char) optarg[1] < 128)
        !           308:                                options.escape_char = (unsigned char) optarg[1] & 31;
        !           309:                        else if (strlen(optarg) == 1)
        !           310:                                options.escape_char = (unsigned char) optarg[0];
        !           311:                        else if (strcmp(optarg, "none") == 0)
        !           312:                                options.escape_char = -2;
        !           313:                        else {
        !           314:                                fprintf(stderr, "Bad escape character '%s'.\n", optarg);
        !           315:                                exit(1);
        !           316:                        }
        !           317:                        break;
        !           318:
        !           319:                case 'c':
        !           320:                        options.cipher = cipher_number(optarg);
        !           321:                        if (options.cipher == -1) {
        !           322:                                fprintf(stderr, "Unknown cipher type '%s'\n", optarg);
        !           323:                                exit(1);
        !           324:                        }
        !           325:                        break;
        !           326:
        !           327:                case 'p':
        !           328:                        options.port = atoi(optarg);
        !           329:                        if (options.port < 1 || options.port > 65535) {
        !           330:                                fprintf(stderr, "Bad port %s.\n", optarg);
        !           331:                                exit(1);
        !           332:                        }
        !           333:                        break;
        !           334:
        !           335:                case 'l':
        !           336:                        options.user = optarg;
        !           337:                        break;
        !           338:
        !           339:                case 'R':
        !           340:                        if (sscanf(optarg, "%d:%255[^:]:%d", &fwd_port, buf,
        !           341:                                   &fwd_host_port) != 3) {
        !           342:                                fprintf(stderr, "Bad forwarding specification '%s'.\n", optarg);
        !           343:                                usage();
        !           344:                                /* NOTREACHED */
        !           345:                        }
        !           346:                        add_remote_forward(&options, fwd_port, buf, fwd_host_port);
        !           347:                        break;
        !           348:
        !           349:                case 'L':
        !           350:                        if (sscanf(optarg, "%d:%255[^:]:%d", &fwd_port, buf,
        !           351:                                   &fwd_host_port) != 3) {
        !           352:                                fprintf(stderr, "Bad forwarding specification '%s'.\n", optarg);
        !           353:                                usage();
        !           354:                                /* NOTREACHED */
        !           355:                        }
        !           356:                        add_local_forward(&options, fwd_port, buf, fwd_host_port);
        !           357:                        break;
        !           358:
        !           359:                case 'C':
        !           360:                        options.compression = 1;
        !           361:                        break;
        !           362:
        !           363:                case 'o':
        !           364:                        dummy = 1;
        !           365:                        if (process_config_line(&options, host ? host : "", optarg,
        !           366:                                         "command-line", 0, &dummy) != 0)
        !           367:                                exit(1);
        !           368:                        break;
        !           369:
        !           370:                default:
        !           371:                        usage();
1.1       deraadt   372:                }
1.31    ! markus    373:        }
        !           374:
        !           375:        /* Check that we got a host name. */
        !           376:        if (!host)
        !           377:                usage();
        !           378:
        !           379:        /* check if RSA support exists */
        !           380:        if (rsa_alive() == 0) {
        !           381:                extern char *__progname;
        !           382:
        !           383:                fprintf(stderr,
        !           384:                        "%s: no RSA support in libssl and libcrypto.  See ssl(8).\n",
        !           385:                        __progname);
        !           386:                exit(1);
        !           387:        }
        !           388:        /* Initialize the command to execute on remote host. */
        !           389:        buffer_init(&command);
1.1       deraadt   390:
1.31    ! markus    391:        /* Save the command to execute on the remote host in a buffer.
        !           392:           There is no limit on the length of the command, except by the
        !           393:           maximum packet size.  Also sets the tty flag if there is no
        !           394:           command. */
        !           395:        if (optind == ac) {
        !           396:                /* No command specified - execute shell on a tty. */
        !           397:                tty_flag = 1;
        !           398:        } else {
        !           399:                /* A command has been specified.  Store it into the
        !           400:                   buffer. */
        !           401:                for (i = optind; i < ac; i++) {
        !           402:                        if (i > optind)
        !           403:                                buffer_append(&command, " ", 1);
        !           404:                        buffer_append(&command, av[i], strlen(av[i]));
        !           405:                }
        !           406:        }
        !           407:
        !           408:        /* Cannot fork to background if no command. */
        !           409:        if (fork_after_authentication_flag && buffer_len(&command) == 0)
        !           410:                fatal("Cannot fork into background without a command to execute.");
        !           411:
        !           412:        /* Allocate a tty by default if no command specified. */
        !           413:        if (buffer_len(&command) == 0)
        !           414:                tty_flag = 1;
        !           415:
        !           416:        /* Do not allocate a tty if stdin is not a tty. */
        !           417:        if (!isatty(fileno(stdin))) {
        !           418:                if (tty_flag)
        !           419:                        fprintf(stderr, "Pseudo-terminal will not be allocated because stdin is not a terminal.\n");
        !           420:                tty_flag = 0;
        !           421:        }
        !           422:        /* Get user data. */
        !           423:        pw = getpwuid(original_real_uid);
        !           424:        if (!pw) {
        !           425:                fprintf(stderr, "You don't exist, go away!\n");
        !           426:                exit(1);
        !           427:        }
        !           428:        /* Take a copy of the returned structure. */
        !           429:        memset(&pwcopy, 0, sizeof(pwcopy));
        !           430:        pwcopy.pw_name = xstrdup(pw->pw_name);
        !           431:        pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
        !           432:        pwcopy.pw_uid = pw->pw_uid;
        !           433:        pwcopy.pw_gid = pw->pw_gid;
        !           434:        pwcopy.pw_dir = xstrdup(pw->pw_dir);
        !           435:        pwcopy.pw_shell = xstrdup(pw->pw_shell);
        !           436:        pw = &pwcopy;
        !           437:
        !           438:        /* Initialize "log" output.  Since we are the client all output
        !           439:           actually goes to the terminal. */
        !           440:        log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 0);
        !           441:
        !           442:        /* Read per-user configuration file. */
        !           443:        snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, SSH_USER_CONFFILE);
        !           444:        read_config_file(buf, host, &options);
        !           445:
        !           446:        /* Read systemwide configuration file. */
        !           447:        read_config_file(HOST_CONFIG_FILE, host, &options);
        !           448:
        !           449:        /* Fill configuration defaults. */
        !           450:        fill_default_options(&options);
        !           451:
        !           452:        /* reinit */
        !           453:        log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 0);
        !           454:
        !           455:        if (options.user == NULL)
        !           456:                options.user = xstrdup(pw->pw_name);
        !           457:
        !           458:        if (options.hostname != NULL)
        !           459:                host = options.hostname;
        !           460:
        !           461:        /* Find canonic host name. */
        !           462:        if (strchr(host, '.') == 0) {
        !           463:                struct hostent *hp = gethostbyname(host);
        !           464:                if (hp != 0) {
        !           465:                        if (strchr(hp->h_name, '.') != 0)
        !           466:                                host = xstrdup(hp->h_name);
        !           467:                        else if (hp->h_aliases != 0
        !           468:                                 && hp->h_aliases[0] != 0
        !           469:                                 && strchr(hp->h_aliases[0], '.') != 0)
        !           470:                                host = xstrdup(hp->h_aliases[0]);
        !           471:                }
        !           472:        }
        !           473:        /* Disable rhosts authentication if not running as root. */
        !           474:        if (original_effective_uid != 0 || !options.use_privileged_port) {
        !           475:                options.rhosts_authentication = 0;
        !           476:                options.rhosts_rsa_authentication = 0;
        !           477:        }
        !           478:        /* If using rsh has been selected, exec it now (without trying
        !           479:           anything else).  Note that we must release privileges first. */
        !           480:        if (options.use_rsh) {
        !           481:                /* Restore our superuser privileges.  This must be done
        !           482:                   before permanently setting the uid. */
        !           483:                restore_uid();
        !           484:
        !           485:                /* Switch to the original uid permanently. */
        !           486:                permanently_set_uid(original_real_uid);
        !           487:
        !           488:                /* Execute rsh. */
        !           489:                rsh_connect(host, options.user, &command);
        !           490:                fatal("rsh_connect returned");
        !           491:        }
        !           492:        /* Restore our superuser privileges. */
        !           493:        restore_uid();
        !           494:
        !           495:        /* Open a connection to the remote host.  This needs root
        !           496:           privileges if rhosts_{rsa_}authentication is enabled. */
        !           497:
        !           498:        ok = ssh_connect(host, &hostaddr, options.port,
        !           499:                         options.connection_attempts,
        !           500:                         !options.rhosts_authentication &&
        !           501:                         !options.rhosts_rsa_authentication,
        !           502:                         original_real_uid,
        !           503:                         options.proxy_command);
        !           504:
        !           505:        /* If we successfully made the connection, load the host private
        !           506:           key in case we will need it later for combined rsa-rhosts
        !           507:           authentication. This must be done before releasing extra
        !           508:           privileges, because the file is only readable by root. */
        !           509:        if (ok) {
        !           510:                host_private_key = RSA_new();
        !           511:                if (load_private_key(HOST_KEY_FILE, "", host_private_key, NULL))
        !           512:                        host_private_key_loaded = 1;
        !           513:        }
        !           514:        /* Get rid of any extra privileges that we may have.  We will no
        !           515:           longer need them.  Also, extra privileges could make it very
        !           516:           hard to read identity files and other non-world-readable files
        !           517:           from the user's home directory if it happens to be on a NFS
        !           518:           volume where root is mapped to nobody. */
        !           519:
        !           520:        /* Note that some legacy systems need to postpone the following
        !           521:           call to permanently_set_uid() until the private hostkey is
        !           522:           destroyed with RSA_free().  Otherwise the calling user could
        !           523:           ptrace() the process, read the private hostkey and impersonate
        !           524:           the host.  OpenBSD does not allow ptracing of setuid processes. */
        !           525:
        !           526:        permanently_set_uid(original_real_uid);
        !           527:
        !           528:        /* Now that we are back to our own permissions, create ~/.ssh
        !           529:           directory if it doesn\'t already exist. */
        !           530:        snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, SSH_USER_DIR);
        !           531:        if (stat(buf, &st) < 0)
        !           532:                if (mkdir(buf, 0755) < 0)
        !           533:                        error("Could not create directory '%.200s'.", buf);
        !           534:
        !           535:        /* Check if the connection failed, and try "rsh" if appropriate. */
        !           536:        if (!ok) {
        !           537:                if (options.port != 0)
        !           538:                        log("Secure connection to %.100s on port %d refused%.100s.",
        !           539:                            host, options.port,
        !           540:                            options.fallback_to_rsh ? "; reverting to insecure method" : "");
        !           541:                else
        !           542:                        log("Secure connection to %.100s refused%.100s.", host,
        !           543:                            options.fallback_to_rsh ? "; reverting to insecure method" : "");
        !           544:
        !           545:                if (options.fallback_to_rsh) {
        !           546:                        rsh_connect(host, options.user, &command);
        !           547:                        fatal("rsh_connect returned");
        !           548:                }
        !           549:                exit(1);
        !           550:        }
        !           551:        /* Expand ~ in options.identity_files. */
        !           552:        for (i = 0; i < options.num_identity_files; i++)
        !           553:                options.identity_files[i] =
        !           554:                        tilde_expand_filename(options.identity_files[i], original_real_uid);
        !           555:
        !           556:        /* Expand ~ in known host file names. */
        !           557:        options.system_hostfile = tilde_expand_filename(options.system_hostfile,
        !           558:                                                        original_real_uid);
        !           559:        options.user_hostfile = tilde_expand_filename(options.user_hostfile,
        !           560:                                                      original_real_uid);
        !           561:
        !           562:        /* Log into the remote system.  This never returns if the login fails. */
        !           563:        ssh_login(host_private_key_loaded, host_private_key,
        !           564:                  host, &hostaddr, original_real_uid);
        !           565:
        !           566:        /* We no longer need the host private key.  Clear it now. */
        !           567:        if (host_private_key_loaded)
        !           568:                RSA_free(host_private_key);     /* Destroys contents safely */
        !           569:
        !           570:        /* Close connection cleanly after attack. */
        !           571:        cipher_attack_detected = packet_disconnect;
        !           572:
        !           573:        /* If requested, fork and let ssh continue in the background. */
        !           574:        if (fork_after_authentication_flag) {
        !           575:                int ret = fork();
        !           576:                if (ret == -1)
        !           577:                        fatal("fork failed: %.100s", strerror(errno));
        !           578:                if (ret != 0)
        !           579:                        exit(0);
        !           580:                setsid();
        !           581:        }
        !           582:        /* Enable compression if requested. */
        !           583:        if (options.compression) {
        !           584:                debug("Requesting compression at level %d.", options.compression_level);
        !           585:
        !           586:                if (options.compression_level < 1 || options.compression_level > 9)
        !           587:                        fatal("Compression level must be from 1 (fast) to 9 (slow, best).");
        !           588:
        !           589:                /* Send the request. */
        !           590:                packet_start(SSH_CMSG_REQUEST_COMPRESSION);
        !           591:                packet_put_int(options.compression_level);
        !           592:                packet_send();
        !           593:                packet_write_wait();
        !           594:                type = packet_read(&plen);
        !           595:                if (type == SSH_SMSG_SUCCESS)
        !           596:                        packet_start_compression(options.compression_level);
        !           597:                else if (type == SSH_SMSG_FAILURE)
        !           598:                        log("Warning: Remote host refused compression.");
        !           599:                else
        !           600:                        packet_disconnect("Protocol error waiting for compression response.");
        !           601:        }
        !           602:        /* Allocate a pseudo tty if appropriate. */
        !           603:        if (tty_flag) {
        !           604:                debug("Requesting pty.");
        !           605:
        !           606:                /* Start the packet. */
        !           607:                packet_start(SSH_CMSG_REQUEST_PTY);
        !           608:
        !           609:                /* Store TERM in the packet.  There is no limit on the
        !           610:                   length of the string. */
        !           611:                cp = getenv("TERM");
        !           612:                if (!cp)
        !           613:                        cp = "";
        !           614:                packet_put_string(cp, strlen(cp));
        !           615:
        !           616:                /* Store window size in the packet. */
        !           617:                if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
        !           618:                        memset(&ws, 0, sizeof(ws));
        !           619:                packet_put_int(ws.ws_row);
        !           620:                packet_put_int(ws.ws_col);
        !           621:                packet_put_int(ws.ws_xpixel);
        !           622:                packet_put_int(ws.ws_ypixel);
        !           623:
        !           624:                /* Store tty modes in the packet. */
        !           625:                tty_make_modes(fileno(stdin));
        !           626:
        !           627:                /* Send the packet, and wait for it to leave. */
        !           628:                packet_send();
        !           629:                packet_write_wait();
        !           630:
        !           631:                /* Read response from the server. */
        !           632:                type = packet_read(&plen);
        !           633:                if (type == SSH_SMSG_SUCCESS)
        !           634:                        interactive = 1;
        !           635:                else if (type == SSH_SMSG_FAILURE)
        !           636:                        log("Warning: Remote host failed or refused to allocate a pseudo tty.");
        !           637:                else
        !           638:                        packet_disconnect("Protocol error waiting for pty request response.");
        !           639:        }
        !           640:        /* Request X11 forwarding if enabled and DISPLAY is set. */
        !           641:        if (options.forward_x11 && getenv("DISPLAY") != NULL) {
        !           642:                char line[512], proto[512], data[512];
        !           643:                FILE *f;
        !           644:                int forwarded = 0, got_data = 0, i;
1.1       deraadt   645:
                    646: #ifdef XAUTH_PATH
1.31    ! markus    647:                /* Try to get Xauthority information for the display. */
        !           648:                snprintf(line, sizeof line, "%.100s list %.200s 2>/dev/null",
        !           649:                         XAUTH_PATH, getenv("DISPLAY"));
        !           650:                f = popen(line, "r");
        !           651:                if (f && fgets(line, sizeof(line), f) &&
        !           652:                    sscanf(line, "%*s %s %s", proto, data) == 2)
        !           653:                        got_data = 1;
        !           654:                if (f)
        !           655:                        pclose(f);
1.1       deraadt   656: #endif /* XAUTH_PATH */
1.31    ! markus    657:                /* If we didn't get authentication data, just make up some
        !           658:                   data.  The forwarding code will check the validity of
        !           659:                   the response anyway, and substitute this data.  The X11
        !           660:                   server, however, will ignore this fake data and use
        !           661:                   whatever authentication mechanisms it was using
        !           662:                   otherwise for the local connection. */
        !           663:                if (!got_data) {
        !           664:                        u_int32_t rand = 0;
        !           665:
        !           666:                        strlcpy(proto, "MIT-MAGIC-COOKIE-1", sizeof proto);
        !           667:                        for (i = 0; i < 16; i++) {
        !           668:                                if (i % 4 == 0)
        !           669:                                        rand = arc4random();
        !           670:                                snprintf(data + 2 * i, sizeof data - 2 * i, "%02x", rand & 0xff);
        !           671:                                rand >>= 8;
        !           672:                        }
        !           673:                }
        !           674:                /* Got local authentication reasonable information.
        !           675:                   Request forwarding with authentication spoofing. */
        !           676:                debug("Requesting X11 forwarding with authentication spoofing.");
        !           677:                x11_request_forwarding_with_spoofing(proto, data);
        !           678:
        !           679:                /* Read response from the server. */
        !           680:                type = packet_read(&plen);
        !           681:                if (type == SSH_SMSG_SUCCESS) {
        !           682:                        forwarded = 1;
        !           683:                        interactive = 1;
        !           684:                } else if (type == SSH_SMSG_FAILURE)
        !           685:                        log("Warning: Remote host denied X11 forwarding.");
        !           686:                else
        !           687:                        packet_disconnect("Protocol error waiting for X11 forwarding");
        !           688:        }
        !           689:        /* Tell the packet module whether this is an interactive session. */
        !           690:        packet_set_interactive(interactive, options.keepalives);
        !           691:
        !           692:        /* Clear agent forwarding if we don\'t have an agent. */
        !           693:        authfd = ssh_get_authentication_socket();
        !           694:        if (authfd < 0)
        !           695:                options.forward_agent = 0;
        !           696:        else
        !           697:                ssh_close_authentication_socket(authfd);
        !           698:
        !           699:        /* Request authentication agent forwarding if appropriate. */
        !           700:        if (options.forward_agent) {
        !           701:                debug("Requesting authentication agent forwarding.");
        !           702:                auth_request_forwarding();
        !           703:
        !           704:                /* Read response from the server. */
        !           705:                type = packet_read(&plen);
        !           706:                packet_integrity_check(plen, 0, type);
        !           707:                if (type != SSH_SMSG_SUCCESS)
        !           708:                        log("Warning: Remote host denied authentication agent forwarding.");
        !           709:        }
        !           710:        /* Initiate local TCP/IP port forwardings. */
        !           711:        for (i = 0; i < options.num_local_forwards; i++) {
        !           712:                debug("Connections to local port %d forwarded to remote address %.200s:%d",
        !           713:                      options.local_forwards[i].port,
        !           714:                      options.local_forwards[i].host,
        !           715:                      options.local_forwards[i].host_port);
        !           716:                channel_request_local_forwarding(options.local_forwards[i].port,
        !           717:                                                 options.local_forwards[i].host,
        !           718:                                                 options.local_forwards[i].host_port);
        !           719:        }
        !           720:
        !           721:        /* Initiate remote TCP/IP port forwardings. */
        !           722:        for (i = 0; i < options.num_remote_forwards; i++) {
        !           723:                debug("Connections to remote port %d forwarded to local address %.200s:%d",
        !           724:                      options.remote_forwards[i].port,
        !           725:                      options.remote_forwards[i].host,
        !           726:                      options.remote_forwards[i].host_port);
        !           727:                channel_request_remote_forwarding(options.remote_forwards[i].port,
        !           728:                                                  options.remote_forwards[i].host,
        !           729:                                                  options.remote_forwards[i].host_port);
        !           730:        }
        !           731:
        !           732:        /* If a command was specified on the command line, execute the
        !           733:           command now. Otherwise request the server to start a shell. */
        !           734:        if (buffer_len(&command) > 0) {
        !           735:                int len = buffer_len(&command);
        !           736:                if (len > 900)
        !           737:                        len = 900;
        !           738:                debug("Sending command: %.*s", len, buffer_ptr(&command));
        !           739:                packet_start(SSH_CMSG_EXEC_CMD);
        !           740:                packet_put_string(buffer_ptr(&command), buffer_len(&command));
        !           741:                packet_send();
        !           742:                packet_write_wait();
        !           743:        } else {
        !           744:                debug("Requesting shell.");
        !           745:                packet_start(SSH_CMSG_EXEC_SHELL);
        !           746:                packet_send();
        !           747:                packet_write_wait();
        !           748:        }
        !           749:
        !           750:        /* Enter the interactive session. */
        !           751:        exit_status = client_loop(tty_flag, tty_flag ? options.escape_char : -1);
        !           752:
        !           753:        /* Close the connection to the remote host. */
        !           754:        packet_close();
        !           755:
        !           756:        /* Exit with the status returned by the program on the remote side. */
        !           757:        exit(exit_status);
1.1       deraadt   758: }