]> andersk Git - openssh.git/blobdiff - ssh.c
- markus@cvs.openbsd.org 2003/12/16 15:49:51
[openssh.git] / ssh.c
diff --git a/ssh.c b/ssh.c
index be9c78b0fc28f1fa865ea4ac4d335f50a26c2949..da390c12db429c7eed60364f7b8a210a5871bcf7 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -13,7 +13,7 @@
  * called by a name other than "ssh" or "Secure Shell".
  *
  * Copyright (c) 1999 Niels Provos.  All rights reserved.
- * Copyright (c) 2000, 2001, 2002 Markus Friedl.  All rights reserved.
+ * Copyright (c) 2000, 2001, 2002, 2003 Markus Friedl.  All rights reserved.
  *
  * Modified to work with SSL by Niels Provos <provos@citi.umich.edu>
  * in Canada (German citizen).
@@ -40,7 +40,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: ssh.c,v 1.177 2002/06/11 04:14:26 markus Exp $");
+RCSID("$OpenBSD: ssh.c,v 1.206 2003/12/16 15:49:51 markus Exp $");
 
 #include <openssl/evp.h>
 #include <openssl/err.h>
@@ -79,14 +79,6 @@ extern char *__progname;
 char *__progname;
 #endif
 
-/* Flag indicating whether IPv4 or IPv6.  This can be set on the command line.
-   Default value is AF_UNSPEC means both IPv4 and IPv6. */
-#ifdef IPV4_DEFAULT
-int IPv4or6 = AF_INET;
-#else
-int IPv4or6 = AF_UNSPEC;
-#endif
-
 /* Flag indicating whether debug mode is on.  This can be set on the command line. */
 int debug_flag = 0;
 
@@ -146,6 +138,9 @@ int subsystem_flag = 0;
 /* # of replies received for global requests */
 static int client_global_request_id = 0;
 
+/* pid of proxycommand child process */
+pid_t proxy_command_pid = 0;
+
 /* Prints a help message to the user.  This function never returns. */
 
 static void
@@ -159,10 +154,8 @@ usage(void)
             _PATH_SSH_USER_CONFFILE);
        fprintf(stderr, "  -A          Enable authentication agent forwarding.\n");
        fprintf(stderr, "  -a          Disable authentication agent forwarding (default).\n");
-#ifdef AFS
-       fprintf(stderr, "  -k          Disable Kerberos ticket and AFS token forwarding.\n");
-#endif                         /* AFS */
        fprintf(stderr, "  -X          Enable X11 connection forwarding.\n");
+       fprintf(stderr, "  -Y          Enable trusted X11 connection forwarding.\n");
        fprintf(stderr, "  -x          Disable X11 connection forwarding (default).\n");
        fprintf(stderr, "  -i file     Identity for public key authentication "
            "(default: ~/.ssh/identity)\n");
@@ -174,7 +167,6 @@ usage(void)
        fprintf(stderr, "  -v          Verbose; display verbose debugging messages.\n");
        fprintf(stderr, "              Multiple -v increases verbosity.\n");
        fprintf(stderr, "  -V          Display version number only.\n");
-       fprintf(stderr, "  -P          Don't allocate a privileged port.\n");
        fprintf(stderr, "  -q          Quiet; don't display any warning messages.\n");
        fprintf(stderr, "  -f          Fork into background after authentication.\n");
        fprintf(stderr, "  -e char     Set escape character; ``none'' = disable (default: ~).\n");
