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