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