2 * Author: Tatu Ylonen <ylo@cs.hut.fi>
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 * Ssh client program. This program can be used to log into a remote machine.
6 * The software supports strong authentication, encryption, and forwarding
7 * of X11, TCP/IP, and authentication connections.
9 * As far as I am concerned, the code I have written for this software
10 * can be used freely for any purpose. Any derived versions of this
11 * software must be clearly marked as such, and if the derived work is
12 * incompatible with the protocol description in the RFC file, it must be
13 * called by a name other than "ssh" or "Secure Shell".
15 * Copyright (c) 1999 Niels Provos. All rights reserved.
16 * Copyright (c) 2000, 2001, 2002, 2003 Markus Friedl. All rights reserved.
18 * Modified to work with SSL by Niels Provos <provos@citi.umich.edu>
19 * in Canada (German citizen).
21 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions
24 * 1. Redistributions of source code must retain the above copyright
25 * notice, this list of conditions and the following disclaimer.
26 * 2. Redistributions in binary form must reproduce the above copyright
27 * notice, this list of conditions and the following disclaimer in the
28 * documentation and/or other materials provided with the distribution.
30 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
31 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
32 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
33 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
34 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
35 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
39 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 RCSID("$OpenBSD: ssh.c,v 1.209 2004/03/11 10:21:17 markus Exp $");
45 #include <openssl/evp.h>
46 #include <openssl/err.h>
60 #include "pathnames.h"
61 #include "clientloop.h"
64 #include "sshconnect.h"
65 #include "tildexpand.h"
76 #ifdef HAVE___PROGNAME
77 extern char *__progname
;
82 /* Flag indicating whether debug mode is on. This can be set on the command line. */
85 /* Flag indicating whether a tty should be allocated */
88 int force_tty_flag
= 0;
90 /* don't exec a shell */
91 int no_shell_flag
= 0;
94 * Flag indicating that nothing should be read from stdin. This can be set
95 * on the command line.
97 int stdin_null_flag
= 0;
100 * Flag indicating that ssh should fork after authentication. This is useful
101 * so that the passphrase can be entered manually, and then ssh goes to the
104 int fork_after_authentication_flag
= 0;
107 * General data structure for command line options and options configurable
108 * in configuration files. See readconf.h.
112 /* optional user configfile */
116 * Name of the host we are connecting to. This is the name given on the
117 * command line, or the HostName specified for the user-supplied name in a
118 * configuration file.
122 /* socket address the host resolves to */
123 struct sockaddr_storage hostaddr
;
125 /* Private host keys. */
126 Sensitive sensitive_data
;
128 /* Original real UID. */
129 uid_t original_real_uid
;
130 uid_t original_effective_uid
;
132 /* command to be executed */
135 /* Should we execute a command or invoke a subsystem? */
136 int subsystem_flag
= 0;
138 /* # of replies received for global requests */
139 static int client_global_request_id
= 0;
141 /* pid of proxycommand child process */
142 pid_t proxy_command_pid
= 0;
144 /* Prints a help message to the user. This function never returns. */
150 "usage: ssh [-1246AaCfghkNnqsTtVvXxY] [-b bind_address] [-c cipher_spec]\n"
151 " [-D port] [-e escape_char] [-F configfile] [-i identity_file]\n"
152 " [-L port:host:hostport] [-l login_name] [-m mac_spec] [-o option]\n"
153 " [-p port] [-R port:host:hostport] [user@]hostname [command]\n"
158 static int ssh_session(void);
159 static int ssh_session2(void);
160 static void load_public_identity_files(void);
163 * Main program for the ssh client.
166 main(int ac
, char **av
)
168 int i
, opt
, exit_status
;
169 u_short fwd_port
, fwd_host_port
;
170 char sfwd_port
[6], sfwd_host_port
[6];
171 char *p
, *cp
, *line
, buf
[256];
175 extern int optind
, optreset
;
178 __progname
= ssh_get_progname(av
[0]);
182 * Save the original real uid. It will be needed later (uid-swapping
183 * may clobber the real uid).
185 original_real_uid
= getuid();
186 original_effective_uid
= geteuid();
189 * Use uid-swapping to give up root privileges for the duration of
190 * option processing. We will re-instantiate the rights when we are
191 * ready to create the privileged port, and will permanently drop
192 * them when the port has been created (actually, when the connection
193 * has been made, as we may need to create the port several times).
197 #ifdef HAVE_SETRLIMIT
198 /* If we are installed setuid root be careful to not drop core. */
199 if (original_real_uid
!= original_effective_uid
) {
201 rlim
.rlim_cur
= rlim
.rlim_max
= 0;
202 if (setrlimit(RLIMIT_CORE
, &rlim
) < 0)
203 fatal("setrlimit failed: %.100s", strerror(errno
));
207 pw
= getpwuid(original_real_uid
);
209 logit("You don't exist, go away!");
212 /* Take a copy of the returned structure. */
216 * Set our umask to something reasonable, as some files are created
217 * with the default umask. This will make them world-readable but
218 * writable only by the owner, which is ok for all files for which we
219 * don't set the modes explicitly.
223 /* Initialize option structure to indicate that no values have been set. */
224 initialize_options(&options
);
226 /* Parse command-line arguments. */
230 while ((opt
= getopt(ac
, av
,
231 "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:NPR:TVXY")) != -1) {
234 options
.protocol
= SSH_PROTO_1
;
237 options
.protocol
= SSH_PROTO_2
;
240 options
.address_family
= AF_INET
;
243 options
.address_family
= AF_INET6
;
249 fork_after_authentication_flag
= 1;
253 options
.forward_x11
= 0;
256 options
.forward_x11
= 1;
259 options
.forward_x11
= 1;
260 options
.forward_x11_trusted
= 1;
263 options
.gateway_ports
= 1;
265 case 'P': /* deprecated */
266 options
.use_privileged_port
= 0;
269 options
.forward_agent
= 0;
272 options
.forward_agent
= 1;
275 options
.gss_deleg_creds
= 0;
278 if (stat(optarg
, &st
) < 0) {
279 fprintf(stderr
, "Warning: Identity file %s "
280 "does not exist.\n", optarg
);
283 if (options
.num_identity_files
>=
284 SSH_MAX_IDENTITY_FILES
)
285 fatal("Too many identity files specified "
286 "(max %d)", SSH_MAX_IDENTITY_FILES
);
287 options
.identity_files
[options
.num_identity_files
++] =
292 options
.smartcard_device
= xstrdup(optarg
);
294 fprintf(stderr
, "no support for smartcards.\n");
303 if (debug_flag
== 0) {
305 options
.log_level
= SYSLOG_LEVEL_DEBUG1
;
307 if (options
.log_level
< SYSLOG_LEVEL_DEBUG3
)
313 fprintf(stderr
, "%s, %s\n",
314 SSH_VERSION
, SSLeay_version(SSLEAY_VERSION
));
319 options
.log_level
= SYSLOG_LEVEL_QUIET
;
322 if (optarg
[0] == '^' && optarg
[2] == 0 &&
323 (u_char
) optarg
[1] >= 64 &&
324 (u_char
) optarg
[1] < 128)
325 options
.escape_char
= (u_char
) optarg
[1] & 31;
326 else if (strlen(optarg
) == 1)
327 options
.escape_char
= (u_char
) optarg
[0];
328 else if (strcmp(optarg
, "none") == 0)
329 options
.escape_char
= SSH_ESCAPECHAR_NONE
;
331 fprintf(stderr
, "Bad escape character '%s'.\n",
337 if (ciphers_valid(optarg
)) {
339 options
.ciphers
= xstrdup(optarg
);
340 options
.cipher
= SSH_CIPHER_ILLEGAL
;
343 options
.cipher
= cipher_number(optarg
);
344 if (options
.cipher
== -1) {
346 "Unknown cipher type '%s'\n",
350 if (options
.cipher
== SSH_CIPHER_3DES
)
351 options
.ciphers
= "3des-cbc";
352 else if (options
.cipher
== SSH_CIPHER_BLOWFISH
)
353 options
.ciphers
= "blowfish-cbc";
355 options
.ciphers
= (char *)-1;
359 if (mac_valid(optarg
))
360 options
.macs
= xstrdup(optarg
);
362 fprintf(stderr
, "Unknown mac type '%s'\n",
368 options
.port
= a2port(optarg
);
369 if (options
.port
== 0) {
370 fprintf(stderr
, "Bad port '%s'\n", optarg
);
375 options
.user
= optarg
;
380 if (sscanf(optarg
, "%5[0123456789]:%255[^:]:%5[0123456789]",
381 sfwd_port
, buf
, sfwd_host_port
) != 3 &&
382 sscanf(optarg
, "%5[0123456789]/%255[^/]/%5[0123456789]",
383 sfwd_port
, buf
, sfwd_host_port
) != 3) {
385 "Bad forwarding specification '%s'\n",
390 if ((fwd_port
= a2port(sfwd_port
)) == 0 ||
391 (fwd_host_port
= a2port(sfwd_host_port
)) == 0) {
393 "Bad forwarding port(s) '%s'\n", optarg
);
397 add_local_forward(&options
, fwd_port
, buf
,
400 add_remote_forward(&options
, fwd_port
, buf
,
405 fwd_port
= a2port(optarg
);
407 fprintf(stderr
, "Bad dynamic port '%s'\n",
411 add_local_forward(&options
, fwd_port
, "socks", 0);
415 options
.compression
= 1;
426 line
= xstrdup(optarg
);
427 if (process_config_line(&options
, host
? host
: "",
428 line
, "command-line", 0, &dummy
) != 0)
436 options
.bind_address
= optarg
;
449 if (ac
> 0 && !host
&& **av
!= '-') {
450 if (strrchr(*av
, '@')) {
452 cp
= strrchr(p
, '@');
453 if (cp
== NULL
|| cp
== p
)
461 optind
= optreset
= 1;
467 /* Check that we got a host name. */
471 SSLeay_add_all_algorithms();
472 ERR_load_crypto_strings();
474 /* Initialize the command to execute on remote host. */
475 buffer_init(&command
);
478 * Save the command to execute on the remote host in a buffer. There
479 * is no limit on the length of the command, except by the maximum
480 * packet size. Also sets the tty flag if there is no command.
483 /* No command specified - execute shell on a tty. */
485 if (subsystem_flag
) {
487 "You must specify a subsystem to invoke.\n");
491 /* A command has been specified. Store it into the buffer. */
492 for (i
= 0; i
< ac
; i
++) {
494 buffer_append(&command
, " ", 1);
495 buffer_append(&command
, av
[i
], strlen(av
[i
]));
499 /* Cannot fork to background if no command. */
500 if (fork_after_authentication_flag
&& buffer_len(&command
) == 0 && !no_shell_flag
)
501 fatal("Cannot fork into background without a command to execute.");
503 /* Allocate a tty by default if no command specified. */
504 if (buffer_len(&command
) == 0)
510 /* Do not allocate a tty if stdin is not a tty. */
511 if (!isatty(fileno(stdin
)) && !force_tty_flag
) {
513 logit("Pseudo-terminal will not be allocated because stdin is not a terminal.");
518 * Initialize "log" output. Since we are the client all output
519 * actually goes to stderr.
521 log_init(av
[0], options
.log_level
== -1 ? SYSLOG_LEVEL_INFO
: options
.log_level
,
522 SYSLOG_FACILITY_USER
, 1);
525 * Read per-user configuration file. Ignore the system wide config
526 * file if the user specifies a config file on the command line.
528 if (config
!= NULL
) {
529 if (!read_config_file(config
, host
, &options
))
530 fatal("Can't open user config file %.100s: "
531 "%.100s", config
, strerror(errno
));
533 snprintf(buf
, sizeof buf
, "%.100s/%.100s", pw
->pw_dir
,
534 _PATH_SSH_USER_CONFFILE
);
535 (void)read_config_file(buf
, host
, &options
);
537 /* Read systemwide configuration file after use config. */
538 (void)read_config_file(_PATH_HOST_CONFIG_FILE
, host
, &options
);
541 /* Fill configuration defaults. */
542 fill_default_options(&options
);
544 channel_set_af(options
.address_family
);
547 log_init(av
[0], options
.log_level
, SYSLOG_FACILITY_USER
, 1);
551 if (options
.user
== NULL
)
552 options
.user
= xstrdup(pw
->pw_name
);
554 if (options
.hostname
!= NULL
)
555 host
= options
.hostname
;
557 /* force lowercase for hostkey matching */
558 if (options
.host_key_alias
!= NULL
) {
559 for (p
= options
.host_key_alias
; *p
; p
++)
564 if (options
.proxy_command
!= NULL
&&
565 strcmp(options
.proxy_command
, "none") == 0)
566 options
.proxy_command
= NULL
;
568 /* Open a connection to the remote host. */
569 if (ssh_connect(host
, &hostaddr
, options
.port
,
570 options
.address_family
, options
.connection_attempts
,
572 options
.use_privileged_port
,
574 original_effective_uid
== 0 && options
.use_privileged_port
,
576 options
.proxy_command
) != 0)
580 * If we successfully made the connection, load the host private key
581 * in case we will need it later for combined rsa-rhosts
582 * authentication. This must be done before releasing extra
583 * privileges, because the file is only readable by root.
584 * If we cannot access the private keys, load the public keys
585 * instead and try to execute the ssh-keysign helper instead.
587 sensitive_data
.nkeys
= 0;
588 sensitive_data
.keys
= NULL
;
589 sensitive_data
.external_keysign
= 0;
590 if (options
.rhosts_rsa_authentication
||
591 options
.hostbased_authentication
) {
592 sensitive_data
.nkeys
= 3;
593 sensitive_data
.keys
= xmalloc(sensitive_data
.nkeys
*
597 sensitive_data
.keys
[0] = key_load_private_type(KEY_RSA1
,
598 _PATH_HOST_KEY_FILE
, "", NULL
);
599 sensitive_data
.keys
[1] = key_load_private_type(KEY_DSA
,
600 _PATH_HOST_DSA_KEY_FILE
, "", NULL
);
601 sensitive_data
.keys
[2] = key_load_private_type(KEY_RSA
,
602 _PATH_HOST_RSA_KEY_FILE
, "", NULL
);
605 if (options
.hostbased_authentication
== 1 &&
606 sensitive_data
.keys
[0] == NULL
&&
607 sensitive_data
.keys
[1] == NULL
&&
608 sensitive_data
.keys
[2] == NULL
) {
609 sensitive_data
.keys
[1] = key_load_public(
610 _PATH_HOST_DSA_KEY_FILE
, NULL
);
611 sensitive_data
.keys
[2] = key_load_public(
612 _PATH_HOST_RSA_KEY_FILE
, NULL
);
613 sensitive_data
.external_keysign
= 1;
617 * Get rid of any extra privileges that we may have. We will no
618 * longer need them. Also, extra privileges could make it very hard
619 * to read identity files and other non-world-readable files from the
620 * user's home directory if it happens to be on a NFS volume where
621 * root is mapped to nobody.
623 seteuid(original_real_uid
);
624 setuid(original_real_uid
);
627 * Now that we are back to our own permissions, create ~/.ssh
628 * directory if it doesn\'t already exist.
630 snprintf(buf
, sizeof buf
, "%.100s%s%.100s", pw
->pw_dir
, strcmp(pw
->pw_dir
, "/") ? "/" : "", _PATH_SSH_USER_DIR
);
631 if (stat(buf
, &st
) < 0)
632 if (mkdir(buf
, 0700) < 0)
633 error("Could not create directory '%.200s'.", buf
);
635 /* load options.identity_files */
636 load_public_identity_files();
638 /* Expand ~ in known host file names. */
640 options
.system_hostfile
=
641 tilde_expand_filename(options
.system_hostfile
, original_real_uid
);
642 options
.user_hostfile
=
643 tilde_expand_filename(options
.user_hostfile
, original_real_uid
);
644 options
.system_hostfile2
=
645 tilde_expand_filename(options
.system_hostfile2
, original_real_uid
);
646 options
.user_hostfile2
=
647 tilde_expand_filename(options
.user_hostfile2
, original_real_uid
);
649 signal(SIGPIPE
, SIG_IGN
); /* ignore SIGPIPE early */
651 /* Log into the remote system. This never returns if the login fails. */
652 ssh_login(&sensitive_data
, host
, (struct sockaddr
*)&hostaddr
, pw
);
654 /* We no longer need the private host keys. Clear them now. */
655 if (sensitive_data
.nkeys
!= 0) {
656 for (i
= 0; i
< sensitive_data
.nkeys
; i
++) {
657 if (sensitive_data
.keys
[i
] != NULL
) {
658 /* Destroys contents safely */
659 debug3("clear hostkey %d", i
);
660 key_free(sensitive_data
.keys
[i
]);
661 sensitive_data
.keys
[i
] = NULL
;
664 xfree(sensitive_data
.keys
);
666 for (i
= 0; i
< options
.num_identity_files
; i
++) {
667 if (options
.identity_files
[i
]) {
668 xfree(options
.identity_files
[i
]);
669 options
.identity_files
[i
] = NULL
;
671 if (options
.identity_keys
[i
]) {
672 key_free(options
.identity_keys
[i
]);
673 options
.identity_keys
[i
] = NULL
;
677 exit_status
= compat20
? ssh_session2() : ssh_session();
681 * Send SIGHUP to proxy command if used. We don't wait() in
682 * case it hangs and instead rely on init to reap the child
684 if (proxy_command_pid
> 1)
685 kill(proxy_command_pid
, SIGHUP
);
690 #define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1"
693 x11_get_proto(char **_proto
, char **_data
)
698 static char proto
[512], data
[512];
700 int got_data
= 0, generated
= 0, do_unlink
= 0, i
;
701 char *display
, *xauthdir
, *xauthfile
;
704 xauthdir
= xauthfile
= NULL
;
707 proto
[0] = data
[0] = '\0';
709 if (!options
.xauth_location
||
710 (stat(options
.xauth_location
, &st
) == -1)) {
711 debug("No xauth program.");
713 if ((display
= getenv("DISPLAY")) == NULL
) {
714 debug("x11_get_proto: DISPLAY not set");
718 * Handle FamilyLocal case where $DISPLAY does
719 * not match an authorization entry. For this we
720 * just try "xauth list unix:displaynum.screennum".
721 * XXX: "localhost" match to determine FamilyLocal
724 if (strncmp(display
, "localhost:", 10) == 0) {
725 snprintf(xdisplay
, sizeof(xdisplay
), "unix:%s",
729 if (options
.forward_x11_trusted
== 0) {
730 xauthdir
= xmalloc(MAXPATHLEN
);
731 xauthfile
= xmalloc(MAXPATHLEN
);
732 strlcpy(xauthdir
, "/tmp/ssh-XXXXXXXXXX", MAXPATHLEN
);
733 if (mkdtemp(xauthdir
) != NULL
) {
735 snprintf(xauthfile
, MAXPATHLEN
, "%s/xauthfile",
737 snprintf(cmd
, sizeof(cmd
),
738 "%s -f %s generate %s " SSH_X11_PROTO
739 " untrusted timeout 1200 2>" _PATH_DEVNULL
,
740 options
.xauth_location
, xauthfile
, display
);
741 debug2("x11_get_proto: %s", cmd
);
742 if (system(cmd
) == 0)
746 snprintf(cmd
, sizeof(cmd
),
747 "%s %s%s list %s . 2>" _PATH_DEVNULL
,
748 options
.xauth_location
,
749 generated
? "-f " : "" ,
750 generated
? xauthfile
: "",
752 debug2("x11_get_proto: %s", cmd
);
754 if (f
&& fgets(line
, sizeof(line
), f
) &&
755 sscanf(line
, "%*s %511s %511s", proto
, data
) == 2)
771 * If we didn't get authentication data, just make up some
772 * data. The forwarding code will check the validity of the
773 * response anyway, and substitute this data. The X11
774 * server, however, will ignore this fake data and use
775 * whatever authentication mechanisms it was using otherwise
776 * for the local connection.
781 logit("Warning: No xauth data; "
782 "using fake authentication data for X11 forwarding.");
783 strlcpy(proto
, SSH_X11_PROTO
, sizeof proto
);
784 for (i
= 0; i
< 16; i
++) {
787 snprintf(data
+ 2 * i
, sizeof data
- 2 * i
, "%02x",
795 ssh_init_forwarding(void)
800 /* Initiate local TCP/IP port forwardings. */
801 for (i
= 0; i
< options
.num_local_forwards
; i
++) {
802 debug("Connections to local port %d forwarded to remote address %.200s:%d",
803 options
.local_forwards
[i
].port
,
804 options
.local_forwards
[i
].host
,
805 options
.local_forwards
[i
].host_port
);
806 success
+= channel_setup_local_fwd_listener(
807 options
.local_forwards
[i
].port
,
808 options
.local_forwards
[i
].host
,
809 options
.local_forwards
[i
].host_port
,
810 options
.gateway_ports
);
812 if (i
> 0 && success
== 0)
813 error("Could not request local forwarding.");
815 /* Initiate remote TCP/IP port forwardings. */
816 for (i
= 0; i
< options
.num_remote_forwards
; i
++) {
817 debug("Connections to remote port %d forwarded to local address %.200s:%d",
818 options
.remote_forwards
[i
].port
,
819 options
.remote_forwards
[i
].host
,
820 options
.remote_forwards
[i
].host_port
);
821 channel_request_remote_forwarding(
822 options
.remote_forwards
[i
].port
,
823 options
.remote_forwards
[i
].host
,
824 options
.remote_forwards
[i
].host_port
);
829 check_agent_present(void)
831 if (options
.forward_agent
) {
832 /* Clear agent forwarding if we don\'t have an agent. */
833 if (!ssh_agent_present())
834 options
.forward_agent
= 0;
847 /* Enable compression if requested. */
848 if (options
.compression
) {
849 debug("Requesting compression at level %d.", options
.compression_level
);
851 if (options
.compression_level
< 1 || options
.compression_level
> 9)
852 fatal("Compression level must be from 1 (fast) to 9 (slow, best).");
854 /* Send the request. */
855 packet_start(SSH_CMSG_REQUEST_COMPRESSION
);
856 packet_put_int(options
.compression_level
);
859 type
= packet_read();
860 if (type
== SSH_SMSG_SUCCESS
)
861 packet_start_compression(options
.compression_level
);
862 else if (type
== SSH_SMSG_FAILURE
)
863 logit("Warning: Remote host refused compression.");
865 packet_disconnect("Protocol error waiting for compression response.");
867 /* Allocate a pseudo tty if appropriate. */
869 debug("Requesting pty.");
871 /* Start the packet. */
872 packet_start(SSH_CMSG_REQUEST_PTY
);
874 /* Store TERM in the packet. There is no limit on the
875 length of the string. */
879 packet_put_cstring(cp
);
881 /* Store window size in the packet. */
882 if (ioctl(fileno(stdin
), TIOCGWINSZ
, &ws
) < 0)
883 memset(&ws
, 0, sizeof(ws
));
884 packet_put_int(ws
.ws_row
);
885 packet_put_int(ws
.ws_col
);
886 packet_put_int(ws
.ws_xpixel
);
887 packet_put_int(ws
.ws_ypixel
);
889 /* Store tty modes in the packet. */
890 tty_make_modes(fileno(stdin
), NULL
);
892 /* Send the packet, and wait for it to leave. */
896 /* Read response from the server. */
897 type
= packet_read();
898 if (type
== SSH_SMSG_SUCCESS
) {
901 } else if (type
== SSH_SMSG_FAILURE
)
902 logit("Warning: Remote host failed or refused to allocate a pseudo tty.");
904 packet_disconnect("Protocol error waiting for pty request response.");
906 /* Request X11 forwarding if enabled and DISPLAY is set. */
907 if (options
.forward_x11
&& getenv("DISPLAY") != NULL
) {
909 /* Get reasonable local authentication information. */
910 x11_get_proto(&proto
, &data
);
911 /* Request forwarding with authentication spoofing. */
912 debug("Requesting X11 forwarding with authentication spoofing.");
913 x11_request_forwarding_with_spoofing(0, proto
, data
);
915 /* Read response from the server. */
916 type
= packet_read();
917 if (type
== SSH_SMSG_SUCCESS
) {
919 } else if (type
== SSH_SMSG_FAILURE
) {
920 logit("Warning: Remote host denied X11 forwarding.");
922 packet_disconnect("Protocol error waiting for X11 forwarding");
925 /* Tell the packet module whether this is an interactive session. */
926 packet_set_interactive(interactive
);
928 /* Request authentication agent forwarding if appropriate. */
929 check_agent_present();
931 if (options
.forward_agent
) {
932 debug("Requesting authentication agent forwarding.");
933 auth_request_forwarding();
935 /* Read response from the server. */
936 type
= packet_read();
938 if (type
!= SSH_SMSG_SUCCESS
)
939 logit("Warning: Remote host denied authentication agent forwarding.");
942 /* Initiate port forwardings. */
943 ssh_init_forwarding();
945 /* If requested, let ssh continue in the background. */
946 if (fork_after_authentication_flag
)
947 if (daemon(1, 1) < 0)
948 fatal("daemon() failed: %.200s", strerror(errno
));
951 * If a command was specified on the command line, execute the
952 * command now. Otherwise request the server to start a shell.
954 if (buffer_len(&command
) > 0) {
955 int len
= buffer_len(&command
);
958 debug("Sending command: %.*s", len
, (u_char
*)buffer_ptr(&command
));
959 packet_start(SSH_CMSG_EXEC_CMD
);
960 packet_put_string(buffer_ptr(&command
), buffer_len(&command
));
964 debug("Requesting shell.");
965 packet_start(SSH_CMSG_EXEC_SHELL
);
970 /* Enter the interactive session. */
971 return client_loop(have_tty
, tty_flag
?
972 options
.escape_char
: SSH_ESCAPECHAR_NONE
, 0);
976 client_subsystem_reply(int type
, u_int32_t seq
, void *ctxt
)
980 id
= packet_get_int();
981 len
= buffer_len(&command
);
985 if (type
== SSH2_MSG_CHANNEL_FAILURE
)
986 fatal("Request for subsystem '%.*s' failed on channel %d",
987 len
, (u_char
*)buffer_ptr(&command
), id
);
991 client_global_request_reply_fwd(int type
, u_int32_t seq
, void *ctxt
)
995 i
= client_global_request_id
++;
996 if (i
>= options
.num_remote_forwards
)
998 debug("remote forward %s for: listen %d, connect %s:%d",
999 type
== SSH2_MSG_REQUEST_SUCCESS
? "success" : "failure",
1000 options
.remote_forwards
[i
].port
,
1001 options
.remote_forwards
[i
].host
,
1002 options
.remote_forwards
[i
].host_port
);
1003 if (type
== SSH2_MSG_REQUEST_FAILURE
)
1004 logit("Warning: remote port forwarding failed for listen port %d",
1005 options
.remote_forwards
[i
].port
);
1008 /* request pty/x11/agent/tcpfwd/shell for channel */
1010 ssh_session2_setup(int id
, void *arg
)
1013 int interactive
= 0;
1016 debug2("ssh_session2_setup: id %d", id
);
1021 cp
= getenv("TERM");
1024 /* Store window size in the packet. */
1025 if (ioctl(fileno(stdin
), TIOCGWINSZ
, &ws
) < 0)
1026 memset(&ws
, 0, sizeof(ws
));
1028 channel_request_start(id
, "pty-req", 0);
1029 packet_put_cstring(cp
);
1030 packet_put_int(ws
.ws_col
);
1031 packet_put_int(ws
.ws_row
);
1032 packet_put_int(ws
.ws_xpixel
);
1033 packet_put_int(ws
.ws_ypixel
);
1034 tio
= get_saved_tio();
1035 tty_make_modes(/*ignored*/ 0, &tio
);
1038 /* XXX wait for reply */
1040 if (options
.forward_x11
&&
1041 getenv("DISPLAY") != NULL
) {
1043 /* Get reasonable local authentication information. */
1044 x11_get_proto(&proto
, &data
);
1045 /* Request forwarding with authentication spoofing. */
1046 debug("Requesting X11 forwarding with authentication spoofing.");
1047 x11_request_forwarding_with_spoofing(id
, proto
, data
);
1049 /* XXX wait for reply */
1052 check_agent_present();
1053 if (options
.forward_agent
) {
1054 debug("Requesting authentication agent forwarding.");
1055 channel_request_start(id
, "auth-agent-req@openssh.com", 0);
1059 len
= buffer_len(&command
);
1063 if (subsystem_flag
) {
1064 debug("Sending subsystem: %.*s", len
, (u_char
*)buffer_ptr(&command
));
1065 channel_request_start(id
, "subsystem", /*want reply*/ 1);
1066 /* register callback for reply */
1067 /* XXX we assume that client_loop has already been called */
1068 dispatch_set(SSH2_MSG_CHANNEL_FAILURE
, &client_subsystem_reply
);
1069 dispatch_set(SSH2_MSG_CHANNEL_SUCCESS
, &client_subsystem_reply
);
1071 debug("Sending command: %.*s", len
, (u_char
*)buffer_ptr(&command
));
1072 channel_request_start(id
, "exec", 0);
1074 packet_put_string(buffer_ptr(&command
), buffer_len(&command
));
1077 channel_request_start(id
, "shell", 0);
1081 packet_set_interactive(interactive
);
1084 /* open new channel for a session */
1086 ssh_session2_open(void)
1089 int window
, packetmax
, in
, out
, err
;
1091 if (stdin_null_flag
) {
1092 in
= open(_PATH_DEVNULL
, O_RDONLY
);
1094 in
= dup(STDIN_FILENO
);
1096 out
= dup(STDOUT_FILENO
);
1097 err
= dup(STDERR_FILENO
);
1099 if (in
< 0 || out
< 0 || err
< 0)
1100 fatal("dup() in/out/err failed");
1102 /* enable nonblocking unless tty */
1110 window
= CHAN_SES_WINDOW_DEFAULT
;
1111 packetmax
= CHAN_SES_PACKET_DEFAULT
;
1117 "session", SSH_CHANNEL_OPENING
, in
, out
, err
,
1118 window
, packetmax
, CHAN_EXTENDED_WRITE
,
1119 "client-session", /*nonblock*/0);
1121 debug3("ssh_session2_open: channel_new: %d", c
->self
);
1123 channel_send_open(c
->self
);
1125 channel_register_confirm(c
->self
, ssh_session2_setup
);
1135 /* XXX should be pre-session */
1136 ssh_init_forwarding();
1138 if (!no_shell_flag
|| (datafellows
& SSH_BUG_DUMMYCHAN
))
1139 id
= ssh_session2_open();
1141 /* If requested, let ssh continue in the background. */
1142 if (fork_after_authentication_flag
)
1143 if (daemon(1, 1) < 0)
1144 fatal("daemon() failed: %.200s", strerror(errno
));
1146 return client_loop(tty_flag
, tty_flag
?
1147 options
.escape_char
: SSH_ESCAPECHAR_NONE
, id
);
1151 load_public_identity_files(void)
1159 if (options
.smartcard_device
!= NULL
&&
1160 options
.num_identity_files
< SSH_MAX_IDENTITY_FILES
&&
1161 (keys
= sc_get_keys(options
.smartcard_device
, NULL
)) != NULL
) {
1163 for (i
= 0; keys
[i
] != NULL
; i
++) {
1165 memmove(&options
.identity_files
[1], &options
.identity_files
[0],
1166 sizeof(char *) * (SSH_MAX_IDENTITY_FILES
- 1));
1167 memmove(&options
.identity_keys
[1], &options
.identity_keys
[0],
1168 sizeof(Key
*) * (SSH_MAX_IDENTITY_FILES
- 1));
1169 options
.num_identity_files
++;
1170 options
.identity_keys
[0] = keys
[i
];
1171 options
.identity_files
[0] = sc_get_key_label(keys
[i
]);
1173 if (options
.num_identity_files
> SSH_MAX_IDENTITY_FILES
)
1174 options
.num_identity_files
= SSH_MAX_IDENTITY_FILES
;
1178 #endif /* SMARTCARD */
1179 for (; i
< options
.num_identity_files
; i
++) {
1180 filename
= tilde_expand_filename(options
.identity_files
[i
],
1182 public = key_load_public(filename
, NULL
);
1183 debug("identity file %s type %d", filename
,
1184 public ? public->type
: -1);
1185 xfree(options
.identity_files
[i
]);
1186 options
.identity_files
[i
] = filename
;
1187 options
.identity_keys
[i
] = public;