diff options
| author | jp161948 <none@none> | 2007-08-20 13:43:28 -0700 |
|---|---|---|
| committer | jp161948 <none@none> | 2007-08-20 13:43:28 -0700 |
| commit | 383a1232abf6ee8c176a61ee5268f51bb9840224 (patch) | |
| tree | b3c05da23ff3f0c1dfdd40b4e52a4835e1efb03c /usr/src | |
| parent | 02b636c64ad657301ef5f5e6c2d14c6bec693fff (diff) | |
| download | illumos-joyent-383a1232abf6ee8c176a61ee5268f51bb9840224.tar.gz | |
PSARC/2007/034 ssh/sshd resync with OpenSSH
6472998 implement untrusted X11 forwarding in ssh(1)
Diffstat (limited to 'usr/src')
| -rw-r--r-- | usr/src/cmd/ssh/include/channels.h | 3 | ||||
| -rw-r--r-- | usr/src/cmd/ssh/include/clientloop.h | 2 | ||||
| -rw-r--r-- | usr/src/cmd/ssh/include/misc.h | 3 | ||||
| -rw-r--r-- | usr/src/cmd/ssh/include/readconf.h | 1 | ||||
| -rw-r--r-- | usr/src/cmd/ssh/libssh/common/channels.c | 18 | ||||
| -rw-r--r-- | usr/src/cmd/ssh/libssh/common/misc.c | 19 | ||||
| -rw-r--r-- | usr/src/cmd/ssh/libssh/common/readconf.c | 15 | ||||
| -rw-r--r-- | usr/src/cmd/ssh/ssh/clientloop.c | 114 | ||||
| -rw-r--r-- | usr/src/cmd/ssh/ssh/ssh.c | 85 |
9 files changed, 174 insertions, 86 deletions
diff --git a/usr/src/cmd/ssh/include/channels.h b/usr/src/cmd/ssh/include/channels.h index 806d9cf205..449f7a6640 100644 --- a/usr/src/cmd/ssh/include/channels.h +++ b/usr/src/cmd/ssh/include/channels.h @@ -225,7 +225,8 @@ int channel_setup_remote_fwd_listener(const char *, u_short, int); int x11_connect_display(void); int x11_create_display_inet(int, int, int, u_int *); void x11_input_open(int, u_int32_t, void *); -void x11_request_forwarding_with_spoofing(int, const char *, const char *); +void x11_request_forwarding_with_spoofing(int, const char *, const char *, + const char *); void deny_input_open(int, u_int32_t, void *); /* agent forwarding */ diff --git a/usr/src/cmd/ssh/include/clientloop.h b/usr/src/cmd/ssh/include/clientloop.h index 6eb2e4c0fe..5e24594195 100644 --- a/usr/src/cmd/ssh/include/clientloop.h +++ b/usr/src/cmd/ssh/include/clientloop.h @@ -47,6 +47,8 @@ extern "C" { /* Client side main loop for the interactive session. */ int client_loop(int, int, int); +void client_x11_get_proto(const char *, const char *, u_int, + char **, char **); void client_global_request_reply_fwd(int type, u_int32_t seq, void *ctxt); #ifdef __cplusplus diff --git a/usr/src/cmd/ssh/include/misc.h b/usr/src/cmd/ssh/include/misc.h index ae506c324f..eb9a805dd6 100644 --- a/usr/src/cmd/ssh/include/misc.h +++ b/usr/src/cmd/ssh/include/misc.h @@ -22,7 +22,7 @@ extern "C" { * called by a name other than "ssh" or "Secure Shell". */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -35,6 +35,7 @@ int a2port(const char *); char *cleanhostname(char *); char *colon(char *); long convtime(const char *); +char *tohex(const void *, size_t); struct passwd *pwcopy(struct passwd *); void pwfree(struct passwd **); diff --git a/usr/src/cmd/ssh/include/readconf.h b/usr/src/cmd/ssh/include/readconf.h index 687bf48172..87440a30dc 100644 --- a/usr/src/cmd/ssh/include/readconf.h +++ b/usr/src/cmd/ssh/include/readconf.h @@ -41,6 +41,7 @@ typedef struct { typedef struct { int forward_agent; /* Forward authentication agent. */ int forward_x11; /* Forward X11 display. */ + int forward_x11_trusted; /* Trust Forward X11 display. */ char *xauth_location; /* Location for xauth program */ int gateway_ports; /* Allow remote connects to forwarded ports. */ int use_privileged_port; /* Don't use privileged port if false. */ diff --git a/usr/src/cmd/ssh/libssh/common/channels.c b/usr/src/cmd/ssh/libssh/common/channels.c index 5980c6ca89..78c5a72f1f 100644 --- a/usr/src/cmd/ssh/libssh/common/channels.c +++ b/usr/src/cmd/ssh/libssh/common/channels.c @@ -127,7 +127,7 @@ static u_int x11_saved_data_len = 0; * Fake X11 authentication data. This is what the server will be sending us; * we should replace any occurrences of this by the real data. */ -static char *x11_fake_data = NULL; +static u_char *x11_fake_data = NULL; static u_int x11_fake_data_len; @@ -2791,19 +2791,19 @@ deny_input_open(int type, u_int32_t seq, void *ctxt) * This should be called in the client only. */ void -x11_request_forwarding_with_spoofing(int client_session_id, +x11_request_forwarding_with_spoofing(int client_session_id, const char *disp, const char *proto, const char *data) { u_int data_len = (u_int) strlen(data) / 2; - u_int i, value, len; + u_int i, value; char *new_data; int screen_number; const char *cp; u_int32_t rand = 0; - cp = getenv("DISPLAY"); - if (cp) - cp = strchr(cp, ':'); + cp = disp; + if (disp) + cp = strchr(disp, ':'); if (cp) cp = strchr(cp, '.'); if (cp) @@ -2833,11 +2833,7 @@ x11_request_forwarding_with_spoofing(int client_session_id, x11_fake_data_len = data_len; /* Convert the fake data into hex. */ - len = 2 * data_len + 1; - new_data = xmalloc(len); - for (i = 0; i < data_len; i++) - snprintf(new_data + 2 * i, len - 2 * i, - "%02x", (u_char) x11_fake_data[i]); + new_data = tohex(x11_fake_data, data_len); /* Send the request packet. */ if (compat20) { diff --git a/usr/src/cmd/ssh/libssh/common/misc.c b/usr/src/cmd/ssh/libssh/common/misc.c index 99c0778307..1b7646f4dc 100644 --- a/usr/src/cmd/ssh/libssh/common/misc.c +++ b/usr/src/cmd/ssh/libssh/common/misc.c @@ -376,6 +376,25 @@ freeargs(arglist *args) } } +char * +tohex(const void *vp, size_t l) +{ + const u_char *p = (const u_char *)vp; + char b[3], *r; + size_t i, hl; + + if (l > 65536) + return xstrdup("tohex: length > 65536"); + + hl = l * 2 + 1; + r = xcalloc(1, hl); + for (i = 0; i < l; i++) { + snprintf(b, sizeof(b), "%02x", p[i]); + strlcat(r, b, hl); + } + return (r); +} + mysig_t mysignal(int sig, mysig_t act) { diff --git a/usr/src/cmd/ssh/libssh/common/readconf.c b/usr/src/cmd/ssh/libssh/common/readconf.c index 1a771c4a31..b3459f2e1f 100644 --- a/usr/src/cmd/ssh/libssh/common/readconf.c +++ b/usr/src/cmd/ssh/libssh/common/readconf.c @@ -97,7 +97,8 @@ RCSID("$OpenBSD: readconf.c,v 1.100 2002/06/19 00:27:55 deraadt Exp $"); typedef enum { oBadOption, - oForwardAgent, oForwardX11, oGatewayPorts, oRhostsAuthentication, + oForwardAgent, oForwardX11, oForwardX11Trusted, oGatewayPorts, + oRhostsAuthentication, oPasswordAuthentication, oRSAAuthentication, oChallengeResponseAuthentication, oXAuthLocation, #if defined(KRB4) || defined(KRB5) @@ -139,6 +140,7 @@ static struct { } keywords[] = { { "forwardagent", oForwardAgent }, { "forwardx11", oForwardX11 }, + { "forwardx11trusted", oForwardX11Trusted }, { "xauthlocation", oXAuthLocation }, { "gatewayports", oGatewayPorts }, { "useprivilegedport", oUsePrivilegedPort }, @@ -358,6 +360,10 @@ parse_flag: intptr = &options->forward_x11; goto parse_flag; + case oForwardX11Trusted: + intptr = &options->forward_x11_trusted; + goto parse_flag; + case oGatewayPorts: intptr = &options->gateway_ports; goto parse_flag; @@ -821,6 +827,7 @@ initialize_options(Options * options) memset(options, 'X', sizeof(*options)); options->forward_agent = -1; options->forward_x11 = -1; + options->forward_x11_trusted = -1; options->xauth_location = NULL; options->gateway_ports = -1; options->use_privileged_port = -1; @@ -904,6 +911,12 @@ fill_default_options(Options * options) options->forward_agent = 0; if (options->forward_x11 == -1) options->forward_x11 = 0; + /* + * Unlike OpenSSH, we keep backward compatibility for '-X' option + * which means that X11 forwarding is trusted by default. + */ + if (options->forward_x11_trusted == -1) + options->forward_x11_trusted = 1; if (options->xauth_location == NULL) options->xauth_location = _PATH_XAUTH; if (options->gateway_ports == -1) diff --git a/usr/src/cmd/ssh/ssh/clientloop.c b/usr/src/cmd/ssh/ssh/clientloop.c index 50d6163e91..f112ac6d90 100644 --- a/usr/src/cmd/ssh/ssh/clientloop.c +++ b/usr/src/cmd/ssh/ssh/clientloop.c @@ -197,6 +197,120 @@ get_current_time(void) return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0; } +#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1" +void +client_x11_get_proto(const char *display, const char *xauth_path, + u_int trusted, 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, generated = 0, do_unlink = 0, i; + char *xauthdir, *xauthfile; + struct stat st; + + xauthdir = xauthfile = NULL; + *_proto = proto; + *_data = data; + proto[0] = data[0] = '\0'; + + if (xauth_path == NULL ||(stat(xauth_path, &st) == -1)) { + debug("No xauth program."); + } else { + if (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 (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 1200 2>" _PATH_DEVNULL, + xauth_path, xauthfile, display); + debug2("x11_get_proto: %s", cmd); + if (system(cmd) == 0) + generated = 1; + } + } + + /* + * When in untrusted mode, we read the cookie only if it was + * successfully generated as an untrusted one in the step + * above. + */ + if (trusted || generated) { + snprintf(cmd, sizeof(cmd), + "%s %s%s list %s 2>" _PATH_DEVNULL, + xauth_path, + 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); + } + else + error("Warning: untrusted X11 forwarding setup failed: " + "xauth key data not generated"); + } + + 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 + * response anyway, and substitute this data. The X11 + * server, however, will ignore this fake data and use + * whatever authentication mechanisms it was using otherwise + * for the local connection. + */ + if (!got_data) { + u_int32_t rnd = 0; + + log("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) + rnd = arc4random(); + snprintf(data + 2 * i, sizeof data - 2 * i, "%02x", + rnd & 0xff); + rnd >>= 8; + } + } +} + /* * This is called when the interactive is entered. This checks if there is * an EOF coming on stdin. We must check this explicitly, as select() does diff --git a/usr/src/cmd/ssh/ssh/ssh.c b/usr/src/cmd/ssh/ssh/ssh.c index d655464cd1..d2eb841d60 100644 --- a/usr/src/cmd/ssh/ssh/ssh.c +++ b/usr/src/cmd/ssh/ssh/ssh.c @@ -788,71 +788,6 @@ again: } static void -x11_get_proto(char **_proto, char **_data) -{ - char line[512]; - static char proto[512], data[512]; - FILE *f; - int got_data = 0, i; - char *display; - struct stat st; - - *_proto = proto; - *_data = data; - proto[0] = data[0] = '\0'; - 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; - } - /* 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 (f && fgets(line, sizeof(line), f) && - sscanf(line, "%*s %511s %511s", proto, data) == 2) - got_data = 1; - if (f) - pclose(f); - } - /* - * If we didn't get authentication data, just make up some - * data. The forwarding code will check the validity of the - * response anyway, and substitute this data. The X11 - * server, however, will ignore this fake data and use - * whatever authentication mechanisms it was using otherwise - * for the local connection. - */ - if (!got_data) { - u_int32_t rand = 0; - - log("Warning: No xauth data; using fake authentication data for X11 forwarding."); - strlcpy(proto, "MIT-MAGIC-COOKIE-1", 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); - rand >>= 8; - } - } -} - -static void ssh_init_forwarding(void) { int success = 0; @@ -904,6 +839,7 @@ ssh_session(void) int have_tty = 0; struct winsize ws; char *cp; + const char *display; /* Enable compression if requested. */ if (options.compression) { @@ -965,13 +901,15 @@ ssh_session(void) packet_disconnect("Protocol error waiting for pty request response."); } /* Request X11 forwarding if enabled and DISPLAY is set. */ - if (options.forward_x11 && getenv("DISPLAY") != NULL) { + display = getenv("DISPLAY"); + if (options.forward_x11 && display != NULL) { char *proto, *data; /* Get reasonable local authentication information. */ - x11_get_proto(&proto, &data); + client_x11_get_proto(display, options.xauth_location, + options.forward_x11_trusted, &proto, &data); /* Request forwarding with authentication spoofing. */ debug("Requesting X11 forwarding with authentication spoofing."); - x11_request_forwarding_with_spoofing(0, proto, data); + x11_request_forwarding_with_spoofing(0, display, proto, data); /* Read response from the server. */ type = packet_read(); @@ -1099,6 +1037,7 @@ static void ssh_session2_setup(int id, void *arg) { int len; + const char *display; int interactive = 0; struct termios tio; @@ -1128,14 +1067,16 @@ ssh_session2_setup(int id, void *arg) interactive = 1; /* XXX wait for reply */ } - if (options.forward_x11 && - getenv("DISPLAY") != NULL) { + + display = getenv("DISPLAY"); + if (options.forward_x11 && display != NULL) { char *proto, *data; /* Get reasonable local authentication information. */ - x11_get_proto(&proto, &data); + client_x11_get_proto(display, options.xauth_location, + options.forward_x11_trusted, &proto, &data); /* Request forwarding with authentication spoofing. */ debug("Requesting X11 forwarding with authentication spoofing."); - x11_request_forwarding_with_spoofing(id, proto, data); + x11_request_forwarding_with_spoofing(id, display, proto, data); interactive = 1; /* XXX wait for reply */ } |
