diff options
-rw-r--r-- | clientloop.c | 114 | ||||
-rw-r--r-- | clientloop.h | 4 | ||||
-rw-r--r-- | mux.c | 22 | ||||
-rw-r--r-- | ssh.c | 23 |
4 files changed, 93 insertions, 70 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 |
304 | void | 307 | int |
305 | client_x11_get_proto(const char *display, const char *xauth_path, | 308 | client_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 | /* |
diff --git a/clientloop.h b/clientloop.h index 338d45186..f4d4c69b7 100644 --- a/clientloop.h +++ b/clientloop.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: clientloop.h,v 1.31 2013/06/02 23:36:29 dtucker Exp $ */ | 1 | /* $OpenBSD: clientloop.h,v 1.32 2016/01/13 23:04:47 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -39,7 +39,7 @@ | |||
39 | 39 | ||
40 | /* Client side main loop for the interactive session. */ | 40 | /* Client side main loop for the interactive session. */ |
41 | int client_loop(int, int, int); | 41 | int client_loop(int, int, int); |
42 | void client_x11_get_proto(const char *, const char *, u_int, u_int, | 42 | int client_x11_get_proto(const char *, const char *, u_int, u_int, |
43 | char **, char **); | 43 | char **, char **); |
44 | void client_global_request_reply_fwd(int, u_int32_t, void *); | 44 | void client_global_request_reply_fwd(int, u_int32_t, void *); |
45 | void client_session2_setup(int, int, int, const char *, struct termios *, | 45 | void client_session2_setup(int, int, int, const char *, struct termios *, |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: mux.c,v 1.57 2015/12/26 07:46:03 semarie Exp $ */ | 1 | /* $OpenBSD: mux.c,v 1.58 2016/01/13 23:04:47 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org> | 3 | * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org> |
4 | * | 4 | * |
@@ -1354,16 +1354,18 @@ mux_session_confirm(int id, int success, void *arg) | |||
1354 | char *proto, *data; | 1354 | char *proto, *data; |
1355 | 1355 | ||
1356 | /* Get reasonable local authentication information. */ | 1356 | /* Get reasonable local authentication information. */ |
1357 | client_x11_get_proto(display, options.xauth_location, | 1357 | if (client_x11_get_proto(display, options.xauth_location, |
1358 | options.forward_x11_trusted, options.forward_x11_timeout, | 1358 | options.forward_x11_trusted, options.forward_x11_timeout, |
1359 | &proto, &data); | 1359 | &proto, &data) == 0) { |
1360 | /* Request forwarding with authentication spoofing. */ | 1360 | /* Request forwarding with authentication spoofing. */ |
1361 | debug("Requesting X11 forwarding with authentication " | 1361 | debug("Requesting X11 forwarding with authentication " |
1362 | "spoofing."); | 1362 | "spoofing."); |
1363 | x11_request_forwarding_with_spoofing(id, display, proto, | 1363 | x11_request_forwarding_with_spoofing(id, display, proto, |
1364 | data, 1); | 1364 | data, 1); |
1365 | client_expect_confirm(id, "X11 forwarding", CONFIRM_WARN); | 1365 | /* XXX exit_on_forward_failure */ |
1366 | /* XXX exit_on_forward_failure */ | 1366 | client_expect_confirm(id, "X11 forwarding", |
1367 | CONFIRM_WARN); | ||
1368 | } | ||
1367 | } | 1369 | } |
1368 | 1370 | ||
1369 | if (cctx->want_agent_fwd && options.forward_agent) { | 1371 | if (cctx->want_agent_fwd && options.forward_agent) { |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh.c,v 1.432 2015/12/11 03:20:09 djm Exp $ */ | 1 | /* $OpenBSD: ssh.c,v 1.433 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 |
@@ -1626,6 +1626,7 @@ ssh_session(void) | |||
1626 | struct winsize ws; | 1626 | struct winsize ws; |
1627 | char *cp; | 1627 | char *cp; |
1628 | const char *display; | 1628 | const char *display; |
1629 | char *proto = NULL, *data = NULL; | ||
1629 | 1630 | ||
1630 | /* Enable compression if requested. */ | 1631 | /* Enable compression if requested. */ |
1631 | if (options.compression) { | 1632 | if (options.compression) { |
@@ -1696,13 +1697,9 @@ ssh_session(void) | |||
1696 | display = getenv("DISPLAY"); | 1697 | display = getenv("DISPLAY"); |
1697 | if (display == NULL && options.forward_x11) | 1698 | if (display == NULL && options.forward_x11) |
1698 | debug("X11 forwarding requested but DISPLAY not set"); | 1699 | debug("X11 forwarding requested but DISPLAY not set"); |
1699 | if (options.forward_x11 && display != NULL) { | 1700 | if (options.forward_x11 && client_x11_get_proto(display, |
1700 | char *proto, *data; | 1701 | options.xauth_location, options.forward_x11_trusted, |
1701 | /* Get reasonable local authentication information. */ | 1702 | options.forward_x11_timeout, &proto, &data) == 0) { |
1702 | client_x11_get_proto(display, options.xauth_location, | ||
1703 | options.forward_x11_trusted, | ||
1704 | options.forward_x11_timeout, | ||
1705 | &proto, &data); | ||
1706 | /* Request forwarding with authentication spoofing. */ | 1703 | /* Request forwarding with authentication spoofing. */ |
1707 | debug("Requesting X11 forwarding with authentication " | 1704 | debug("Requesting X11 forwarding with authentication " |
1708 | "spoofing."); | 1705 | "spoofing."); |
@@ -1792,6 +1789,7 @@ ssh_session2_setup(int id, int success, void *arg) | |||
1792 | extern char **environ; | 1789 | extern char **environ; |
1793 | const char *display; | 1790 | const char *display; |
1794 | int interactive = tty_flag; | 1791 | int interactive = tty_flag; |
1792 | char *proto = NULL, *data = NULL; | ||
1795 | 1793 | ||
1796 | if (!success) | 1794 | if (!success) |
1797 | return; /* No need for error message, channels code sens one */ | 1795 | return; /* No need for error message, channels code sens one */ |
@@ -1799,12 +1797,9 @@ ssh_session2_setup(int id, int success, void *arg) | |||
1799 | display = getenv("DISPLAY"); | 1797 | display = getenv("DISPLAY"); |
1800 | if (display == NULL && options.forward_x11) | 1798 | if (display == NULL && options.forward_x11) |
1801 | debug("X11 forwarding requested but DISPLAY not set"); | 1799 | debug("X11 forwarding requested but DISPLAY not set"); |
1802 | if (options.forward_x11 && display != NULL) { | 1800 | if (options.forward_x11 && client_x11_get_proto(display, |
1803 | char *proto, *data; | 1801 | options.xauth_location, options.forward_x11_trusted, |
1804 | /* Get reasonable local authentication information. */ | 1802 | options.forward_x11_timeout, &proto, &data) == 0) { |
1805 | client_x11_get_proto(display, options.xauth_location, | ||
1806 | options.forward_x11_trusted, | ||
1807 | options.forward_x11_timeout, &proto, &data); | ||
1808 | /* Request forwarding with authentication spoofing. */ | 1803 | /* Request forwarding with authentication spoofing. */ |
1809 | debug("Requesting X11 forwarding with authentication " | 1804 | debug("Requesting X11 forwarding with authentication " |
1810 | "spoofing."); | 1805 | "spoofing."); |