[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.1

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