source: trunk/third/openssh/ssh.c @ 19224

Revision 19224, 34.3 KB checked in by zacheiss, 22 years ago (diff)
Remove useless warning message, since dm will never give us xauth.
Line 
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 * 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.
8 *
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".
14 *
15 * Copyright (c) 1999 Niels Provos.  All rights reserved.
16 * Copyright (c) 2000, 2001, 2002 Markus Friedl.  All rights reserved.
17 *
18 * Modified to work with SSL by Niels Provos <provos@citi.umich.edu>
19 * in Canada (German citizen).
20 *
21 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions
23 * are met:
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.
29 *
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.
40 */
41
42#include "includes.h"
43RCSID("$OpenBSD: ssh.c,v 1.186 2002/09/19 01:58:18 djm Exp $");
44
45#include <openssl/evp.h>
46#include <openssl/err.h>
47
48#include "ssh.h"
49#include "ssh1.h"
50#include "ssh2.h"
51#include "compat.h"
52#include "cipher.h"
53#include "xmalloc.h"
54#include "packet.h"
55#include "buffer.h"
56#include "channels.h"
57#include "key.h"
58#include "authfd.h"
59#include "authfile.h"
60#include "pathnames.h"
61#include "clientloop.h"
62#include "log.h"
63#include "readconf.h"
64#include "sshconnect.h"
65#include "tildexpand.h"
66#include "dispatch.h"
67#include "misc.h"
68#include "kex.h"
69#include "mac.h"
70#include "sshtty.h"
71
72#ifdef SMARTCARD
73#include "scard.h"
74#endif
75
76#ifdef HAVE___PROGNAME
77extern char *__progname;
78#else
79char *__progname;
80#endif
81
82/* Flag indicating whether IPv4 or IPv6.  This can be set on the command line.
83   Default value is AF_UNSPEC means both IPv4 and IPv6. */
84#ifdef IPV4_DEFAULT
85int IPv4or6 = AF_INET;
86#else
87int IPv4or6 = AF_UNSPEC;
88#endif
89
90/* Flag indicating whether debug mode is on.  This can be set on the command line. */
91int debug_flag = 0;
92
93/* Flag indicating whether a tty should be allocated */
94int tty_flag = 0;
95int no_tty_flag = 0;
96int force_tty_flag = 0;
97
98/* don't exec a shell */
99int no_shell_flag = 0;
100
101/*
102 * Flag indicating that nothing should be read from stdin.  This can be set
103 * on the command line.
104 */
105int stdin_null_flag = 0;
106
107/*
108 * Flag indicating that ssh should fork after authentication.  This is useful
109 * so that the passphrase can be entered manually, and then ssh goes to the
110 * background.
111 */
112int fork_after_authentication_flag = 0;
113
114/*
115 * General data structure for command line options and options configurable
116 * in configuration files.  See readconf.h.
117 */
118Options options;
119
120/* optional user configfile */
121char *config = NULL;
122
123/*
124 * Name of the host we are connecting to.  This is the name given on the
125 * command line, or the HostName specified for the user-supplied name in a
126 * configuration file.
127 */
128char *host;
129
130/* socket address the host resolves to */
131struct sockaddr_storage hostaddr;
132
133/* Private host keys. */
134Sensitive sensitive_data;
135
136/* Original real UID. */
137uid_t original_real_uid;
138uid_t original_effective_uid;
139
140/* command to be executed */
141Buffer command;
142
143/* Should we execute a command or invoke a subsystem? */
144int subsystem_flag = 0;
145
146/* # of replies received for global requests */
147static int client_global_request_id = 0;
148
149/* pid of proxycommand child process */
150pid_t proxy_command_pid = 0;
151
152/* Prints a help message to the user.  This function never returns. */
153
154static void
155usage(void)
156{
157        fprintf(stderr, "Usage: %s [options] host [command]\n", __progname);
158        fprintf(stderr, "Options:\n");
159        fprintf(stderr, "  -l user     Log in using this user name.\n");
160        fprintf(stderr, "  -n          Redirect input from " _PATH_DEVNULL ".\n");
161        fprintf(stderr, "  -F config   Config file (default: ~/%s).\n",
162             _PATH_SSH_USER_CONFFILE);
163        fprintf(stderr, "  -A          Enable authentication agent forwarding.\n");
164        fprintf(stderr, "  -a          Disable authentication agent forwarding (default).\n");
165#if defined(AFS) || defined(KRB5)
166        fprintf(stderr, "  -k          Disable Kerberos ticket and AFS token forwarding.\n");
167#endif                          /* AFS */
168        fprintf(stderr, "  -X          Enable X11 connection forwarding.\n");
169        fprintf(stderr, "  -x          Disable X11 connection forwarding (default).\n");
170        fprintf(stderr, "  -i file     Identity for public key authentication "
171            "(default: ~/.ssh/identity)\n");
172#ifdef SMARTCARD
173        fprintf(stderr, "  -I reader   Set smartcard reader.\n");
174#endif
175        fprintf(stderr, "  -t          Tty; allocate a tty even if command is given.\n");
176        fprintf(stderr, "  -T          Do not allocate a tty.\n");
177        fprintf(stderr, "  -v          Verbose; display verbose debugging messages.\n");
178        fprintf(stderr, "              Multiple -v increases verbosity.\n");
179        fprintf(stderr, "  -V          Display version number only.\n");
180        fprintf(stderr, "  -q          Quiet; don't display any warning messages.\n");
181        fprintf(stderr, "  -f          Fork into background after authentication.\n");
182        fprintf(stderr, "  -e char     Set escape character; ``none'' = disable (default: ~).\n");
183
184        fprintf(stderr, "  -c cipher   Select encryption algorithm\n");
185        fprintf(stderr, "  -m macs     Specify MAC algorithms for protocol version 2.\n");
186        fprintf(stderr, "  -p port     Connect to this port.  Server must be on the same port.\n");
187        fprintf(stderr, "  -L listen-port:host:port   Forward local port to remote address\n");
188        fprintf(stderr, "  -R listen-port:host:port   Forward remote port to local address\n");
189        fprintf(stderr, "              These cause %s to listen for connections on a port, and\n", __progname);
190        fprintf(stderr, "              forward them to the other side by connecting to host:port.\n");
191        fprintf(stderr, "  -D port     Enable dynamic application-level port forwarding.\n");
192        fprintf(stderr, "  -C          Enable compression.\n");
193        fprintf(stderr, "  -N          Do not execute a shell or command.\n");
194        fprintf(stderr, "  -g          Allow remote hosts to connect to forwarded ports.\n");
195        fprintf(stderr, "  -1          Force protocol version 1.\n");
196        fprintf(stderr, "  -2          Force protocol version 2.\n");
197        fprintf(stderr, "  -4          Use IPv4 only.\n");
198        fprintf(stderr, "  -6          Use IPv6 only.\n");
199        fprintf(stderr, "  -o 'option' Process the option as if it was read from a configuration file.\n");
200        fprintf(stderr, "  -s          Invoke command (mandatory) as SSH2 subsystem.\n");
201        fprintf(stderr, "  -b addr     Local IP address.\n");
202        exit(1);
203}
204
205static int ssh_session(void);
206static int ssh_session2(void);
207static void load_public_identity_files(void);
208
209/*
210 * Main program for the ssh client.
211 */
212int
213main(int ac, char **av)
214{
215        int i, opt, exit_status;
216        u_short fwd_port, fwd_host_port;
217        char sfwd_port[6], sfwd_host_port[6];
218        char *p, *cp, buf[256];
219        struct stat st;
220        struct passwd *pw;
221        int dummy;
222        extern int optind, optreset;
223        extern char *optarg;
224
225        __progname = get_progname(av[0]);
226        init_rng();
227
228        /*
229         * Save the original real uid.  It will be needed later (uid-swapping
230         * may clobber the real uid).
231         */
232        original_real_uid = getuid();
233        original_effective_uid = geteuid();
234 
235        /*
236         * Use uid-swapping to give up root privileges for the duration of
237         * option processing.  We will re-instantiate the rights when we are
238         * ready to create the privileged port, and will permanently drop
239         * them when the port has been created (actually, when the connection
240         * has been made, as we may need to create the port several times).
241         */
242        PRIV_END;
243
244#ifdef HAVE_SETRLIMIT
245        /* If we are installed setuid root be careful to not drop core. */
246        if (original_real_uid != original_effective_uid) {
247                struct rlimit rlim;
248                rlim.rlim_cur = rlim.rlim_max = 0;
249                if (setrlimit(RLIMIT_CORE, &rlim) < 0)
250                        fatal("setrlimit failed: %.100s", strerror(errno));
251        }
252#endif
253        /* Get user data. */
254        pw = getpwuid(original_real_uid);
255        if (!pw) {
256                log("You don't exist, go away!");
257                exit(1);
258        }
259        /* Take a copy of the returned structure. */
260        pw = pwcopy(pw);
261
262        /*
263         * Set our umask to something reasonable, as some files are created
264         * with the default umask.  This will make them world-readable but
265         * writable only by the owner, which is ok for all files for which we
266         * don't set the modes explicitly.
267         */
268        umask(022);
269
270        /* Initialize option structure to indicate that no values have been set. */
271        initialize_options(&options);
272
273        /* Parse command-line arguments. */
274        host = NULL;
275
276again:
277        while ((opt = getopt(ac, av,
278            "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:NPR:TVX")) != -1) {
279                switch (opt) {
280                case '1':
281                        options.protocol = SSH_PROTO_1;
282                        break;
283                case '2':
284                        options.protocol = SSH_PROTO_2;
285                        break;
286                case '4':
287                        IPv4or6 = AF_INET;
288                        break;
289                case '6':
290                        IPv4or6 = AF_INET6;
291                        break;
292                case 'n':
293                        stdin_null_flag = 1;
294                        break;
295                case 'f':
296                        fork_after_authentication_flag = 1;
297                        stdin_null_flag = 1;
298                        break;
299                case 'x':
300                        options.forward_x11 = 0;
301                        break;
302                case 'X':
303                        options.forward_x11 = 1;
304                        break;
305                case 'g':
306                        options.gateway_ports = 1;
307                        break;
308                case 'P':       /* deprecated */
309                        options.use_privileged_port = 0;
310                        break;
311                case 'a':
312                        options.forward_agent = 0;
313                        break;
314                case 'A':
315                        options.forward_agent = 1;
316                        break;
317#if defined(AFS) || defined(KRB5) || defined(GSSAPI)
318                case 'k':
319#ifdef KRB5
320                        options.kerberos_tgt_passing = 0;
321#endif
322#ifdef AFS
323                        options.afs_token_passing = 0;
324#endif
325#ifdef GSSAPI
326                        options.gss_deleg_creds = 0;
327#endif
328                        break;
329#endif
330                case 'i':
331                        if (stat(optarg, &st) < 0) {
332                                fprintf(stderr, "Warning: Identity file %s "
333                                    "does not exist.\n", optarg);
334                                break;
335                        }
336                        if (options.num_identity_files >=
337                            SSH_MAX_IDENTITY_FILES)
338                                fatal("Too many identity files specified "
339                                    "(max %d)", SSH_MAX_IDENTITY_FILES);
340                        options.identity_files[options.num_identity_files++] =
341                            xstrdup(optarg);
342                        break;
343                case 'I':
344#ifdef SMARTCARD
345                        options.smartcard_device = xstrdup(optarg);
346#else
347                        fprintf(stderr, "no support for smartcards.\n");
348#endif
349                        break;
350                case 't':
351                        if (tty_flag)
352                                force_tty_flag = 1;
353                        tty_flag = 1;
354                        break;
355                case 'v':
356                        if (0 == debug_flag) {
357                                debug_flag = 1;
358                                options.log_level = SYSLOG_LEVEL_DEBUG1;
359                        } else if (options.log_level < SYSLOG_LEVEL_DEBUG3) {
360                                options.log_level++;
361                                break;
362                        } else
363                                fatal("Too high debugging level.");
364                        /* fallthrough */
365                case 'V':
366                        fprintf(stderr,
367                            "%s, SSH protocols %d.%d/%d.%d, OpenSSL 0x%8.8lx\n",
368                            SSH_VERSION,
369                            PROTOCOL_MAJOR_1, PROTOCOL_MINOR_1,
370                            PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2,
371                            SSLeay());
372                        if (opt == 'V')
373                                exit(0);
374                        break;
375                case 'q':
376                        options.log_level = SYSLOG_LEVEL_QUIET;
377                        break;
378                case 'e':
379                        if (optarg[0] == '^' && optarg[2] == 0 &&
380                            (u_char) optarg[1] >= 64 &&
381                            (u_char) optarg[1] < 128)
382                                options.escape_char = (u_char) optarg[1] & 31;
383                        else if (strlen(optarg) == 1)
384                                options.escape_char = (u_char) optarg[0];
385                        else if (strcmp(optarg, "none") == 0)
386                                options.escape_char = SSH_ESCAPECHAR_NONE;
387                        else {
388                                fprintf(stderr, "Bad escape character '%s'.\n",
389                                    optarg);
390                                exit(1);
391                        }
392                        break;
393                case 'c':
394                        if (ciphers_valid(optarg)) {
395                                /* SSH2 only */
396                                options.ciphers = xstrdup(optarg);
397                                options.cipher = SSH_CIPHER_ILLEGAL;
398                        } else {
399                                /* SSH1 only */
400                                options.cipher = cipher_number(optarg);
401                                if (options.cipher == -1) {
402                                        fprintf(stderr,
403                                            "Unknown cipher type '%s'\n",
404                                            optarg);
405                                        exit(1);
406                                }
407                                if (options.cipher == SSH_CIPHER_3DES)
408                                        options.ciphers = "3des-cbc";
409                                else if (options.cipher == SSH_CIPHER_BLOWFISH)
410                                        options.ciphers = "blowfish-cbc";
411                                else
412                                        options.ciphers = (char *)-1;
413                        }
414                        break;
415                case 'm':
416                        if (mac_valid(optarg))
417                                options.macs = xstrdup(optarg);
418                        else {
419                                fprintf(stderr, "Unknown mac type '%s'\n",
420                                    optarg);
421                                exit(1);
422                        }
423                        break;
424                case 'p':
425                        options.port = a2port(optarg);
426                        if (options.port == 0) {
427                                fprintf(stderr, "Bad port '%s'\n", optarg);
428                                exit(1);
429                        }
430                        break;
431                case 'l':
432                        options.user = optarg;
433                        break;
434
435                case 'L':
436                case 'R':
437                        if (sscanf(optarg, "%5[0-9]:%255[^:]:%5[0-9]",
438                            sfwd_port, buf, sfwd_host_port) != 3 &&
439                            sscanf(optarg, "%5[0-9]/%255[^/]/%5[0-9]",
440                            sfwd_port, buf, sfwd_host_port) != 3) {
441                                fprintf(stderr,
442                                    "Bad forwarding specification '%s'\n",
443                                    optarg);
444                                usage();
445                                /* NOTREACHED */
446                        }
447                        if ((fwd_port = a2port(sfwd_port)) == 0 ||
448                            (fwd_host_port = a2port(sfwd_host_port)) == 0) {
449                                fprintf(stderr,
450                                    "Bad forwarding port(s) '%s'\n", optarg);
451                                exit(1);
452                        }
453                        if (opt == 'L')
454                                add_local_forward(&options, fwd_port, buf,
455                                    fwd_host_port);
456                        else if (opt == 'R')
457                                add_remote_forward(&options, fwd_port, buf,
458                                    fwd_host_port);
459                        break;
460
461                case 'D':
462                        fwd_port = a2port(optarg);
463                        if (fwd_port == 0) {
464                                fprintf(stderr, "Bad dynamic port '%s'\n",
465                                    optarg);
466                                exit(1);
467                        }
468                        add_local_forward(&options, fwd_port, "socks4", 0);
469                        break;
470
471                case 'C':
472                        options.compression = 1;
473                        break;
474                case 'N':
475                        no_shell_flag = 1;
476                        no_tty_flag = 1;
477                        break;
478                case 'T':
479                        no_tty_flag = 1;
480                        break;
481                case 'o':
482                        dummy = 1;
483                        if (process_config_line(&options, host ? host : "",
484                            optarg, "command-line", 0, &dummy) != 0)
485                                exit(1);
486                        break;
487                case 's':
488                        subsystem_flag = 1;
489                        break;
490                case 'b':
491                        options.bind_address = optarg;
492                        break;
493                case 'F':
494                        config = optarg;
495                        break;
496                default:
497                        usage();
498                }
499        }
500
501        ac -= optind;
502        av += optind;
503
504        if (ac > 0 && !host && **av != '-') {
505                if (strchr(*av, '@')) {
506                        p = xstrdup(*av);
507                        cp = strchr(p, '@');
508                        if (cp == NULL || cp == p)
509                                usage();
510                        options.user = p;
511                        *cp = '\0';
512                        host = ++cp;
513                } else
514                        host = *av;
515                ac--, av++;
516                if (ac > 0) {
517                        optind = 0;
518                        optreset = 1;
519                        goto again;
520                }
521        }
522
523        /* Check that we got a host name. */
524        if (!host)
525                usage();
526
527        SSLeay_add_all_algorithms();
528        ERR_load_crypto_strings();
529        channel_set_af(IPv4or6);
530
531        /* Initialize the command to execute on remote host. */
532        buffer_init(&command);
533
534        /*
535         * Save the command to execute on the remote host in a buffer. There
536         * is no limit on the length of the command, except by the maximum
537         * packet size.  Also sets the tty flag if there is no command.
538         */
539        if (!ac) {
540                /* No command specified - execute shell on a tty. */
541                tty_flag = 1;
542                if (subsystem_flag) {
543                        fprintf(stderr,
544                            "You must specify a subsystem to invoke.\n");
545                        usage();
546                }
547        } else {
548                /* A command has been specified.  Store it into the buffer. */
549                for (i = 0; i < ac; i++) {
550                        if (i)
551                                buffer_append(&command, " ", 1);
552                        buffer_append(&command, av[i], strlen(av[i]));
553                }
554        }
555
556        /* Cannot fork to background if no command. */
557        if (fork_after_authentication_flag && buffer_len(&command) == 0 && !no_shell_flag)
558                fatal("Cannot fork into background without a command to execute.");
559
560        /* Allocate a tty by default if no command specified. */
561        if (buffer_len(&command) == 0)
562                tty_flag = 1;
563
564        /* Force no tty */
565        if (no_tty_flag)
566                tty_flag = 0;
567        /* Do not allocate a tty if stdin is not a tty. */
568        if (!isatty(fileno(stdin)) && !force_tty_flag) {
569                if (tty_flag)
570                        log("Pseudo-terminal will not be allocated because stdin is not a terminal.");
571                tty_flag = 0;
572        }
573
574        /*
575         * Initialize "log" output.  Since we are the client all output
576         * actually goes to stderr.
577         */
578        log_init(av[0], options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level,
579            SYSLOG_FACILITY_USER, 1);
580
581        /*
582         * Read per-user configuration file.  Ignore the system wide config
583         * file if the user specifies a config file on the command line.
584         */
585        if (config != NULL) {
586                if (!read_config_file(config, host, &options))
587                        fatal("Can't open user config file %.100s: "
588                            "%.100s", config, strerror(errno));
589        } else  {
590                snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir,
591                    _PATH_SSH_USER_CONFFILE);
592                (void)read_config_file(buf, host, &options);
593
594                /* Read systemwide configuration file after use config. */
595                (void)read_config_file(_PATH_HOST_CONFIG_FILE, host, &options);
596        }
597
598        /* Fill configuration defaults. */
599        fill_default_options(&options);
600
601        /* reinit */
602        log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 1);
603
604        seed_rng();
605
606        if (options.user == NULL)
607                options.user = xstrdup(pw->pw_name);
608
609        if (options.hostname != NULL)
610                host = options.hostname;
611
612        /* Disable rhosts authentication if not running as root. */
613#ifdef HAVE_CYGWIN
614        /* Ignore uid if running under Windows */
615        if (!options.use_privileged_port) {
616#else
617        if (original_effective_uid != 0 || !options.use_privileged_port) {
618#endif
619                debug("Rhosts Authentication disabled, "
620                    "originating port will not be trusted.");
621                options.rhosts_authentication = 0;
622        }
623        /* Open a connection to the remote host. */
624
625        if (ssh_connect(host, &hostaddr, options.port, IPv4or6,
626            options.connection_attempts,
627#ifdef HAVE_CYGWIN
628            options.use_privileged_port,
629#else
630            original_effective_uid == 0 && options.use_privileged_port,
631#endif
632            options.proxy_command) != 0)
633                exit(1);
634
635        /*
636         * If we successfully made the connection, load the host private key
637         * in case we will need it later for combined rsa-rhosts
638         * authentication. This must be done before releasing extra
639         * privileges, because the file is only readable by root.
640         * If we cannot access the private keys, load the public keys
641         * instead and try to execute the ssh-keysign helper instead.
642         */
643        sensitive_data.nkeys = 0;
644        sensitive_data.keys = NULL;
645        sensitive_data.external_keysign = 0;
646        if (options.rhosts_rsa_authentication ||
647            options.hostbased_authentication) {
648                sensitive_data.nkeys = 3;
649                sensitive_data.keys = xmalloc(sensitive_data.nkeys *
650                    sizeof(Key));
651
652                PRIV_START;
653                sensitive_data.keys[0] = key_load_private_type(KEY_RSA1,
654                    _PATH_HOST_KEY_FILE, "", NULL);
655                sensitive_data.keys[1] = key_load_private_type(KEY_DSA,
656                    _PATH_HOST_DSA_KEY_FILE, "", NULL);
657                sensitive_data.keys[2] = key_load_private_type(KEY_RSA,
658                    _PATH_HOST_RSA_KEY_FILE, "", NULL);
659                PRIV_END;
660
661                if (options.hostbased_authentication == 1 &&
662                    sensitive_data.keys[0] == NULL &&
663                    sensitive_data.keys[1] == NULL &&
664                    sensitive_data.keys[2] == NULL) {
665                        sensitive_data.keys[1] = key_load_public(
666                            _PATH_HOST_DSA_KEY_FILE, NULL);
667                        sensitive_data.keys[2] = key_load_public(
668                            _PATH_HOST_RSA_KEY_FILE, NULL);
669                        sensitive_data.external_keysign = 1;
670                }
671        }
672        /*
673         * Get rid of any extra privileges that we may have.  We will no
674         * longer need them.  Also, extra privileges could make it very hard
675         * to read identity files and other non-world-readable files from the
676         * user's home directory if it happens to be on a NFS volume where
677         * root is mapped to nobody.
678         */
679        seteuid(original_real_uid);
680        setuid(original_real_uid);
681
682        /*
683         * Now that we are back to our own permissions, create ~/.ssh
684         * directory if it doesn\'t already exist.
685         */
686        snprintf(buf, sizeof buf, "%.100s%s%.100s", pw->pw_dir, strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR);
687        if (stat(buf, &st) < 0)
688                if (mkdir(buf, 0700) < 0)
689                        error("Could not create directory '%.200s'.", buf);
690
691        /* load options.identity_files */
692        load_public_identity_files();
693
694        /* Expand ~ in known host file names. */
695        /* XXX mem-leaks: */
696        options.system_hostfile =
697            tilde_expand_filename(options.system_hostfile, original_real_uid);
698        options.user_hostfile =
699            tilde_expand_filename(options.user_hostfile, original_real_uid);
700        options.system_hostfile2 =
701            tilde_expand_filename(options.system_hostfile2, original_real_uid);
702        options.user_hostfile2 =
703            tilde_expand_filename(options.user_hostfile2, original_real_uid);
704
705        signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */
706
707        /* Log into the remote system.  This never returns if the login fails. */
708        ssh_login(&sensitive_data, host, (struct sockaddr *)&hostaddr, pw);
709
710        /* We no longer need the private host keys.  Clear them now. */
711        if (sensitive_data.nkeys != 0) {
712                for (i = 0; i < sensitive_data.nkeys; i++) {
713                        if (sensitive_data.keys[i] != NULL) {
714                                /* Destroys contents safely */
715                                debug3("clear hostkey %d", i);
716                                key_free(sensitive_data.keys[i]);
717                                sensitive_data.keys[i] = NULL;
718                        }
719                }
720                xfree(sensitive_data.keys);
721        }
722        for (i = 0; i < options.num_identity_files; i++) {
723                if (options.identity_files[i]) {
724                        xfree(options.identity_files[i]);
725                        options.identity_files[i] = NULL;
726                }
727                if (options.identity_keys[i]) {
728                        key_free(options.identity_keys[i]);
729                        options.identity_keys[i] = NULL;
730                }
731        }
732
733        exit_status = compat20 ? ssh_session2() : ssh_session();
734        packet_close();
735
736        /*
737         * Send SIGHUP to proxy command if used. We don't wait() in
738         * case it hangs and instead rely on init to reap the child
739         */
740        if (proxy_command_pid > 1)
741                kill(proxy_command_pid, SIGHUP);
742
743        return exit_status;
744}
745
746static void
747x11_get_proto(char **_proto, char **_data)
748{
749        char line[512];
750        static char proto[512], data[512];
751        FILE *f;
752        int got_data = 0, i;
753        char *display;
754        struct stat st;
755
756        *_proto = proto;
757        *_data = data;
758        proto[0] = data[0] = '\0';
759        if (!options.xauth_location ||
760            (stat(options.xauth_location, &st) == -1)) {
761                debug("No xauth program.");
762        } else {
763                if ((display = getenv("DISPLAY")) == NULL) {
764                        debug("x11_get_proto: DISPLAY not set");
765                        return;
766                }
767                /* Try to get Xauthority information for the display. */
768                if (strncmp(display, "localhost:", 10) == 0)
769                        /*
770                         * Handle FamilyLocal case where $DISPLAY does
771                         * not match an authorization entry.  For this we
772                         * just try "xauth list unix:displaynum.screennum".
773                         * XXX: "localhost" match to determine FamilyLocal
774                         *      is not perfect.
775                         */
776                        snprintf(line, sizeof line, "%s list unix:%s 2>"
777                            _PATH_DEVNULL, options.xauth_location, display+10);
778                else
779                        snprintf(line, sizeof line, "%s list %.200s 2>"
780                            _PATH_DEVNULL, options.xauth_location, display);
781                debug2("x11_get_proto: %s", line);
782                f = popen(line, "r");
783                if (f && fgets(line, sizeof(line), f) &&
784                    sscanf(line, "%*s %511s %511s", proto, data) == 2)
785                        got_data = 1;
786                if (f)
787                        pclose(f);
788        }
789        /*
790         * If we didn't get authentication data, just make up some
791         * data.  The forwarding code will check the validity of the
792         * response anyway, and substitute this data.  The X11
793         * server, however, will ignore this fake data and use
794         * whatever authentication mechanisms it was using otherwise
795         * for the local connection.
796         */
797        if (!got_data) {
798                u_int32_t rand = 0;
799
800                strlcpy(proto, "MIT-MAGIC-COOKIE-1", sizeof proto);
801                for (i = 0; i < 16; i++) {
802                        if (i % 4 == 0)
803                                rand = arc4random();
804                        snprintf(data + 2 * i, sizeof data - 2 * i, "%02x", rand & 0xff);
805                        rand >>= 8;
806                }
807        }
808}
809
810static void
811ssh_init_forwarding(void)
812{
813        int success = 0;
814        int i;
815
816        /* Initiate local TCP/IP port forwardings. */
817        for (i = 0; i < options.num_local_forwards; i++) {
818                debug("Connections to local port %d forwarded to remote address %.200s:%d",
819                    options.local_forwards[i].port,
820                    options.local_forwards[i].host,
821                    options.local_forwards[i].host_port);
822                success += channel_setup_local_fwd_listener(
823                    options.local_forwards[i].port,
824                    options.local_forwards[i].host,
825                    options.local_forwards[i].host_port,
826                    options.gateway_ports);
827        }
828        if (i > 0 && success == 0)
829                error("Could not request local forwarding.");
830
831        /* Initiate remote TCP/IP port forwardings. */
832        for (i = 0; i < options.num_remote_forwards; i++) {
833                debug("Connections to remote port %d forwarded to local address %.200s:%d",
834                    options.remote_forwards[i].port,
835                    options.remote_forwards[i].host,
836                    options.remote_forwards[i].host_port);
837                channel_request_remote_forwarding(
838                    options.remote_forwards[i].port,
839                    options.remote_forwards[i].host,
840                    options.remote_forwards[i].host_port);
841        }
842}
843
844static void
845check_agent_present(void)
846{
847        if (options.forward_agent) {
848                /* Clear agent forwarding if we don\'t have an agent. */
849                if (!ssh_agent_present())
850                        options.forward_agent = 0;
851        }
852}
853
854static int
855ssh_session(void)
856{
857        int type;
858        int interactive = 0;
859        int have_tty = 0;
860        struct winsize ws;
861        char *cp;
862
863        /* Enable compression if requested. */
864        if (options.compression) {
865                debug("Requesting compression at level %d.", options.compression_level);
866
867                if (options.compression_level < 1 || options.compression_level > 9)
868                        fatal("Compression level must be from 1 (fast) to 9 (slow, best).");
869
870                /* Send the request. */
871                packet_start(SSH_CMSG_REQUEST_COMPRESSION);
872                packet_put_int(options.compression_level);
873                packet_send();
874                packet_write_wait();
875                type = packet_read();
876                if (type == SSH_SMSG_SUCCESS)
877                        packet_start_compression(options.compression_level);
878                else if (type == SSH_SMSG_FAILURE)
879                        log("Warning: Remote host refused compression.");
880                else
881                        packet_disconnect("Protocol error waiting for compression response.");
882        }
883        /* Allocate a pseudo tty if appropriate. */
884        if (tty_flag) {
885                debug("Requesting pty.");
886
887                /* Start the packet. */
888                packet_start(SSH_CMSG_REQUEST_PTY);
889
890                /* Store TERM in the packet.  There is no limit on the
891                   length of the string. */
892                cp = getenv("TERM");
893                if (!cp)
894                        cp = "";
895                packet_put_cstring(cp);
896
897                /* Store window size in the packet. */
898                if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
899                        memset(&ws, 0, sizeof(ws));
900                packet_put_int(ws.ws_row);
901                packet_put_int(ws.ws_col);
902                packet_put_int(ws.ws_xpixel);
903                packet_put_int(ws.ws_ypixel);
904
905                /* Store tty modes in the packet. */
906                tty_make_modes(fileno(stdin), NULL);
907
908                /* Send the packet, and wait for it to leave. */
909                packet_send();
910                packet_write_wait();
911
912                /* Read response from the server. */
913                type = packet_read();
914                if (type == SSH_SMSG_SUCCESS) {
915                        interactive = 1;
916                        have_tty = 1;
917                } else if (type == SSH_SMSG_FAILURE)
918                        log("Warning: Remote host failed or refused to allocate a pseudo tty.");
919                else
920                        packet_disconnect("Protocol error waiting for pty request response.");
921        }
922        /* Request X11 forwarding if enabled and DISPLAY is set. */
923        if (options.forward_x11 && getenv("DISPLAY") != NULL) {
924                char *proto, *data;
925                /* Get reasonable local authentication information. */
926                x11_get_proto(&proto, &data);
927                /* Request forwarding with authentication spoofing. */
928                debug("Requesting X11 forwarding with authentication spoofing.");
929                x11_request_forwarding_with_spoofing(0, proto, data);
930
931                /* Read response from the server. */
932                type = packet_read();
933                if (type == SSH_SMSG_SUCCESS) {
934                        interactive = 1;
935                } else if (type == SSH_SMSG_FAILURE) {
936                        log("Warning: Remote host denied X11 forwarding.");
937                } else {
938                        packet_disconnect("Protocol error waiting for X11 forwarding");
939                }
940        }
941        /* Tell the packet module whether this is an interactive session. */
942        packet_set_interactive(interactive);
943
944        /* Request authentication agent forwarding if appropriate. */
945        check_agent_present();
946
947        if (options.forward_agent) {
948                debug("Requesting authentication agent forwarding.");
949                auth_request_forwarding();
950
951                /* Read response from the server. */
952                type = packet_read();
953                packet_check_eom();
954                if (type != SSH_SMSG_SUCCESS)
955                        log("Warning: Remote host denied authentication agent forwarding.");
956        }
957
958        /* Initiate port forwardings. */
959        ssh_init_forwarding();
960
961        /* If requested, let ssh continue in the background. */
962        if (fork_after_authentication_flag)
963                if (daemon(1, 1) < 0)
964                        fatal("daemon() failed: %.200s", strerror(errno));
965
966        /*
967         * If a command was specified on the command line, execute the
968         * command now. Otherwise request the server to start a shell.
969         */
970        if (buffer_len(&command) > 0) {
971                int len = buffer_len(&command);
972                if (len > 900)
973                        len = 900;
974                debug("Sending command: %.*s", len, (u_char *)buffer_ptr(&command));
975                packet_start(SSH_CMSG_EXEC_CMD);
976                packet_put_string(buffer_ptr(&command), buffer_len(&command));
977                packet_send();
978                packet_write_wait();
979        } else {
980                debug("Requesting shell.");
981                packet_start(SSH_CMSG_EXEC_SHELL);
982                packet_send();
983                packet_write_wait();
984        }
985
986        /* Enter the interactive session. */
987        return client_loop(have_tty, tty_flag ?
988            options.escape_char : SSH_ESCAPECHAR_NONE, 0);
989}
990
991static void
992client_subsystem_reply(int type, u_int32_t seq, void *ctxt)
993{
994        int id, len;
995
996        id = packet_get_int();
997        len = buffer_len(&command);
998        if (len > 900)
999                len = 900;
1000        packet_check_eom();
1001        if (type == SSH2_MSG_CHANNEL_FAILURE)
1002                fatal("Request for subsystem '%.*s' failed on channel %d",
1003                    len, (u_char *)buffer_ptr(&command), id);
1004}
1005
1006void
1007client_global_request_reply(int type, u_int32_t seq, void *ctxt)
1008{
1009        int i;
1010
1011        i = client_global_request_id++;
1012        if (i >= options.num_remote_forwards) {
1013                debug("client_global_request_reply: too many replies %d > %d",
1014                    i, options.num_remote_forwards);
1015                return;
1016        }
1017        debug("remote forward %s for: listen %d, connect %s:%d",
1018            type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
1019            options.remote_forwards[i].port,
1020            options.remote_forwards[i].host,
1021            options.remote_forwards[i].host_port);
1022        if (type == SSH2_MSG_REQUEST_FAILURE)
1023                log("Warning: remote port forwarding failed for listen port %d",
1024                    options.remote_forwards[i].port);
1025}
1026
1027/* request pty/x11/agent/tcpfwd/shell for channel */
1028static void
1029ssh_session2_setup(int id, void *arg)
1030{
1031        int len;
1032        int interactive = 0;
1033        struct termios tio;
1034
1035        debug("ssh_session2_setup: id %d", id);
1036
1037        if (tty_flag) {
1038                struct winsize ws;
1039                char *cp;
1040                cp = getenv("TERM");
1041                if (!cp)
1042                        cp = "";
1043                /* Store window size in the packet. */
1044                if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
1045                        memset(&ws, 0, sizeof(ws));
1046
1047                channel_request_start(id, "pty-req", 0);
1048                packet_put_cstring(cp);
1049                packet_put_int(ws.ws_col);
1050                packet_put_int(ws.ws_row);
1051                packet_put_int(ws.ws_xpixel);
1052                packet_put_int(ws.ws_ypixel);
1053                tio = get_saved_tio();
1054                tty_make_modes(/*ignored*/ 0, &tio);
1055                packet_send();
1056                interactive = 1;
1057                /* XXX wait for reply */
1058        }
1059        if (options.forward_x11 &&
1060            getenv("DISPLAY") != NULL) {
1061                char *proto, *data;
1062                /* Get reasonable local authentication information. */
1063                x11_get_proto(&proto, &data);
1064                /* Request forwarding with authentication spoofing. */
1065                debug("Requesting X11 forwarding with authentication spoofing.");
1066                x11_request_forwarding_with_spoofing(id, proto, data);
1067                interactive = 1;
1068                /* XXX wait for reply */
1069        }
1070
1071        check_agent_present();
1072        if (options.forward_agent) {
1073                debug("Requesting authentication agent forwarding.");
1074                channel_request_start(id, "auth-agent-req@openssh.com", 0);
1075                packet_send();
1076        }
1077
1078        len = buffer_len(&command);
1079        if (len > 0) {
1080                if (len > 900)
1081                        len = 900;
1082                if (subsystem_flag) {
1083                        debug("Sending subsystem: %.*s", len, (u_char *)buffer_ptr(&command));
1084                        channel_request_start(id, "subsystem", /*want reply*/ 1);
1085                        /* register callback for reply */
1086                        /* XXX we assume that client_loop has already been called */
1087                        dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &client_subsystem_reply);
1088                        dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &client_subsystem_reply);
1089                } else {
1090                        debug("Sending command: %.*s", len, (u_char *)buffer_ptr(&command));
1091                        channel_request_start(id, "exec", 0);
1092                }
1093                packet_put_string(buffer_ptr(&command), buffer_len(&command));
1094                packet_send();
1095        } else {
1096                channel_request_start(id, "shell", 0);
1097                packet_send();
1098        }
1099
1100        packet_set_interactive(interactive);
1101}
1102
1103/* open new channel for a session */
1104static int
1105ssh_session2_open(void)
1106{
1107        Channel *c;
1108        int window, packetmax, in, out, err;
1109
1110        if (stdin_null_flag) {
1111                in = open(_PATH_DEVNULL, O_RDONLY);
1112        } else {
1113                in = dup(STDIN_FILENO);
1114        }
1115        out = dup(STDOUT_FILENO);
1116        err = dup(STDERR_FILENO);
1117
1118        if (in < 0 || out < 0 || err < 0)
1119                fatal("dup() in/out/err failed");
1120
1121        /* enable nonblocking unless tty */
1122        if (!isatty(in))
1123                set_nonblock(in);
1124        if (!isatty(out))
1125                set_nonblock(out);
1126        if (!isatty(err))
1127                set_nonblock(err);
1128
1129        window = CHAN_SES_WINDOW_DEFAULT;
1130        packetmax = CHAN_SES_PACKET_DEFAULT;
1131        if (tty_flag) {
1132                window >>= 1;
1133                packetmax >>= 1;
1134        }
1135        c = channel_new(
1136            "session", SSH_CHANNEL_OPENING, in, out, err,
1137            window, packetmax, CHAN_EXTENDED_WRITE,
1138            xstrdup("client-session"), /*nonblock*/0);
1139
1140        debug3("ssh_session2_open: channel_new: %d", c->self);
1141
1142        channel_send_open(c->self);
1143        if (!no_shell_flag)
1144                channel_register_confirm(c->self, ssh_session2_setup);
1145
1146        return c->self;
1147}
1148
1149static int
1150ssh_session2(void)
1151{
1152        int id = -1;
1153
1154        /* XXX should be pre-session */
1155        ssh_init_forwarding();
1156
1157        if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN))
1158                id = ssh_session2_open();
1159
1160        /* If requested, let ssh continue in the background. */
1161        if (fork_after_authentication_flag)
1162                if (daemon(1, 1) < 0)
1163                        fatal("daemon() failed: %.200s", strerror(errno));
1164
1165        return client_loop(tty_flag, tty_flag ?
1166            options.escape_char : SSH_ESCAPECHAR_NONE, id);
1167}
1168
1169static void
1170load_public_identity_files(void)
1171{
1172        char *filename;
1173        int i = 0;
1174        Key *public;
1175#ifdef SMARTCARD
1176        Key **keys;
1177
1178        if (options.smartcard_device != NULL &&
1179            options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
1180            (keys = sc_get_keys(options.smartcard_device, NULL)) != NULL ) {
1181                int count = 0;
1182                for (i = 0; keys[i] != NULL; i++) {
1183                        count++;
1184                        memmove(&options.identity_files[1], &options.identity_files[0],
1185                            sizeof(char *) * (SSH_MAX_IDENTITY_FILES - 1));
1186                        memmove(&options.identity_keys[1], &options.identity_keys[0],
1187                            sizeof(Key *) * (SSH_MAX_IDENTITY_FILES - 1));
1188                        options.num_identity_files++;
1189                        options.identity_keys[0] = keys[i];
1190                        options.identity_files[0] = xstrdup("smartcard key");;
1191                }
1192                if (options.num_identity_files > SSH_MAX_IDENTITY_FILES)
1193                        options.num_identity_files = SSH_MAX_IDENTITY_FILES;
1194                i = count;
1195                xfree(keys);
1196        }
1197#endif /* SMARTCARD */
1198        for (; i < options.num_identity_files; i++) {
1199                filename = tilde_expand_filename(options.identity_files[i],
1200                    original_real_uid);
1201                public = key_load_public(filename, NULL);
1202                debug("identity file %s type %d", filename,
1203                    public ? public->type : -1);
1204                xfree(options.identity_files[i]);
1205                options.identity_files[i] = filename;
1206                options.identity_keys[i] = public;
1207        }
1208}
Note: See TracBrowser for help on using the repository browser.