File openssh-6.6p1-X11_forwarding_timeout.patch of Package openssh.10219
# HG changeset patch
# Parent a41ab00d88841b5e8899b6e4014d6c891701d30a
Better way of refusing ForwardX11Trusted=no connections attempted after
ForwardX11Timeout expires.
CVE-2015-5352
bsc#936695
upstream commit: 1bf477d3cdf1a864646d59820878783d42357a1d
diff --git a/openssh-6.6p1/channels.c b/openssh-6.6p1/channels.c
--- a/openssh-6.6p1/channels.c
+++ b/openssh-6.6p1/channels.c
@@ -146,16 +146,19 @@ static char *x11_saved_display = NULL;
/* Saved X11 authentication protocol name. */
static char *x11_saved_proto = NULL;
/* Saved X11 authentication data. This is the real data. */
static char *x11_saved_data = NULL;
static u_int x11_saved_data_len = 0;
+/* Deadline after which all X11 connections are refused */
+static u_int x11_refuse_time;
+
/*
* 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 u_char *x11_fake_data = NULL;
static u_int x11_fake_data_len;
@@ -889,16 +892,23 @@ channel_pre_output_draining(Channel *c,
* Returns: 0 = need more data, -1 = wrong cookie, 1 = ok
*/
static int
x11_open_helper(Buffer *b)
{
u_char *ucp;
u_int proto_len, data_len;
+ /* Is this being called after the refusal deadline? */
+ if (x11_refuse_time != 0 && (u_int)monotime() >= x11_refuse_time) {
+ verbose("Rejected X11 connection after ForwardX11Timeout "
+ "expired");
+ return -1;
+ }
+
/* Check if the fixed size part of the packet is in buffer. */
if (buffer_len(b) < 12)
return 0;
/* Parse the lengths of variable-length fields. */
ucp = buffer_ptr(b);
if (ucp[0] == 0x42) { /* Byte order MSB first. */
proto_len = 256 * ucp[6] + ucp[7];
@@ -1452,16 +1462,22 @@ channel_set_reuseaddr(int fd)
/*
* Set socket options.
* Allow local port reuse in TIME_WAIT.
*/
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)
error("setsockopt SO_REUSEADDR fd %d: %s", fd, strerror(errno));
}
+void
+channel_set_x11_refuse_time(u_int refuse_time)
+{
+ x11_refuse_time = refuse_time;
+}
+
/*
* This socket is listening for connections to a forwarded TCP/IP port.
*/
/* ARGSUSED */
static void
channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset)
{
Channel *nc;
diff --git a/openssh-6.6p1/channels.h b/openssh-6.6p1/channels.h
--- a/openssh-6.6p1/channels.h
+++ b/openssh-6.6p1/channels.h
@@ -274,16 +274,17 @@ int channel_setup_local_fwd_listener(co
int channel_request_rforward_cancel(const char *host, u_short port);
int channel_setup_remote_fwd_listener(const char *, u_short, int *, int);
int channel_cancel_rport_listener(const char *, u_short);
int channel_cancel_lport_listener(const char *, u_short, int, int);
int permitopen_port(const char *);
/* x11 forwarding */
+void channel_set_x11_refuse_time(u_int);
int x11_connect_display(void);
int x11_create_display_inet(int, int, int, u_int *, int **);
void x11_input_open(int, u_int32_t, void *);
void x11_request_forwarding_with_spoofing(int, const char *, const char *,
const char *, int);
void deny_input_open(int, u_int32_t, void *);
/* agent forwarding */
diff --git a/openssh-6.6p1/clientloop.c b/openssh-6.6p1/clientloop.c
--- a/openssh-6.6p1/clientloop.c
+++ b/openssh-6.6p1/clientloop.c
@@ -159,17 +159,17 @@ static int stdin_eof; /* EOF has been e
static Buffer stdin_buffer; /* Buffer for stdin data. */
static Buffer stdout_buffer; /* Buffer for stdout data. */
static Buffer stderr_buffer; /* Buffer for stderr data. */
static u_int buffer_high; /* Soft max buffer size. */
static int connection_in; /* Connection to server (input). */
static int connection_out; /* Connection to server (output). */
static int need_rekeying; /* Set to non-zero if rekeying is requested. */
static int session_closed; /* In SSH2: login session closed. */
-static int x11_refuse_time; /* If >0, refuse x11 opens after this time. */
+static u_int x11_refuse_time; /* If >0, refuse x11 opens after this time. */
static void client_init_dispatch(void);
int session_ident = -1;
int session_resumed = 0;
/* Track escape per proto2 channel */
struct escape_filter_ctx {
@@ -297,30 +297,31 @@ client_x11_display_valid(const char *dis
strchr(SSH_X11_VALID_DISPLAY_CHARS, display[i]) == NULL) {
debug("Invalid character '%c' in DISPLAY", display[i]);
return 0;
}
}
return 1;
}
-#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1"
+#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1"
+#define X11_TIMEOUT_SLACK 60
void
client_x11_get_proto(const char *display, const char *xauth_path,
u_int trusted, u_int timeout, 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;
- u_int now;
+ u_int now, x11_timeout_real;
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.");
@@ -343,34 +344,46 @@ client_x11_get_proto(const char *display
snprintf(xdisplay, sizeof(xdisplay), "unix:%s",
display + 10);
display = xdisplay;
}
if (trusted == 0) {
xauthdir = xmalloc(MAXPATHLEN);
xauthfile = xmalloc(MAXPATHLEN);
mktemp_proto(xauthdir, MAXPATHLEN);
+ /*
+ * The authentication cookie should briefly outlive
+ * ssh's willingness to forward X11 connections to
+ * avoid nasty fail-open behaviour in the X server.
+ */
+ if (timeout >= UINT_MAX - X11_TIMEOUT_SLACK)
+ x11_timeout_real = UINT_MAX;
+ else
+ x11_timeout_real = timeout + X11_TIMEOUT_SLACK;
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 %u 2>" _PATH_DEVNULL,
- xauth_path, xauthfile, display, timeout);
+ xauth_path, xauthfile, display,
+ x11_timeout_real);
debug2("x11_get_proto: %s", cmd);
- if (system(cmd) == 0)
- generated = 1;
if (x11_refuse_time == 0) {
now = monotime() + 1;
if (UINT_MAX - timeout < now)
x11_refuse_time = UINT_MAX;
else
x11_refuse_time = now + timeout;
+ channel_set_x11_refuse_time(
+ x11_refuse_time);
}
+ 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.
*/
@@ -1879,17 +1892,17 @@ client_request_x11(const char *request_t
int sock;
if (!options.forward_x11) {
error("Warning: ssh server tried X11 forwarding.");
error("Warning: this is probably a break-in attempt by a "
"malicious server.");
return NULL;
}
- if (x11_refuse_time != 0 && monotime() >= x11_refuse_time) {
+ if (x11_refuse_time != 0 && (u_int)monotime() >= x11_refuse_time) {
verbose("Rejected X11 connection after ForwardX11Timeout "
"expired");
return NULL;
}
originator = packet_get_string(NULL);
if (datafellows & SSH_BUG_X11FWD) {
debug2("buggy server: x11 request w/o originator_port");
originator_port = 0;