summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorjp161948 <none@none>2007-08-20 13:43:28 -0700
committerjp161948 <none@none>2007-08-20 13:43:28 -0700
commit383a1232abf6ee8c176a61ee5268f51bb9840224 (patch)
treeb3c05da23ff3f0c1dfdd40b4e52a4835e1efb03c /usr/src
parent02b636c64ad657301ef5f5e6c2d14c6bec693fff (diff)
downloadillumos-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.h3
-rw-r--r--usr/src/cmd/ssh/include/clientloop.h2
-rw-r--r--usr/src/cmd/ssh/include/misc.h3
-rw-r--r--usr/src/cmd/ssh/include/readconf.h1
-rw-r--r--usr/src/cmd/ssh/libssh/common/channels.c18
-rw-r--r--usr/src/cmd/ssh/libssh/common/misc.c19
-rw-r--r--usr/src/cmd/ssh/libssh/common/readconf.c15
-rw-r--r--usr/src/cmd/ssh/ssh/clientloop.c114
-rw-r--r--usr/src/cmd/ssh/ssh/ssh.c85
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 */
}