summaryrefslogtreecommitdiff
path: root/clientloop.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2016-01-13 23:04:47 +0000
committerDamien Miller <djm@mindrot.org>2016-01-14 10:06:01 +1100
commited4ce82dbfa8a3a3c8ea6fa0db113c71e234416c (patch)
tree008ac3334471370857e32b48893cb6f07d28e987 /clientloop.c
parent9a728cc918fad67c8a9a71201088b1e150340ba4 (diff)
upstream commit
eliminate fallback from untrusted X11 forwarding to trusted forwarding when the X server disables the SECURITY extension; Reported by Thomas Hoger; ok deraadt@ Upstream-ID: f76195bd2064615a63ef9674a0e4096b0713f938
Diffstat (limited to 'clientloop.c')
-rw-r--r--clientloop.c114
1 files changed, 70 insertions, 44 deletions
diff --git a/clientloop.c b/clientloop.c
index f55545194..c0386d56b 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: clientloop.c,v 1.278 2015/12/26 07:46:03 semarie Exp $ */ 1/* $OpenBSD: clientloop.c,v 1.279 2016/01/13 23:04:47 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -288,6 +288,9 @@ client_x11_display_valid(const char *display)
288{ 288{
289 size_t i, dlen; 289 size_t i, dlen;
290 290
291 if (display == NULL)
292 return 0;
293
291 dlen = strlen(display); 294 dlen = strlen(display);
292 for (i = 0; i < dlen; i++) { 295 for (i = 0; i < dlen; i++) {
293 if (!isalnum((u_char)display[i]) && 296 if (!isalnum((u_char)display[i]) &&
@@ -301,34 +304,33 @@ client_x11_display_valid(const char *display)
301 304
302#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1" 305#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1"
303#define X11_TIMEOUT_SLACK 60 306#define X11_TIMEOUT_SLACK 60
304void 307int
305client_x11_get_proto(const char *display, const char *xauth_path, 308client_x11_get_proto(const char *display, const char *xauth_path,
306 u_int trusted, u_int timeout, char **_proto, char **_data) 309 u_int trusted, u_int timeout, char **_proto, char **_data)
307{ 310{
308 char cmd[1024]; 311 char cmd[1024], line[512], xdisplay[512];
309 char line[512]; 312 char xauthfile[PATH_MAX], xauthdir[PATH_MAX];
310 char xdisplay[512];
311 static char proto[512], data[512]; 313 static char proto[512], data[512];
312 FILE *f; 314 FILE *f;
313 int got_data = 0, generated = 0, do_unlink = 0, i; 315 int got_data = 0, generated = 0, do_unlink = 0, i, r;
314 char xauthdir[PATH_MAX] = "", xauthfile[PATH_MAX] = "";
315 struct stat st; 316 struct stat st;
316 u_int now, x11_timeout_real; 317 u_int now, x11_timeout_real;
317 318
318 *_proto = proto; 319 *_proto = proto;
319 *_data = data; 320 *_data = data;
320 proto[0] = data[0] = '\0'; 321 proto[0] = data[0] = xauthfile[0] = xauthdir[0] = '\0';
321 322
322 if (xauth_path == NULL ||(stat(xauth_path, &st) == -1)) { 323 if (!client_x11_display_valid(display)) {
323 debug("No xauth program."); 324 logit("DISPLAY \"%s\" invalid; disabling X11 forwarding",
324 } else if (!client_x11_display_valid(display)) {
325 logit("DISPLAY '%s' invalid, falling back to fake xauth data",
326 display); 325 display);
327 } else { 326 return -1;
328 if (display == NULL) { 327 }
329 debug("x11_get_proto: DISPLAY not set"); 328 if (xauth_path != NULL && stat(xauth_path, &st) == -1) {
330 return; 329 debug("No xauth program.");
331 } 330 xauth_path = NULL;
331 }
332
333 if (xauth_path != NULL) {
332 /* 334 /*
333 * Handle FamilyLocal case where $DISPLAY does 335 * Handle FamilyLocal case where $DISPLAY does
334 * not match an authorization entry. For this we 336 * not match an authorization entry. For this we
@@ -337,43 +339,60 @@ client_x11_get_proto(const char *display, const char *xauth_path,
337 * is not perfect. 339 * is not perfect.
338 */ 340 */
339 if (strncmp(display, "localhost:", 10) == 0) { 341 if (strncmp(display, "localhost:", 10) == 0) {
340 snprintf(xdisplay, sizeof(xdisplay), "unix:%s", 342 if ((r = snprintf(xdisplay, sizeof(xdisplay), "unix:%s",
341 display + 10); 343 display + 10)) < 0 ||
344 (size_t)r >= sizeof(xdisplay)) {
345 error("%s: display name too long", __func__);
346 return -1;
347 }
342 display = xdisplay; 348 display = xdisplay;
343 } 349 }
344 if (trusted == 0) { 350 if (trusted == 0) {
345 mktemp_proto(xauthdir, PATH_MAX);
346 /* 351 /*
352 * Generate an untrusted X11 auth cookie.
353 *
347 * The authentication cookie should briefly outlive 354 * The authentication cookie should briefly outlive
348 * ssh's willingness to forward X11 connections to 355 * ssh's willingness to forward X11 connections to
349 * avoid nasty fail-open behaviour in the X server. 356 * avoid nasty fail-open behaviour in the X server.
350 */ 357 */
358 mktemp_proto(xauthdir, sizeof(xauthdir));
359 if (mkdtemp(xauthdir) == NULL) {
360 error("%s: mkdtemp: %s",
361 __func__, strerror(errno));
362 return -1;
363 }
364 do_unlink = 1;
365 if ((r = snprintf(xauthfile, sizeof(xauthfile),
366 "%s/xauthfile", xauthdir)) < 0 ||
367 (size_t)r >= sizeof(xauthfile)) {
368 error("%s: xauthfile path too long", __func__);
369 unlink(xauthfile);
370 rmdir(xauthdir);
371 return -1;
372 }
373
351 if (timeout >= UINT_MAX - X11_TIMEOUT_SLACK) 374 if (timeout >= UINT_MAX - X11_TIMEOUT_SLACK)
352 x11_timeout_real = UINT_MAX; 375 x11_timeout_real = UINT_MAX;
353 else 376 else
354 x11_timeout_real = timeout + X11_TIMEOUT_SLACK; 377 x11_timeout_real = timeout + X11_TIMEOUT_SLACK;
355 if (mkdtemp(xauthdir) != NULL) { 378 if ((r = snprintf(cmd, sizeof(cmd),
356 do_unlink = 1; 379 "%s -f %s generate %s " SSH_X11_PROTO
357 snprintf(xauthfile, PATH_MAX, "%s/xauthfile", 380 " untrusted timeout %u 2>" _PATH_DEVNULL,
358 xauthdir); 381 xauth_path, xauthfile, display,
359 snprintf(cmd, sizeof(cmd), 382 x11_timeout_real)) < 0 ||
360 "%s -f %s generate %s " SSH_X11_PROTO 383 (size_t)r >= sizeof(cmd))
361 " untrusted timeout %u 2>" _PATH_DEVNULL, 384 fatal("%s: cmd too long", __func__);
362 xauth_path, xauthfile, display, 385 debug2("%s: %s", __func__, cmd);
363 x11_timeout_real); 386 if (x11_refuse_time == 0) {
364 debug2("x11_get_proto: %s", cmd); 387 now = monotime() + 1;
365 if (x11_refuse_time == 0) { 388 if (UINT_MAX - timeout < now)
366 now = monotime() + 1; 389 x11_refuse_time = UINT_MAX;
367 if (UINT_MAX - timeout < now) 390 else
368 x11_refuse_time = UINT_MAX; 391 x11_refuse_time = now + timeout;
369 else 392 channel_set_x11_refuse_time(x11_refuse_time);
370 x11_refuse_time = now + timeout;
371 channel_set_x11_refuse_time(
372 x11_refuse_time);
373 }
374 if (system(cmd) == 0)
375 generated = 1;
376 } 393 }
394 if (system(cmd) == 0)
395 generated = 1;
377 } 396 }
378 397
379 /* 398 /*
@@ -395,9 +414,7 @@ client_x11_get_proto(const char *display, const char *xauth_path,
395 got_data = 1; 414 got_data = 1;
396 if (f) 415 if (f)
397 pclose(f); 416 pclose(f);
398 } else 417 }
399 error("Warning: untrusted X11 forwarding setup failed: "
400 "xauth key data not generated");
401 } 418 }
402 419
403 if (do_unlink) { 420 if (do_unlink) {
@@ -405,6 +422,13 @@ client_x11_get_proto(const char *display, const char *xauth_path,
405 rmdir(xauthdir); 422 rmdir(xauthdir);
406 } 423 }
407 424
425 /* Don't fall back to fake X11 data for untrusted forwarding */
426 if (!trusted && !got_data) {
427 error("Warning: untrusted X11 forwarding setup failed: "
428 "xauth key data not generated");
429 return -1;
430 }
431
408 /* 432 /*
409 * If we didn't get authentication data, just make up some 433 * If we didn't get authentication data, just make up some
410 * data. The forwarding code will check the validity of the 434 * data. The forwarding code will check the validity of the
@@ -427,6 +451,8 @@ client_x11_get_proto(const char *display, const char *xauth_path,
427 rnd >>= 8; 451 rnd >>= 8;
428 } 452 }
429 } 453 }
454
455 return 0;
430} 456}
431 457
432/* 458/*