@@ -210,17 +202,17 @@ static void load_public_identity_files(void);
 int
 main(int ac, char **av)
 {
-       int i, opt, exit_status, cerr;
+       int i, opt, exit_status;
        u_short fwd_port, fwd_host_port;
        char sfwd_port[6], sfwd_host_port[6];
-       char *p, *cp, buf[256];
+       char *p, *cp, *line, buf[256];
        struct stat st;
        struct passwd *pw;
        int dummy;
        extern int optind, optreset;
        extern char *optarg;
 
-       __progname = get_progname(av[0]);
+       __progname = ssh_get_progname(av[0]);
        init_rng();
 
        /*
@@ -230,6 +222,15 @@ main(int ac, char **av)
        original_real_uid = getuid();
        original_effective_uid = geteuid();
 
+       /*
+        * Use uid-swapping to give up root privileges for the duration of
+        * option processing.  We will re-instantiate the rights when we are
+        * ready to create the privileged port, and will permanently drop
+        * them when the port has been created (actually, when the connection
+        * has been made, as we may need to create the port several times).
+        */
+       PRIV_END;
+
 #ifdef HAVE_SETRLIMIT
        /* If we are installed setuid root be careful to not drop core. */
        if (original_real_uid != original_effective_uid) {
@@ -242,21 +243,12 @@ main(int ac, char **av)
        /* Get user data. */
        pw = getpwuid(original_real_uid);
        if (!pw) {
-               log("You don't exist, go away!");
+               logit("You don't exist, go away!");
                exit(1);
        }
        /* Take a copy of the returned structure. */
        pw = pwcopy(pw);
 
-       /*
-        * Use uid-swapping to give up root privileges for the duration of
-        * option processing.  We will re-instantiate the rights when we are
-        * ready to create the privileged port, and will permanently drop
-        * them when the port has been created (actually, when the connection
-        * has been made, as we may need to create the port several times).
-        */
-       PRIV_END;
-
        /*
         * Set our umask to something reasonable, as some files are created
         * with the default umask.  This will make them world-readable but
@@ -273,7 +265,7 @@ main(int ac, char **av)
 
 again:
        while ((opt = getopt(ac, av,
-           "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:NPR:TVX")) != -1) {
+           "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:NPR:TVXY")) != -1) {
                switch (opt) {
                case '1':
                        options.protocol = SSH_PROTO_1;
@@ -282,10 +274,10 @@ again:
                        options.protocol = SSH_PROTO_2;
                        break;
                case '4':
-                       IPv4or6 = AF_INET;
+                       options.address_family = AF_INET;
                        break;
                case '6':
-                       IPv4or6 = AF_INET6;
+                       options.address_family = AF_INET6;
                        break;
                case 'n':
                        stdin_null_flag = 1;
@@ -300,10 +292,14 @@ again:
                case 'X':
                        options.forward_x11 = 1;
                        break;
+               case 'Y':
+                       options.forward_x11 = 1;
+                       options.forward_x11_trusted = 1;
+                       break;
                case 'g':
                        options.gateway_ports = 1;
                        break;
-               case 'P':
+               case 'P':       /* deprecated */
                        options.use_privileged_port = 0;
                        break;
                case 'a':
@@ -312,12 +308,9 @@ again:
                case 'A':
                        options.forward_agent = 1;
                        break;
-#ifdef AFS
                case 'k':
-                       options.kerberos_tgt_passing = 0;
-                       options.afs_token_passing = 0;
+                       options.gss_deleg_creds = 0;
                        break;
-#endif
                case 'i':
                        if (stat(optarg, &st) < 0) {
                                fprintf(stderr, "Warning: Identity file %s "
@@ -344,22 +337,22 @@ again:
                        tty_flag = 1;
                        break;
                case 'v':
-                       if (0 == debug_flag) {
+                       if (debug_flag == 0) {
                                debug_flag = 1;
                                options.log_level = SYSLOG_LEVEL_DEBUG1;
-                       } else if (options.log_level < SYSLOG_LEVEL_DEBUG3) {
-                               options.log_level++;
+                       } else {
+                               if (options.log_level < SYSLOG_LEVEL_DEBUG3)
+                                       options.log_level++;
                                break;
-                       } else
-                               fatal("Too high debugging level.");
+                       }
                        /* fallthrough */
                case 'V':
                        fprintf(stderr,
-                           "%s, SSH protocols %d.%d/%d.%d, OpenSSL 0x%8.8lx\n",
+                           "%s, SSH protocols %d.%d/%d.%d, %s\n",
                            SSH_VERSION,
                            PROTOCOL_MAJOR_1, PROTOCOL_MINOR_1,
                            PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2,
-                           SSLeay());
+                           SSLeay_version(SSLEAY_VERSION));
                        if (opt == 'V')
                                exit(0);
                        break;
@@ -425,9 +418,9 @@ again:
 
                case 'L':
                case 'R':
-                       if (sscanf(optarg, "%5[0-9]:%255[^:]:%5[0-9]",
+                       if (sscanf(optarg, "%5[0123456789]:%255[^:]:%5[0123456789]",
                            sfwd_port, buf, sfwd_host_port) != 3 &&
-                           sscanf(optarg, "%5[0-9]/%255[^/]/%5[0-9]",
+                           sscanf(optarg, "%5[0123456789]/%255[^/]/%5[0123456789]",
                            sfwd_port, buf, sfwd_host_port) != 3) {
                                fprintf(stderr,
                                    "Bad forwarding specification '%s'\n",
@@ -456,7 +449,7 @@ again:
                                    optarg);
                                exit(1);
                        }
-                       add_local_forward(&options, fwd_port, "socks4", 0);
+                       add_local_forward(&options, fwd_port, "socks", 0);
                        break;
 
                case 'C':
@@ -471,9 +464,11 @@ again:
                        break;
                case 'o':
                        dummy = 1;
+                       line = xstrdup(optarg);
                        if (process_config_line(&options, host ? host : "",
-                           optarg, "command-line", 0, &dummy) != 0)
+                           line, "command-line", 0, &dummy) != 0)
                                exit(1);
+                       xfree(line);
                        break;
                case 's':
                        subsystem_flag = 1;
@@ -493,9 +488,9 @@ again:
        av += optind;
 
        if (ac > 0 && !host && **av != '-') {
-               if (strchr(*av, '@')) {
+               if (strrchr(*av, '@')) {
                        p = xstrdup(*av);
-                       cp = strchr(p, '@');
+                       cp = strrchr(p, '@');
                        if (cp == NULL || cp == p)
                                usage();
                        options.user = p;
@@ -503,12 +498,11 @@ again:
                        host = ++cp;
                } else
                        host = *av;
-               ac--, av++;
-               if (ac > 0) {
-                       optind = 0;
-                       optreset = 1;
+               if (ac > 1) {
+                       optind = optreset = 1;
                        goto again;
                }
+               ac--, av++;
        }
 
        /* Check that we got a host name. */
@@ -517,7 +511,6 @@ again:
 
        SSLeay_add_all_algorithms();
        ERR_load_crypto_strings();
-       channel_set_af(IPv4or6);
 
        /* Initialize the command to execute on remote host. */
        buffer_init(&command);
@@ -552,13 +545,13 @@ again:
        if (buffer_len(&command) == 0)
                tty_flag = 1;
 
-       /* Force no tty*/
+       /* Force no tty */
        if (no_tty_flag)
                tty_flag = 0;
        /* Do not allocate a tty if stdin is not a tty. */
        if (!isatty(fileno(stdin)) && !force_tty_flag) {
                if (tty_flag)
-                       log("Pseudo-terminal will not be allocated because stdin is not a terminal.");
+                       logit("Pseudo-terminal will not be allocated because stdin is not a terminal.");
                tty_flag = 0;
        }
 
@@ -589,6 +582,8 @@ again:
        /* Fill configuration defaults. */
        fill_default_options(&options);
 
+       channel_set_af(options.address_family);
+
        /* reinit */
        log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 1);
 
@@ -600,27 +595,27 @@ again:
        if (options.hostname != NULL)
                host = options.hostname;
 
-       /* Disable rhosts authentication if not running as root. */
-#ifdef HAVE_CYGWIN
-       /* Ignore uid if running under Windows */
-       if (!options.use_privileged_port) {
-#else
-       if (original_effective_uid != 0 || !options.use_privileged_port) {
-#endif
-               debug("Rhosts Authentication disabled, "
-                   "originating port will not be trusted.");
-               options.rhosts_authentication = 0;
+       /* force lowercase for hostkey matching */
+       if (options.host_key_alias != NULL) {
+               for (p = options.host_key_alias; *p; p++)
+                       if (isupper(*p))
+                               *p = tolower(*p);
        }
-       /* Open a connection to the remote host. */
 
-       cerr = ssh_connect(host, &hostaddr, options.port, IPv4or6,
-           options.connection_attempts,
+       if (options.proxy_command != NULL &&
+           strcmp(options.proxy_command, "none") == 0)
+               options.proxy_command = NULL;
+
+       /* Open a connection to the remote host. */
+       if (ssh_connect(host, &hostaddr, options.port,
+           options.address_family, options.connection_attempts,
 #ifdef HAVE_CYGWIN
            options.use_privileged_port,
 #else
            original_effective_uid == 0 && options.use_privileged_port,
 #endif
-           options.proxy_command);
+           options.proxy_command) != 0)
+               exit(1);
 
        /*
         * If we successfully made the connection, load the host private key
@@ -633,10 +628,11 @@ again:
        sensitive_data.nkeys = 0;
        sensitive_data.keys = NULL;
        sensitive_data.external_keysign = 0;
-       if (!cerr && (options.rhosts_rsa_authentication ||
-           options.hostbased_authentication)) {
+       if (options.rhosts_rsa_authentication ||
+           options.hostbased_authentication) {
                sensitive_data.nkeys = 3;
-               sensitive_data.keys = xmalloc(sensitive_data.nkeys*sizeof(Key));
+               sensitive_data.keys = xmalloc(sensitive_data.nkeys *
+                   sizeof(Key));
 
                PRIV_START;
                sensitive_data.keys[0] = key_load_private_type(KEY_RSA1,
@@ -647,7 +643,8 @@ again:
                    _PATH_HOST_RSA_KEY_FILE, "", NULL);
                PRIV_END;
 
-               if (sensitive_data.keys[0] == NULL &&
+               if (options.hostbased_authentication == 1 &&
+                   sensitive_data.keys[0] == NULL &&
                    sensitive_data.keys[1] == NULL &&
                    sensitive_data.keys[2] == NULL) {
                        sensitive_data.keys[1] = key_load_public(
@@ -676,9 +673,6 @@ again:
                if (mkdir(buf, 0700) < 0)
                        error("Could not create directory '%.200s'.", buf);
 
-       if (cerr)
-               exit(1);
-
        /* load options.identity_files */
        load_public_identity_files();
 
@@ -723,44 +717,97 @@ again:
 
        exit_status = compat20 ? ssh_session2() : ssh_session();
        packet_close();
+
+       /*
+        * Send SIGHUP to proxy command if used. We don't wait() in
+        * case it hangs and instead rely on init to reap the child
+        */
+       if (proxy_command_pid > 1)
+               kill(proxy_command_pid, SIGHUP);
+
        return exit_status;
 }
 
+#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1"
+
 static void
 x11_get_proto(char **_proto, char **_data)
 {
+       char cmd[1024];
        char line[512];
+       char xdisplay[512];
        static char proto[512], data[512];
        FILE *f;
-       int got_data = 0, i;
-       char *display;
+       int got_data = 0, generated = 0, do_unlink = 0, i;
+       char *display, *xauthdir, *xauthfile;
+       struct stat st;
 
+       xauthdir = xauthfile = NULL;
        *_proto = proto;
        *_data = data;
        proto[0] = data[0] = '\0';
-       if (options.xauth_location && (display = getenv("DISPLAY"))) {
-               /* Try to get Xauthority information for the display. */
-               if (strncmp(display, "localhost:", 10) == 0)
-                       /*
-                        * Handle FamilyLocal case where $DISPLAY does
-                        * not match an authorization entry.  For this we
-                        * just try "xauth list unix:displaynum.screennum".
-                        * XXX: "localhost" match to determine FamilyLocal
-                        *      is not perfect.
-                        */
-                       snprintf(line, sizeof line, "%s list unix:%s 2>"
-                           _PATH_DEVNULL, options.xauth_location, display+10);
-               else
-                       snprintf(line, sizeof line, "%s list %.200s 2>"
-                           _PATH_DEVNULL, options.xauth_location, display);
-               debug2("x11_get_proto %s", line);
-               f = popen(line, "r");
+
+       if (!options.xauth_location ||
+           (stat(options.xauth_location, &st) == -1)) {
+               debug("No xauth program.");
+       } else {
+               if ((display = getenv("DISPLAY")) == NULL) {
+                       debug("x11_get_proto: DISPLAY not set");
+                       return;
+               }
+               /*
+                * Handle FamilyLocal case where $DISPLAY does
+                * not match an authorization entry.  For this we
+                * just try "xauth list unix:displaynum.screennum".
+                * XXX: "localhost" match to determine FamilyLocal
+                *      is not perfect.
+                */
+               if (strncmp(display, "localhost:", 10) == 0) {
+                       snprintf(xdisplay, sizeof(xdisplay), "unix:%s",
+                           display + 10);
+                       display = xdisplay;
+               }
+               if (options.forward_x11_trusted == 0) {
+                       xauthdir = xmalloc(MAXPATHLEN);
+                       xauthfile = xmalloc(MAXPATHLEN);
+                       strlcpy(xauthdir, "/tmp/ssh-XXXXXXXXXX", MAXPATHLEN);
+                       if (mkdtemp(xauthdir) != NULL) {
+                               do_unlink = 1;
+                               snprintf(xauthfile, MAXPATHLEN, "%s/xauthfile",
+                                   xauthdir);
+                               snprintf(cmd, sizeof(cmd),
+                                   "%s -f %s generate %s " SSH_X11_PROTO
+                                   " untrusted timeout 120 2>" _PATH_DEVNULL,
+                                   options.xauth_location, xauthfile, display);
+                               debug2("x11_get_proto: %s", cmd);
+                               if (system(cmd) == 0)
+                                       generated = 1;
+                       }
+               }
+               snprintf(cmd, sizeof(cmd),
+                   "%s %s%s list %s . 2>" _PATH_DEVNULL,
+                   options.xauth_location,
+                   generated ? "-f " : "" ,
+                   generated ? xauthfile : "",
+                   display);
+               debug2("x11_get_proto: %s", cmd);
+               f = popen(cmd, "r");
                if (f && fgets(line, sizeof(line), f) &&
                    sscanf(line, "%*s %511s %511s", proto, data) == 2)
                        got_data = 1;
                if (f)
                        pclose(f);
        }
+
+       if (do_unlink) {
+               unlink(xauthfile);
+               rmdir(xauthdir);
+       }
+       if (xauthdir)
+               xfree(xauthdir);
+       if (xauthfile)
+               xfree(xauthfile);
+
        /*
         * If we didn't get authentication data, just make up some
         * data.  The forwarding code will check the validity of the
@@ -772,11 +819,14 @@ x11_get_proto(char **_proto, char **_data)
        if (!got_data) {
                u_int32_t rand = 0;
 
-               strlcpy(proto, "MIT-MAGIC-COOKIE-1", sizeof proto);
+               logit("Warning: No xauth data; "
+                   "using fake authentication data for X11 forwarding.");
+               strlcpy(proto, SSH_X11_PROTO, sizeof proto);
                for (i = 0; i < 16; i++) {
                        if (i % 4 == 0)
                                rand = arc4random();
-                       snprintf(data + 2 * i, sizeof data - 2 * i, "%02x", rand & 0xff);
+                       snprintf(data + 2 * i, sizeof data - 2 * i, "%02x",
+                           rand & 0xff);
                        rand >>= 8;
                }
        }
@@ -821,11 +871,8 @@ check_agent_present(void)
 {
        if (options.forward_agent) {
                /* Clear agent forwarding if we don\'t have an agent. */
-               int authfd = ssh_get_authentication_socket();
-               if (authfd < 0)
+               if (!ssh_agent_present())
                        options.forward_agent = 0;
-               else
-                       ssh_close_authentication_socket(authfd);
        }
 }
 
@@ -854,7 +901,7 @@ ssh_session(void)
                if (type == SSH_SMSG_SUCCESS)
                        packet_start_compression(options.compression_level);
                else if (type == SSH_SMSG_FAILURE)
-                       log("Warning: Remote host refused compression.");
+                       logit("Warning: Remote host refused compression.");
                else
                        packet_disconnect("Protocol error waiting for compression response.");
        }
@@ -893,7 +940,7 @@ ssh_session(void)
                        interactive = 1;
                        have_tty = 1;
                } else if (type == SSH_SMSG_FAILURE)
-                       log("Warning: Remote host failed or refused to allocate a pseudo tty.");
+                       logit("Warning: Remote host failed or refused to allocate a pseudo tty.");
                else
                        packet_disconnect("Protocol error waiting for pty request response.");
        }
@@ -911,7 +958,7 @@ ssh_session(void)
                if (type == SSH_SMSG_SUCCESS) {
                        interactive = 1;
                } else if (type == SSH_SMSG_FAILURE) {
-                       log("Warning: Remote host denied X11 forwarding.");
+                       logit("Warning: Remote host denied X11 forwarding.");
                } else {
                        packet_disconnect("Protocol error waiting for X11 forwarding");
                }
@@ -930,7 +977,7 @@ ssh_session(void)
                type = packet_read();
                packet_check_eom();
                if (type != SSH_SMSG_SUCCESS)
-                       log("Warning: Remote host denied authentication agent forwarding.");
+                       logit("Warning: Remote host denied authentication agent forwarding.");
        }
 
        /* Initiate port forwardings. */
@@ -982,23 +1029,20 @@ client_subsystem_reply(int type, u_int32_t seq, void *ctxt)
 }
 
 void
-client_global_request_reply(int type, u_int32_t seq, void *ctxt)
+client_global_request_reply_fwd(int type, u_int32_t seq, void *ctxt)
 {
        int i;
 
        i = client_global_request_id++;
-       if (i >= options.num_remote_forwards) {
-               debug("client_global_request_reply: too many replies %d > %d",
-                   i, options.num_remote_forwards);
+       if (i >= options.num_remote_forwards)
                return;
-       }
        debug("remote forward %s for: listen %d, connect %s:%d",
            type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
            options.remote_forwards[i].port,
            options.remote_forwards[i].host,
            options.remote_forwards[i].host_port);
        if (type == SSH2_MSG_REQUEST_FAILURE)
-               log("Warning: remote port forwarding failed for listen port %d",
+               logit("Warning: remote port forwarding failed for listen port %d",
                    options.remote_forwards[i].port);
 }
 
@@ -1010,7 +1054,7 @@ ssh_session2_setup(int id, void *arg)
        int interactive = 0;
        struct termios tio;
 
-       debug("ssh_session2_setup: id %d", id);
+       debug2("ssh_session2_setup: id %d", id);
 
        if (tty_flag) {
                struct winsize ws;
@@ -1113,7 +1157,7 @@ ssh_session2_open(void)
        c = channel_new(
            "session", SSH_CHANNEL_OPENING, in, out, err,
            window, packetmax, CHAN_EXTENDED_WRITE,
-           xstrdup("client-session"), /*nonblock*/0);
+           "client-session", /*nonblock*/0);
 
        debug3("ssh_session2_open: channel_new: %d", c->self);
 
@@ -1165,7 +1209,7 @@ load_public_identity_files(void)
                            sizeof(Key *) * (SSH_MAX_IDENTITY_FILES - 1));
                        options.num_identity_files++;
                        options.identity_keys[0] = keys[i];
-                       options.identity_files[0] = xstrdup("smartcard key");;
+                       options.identity_files[0] = sc_get_key_label(keys[i]);
                }
                if (options.num_identity_files > SSH_MAX_IDENTITY_FILES)
                        options.num_identity_files = SSH_MAX_IDENTITY_FILES;
This page took 0.065626 seconds and 4 git commands to generate.