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