mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +00:00
Prepare to have multiple X11 auth cookies valid at once.
Rather than the top-level component of X forwarding being an X11Display structure which owns some auth data, it's now a collection of X11FakeAuth structures, each of which owns a display. The idea is that when we receive an X connection, we wait to see which of our available auth cookies it matches, and then connect to whatever X display that auth cookie identifies. At present the tree will only have one thing in it; this is all groundwork for later changes. [originally from svn r10079]
This commit is contained in:
parent
01085358e4
commit
cc4fbe33bc
109
ssh.c
109
ssh.c
@ -786,6 +786,8 @@ struct ssh_tag {
|
||||
Pkt_ACtx pkt_actx;
|
||||
|
||||
struct X11Display *x11disp;
|
||||
struct X11FakeAuth *x11auth;
|
||||
tree234 *x11authtree;
|
||||
|
||||
int version;
|
||||
int conn_throttle_count;
|
||||
@ -4890,7 +4892,7 @@ static void ssh1_smsg_x11_open(Ssh ssh, struct Packet *pktin)
|
||||
c = snew(struct ssh_channel);
|
||||
c->ssh = ssh;
|
||||
|
||||
if ((err = x11_init(&c->u.x11.xconn, ssh->x11disp, c,
|
||||
if ((err = x11_init(&c->u.x11.xconn, ssh->x11authtree, c,
|
||||
NULL, -1)) != NULL) {
|
||||
logeventf(ssh, "Opening X11 forward connection failed: %s", err);
|
||||
sfree(err);
|
||||
@ -5259,36 +5261,47 @@ static void do_ssh1_connection(Ssh ssh, unsigned char *in, int inlen,
|
||||
}
|
||||
}
|
||||
|
||||
if (conf_get_int(ssh->conf, CONF_x11_forward) &&
|
||||
(ssh->x11disp = x11_setup_display(conf_get_str(ssh->conf, CONF_x11_display),
|
||||
conf_get_int(ssh->conf, CONF_x11_auth), ssh->conf))) {
|
||||
logevent("Requesting X11 forwarding");
|
||||
if (ssh->v1_local_protoflags & SSH1_PROTOFLAG_SCREEN_NUMBER) {
|
||||
send_packet(ssh, SSH1_CMSG_X11_REQUEST_FORWARDING,
|
||||
PKT_STR, ssh->x11disp->remoteauthprotoname,
|
||||
PKT_STR, ssh->x11disp->remoteauthdatastring,
|
||||
PKT_INT, ssh->x11disp->screennum,
|
||||
PKT_END);
|
||||
} else {
|
||||
send_packet(ssh, SSH1_CMSG_X11_REQUEST_FORWARDING,
|
||||
PKT_STR, ssh->x11disp->remoteauthprotoname,
|
||||
PKT_STR, ssh->x11disp->remoteauthdatastring,
|
||||
PKT_END);
|
||||
}
|
||||
do {
|
||||
crReturnV;
|
||||
} while (!pktin);
|
||||
if (pktin->type != SSH1_SMSG_SUCCESS
|
||||
&& pktin->type != SSH1_SMSG_FAILURE) {
|
||||
bombout(("Protocol confusion"));
|
||||
crStopV;
|
||||
} else if (pktin->type == SSH1_SMSG_FAILURE) {
|
||||
logevent("X11 forwarding refused");
|
||||
} else {
|
||||
logevent("X11 forwarding enabled");
|
||||
ssh->X11_fwd_enabled = TRUE;
|
||||
ssh->packet_dispatch[SSH1_SMSG_X11_OPEN] = ssh1_smsg_x11_open;
|
||||
}
|
||||
if (conf_get_int(ssh->conf, CONF_x11_forward)) {
|
||||
ssh->x11disp =
|
||||
x11_setup_display(conf_get_str(ssh->conf, CONF_x11_display),
|
||||
ssh->conf);
|
||||
if (!ssh->x11disp) {
|
||||
/* FIXME: return an error message from x11_setup_display */
|
||||
logevent("X11 forwarding not enabled: unable to"
|
||||
" initialise X display");
|
||||
} else {
|
||||
ssh->x11auth = x11_invent_fake_auth
|
||||
(ssh->x11authtree, conf_get_int(ssh->conf, CONF_x11_auth));
|
||||
ssh->x11auth->disp = ssh->x11disp;
|
||||
|
||||
logevent("Requesting X11 forwarding");
|
||||
if (ssh->v1_local_protoflags & SSH1_PROTOFLAG_SCREEN_NUMBER) {
|
||||
send_packet(ssh, SSH1_CMSG_X11_REQUEST_FORWARDING,
|
||||
PKT_STR, ssh->x11auth->protoname,
|
||||
PKT_STR, ssh->x11auth->datastring,
|
||||
PKT_INT, ssh->x11disp->screennum,
|
||||
PKT_END);
|
||||
} else {
|
||||
send_packet(ssh, SSH1_CMSG_X11_REQUEST_FORWARDING,
|
||||
PKT_STR, ssh->x11auth->protoname,
|
||||
PKT_STR, ssh->x11auth->datastring,
|
||||
PKT_END);
|
||||
}
|
||||
do {
|
||||
crReturnV;
|
||||
} while (!pktin);
|
||||
if (pktin->type != SSH1_SMSG_SUCCESS
|
||||
&& pktin->type != SSH1_SMSG_FAILURE) {
|
||||
bombout(("Protocol confusion"));
|
||||
crStopV;
|
||||
} else if (pktin->type == SSH1_SMSG_FAILURE) {
|
||||
logevent("X11 forwarding refused");
|
||||
} else {
|
||||
logevent("X11 forwarding enabled");
|
||||
ssh->X11_fwd_enabled = TRUE;
|
||||
ssh->packet_dispatch[SSH1_SMSG_X11_OPEN] = ssh1_smsg_x11_open;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ssh_setup_portfwd(ssh, ssh->conf);
|
||||
@ -7563,7 +7576,7 @@ static void ssh2_msg_channel_open(Ssh ssh, struct Packet *pktin)
|
||||
|
||||
if (!ssh->X11_fwd_enabled)
|
||||
error = "X11 forwarding is not enabled";
|
||||
else if ((x11err = x11_init(&c->u.x11.xconn, ssh->x11disp, c,
|
||||
else if ((x11err = x11_init(&c->u.x11.xconn, ssh->x11authtree, c,
|
||||
addrstr, peerport)) != NULL) {
|
||||
logeventf(ssh, "Local X11 connection failed: %s", x11err);
|
||||
sfree(x11err);
|
||||
@ -7700,8 +7713,8 @@ static void ssh2_setup_x11(struct ssh_channel *c, struct Packet *pktin,
|
||||
pktout = ssh2_chanreq_init(ssh->mainchan, "x11-req",
|
||||
ssh2_setup_x11, s);
|
||||
ssh2_pkt_addbool(pktout, 0); /* many connections */
|
||||
ssh2_pkt_addstring(pktout, ssh->x11disp->remoteauthprotoname);
|
||||
ssh2_pkt_addstring(pktout, ssh->x11disp->remoteauthdatastring);
|
||||
ssh2_pkt_addstring(pktout, ssh->x11auth->protoname);
|
||||
ssh2_pkt_addstring(pktout, ssh->x11auth->datastring);
|
||||
ssh2_pkt_adduint32(pktout, ssh->x11disp->screennum);
|
||||
ssh2_pkt_send(ssh, pktout);
|
||||
|
||||
@ -9449,12 +9462,22 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
|
||||
*/
|
||||
|
||||
/* Potentially enable X11 forwarding. */
|
||||
if (conf_get_int(ssh->conf, CONF_x11_forward) &&
|
||||
(ssh->x11disp =
|
||||
x11_setup_display(conf_get_str(ssh->conf, CONF_x11_display),
|
||||
conf_get_int(ssh->conf, CONF_x11_auth),
|
||||
ssh->conf)))
|
||||
ssh2_setup_x11(ssh->mainchan, NULL, NULL);
|
||||
if (conf_get_int(ssh->conf, CONF_x11_forward)) {
|
||||
ssh->x11disp =
|
||||
x11_setup_display(conf_get_str(ssh->conf, CONF_x11_display),
|
||||
ssh->conf);
|
||||
if (!ssh->x11disp) {
|
||||
/* FIXME: return an error message from x11_setup_display */
|
||||
logevent("X11 forwarding not enabled: unable to"
|
||||
" initialise X display");
|
||||
} else {
|
||||
ssh->x11auth = x11_invent_fake_auth
|
||||
(ssh->x11authtree, conf_get_int(ssh->conf, CONF_x11_auth));
|
||||
ssh->x11auth->disp = ssh->x11disp;
|
||||
|
||||
ssh2_setup_x11(ssh->mainchan, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Potentially enable agent forwarding. */
|
||||
if (conf_get_int(ssh->conf, CONF_agentfwd) && agent_exists())
|
||||
@ -9805,6 +9828,8 @@ static const char *ssh_init(void *frontend_handle, void **backend_handle,
|
||||
ssh->pkt_kctx = SSH2_PKTCTX_NOKEX;
|
||||
ssh->pkt_actx = SSH2_PKTCTX_NOAUTH;
|
||||
ssh->x11disp = NULL;
|
||||
ssh->x11auth = NULL;
|
||||
ssh->x11authtree = newtree234(x11_authcmp);
|
||||
ssh->v1_compressing = FALSE;
|
||||
ssh->v2_outgoing_sequence = 0;
|
||||
ssh->ssh1_rdpkt_crstate = 0;
|
||||
@ -9883,6 +9908,7 @@ static void ssh_free(void *handle)
|
||||
Ssh ssh = (Ssh) handle;
|
||||
struct ssh_channel *c;
|
||||
struct ssh_rportfwd *pf;
|
||||
struct X11FakeAuth *auth;
|
||||
|
||||
if (ssh->v1_cipher_ctx)
|
||||
ssh->cipher->free_context(ssh->v1_cipher_ctx);
|
||||
@ -9960,6 +9986,9 @@ static void ssh_free(void *handle)
|
||||
sfree(ssh->deferred_send_data);
|
||||
if (ssh->x11disp)
|
||||
x11_free_display(ssh->x11disp);
|
||||
while ((auth = delpos234(ssh->x11authtree, 0)) != NULL)
|
||||
x11_free_fake_auth(auth);
|
||||
freetree234(ssh->x11authtree);
|
||||
sfree(ssh->do_ssh_init_state);
|
||||
sfree(ssh->do_ssh1_login_state);
|
||||
sfree(ssh->do_ssh2_transport_state);
|
||||
|
33
ssh.h
33
ssh.h
@ -372,24 +372,36 @@ struct X11Display {
|
||||
int port;
|
||||
char *realhost;
|
||||
|
||||
/* Auth details we invented for the virtual display on the SSH server. */
|
||||
int remoteauthproto;
|
||||
unsigned char *remoteauthdata;
|
||||
int remoteauthdatalen;
|
||||
char *remoteauthprotoname;
|
||||
char *remoteauthdatastring;
|
||||
|
||||
/* Our local auth details for talking to the real X display. */
|
||||
int localauthproto;
|
||||
unsigned char *localauthdata;
|
||||
int localauthdatalen;
|
||||
};
|
||||
struct X11FakeAuth {
|
||||
/* Auth details we invented for a virtual display on the SSH server. */
|
||||
int proto;
|
||||
unsigned char *data;
|
||||
int datalen;
|
||||
char *protoname;
|
||||
char *datastring;
|
||||
|
||||
/* The encrypted form of the first block, in XDM-AUTHORIZATION-1.
|
||||
* Used as part of the key when these structures are organised
|
||||
* into a tree. See x11_invent_fake_auth for explanation. */
|
||||
unsigned char *xa1_firstblock;
|
||||
|
||||
/*
|
||||
* Used inside x11fwd.c to remember recently seen
|
||||
* XDM-AUTHORIZATION-1 strings, to avoid replay attacks.
|
||||
*/
|
||||
tree234 *xdmseen;
|
||||
|
||||
/*
|
||||
* What to do with an X connection matching this auth data.
|
||||
*/
|
||||
struct X11Display *disp;
|
||||
};
|
||||
int x11_authcmp(void *av, void *bv); /* for putting X11FakeAuth in a tree234 */
|
||||
/*
|
||||
* x11_setup_display() parses the display variable and fills in an
|
||||
* X11Display structure. Some remote auth details are invented;
|
||||
@ -397,11 +409,12 @@ struct X11Display {
|
||||
* authorisation protocol to use at the remote end. The local auth
|
||||
* details are looked up by calling platform_get_x11_auth.
|
||||
*/
|
||||
extern struct X11Display *x11_setup_display(char *display, int authtype,
|
||||
Conf *);
|
||||
extern struct X11Display *x11_setup_display(char *display, Conf *);
|
||||
void x11_free_display(struct X11Display *disp);
|
||||
struct X11FakeAuth *x11_invent_fake_auth(tree234 *t, int authtype);
|
||||
void x11_free_fake_auth(struct X11FakeAuth *auth);
|
||||
struct X11Connection; /* opaque outside x11fwd.c */
|
||||
extern char *x11_init(struct X11Connection **, struct X11Display *,
|
||||
extern char *x11_init(struct X11Connection **, tree234 *authtree,
|
||||
void *, const char *, int);
|
||||
extern void x11_close(struct X11Connection *);
|
||||
extern int x11_send(struct X11Connection *, char *, int);
|
||||
|
4
sshdes.c
4
sshdes.c
@ -934,7 +934,7 @@ void des_encrypt_xdmauth(const unsigned char *keydata,
|
||||
{
|
||||
DESContext dc;
|
||||
des_keysetup_xdmauth(keydata, &dc);
|
||||
des_cbc_encrypt(blk, 24, &dc);
|
||||
des_cbc_encrypt(blk, len, &dc);
|
||||
}
|
||||
|
||||
void des_decrypt_xdmauth(const unsigned char *keydata,
|
||||
@ -942,7 +942,7 @@ void des_decrypt_xdmauth(const unsigned char *keydata,
|
||||
{
|
||||
DESContext dc;
|
||||
des_keysetup_xdmauth(keydata, &dc);
|
||||
des_cbc_decrypt(blk, 24, &dc);
|
||||
des_cbc_decrypt(blk, len, &dc);
|
||||
}
|
||||
|
||||
static const struct ssh2_cipher ssh_3des_ssh2 = {
|
||||
|
218
x11fwd.c
218
x11fwd.c
@ -30,6 +30,7 @@ struct X11Connection {
|
||||
const struct plug_function_table *fn;
|
||||
/* the above variable absolutely *must* be the first in this structure */
|
||||
unsigned char firstpkt[12]; /* first X data packet */
|
||||
tree234 *authtree;
|
||||
struct X11Display *disp;
|
||||
char *auth_protocol;
|
||||
unsigned char *auth_data;
|
||||
@ -69,11 +70,102 @@ static const struct plug_function_table dummy_plug = {
|
||||
dummy_plug_sent, dummy_plug_accepting
|
||||
};
|
||||
|
||||
struct X11Display *x11_setup_display(char *display, int authtype, Conf *conf)
|
||||
struct X11FakeAuth *x11_invent_fake_auth(tree234 *authtree, int authtype)
|
||||
{
|
||||
struct X11FakeAuth *auth = snew(struct X11FakeAuth);
|
||||
int i;
|
||||
|
||||
if (authtype == X11_MIT) {
|
||||
auth->proto = X11_MIT;
|
||||
|
||||
/* MIT-MAGIC-COOKIE-1. Cookie size is 128 bits (16 bytes). */
|
||||
auth->datalen = 16;
|
||||
auth->data = snewn(auth->datalen, unsigned char);
|
||||
auth->xa1_firstblock = NULL;
|
||||
|
||||
while (1) {
|
||||
for (i = 0; i < auth->datalen; i++)
|
||||
auth->data[i] = random_byte();
|
||||
if (add234(authtree, auth) == auth)
|
||||
break;
|
||||
}
|
||||
|
||||
auth->xdmseen = NULL;
|
||||
} else {
|
||||
assert(authtype == X11_XDM);
|
||||
auth->proto = X11_XDM;
|
||||
|
||||
/* XDM-AUTHORIZATION-1. Cookie size is 16 bytes; byte 8 is zero. */
|
||||
auth->datalen = 16;
|
||||
auth->data = snewn(auth->datalen, unsigned char);
|
||||
auth->xa1_firstblock = snewn(8, unsigned char);
|
||||
memset(auth->xa1_firstblock, 0, 8);
|
||||
|
||||
while (1) {
|
||||
for (i = 0; i < auth->datalen; i++)
|
||||
auth->data[i] = (i == 8 ? 0 : random_byte());
|
||||
memcpy(auth->xa1_firstblock, auth->data, 8);
|
||||
des_encrypt_xdmauth(auth->data + 9, auth->xa1_firstblock, 8);
|
||||
if (add234(authtree, auth) == auth)
|
||||
break;
|
||||
}
|
||||
|
||||
auth->xdmseen = newtree234(xdmseen_cmp);
|
||||
}
|
||||
auth->protoname = dupstr(x11_authnames[auth->proto]);
|
||||
auth->datastring = snewn(auth->datalen * 2 + 1, char);
|
||||
for (i = 0; i < auth->datalen; i++)
|
||||
sprintf(auth->datastring + i*2, "%02x",
|
||||
auth->data[i]);
|
||||
|
||||
return auth;
|
||||
}
|
||||
|
||||
void x11_free_fake_auth(struct X11FakeAuth *auth)
|
||||
{
|
||||
if (auth->data)
|
||||
smemclr(auth->data, auth->datalen);
|
||||
sfree(auth->data);
|
||||
sfree(auth->protoname);
|
||||
sfree(auth->datastring);
|
||||
sfree(auth->xa1_firstblock);
|
||||
if (auth->xdmseen != NULL) {
|
||||
struct XDMSeen *seen;
|
||||
while ((seen = delpos234(auth->xdmseen, 0)) != NULL)
|
||||
sfree(seen);
|
||||
freetree234(auth->xdmseen);
|
||||
}
|
||||
sfree(auth);
|
||||
}
|
||||
|
||||
int x11_authcmp(void *av, void *bv)
|
||||
{
|
||||
struct X11FakeAuth *a = (struct X11FakeAuth *)av;
|
||||
struct X11FakeAuth *b = (struct X11FakeAuth *)bv;
|
||||
|
||||
if (a->proto < b->proto)
|
||||
return -1;
|
||||
else if (a->proto > b->proto)
|
||||
return +1;
|
||||
|
||||
if (a->proto == X11_MIT) {
|
||||
if (a->datalen < b->datalen)
|
||||
return -1;
|
||||
else if (a->datalen > b->datalen)
|
||||
return +1;
|
||||
|
||||
return memcmp(a->data, b->data, a->datalen);
|
||||
} else {
|
||||
assert(a->proto == X11_XDM);
|
||||
|
||||
return memcmp(a->xa1_firstblock, b->xa1_firstblock, 8);
|
||||
}
|
||||
}
|
||||
|
||||
struct X11Display *x11_setup_display(char *display, Conf *conf)
|
||||
{
|
||||
struct X11Display *disp = snew(struct X11Display);
|
||||
char *localcopy;
|
||||
int i;
|
||||
|
||||
if (!display || !*display) {
|
||||
localcopy = platform_get_x_display();
|
||||
@ -213,37 +305,6 @@ struct X11Display *x11_setup_display(char *display, int authtype, Conf *conf)
|
||||
disp->port = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Invent the remote authorisation details.
|
||||
*/
|
||||
if (authtype == X11_MIT) {
|
||||
disp->remoteauthproto = X11_MIT;
|
||||
|
||||
/* MIT-MAGIC-COOKIE-1. Cookie size is 128 bits (16 bytes). */
|
||||
disp->remoteauthdata = snewn(16, unsigned char);
|
||||
for (i = 0; i < 16; i++)
|
||||
disp->remoteauthdata[i] = random_byte();
|
||||
disp->remoteauthdatalen = 16;
|
||||
|
||||
disp->xdmseen = NULL;
|
||||
} else {
|
||||
assert(authtype == X11_XDM);
|
||||
disp->remoteauthproto = X11_XDM;
|
||||
|
||||
/* XDM-AUTHORIZATION-1. Cookie size is 16 bytes; byte 8 is zero. */
|
||||
disp->remoteauthdata = snewn(16, unsigned char);
|
||||
for (i = 0; i < 16; i++)
|
||||
disp->remoteauthdata[i] = (i == 8 ? 0 : random_byte());
|
||||
disp->remoteauthdatalen = 16;
|
||||
|
||||
disp->xdmseen = newtree234(xdmseen_cmp);
|
||||
}
|
||||
disp->remoteauthprotoname = dupstr(x11_authnames[disp->remoteauthproto]);
|
||||
disp->remoteauthdatastring = snewn(disp->remoteauthdatalen * 2 + 1, char);
|
||||
for (i = 0; i < disp->remoteauthdatalen; i++)
|
||||
sprintf(disp->remoteauthdatastring + i*2, "%02x",
|
||||
disp->remoteauthdata[i]);
|
||||
|
||||
/*
|
||||
* Fetch the local authorisation details.
|
||||
*/
|
||||
@ -257,22 +318,11 @@ struct X11Display *x11_setup_display(char *display, int authtype, Conf *conf)
|
||||
|
||||
void x11_free_display(struct X11Display *disp)
|
||||
{
|
||||
if (disp->xdmseen != NULL) {
|
||||
struct XDMSeen *seen;
|
||||
while ((seen = delpos234(disp->xdmseen, 0)) != NULL)
|
||||
sfree(seen);
|
||||
freetree234(disp->xdmseen);
|
||||
}
|
||||
sfree(disp->hostname);
|
||||
sfree(disp->unixsocketpath);
|
||||
if (disp->localauthdata)
|
||||
smemclr(disp->localauthdata, disp->localauthdatalen);
|
||||
sfree(disp->localauthdata);
|
||||
if (disp->remoteauthdata)
|
||||
smemclr(disp->remoteauthdata, disp->remoteauthdatalen);
|
||||
sfree(disp->remoteauthdata);
|
||||
sfree(disp->remoteauthprotoname);
|
||||
sfree(disp->remoteauthdatastring);
|
||||
sk_addr_free(disp->addr);
|
||||
sfree(disp);
|
||||
}
|
||||
@ -280,18 +330,37 @@ void x11_free_display(struct X11Display *disp)
|
||||
#define XDM_MAXSKEW 20*60 /* 20 minute clock skew should be OK */
|
||||
|
||||
static char *x11_verify(unsigned long peer_ip, int peer_port,
|
||||
struct X11Display *disp, char *proto,
|
||||
unsigned char *data, int dlen)
|
||||
tree234 *authtree, char *proto,
|
||||
unsigned char *data, int dlen,
|
||||
struct X11FakeAuth **auth_ret)
|
||||
{
|
||||
if (strcmp(proto, x11_authnames[disp->remoteauthproto]) != 0)
|
||||
return "wrong authorisation protocol attempted";
|
||||
if (disp->remoteauthproto == X11_MIT) {
|
||||
if (dlen != disp->remoteauthdatalen)
|
||||
return "MIT-MAGIC-COOKIE-1 data was wrong length";
|
||||
if (memcmp(disp->remoteauthdata, data, dlen) != 0)
|
||||
return "MIT-MAGIC-COOKIE-1 data did not match";
|
||||
struct X11FakeAuth match_dummy; /* for passing to find234 */
|
||||
struct X11FakeAuth *auth;
|
||||
|
||||
/*
|
||||
* First, do a lookup in our tree to find the only authorisation
|
||||
* record that _might_ match.
|
||||
*/
|
||||
if (!strcmp(proto, x11_authnames[X11_MIT])) {
|
||||
match_dummy.proto = X11_MIT;
|
||||
match_dummy.datalen = dlen;
|
||||
match_dummy.data = data;
|
||||
} else if (!strcmp(proto, x11_authnames[X11_XDM])) {
|
||||
match_dummy.proto = X11_XDM;
|
||||
match_dummy.xa1_firstblock = data;
|
||||
} else {
|
||||
return "Unsupported authorisation protocol";
|
||||
}
|
||||
if (disp->remoteauthproto == X11_XDM) {
|
||||
|
||||
if ((auth = find234(authtree, &match_dummy, 0)) == NULL)
|
||||
return "Authorisation not recognised";
|
||||
|
||||
/*
|
||||
* If we're using MIT-MAGIC-COOKIE-1, that was all we needed. If
|
||||
* we're doing XDM-AUTHORIZATION-1, though, we have to check the
|
||||
* rest of the auth data.
|
||||
*/
|
||||
if (auth->proto == X11_XDM) {
|
||||
unsigned long t;
|
||||
time_t tim;
|
||||
int i;
|
||||
@ -301,8 +370,8 @@ static char *x11_verify(unsigned long peer_ip, int peer_port,
|
||||
return "XDM-AUTHORIZATION-1 data was wrong length";
|
||||
if (peer_port == -1)
|
||||
return "cannot do XDM-AUTHORIZATION-1 without remote address data";
|
||||
des_decrypt_xdmauth(disp->remoteauthdata+9, data, 24);
|
||||
if (memcmp(disp->remoteauthdata, data, 8) != 0)
|
||||
des_decrypt_xdmauth(auth->data+9, data, 24);
|
||||
if (memcmp(auth->data, data, 8) != 0)
|
||||
return "XDM-AUTHORIZATION-1 data failed check"; /* cookie wrong */
|
||||
if (GET_32BIT_MSB_FIRST(data+8) != peer_ip)
|
||||
return "XDM-AUTHORIZATION-1 data failed check"; /* IP wrong */
|
||||
@ -318,22 +387,24 @@ static char *x11_verify(unsigned long peer_ip, int peer_port,
|
||||
seen = snew(struct XDMSeen);
|
||||
seen->time = t;
|
||||
memcpy(seen->clientid, data+8, 6);
|
||||
assert(disp->xdmseen != NULL);
|
||||
ret = add234(disp->xdmseen, seen);
|
||||
assert(auth->xdmseen != NULL);
|
||||
ret = add234(auth->xdmseen, seen);
|
||||
if (ret != seen) {
|
||||
sfree(seen);
|
||||
return "XDM-AUTHORIZATION-1 data replayed";
|
||||
}
|
||||
/* While we're here, purge entries too old to be replayed. */
|
||||
for (;;) {
|
||||
seen = index234(disp->xdmseen, 0);
|
||||
seen = index234(auth->xdmseen, 0);
|
||||
assert(seen != NULL);
|
||||
if (t - seen->time <= XDM_MAXSKEW)
|
||||
break;
|
||||
sfree(delpos234(disp->xdmseen, 0));
|
||||
sfree(delpos234(auth->xdmseen, 0));
|
||||
}
|
||||
}
|
||||
/* implement other protocols here if ever required */
|
||||
|
||||
*auth_ret = auth;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -584,7 +655,7 @@ int x11_get_screen_number(char *display)
|
||||
* a dynamically allocated error message string.
|
||||
*/
|
||||
extern char *x11_init(struct X11Connection **xconnret,
|
||||
struct X11Display *disp, void *c,
|
||||
tree234 *authtree, void *c,
|
||||
const char *peeraddr, int peerport)
|
||||
{
|
||||
static const struct plug_function_table fn_table = {
|
||||
@ -603,7 +674,7 @@ extern char *x11_init(struct X11Connection **xconnret,
|
||||
xconn = *xconnret = snew(struct X11Connection);
|
||||
xconn->fn = &fn_table;
|
||||
xconn->auth_protocol = NULL;
|
||||
xconn->disp = disp;
|
||||
xconn->authtree = authtree;
|
||||
xconn->verified = 0;
|
||||
xconn->data_read = 0;
|
||||
xconn->throttled = xconn->throttle_override = 0;
|
||||
@ -611,12 +682,14 @@ extern char *x11_init(struct X11Connection **xconnret,
|
||||
xconn->c = c;
|
||||
|
||||
/*
|
||||
* We don't actually open a local socket to the X server just yet.
|
||||
* Instead, we'll wait until we see the incoming authentication
|
||||
* data, which may tell us we have to divert this X forwarding
|
||||
* channel to a connection-sharing downstream rather than handling
|
||||
* it ourself.
|
||||
* We don't actually open a local socket to the X server just yet,
|
||||
* because we don't know which one it is. Instead, we'll wait
|
||||
* until we see the incoming authentication data, which may tell
|
||||
* us what display to connect to, or whether we have to divert
|
||||
* this X forwarding channel to a connection-sharing downstream
|
||||
* rather than handling it ourself.
|
||||
*/
|
||||
xconn->disp = NULL;
|
||||
xconn->s = NULL;
|
||||
|
||||
/*
|
||||
@ -745,22 +818,25 @@ int x11_send(struct X11Connection *xconn, char *data, int len)
|
||||
*/
|
||||
if (!xconn->verified) {
|
||||
const char *err;
|
||||
struct X11FakeAuth *auth_matched = NULL;
|
||||
|
||||
assert(!xconn->s);
|
||||
|
||||
xconn->auth_protocol[xconn->auth_plen] = '\0'; /* ASCIZ */
|
||||
err = x11_verify(xconn->peer_ip, xconn->peer_port,
|
||||
xconn->disp, xconn->auth_protocol,
|
||||
xconn->auth_data, xconn->auth_dlen);
|
||||
xconn->authtree, xconn->auth_protocol,
|
||||
xconn->auth_data, xconn->auth_dlen, &auth_matched);
|
||||
if (err) {
|
||||
x11_send_init_error(xconn, err);
|
||||
return 0;
|
||||
}
|
||||
assert(auth_matched);
|
||||
|
||||
/*
|
||||
* Now we know we're going to accept the connection. Actually
|
||||
* connect to the X server.
|
||||
* Now we know we're going to accept the connection, and what
|
||||
* X display to connect to. Actually connect to it.
|
||||
*/
|
||||
xconn->disp = auth_matched->disp;
|
||||
xconn->s = new_connection(sk_addr_dup(xconn->disp->addr),
|
||||
xconn->disp->realhost, xconn->disp->port,
|
||||
0, 1, 0, 0, (Plug) xconn,
|
||||
|
Loading…
Reference in New Issue
Block a user