]> andersk Git - openssh.git/blame - ssh.c
Changed name of directory in tarball
[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
31/* Flag indicating whether debug mode is on. This can be set on the
32 command line. */
33int debug_flag = 0;
34
35/* Flag indicating whether quiet mode is on. */
36int 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. */
41int tty_flag = 0;
42
43/* Flag indicating that nothing should be read from stdin. This can be set
44 on the command line. */
45int 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. */
50int fork_after_authentication_flag = 0;
51
52/* General data structure for command line options and options configurable
53 in configuration files. See readconf.h. */
54Options 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. */
59char *host;
60
61/* socket address the host resolves to */
62struct 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. */
68volatile int received_window_change_signal = 0;
69
70/* Value of argv[0] (set in the main program). */
71char *av0;
72
73/* Flag indicating whether we have a valid host private key loaded. */
74int host_private_key_loaded = 0;
75
76/* Host private key. */
77RSA *host_private_key = NULL;
78
79/* Original real UID. */
80uid_t original_real_uid;
81
82/* Prints a help message to the user. This function never returns. */
83
84void
85usage()
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
122void
123rsh_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
8efc0c15 161int
162main(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. */
69256d9d 502 if (original_effective_uid != 0 || !options.use_privileged_port)
8efc0c15 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
69256d9d 528 rhosts_{rsa_}authentication is enabled. */
8efc0c15 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.155546 seconds and 5 git commands to generate.