]> andersk Git - openssh.git/blob - ssh.c
Fixed spello
[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           if (process_config_line(&options, host ? host : "", optarg,
387                                   "command-line", 0, &dummy) != 0)
388             exit(1);
389           break;
390
391         default:
392           usage();
393         }
394     }
395
396  /* Check that we got a host name. */
397   if (!host)
398     usage();
399
400   /* check if RSA support exists */
401   if (rsa_alive() == 0) {
402     extern char *__progname;
403
404     fprintf(stderr,
405       "%s: no RSA support in libssl and libcrypto.  See ssl(8).\n",
406       __progname);
407     exit(1);
408   }
409
410   /* Initialize the command to execute on remote host. */
411   buffer_init(&command);
412
413   /* Save the command to execute on the remote host in a buffer.  There is
414      no limit on the length of the command, except by the maximum packet
415      size.  Also sets the tty flag if there is no command. */
416   if (optind == ac)
417     {
418       /* No command specified - execute shell on a tty. */
419       tty_flag = 1;
420     }
421   else
422     {
423       /* A command has been specified.  Store it into the buffer. */
424       for (i = optind; i < ac; i++)
425         {
426           if (i > optind)
427             buffer_append(&command, " ", 1);
428           buffer_append(&command, av[i], strlen(av[i]));
429         }
430     }
431
432   /* Cannot fork to background if no command. */
433   if (fork_after_authentication_flag && buffer_len(&command) == 0)
434     fatal("Cannot fork into background without a command to execute.");
435   
436   /* Allocate a tty by default if no command specified. */
437   if (buffer_len(&command) == 0)
438     tty_flag = 1;
439
440   /* Do not allocate a tty if stdin is not a tty. */
441   if (!isatty(fileno(stdin)))
442     {
443       if (tty_flag)
444         fprintf(stderr, "Pseudo-terminal will not be allocated because stdin is not a terminal.\n");
445       tty_flag = 0;
446     }
447
448   /* Get user data. */
449   pw = getpwuid(original_real_uid);
450   if (!pw)
451     {
452       fprintf(stderr, "You don't exist, go away!\n");
453       exit(1);
454     }
455   
456   /* Take a copy of the returned structure. */
457   memset(&pwcopy, 0, sizeof(pwcopy));
458   pwcopy.pw_name = xstrdup(pw->pw_name);
459   pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
460   pwcopy.pw_uid = pw->pw_uid;
461   pwcopy.pw_gid = pw->pw_gid;
462   pwcopy.pw_dir = xstrdup(pw->pw_dir);
463   pwcopy.pw_shell = xstrdup(pw->pw_shell);
464   pw = &pwcopy;
465
466   /* Initialize "log" output.  Since we are the client all output actually
467      goes to the terminal. */
468   log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 0);
469
470   /* Read per-user configuration file. */
471   snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, SSH_USER_CONFFILE);
472   read_config_file(buf, host, &options);
473
474   /* Read systemwide configuration file. */
475   read_config_file(HOST_CONFIG_FILE, host, &options);
476
477   /* Fill configuration defaults. */
478   fill_default_options(&options);
479
480   /* reinit */
481   log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 0);
482
483   if (options.user == NULL)
484     options.user = xstrdup(pw->pw_name);
485
486   if (options.hostname != NULL)
487     host = options.hostname;
488
489   /* Find canonic host name. */
490   if (strchr(host, '.') == 0)
491     {
492       struct hostent *hp = gethostbyname(host);
493       if (hp != 0)
494         {
495           if (strchr(hp->h_name, '.') != 0)
496             host = xstrdup(hp->h_name);
497           else if (hp->h_aliases != 0
498                    && hp->h_aliases[0] != 0
499                    && strchr(hp->h_aliases[0], '.') != 0)
500             host = xstrdup(hp->h_aliases[0]);
501         }
502     }
503
504   /* Disable rhosts authentication if not running as root. */
505   if (original_effective_uid != 0 || !options.use_privileged_port)
506     {
507       options.rhosts_authentication = 0;
508       options.rhosts_rsa_authentication = 0;
509     }
510
511   /* If using rsh has been selected, exec it now (without trying anything
512      else).  Note that we must release privileges first. */
513   if (options.use_rsh)
514     {
515       /* Restore our superuser privileges.  This must be done before
516          permanently setting the uid. */
517       restore_uid();
518
519       /* Switch to the original uid permanently. */
520       permanently_set_uid(original_real_uid);
521
522       /* Execute rsh. */
523       rsh_connect(host, options.user, &command);
524       fatal("rsh_connect returned");
525     }
526
527   /* Restore our superuser privileges. */
528   restore_uid();
529
530   /* Open a connection to the remote host.  This needs root privileges if
531      rhosts_{rsa_}authentication is enabled. */
532
533   ok = ssh_connect(host, &hostaddr, options.port, options.connection_attempts,
534                    !options.rhosts_authentication &&
535                    !options.rhosts_rsa_authentication,
536                    original_real_uid, options.proxy_command);
537
538   /* If we successfully made the connection, load the host private key in
539      case we will need it later for combined rsa-rhosts authentication. 
540      This must be done before releasing extra privileges, because the file
541      is only readable by root. */
542   if (ok)
543     {
544       host_private_key = RSA_new();
545       if (load_private_key(HOST_KEY_FILE, "", host_private_key, NULL))
546         host_private_key_loaded = 1;
547     }
548
549   /* Get rid of any extra privileges that we may have.  We will no longer need
550      them.  Also, extra privileges could make it very hard to read identity
551      files and other non-world-readable files from the user's home directory
552      if it happens to be on a NFS volume where root is mapped to nobody. */
553   permanently_set_uid(original_real_uid);
554
555   /* Now that we are back to our own permissions, create ~/.ssh directory
556      if it doesn\'t already exist. */
557   snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, SSH_USER_DIR);
558   if (stat(buf, &st) < 0)
559     if (mkdir(buf, 0755) < 0)
560       error("Could not create directory '%.200s'.", buf);
561
562   /* Check if the connection failed, and try "rsh" if appropriate. */
563   if (!ok)
564     {
565       if (options.port != 0)
566         log("Secure connection to %.100s on port %d refused%.100s.", 
567             host, options.port,
568             options.fallback_to_rsh ? "; reverting to insecure method" : "");
569       else
570         log("Secure connection to %.100s refused%.100s.", host,
571             options.fallback_to_rsh ? "; reverting to insecure method" : "");
572
573       if (options.fallback_to_rsh)
574         {
575           rsh_connect(host, options.user, &command);
576           fatal("rsh_connect returned");
577         }
578       exit(1);
579     }
580
581   /* Expand ~ in options.identity_files. */
582   for (i = 0; i < options.num_identity_files; i++)
583     options.identity_files[i] = 
584       tilde_expand_filename(options.identity_files[i], original_real_uid);
585
586   /* Expand ~ in known host file names. */
587   options.system_hostfile = tilde_expand_filename(options.system_hostfile,
588                                                   original_real_uid);
589   options.user_hostfile = tilde_expand_filename(options.user_hostfile,
590                                                 original_real_uid);
591
592   /* Log into the remote system.  This never returns if the login fails. */
593   ssh_login(host_private_key_loaded, host_private_key, 
594             host, &hostaddr, original_real_uid);
595
596   /* We no longer need the host private key.  Clear it now. */
597   if (host_private_key_loaded)
598     RSA_free(host_private_key); /* Destroys contents safely */
599
600   /* Close connection cleanly after attack. */
601   cipher_attack_detected = packet_disconnect;
602
603   /* Enable compression if requested. */
604   if (options.compression)
605     {
606       debug("Requesting compression at level %d.", options.compression_level);
607
608       if (options.compression_level < 1 || options.compression_level > 9)
609         fatal("Compression level must be from 1 (fast) to 9 (slow, best).");
610
611       /* Send the request. */
612       packet_start(SSH_CMSG_REQUEST_COMPRESSION);
613       packet_put_int(options.compression_level);
614       packet_send();
615       packet_write_wait();
616       type = packet_read(&plen);
617       if (type == SSH_SMSG_SUCCESS)
618         packet_start_compression(options.compression_level);
619       else if (type == SSH_SMSG_FAILURE)
620         log("Warning: Remote host refused compression.");
621       else
622         packet_disconnect("Protocol error waiting for compression response.");
623     }
624
625   /* Allocate a pseudo tty if appropriate. */
626   if (tty_flag)
627     {
628       debug("Requesting pty.");
629
630       /* Start the packet. */
631       packet_start(SSH_CMSG_REQUEST_PTY);
632
633       /* Store TERM in the packet.  There is no limit on the length of the
634          string. */
635       cp = getenv("TERM");
636       if (!cp)
637         cp = "";
638       packet_put_string(cp, strlen(cp));
639
640       /* Store window size in the packet. */
641       if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
642         memset(&ws, 0, sizeof(ws));
643       packet_put_int(ws.ws_row);
644       packet_put_int(ws.ws_col);
645       packet_put_int(ws.ws_xpixel);
646       packet_put_int(ws.ws_ypixel);
647       
648       /* Store tty modes in the packet. */
649       tty_make_modes(fileno(stdin));
650
651       /* Send the packet, and wait for it to leave. */
652       packet_send();
653       packet_write_wait();
654
655       /* Read response from the server. */
656       type = packet_read(&plen);
657       if (type == SSH_SMSG_SUCCESS)
658         interactive = 1;
659       else if (type == SSH_SMSG_FAILURE)
660         log("Warning: Remote host failed or refused to allocate a pseudo tty.");
661       else
662         packet_disconnect("Protocol error waiting for pty request response.");
663     }
664
665   /* Request X11 forwarding if enabled and DISPLAY is set. */
666   if (options.forward_x11 && getenv("DISPLAY") != NULL)
667     {
668       char line[512], proto[512], data[512];
669       FILE *f;
670       int forwarded = 0, got_data = 0, i;
671
672 #ifdef XAUTH_PATH
673       /* Try to get Xauthority information for the display. */
674       snprintf(line, sizeof line, "%.100s list %.200s 2>/dev/null", 
675               XAUTH_PATH, getenv("DISPLAY"));
676       f = popen(line, "r");
677       if (f && fgets(line, sizeof(line), f) && 
678           sscanf(line, "%*s %s %s", proto, data) == 2)
679         got_data = 1;
680       if (f)
681         pclose(f);
682 #endif /* XAUTH_PATH */
683       /* If we didn't get authentication data, just make up some data.  The
684          forwarding code will check the validity of the response anyway, and
685          substitute this data.  The X11 server, however, will ignore this
686          fake data and use whatever authentication mechanisms it was using
687          otherwise for the local connection. */
688       if (!got_data)
689         {
690           u_int32_t rand = 0;
691
692           strlcpy(proto, "MIT-MAGIC-COOKIE-1", sizeof proto);
693           for (i = 0; i < 16; i++) {
694             if (i % 4 == 0)
695               rand = arc4random();
696             snprintf(data + 2 * i, sizeof data - 2 * i, "%02x", rand & 0xff);
697             rand >>= 8;
698           }
699         }
700
701       /* Got local authentication reasonable information.  Request forwarding
702          with authentication spoofing. */
703       debug("Requesting X11 forwarding with authentication spoofing.");
704       x11_request_forwarding_with_spoofing(proto, data);
705
706       /* Read response from the server. */
707       type = packet_read(&plen);
708       if (type == SSH_SMSG_SUCCESS)
709         {
710           forwarded = 1;
711           interactive = 1;
712         }
713       else if (type == SSH_SMSG_FAILURE)
714         log("Warning: Remote host denied X11 forwarding.");
715       else
716         packet_disconnect("Protocol error waiting for X11 forwarding");
717     }
718
719   /* Tell the packet module whether this is an interactive session. */
720   packet_set_interactive(interactive, options.keepalives);
721
722   /* Clear agent forwarding if we don\'t have an agent. */
723   authfd = ssh_get_authentication_socket();
724   if (authfd < 0)
725     options.forward_agent = 0;
726   else
727     ssh_close_authentication_socket(authfd);
728
729   /* Request authentication agent forwarding if appropriate. */
730   if (options.forward_agent)
731     {
732       debug("Requesting authentication agent forwarding.");
733       auth_request_forwarding();
734       
735       /* Read response from the server. */
736       type = packet_read(&plen);
737       packet_integrity_check(plen, 0, type);
738       if (type != SSH_SMSG_SUCCESS)
739         log("Warning: Remote host denied authentication agent forwarding.");
740     }
741
742   /* Initiate local TCP/IP port forwardings. */
743   for (i = 0; i < options.num_local_forwards; i++)
744     {
745       debug("Connections to local port %d forwarded to remote address %.200s:%d",
746             options.local_forwards[i].port, options.local_forwards[i].host, 
747             options.local_forwards[i].host_port);
748       channel_request_local_forwarding(options.local_forwards[i].port,
749                                        options.local_forwards[i].host,
750                                        options.local_forwards[i].host_port);
751     }
752
753   /* Initiate remote TCP/IP port forwardings. */
754   for (i = 0; i < options.num_remote_forwards; i++)
755     {
756       debug("Connections to remote port %d forwarded to local address %.200s:%d",
757             options.remote_forwards[i].port, options.remote_forwards[i].host, 
758             options.remote_forwards[i].host_port);
759       channel_request_remote_forwarding(options.remote_forwards[i].port,
760                                         options.remote_forwards[i].host,
761                                         options.remote_forwards[i].host_port);
762     }
763
764   /* If requested, fork and let ssh continue in the background. */
765   if (fork_after_authentication_flag)
766     {
767       int ret = fork();
768       if (ret == -1)
769         fatal("fork failed: %.100s", strerror(errno));
770       if (ret != 0)
771         exit(0);
772       setsid();
773     }
774
775   /* If a command was specified on the command line, execute the command now.
776      Otherwise request the server to start a shell. */
777   if (buffer_len(&command) > 0)
778     {
779       int len = buffer_len(&command);
780       if (len > 900)
781         len = 900;
782       debug("Sending command: %.*s", len, buffer_ptr(&command));
783       packet_start(SSH_CMSG_EXEC_CMD);
784       packet_put_string(buffer_ptr(&command), buffer_len(&command));
785       packet_send();
786       packet_write_wait();
787     }
788   else
789     {
790       debug("Requesting shell.");
791       packet_start(SSH_CMSG_EXEC_SHELL);
792       packet_send();
793       packet_write_wait();
794     }
795
796   /* Enter the interactive session. */
797   exit_status = client_loop(tty_flag, tty_flag ? options.escape_char : -1);
798
799   /* Close the connection to the remote host. */
800   packet_close();
801   
802   /* Exit with the status returned by the program on the remote side. */
803   exit(exit_status);
804 }
This page took 0.127004 seconds and 5 git commands to generate.