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