version 1.275.2.2, 2016/01/27 12:19:42 |
version 1.276, 2015/10/20 03:36:35 |
|
|
{ |
{ |
size_t i, dlen; |
size_t i, dlen; |
|
|
if (display == NULL) |
|
return 0; |
|
|
|
dlen = strlen(display); |
dlen = strlen(display); |
for (i = 0; i < dlen; i++) { |
for (i = 0; i < dlen; i++) { |
if (!isalnum((u_char)display[i]) && |
if (!isalnum((u_char)display[i]) && |
|
|
|
|
#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1" |
#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1" |
#define X11_TIMEOUT_SLACK 60 |
#define X11_TIMEOUT_SLACK 60 |
int |
void |
client_x11_get_proto(const char *display, const char *xauth_path, |
client_x11_get_proto(const char *display, const char *xauth_path, |
u_int trusted, u_int timeout, char **_proto, char **_data) |
u_int trusted, u_int timeout, char **_proto, char **_data) |
{ |
{ |
char cmd[1024], line[512], xdisplay[512]; |
char cmd[1024]; |
|
char line[512]; |
|
char xdisplay[512]; |
static char proto[512], data[512]; |
static char proto[512], data[512]; |
FILE *f; |
FILE *f; |
int got_data = 0, generated = 0, do_unlink = 0, i, r; |
int got_data = 0, generated = 0, do_unlink = 0, i; |
char *xauthdir, *xauthfile; |
char xauthdir[PATH_MAX] = "", xauthfile[PATH_MAX] = ""; |
struct stat st; |
struct stat st; |
u_int now, x11_timeout_real; |
u_int now, x11_timeout_real; |
|
|
xauthdir = xauthfile = NULL; |
|
*_proto = proto; |
*_proto = proto; |
*_data = data; |
*_data = data; |
proto[0] = data[0] = '\0'; |
proto[0] = data[0] = '\0'; |
|
|
if (!client_x11_display_valid(display)) { |
if (xauth_path == NULL ||(stat(xauth_path, &st) == -1)) { |
logit("DISPLAY \"%s\" invalid; disabling X11 forwarding", |
|
display); |
|
return -1; |
|
} |
|
if (xauth_path != NULL && stat(xauth_path, &st) == -1) { |
|
debug("No xauth program."); |
debug("No xauth program."); |
xauth_path = NULL; |
} else if (!client_x11_display_valid(display)) { |
} |
logit("DISPLAY '%s' invalid, falling back to fake xauth data", |
|
display); |
if (xauth_path != NULL) { |
} else { |
|
if (display == NULL) { |
|
debug("x11_get_proto: DISPLAY not set"); |
|
return; |
|
} |
/* |
/* |
* Handle FamilyLocal case where $DISPLAY does |
* Handle FamilyLocal case where $DISPLAY does |
* not match an authorization entry. For this we |
* not match an authorization entry. For this we |
|
|
* is not perfect. |
* is not perfect. |
*/ |
*/ |
if (strncmp(display, "localhost:", 10) == 0) { |
if (strncmp(display, "localhost:", 10) == 0) { |
if ((r = snprintf(xdisplay, sizeof(xdisplay), "unix:%s", |
snprintf(xdisplay, sizeof(xdisplay), "unix:%s", |
display + 10)) < 0 || |
display + 10); |
(size_t)r >= sizeof(xdisplay)) { |
|
error("%s: display name too long", __func__); |
|
return -1; |
|
} |
|
display = xdisplay; |
display = xdisplay; |
} |
} |
if (trusted == 0) { |
if (trusted == 0) { |
xauthdir = xmalloc(PATH_MAX); |
mktemp_proto(xauthdir, PATH_MAX); |
xauthfile = xmalloc(PATH_MAX); |
|
/* |
/* |
* Generate an untrusted X11 auth cookie. |
|
* |
|
* The authentication cookie should briefly outlive |
* The authentication cookie should briefly outlive |
* ssh's willingness to forward X11 connections to |
* ssh's willingness to forward X11 connections to |
* avoid nasty fail-open behaviour in the X server. |
* avoid nasty fail-open behaviour in the X server. |
*/ |
*/ |
mktemp_proto(xauthdir, PATH_MAX); |
|
if (mkdtemp(xauthdir) == NULL) { |
|
error("%s: mkdtemp: %s", |
|
__func__, strerror(errno)); |
|
return -1; |
|
} |
|
do_unlink = 1; |
|
if ((r = snprintf(xauthfile, PATH_MAX, |
|
"%s/xauthfile", xauthdir)) < 0 || |
|
(size_t)r >= PATH_MAX) { |
|
error("%s: xauthfile path too long", __func__); |
|
unlink(xauthfile); |
|
rmdir(xauthdir); |
|
return -1; |
|
} |
|
|
|
if (timeout >= UINT_MAX - X11_TIMEOUT_SLACK) |
if (timeout >= UINT_MAX - X11_TIMEOUT_SLACK) |
x11_timeout_real = UINT_MAX; |
x11_timeout_real = UINT_MAX; |
else |
else |
x11_timeout_real = timeout + X11_TIMEOUT_SLACK; |
x11_timeout_real = timeout + X11_TIMEOUT_SLACK; |
if ((r = snprintf(cmd, sizeof(cmd), |
if (mkdtemp(xauthdir) != NULL) { |
"%s -f %s generate %s " SSH_X11_PROTO |
do_unlink = 1; |
" untrusted timeout %u 2>" _PATH_DEVNULL, |
snprintf(xauthfile, PATH_MAX, "%s/xauthfile", |
xauth_path, xauthfile, display, |
xauthdir); |
x11_timeout_real)) < 0 || |
snprintf(cmd, sizeof(cmd), |
(size_t)r >= sizeof(cmd)) |
"%s -f %s generate %s " SSH_X11_PROTO |
fatal("%s: cmd too long", __func__); |
" untrusted timeout %u 2>" _PATH_DEVNULL, |
debug2("%s: %s", __func__, cmd); |
xauth_path, xauthfile, display, |
if (x11_refuse_time == 0) { |
x11_timeout_real); |
now = monotime() + 1; |
debug2("x11_get_proto: %s", cmd); |
if (UINT_MAX - timeout < now) |
if (x11_refuse_time == 0) { |
x11_refuse_time = UINT_MAX; |
now = monotime() + 1; |
else |
if (UINT_MAX - timeout < now) |
x11_refuse_time = now + timeout; |
x11_refuse_time = UINT_MAX; |
channel_set_x11_refuse_time(x11_refuse_time); |
else |
|
x11_refuse_time = now + timeout; |
|
channel_set_x11_refuse_time( |
|
x11_refuse_time); |
|
} |
|
if (system(cmd) == 0) |
|
generated = 1; |
} |
} |
if (system(cmd) == 0) |
|
generated = 1; |
|
} |
} |
|
|
/* |
/* |
|
|
got_data = 1; |
got_data = 1; |
if (f) |
if (f) |
pclose(f); |
pclose(f); |
} |
} else |
|
error("Warning: untrusted X11 forwarding setup failed: " |
|
"xauth key data not generated"); |
} |
} |
|
|
if (do_unlink) { |
if (do_unlink) { |
unlink(xauthfile); |
unlink(xauthfile); |
rmdir(xauthdir); |
rmdir(xauthdir); |
} |
} |
free(xauthdir); |
|
free(xauthfile); |
|
|
|
/* Don't fall back to fake X11 data for untrusted forwarding */ |
|
if (!trusted && !got_data) { |
|
error("Warning: untrusted X11 forwarding setup failed: " |
|
"xauth key data not generated"); |
|
return -1; |
|
} |
|
|
|
/* |
/* |
* If we didn't get authentication data, just make up some |
* If we didn't get authentication data, just make up some |
* data. The forwarding code will check the validity of the |
* data. The forwarding code will check the validity of the |
|
|
rnd >>= 8; |
rnd >>= 8; |
} |
} |
} |
} |
|
|
return 0; |
|
} |
} |
|
|
/* |
/* |