mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-10 09:58:01 +00:00
Decouple X socket opening from x11_init().
Now we wait to open the socket to the X server until we've seen the authorisation data. This prepares us to do something else with the channel if we see different auth data, which will come up in connection sharing. [originally from svn r10078]
This commit is contained in:
parent
961503e449
commit
01085358e4
10
ssh.c
10
ssh.c
@ -4355,6 +4355,12 @@ static void ssh_channel_try_eof(struct ssh_channel *c)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Conf *sshfwd_get_conf(struct ssh_channel *c)
|
||||||
|
{
|
||||||
|
Ssh ssh = c->ssh;
|
||||||
|
return ssh->conf;
|
||||||
|
}
|
||||||
|
|
||||||
void sshfwd_write_eof(struct ssh_channel *c)
|
void sshfwd_write_eof(struct ssh_channel *c)
|
||||||
{
|
{
|
||||||
Ssh ssh = c->ssh;
|
Ssh ssh = c->ssh;
|
||||||
@ -4885,7 +4891,7 @@ static void ssh1_smsg_x11_open(Ssh ssh, struct Packet *pktin)
|
|||||||
c->ssh = ssh;
|
c->ssh = ssh;
|
||||||
|
|
||||||
if ((err = x11_init(&c->u.x11.xconn, ssh->x11disp, c,
|
if ((err = x11_init(&c->u.x11.xconn, ssh->x11disp, c,
|
||||||
NULL, -1, ssh->conf)) != NULL) {
|
NULL, -1)) != NULL) {
|
||||||
logeventf(ssh, "Opening X11 forward connection failed: %s", err);
|
logeventf(ssh, "Opening X11 forward connection failed: %s", err);
|
||||||
sfree(err);
|
sfree(err);
|
||||||
sfree(c);
|
sfree(c);
|
||||||
@ -7558,7 +7564,7 @@ static void ssh2_msg_channel_open(Ssh ssh, struct Packet *pktin)
|
|||||||
if (!ssh->X11_fwd_enabled)
|
if (!ssh->X11_fwd_enabled)
|
||||||
error = "X11 forwarding is not 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->x11disp, c,
|
||||||
addrstr, peerport, ssh->conf)) != NULL) {
|
addrstr, peerport)) != NULL) {
|
||||||
logeventf(ssh, "Local X11 connection failed: %s", x11err);
|
logeventf(ssh, "Local X11 connection failed: %s", x11err);
|
||||||
sfree(x11err);
|
sfree(x11err);
|
||||||
error = "Unable to open an X11 connection";
|
error = "Unable to open an X11 connection";
|
||||||
|
3
ssh.h
3
ssh.h
@ -13,6 +13,7 @@ extern int sshfwd_write(struct ssh_channel *c, char *, int);
|
|||||||
extern void sshfwd_write_eof(struct ssh_channel *c);
|
extern void sshfwd_write_eof(struct ssh_channel *c);
|
||||||
extern void sshfwd_unclean_close(struct ssh_channel *c, const char *err);
|
extern void sshfwd_unclean_close(struct ssh_channel *c, const char *err);
|
||||||
extern void sshfwd_unthrottle(struct ssh_channel *c, int bufsize);
|
extern void sshfwd_unthrottle(struct ssh_channel *c, int bufsize);
|
||||||
|
Conf *sshfwd_get_conf(struct ssh_channel *c);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Useful thing.
|
* Useful thing.
|
||||||
@ -401,7 +402,7 @@ extern struct X11Display *x11_setup_display(char *display, int authtype,
|
|||||||
void x11_free_display(struct X11Display *disp);
|
void x11_free_display(struct X11Display *disp);
|
||||||
struct X11Connection; /* opaque outside x11fwd.c */
|
struct X11Connection; /* opaque outside x11fwd.c */
|
||||||
extern char *x11_init(struct X11Connection **, struct X11Display *,
|
extern char *x11_init(struct X11Connection **, struct X11Display *,
|
||||||
void *, const char *, int, Conf *);
|
void *, const char *, int);
|
||||||
extern void x11_close(struct X11Connection *);
|
extern void x11_close(struct X11Connection *);
|
||||||
extern int x11_send(struct X11Connection *, char *, int);
|
extern int x11_send(struct X11Connection *, char *, int);
|
||||||
extern void x11_send_eof(struct X11Connection *s);
|
extern void x11_send_eof(struct X11Connection *s);
|
||||||
|
129
x11fwd.c
129
x11fwd.c
@ -36,6 +36,7 @@ struct X11Connection {
|
|||||||
int data_read, auth_plen, auth_psize, auth_dlen, auth_dsize;
|
int data_read, auth_plen, auth_psize, auth_dlen, auth_dsize;
|
||||||
int verified;
|
int verified;
|
||||||
int throttled, throttle_override;
|
int throttled, throttle_override;
|
||||||
|
int no_data_sent_to_x_client;
|
||||||
unsigned long peer_ip;
|
unsigned long peer_ip;
|
||||||
int peer_port;
|
int peer_port;
|
||||||
struct ssh_channel *c; /* channel structure held by ssh.c */
|
struct ssh_channel *c; /* channel structure held by ssh.c */
|
||||||
@ -501,6 +502,9 @@ static void x11_log(Plug p, int type, SockAddr addr, int port,
|
|||||||
/* We have no interface to the logging module here, so we drop these. */
|
/* We have no interface to the logging module here, so we drop these. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void x11_send_init_error(struct X11Connection *conn,
|
||||||
|
const char *err_message);
|
||||||
|
|
||||||
static int x11_closing(Plug plug, const char *error_msg, int error_code,
|
static int x11_closing(Plug plug, const char *error_msg, int error_code,
|
||||||
int calling_back)
|
int calling_back)
|
||||||
{
|
{
|
||||||
@ -508,7 +512,19 @@ static int x11_closing(Plug plug, const char *error_msg, int error_code,
|
|||||||
|
|
||||||
if (error_msg) {
|
if (error_msg) {
|
||||||
/*
|
/*
|
||||||
* Socket error. Slam the connection instantly shut.
|
* Socket error. If we're still at the connection setup stage,
|
||||||
|
* construct an X11 error packet passing on the problem.
|
||||||
|
*/
|
||||||
|
if (xconn->no_data_sent_to_x_client) {
|
||||||
|
char *err_message = dupprintf("unable to connect to forwarded "
|
||||||
|
"X server: %s", error_msg);
|
||||||
|
x11_send_init_error(xconn, err_message);
|
||||||
|
sfree(err_message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Whether we did that or not, now we slam the connection
|
||||||
|
* shut.
|
||||||
*/
|
*/
|
||||||
sshfwd_unclean_close(xconn->c, error_msg);
|
sshfwd_unclean_close(xconn->c, error_msg);
|
||||||
} else {
|
} else {
|
||||||
@ -529,6 +545,7 @@ static int x11_receive(Plug plug, int urgent, char *data, int len)
|
|||||||
|
|
||||||
if (sshfwd_write(xconn->c, data, len) > 0) {
|
if (sshfwd_write(xconn->c, data, len) > 0) {
|
||||||
xconn->throttled = 1;
|
xconn->throttled = 1;
|
||||||
|
xconn->no_data_sent_to_x_client = FALSE;
|
||||||
sk_set_frozen(xconn->s, 1);
|
sk_set_frozen(xconn->s, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -568,7 +585,7 @@ int x11_get_screen_number(char *display)
|
|||||||
*/
|
*/
|
||||||
extern char *x11_init(struct X11Connection **xconnret,
|
extern char *x11_init(struct X11Connection **xconnret,
|
||||||
struct X11Display *disp, void *c,
|
struct X11Display *disp, void *c,
|
||||||
const char *peeraddr, int peerport, Conf *conf)
|
const char *peeraddr, int peerport)
|
||||||
{
|
{
|
||||||
static const struct plug_function_table fn_table = {
|
static const struct plug_function_table fn_table = {
|
||||||
x11_log,
|
x11_log,
|
||||||
@ -578,7 +595,6 @@ extern char *x11_init(struct X11Connection **xconnret,
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *err;
|
|
||||||
struct X11Connection *xconn;
|
struct X11Connection *xconn;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -591,18 +607,17 @@ extern char *x11_init(struct X11Connection **xconnret,
|
|||||||
xconn->verified = 0;
|
xconn->verified = 0;
|
||||||
xconn->data_read = 0;
|
xconn->data_read = 0;
|
||||||
xconn->throttled = xconn->throttle_override = 0;
|
xconn->throttled = xconn->throttle_override = 0;
|
||||||
|
xconn->no_data_sent_to_x_client = TRUE;
|
||||||
xconn->c = c;
|
xconn->c = c;
|
||||||
|
|
||||||
xconn->s = new_connection(sk_addr_dup(disp->addr),
|
/*
|
||||||
disp->realhost, disp->port,
|
* We don't actually open a local socket to the X server just yet.
|
||||||
0, 1, 0, 0, (Plug) xconn, conf);
|
* Instead, we'll wait until we see the incoming authentication
|
||||||
if ((err = sk_socket_error(xconn->s)) != NULL) {
|
* data, which may tell us we have to divert this X forwarding
|
||||||
char *err_ret = dupstr(err);
|
* channel to a connection-sharing downstream rather than handling
|
||||||
sk_close(xconn->s);
|
* it ourself.
|
||||||
sfree(xconn);
|
*/
|
||||||
*xconnret = NULL;
|
xconn->s = NULL;
|
||||||
return err_ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* See if we can make sense of the peer address we were given.
|
* See if we can make sense of the peer address we were given.
|
||||||
@ -632,6 +647,7 @@ void x11_close(struct X11Connection *xconn)
|
|||||||
sfree(xconn->auth_data);
|
sfree(xconn->auth_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (xconn->s)
|
||||||
sk_close(xconn->s);
|
sk_close(xconn->s);
|
||||||
sfree(xconn);
|
sfree(xconn);
|
||||||
}
|
}
|
||||||
@ -642,6 +658,7 @@ void x11_unthrottle(struct X11Connection *xconn)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
xconn->throttled = 0;
|
xconn->throttled = 0;
|
||||||
|
if (xconn->s)
|
||||||
sk_set_frozen(xconn->s, xconn->throttled || xconn->throttle_override);
|
sk_set_frozen(xconn->s, xconn->throttled || xconn->throttle_override);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -651,9 +668,35 @@ void x11_override_throttle(struct X11Connection *xconn, int enable)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
xconn->throttle_override = enable;
|
xconn->throttle_override = enable;
|
||||||
|
if (xconn->s)
|
||||||
sk_set_frozen(xconn->s, xconn->throttled || xconn->throttle_override);
|
sk_set_frozen(xconn->s, xconn->throttled || xconn->throttle_override);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void x11_send_init_error(struct X11Connection *xconn,
|
||||||
|
const char *err_message)
|
||||||
|
{
|
||||||
|
char *full_message;
|
||||||
|
int msglen, msgsize;
|
||||||
|
unsigned char *reply;
|
||||||
|
|
||||||
|
full_message = dupprintf("%s X11 proxy: %s\n", appname, err_message);
|
||||||
|
|
||||||
|
msglen = strlen(full_message);
|
||||||
|
reply = snewn(8 + msglen+1 + 4, unsigned char); /* include zero */
|
||||||
|
msgsize = (msglen + 3) & ~3;
|
||||||
|
reply[0] = 0; /* failure */
|
||||||
|
reply[1] = msglen; /* length of reason string */
|
||||||
|
memcpy(reply + 2, xconn->firstpkt + 2, 4); /* major/minor proto vsn */
|
||||||
|
PUT_16BIT(xconn->firstpkt[0], reply + 6, msgsize >> 2);/* data len */
|
||||||
|
memset(reply + 8, 0, msgsize);
|
||||||
|
memcpy(reply + 8, full_message, msglen);
|
||||||
|
sshfwd_write(xconn->c, (char *)reply, 8 + msgsize);
|
||||||
|
sshfwd_write_eof(xconn->c);
|
||||||
|
xconn->no_data_sent_to_x_client = FALSE;
|
||||||
|
sfree(reply);
|
||||||
|
sfree(full_message);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called to send data down the raw connection.
|
* Called to send data down the raw connection.
|
||||||
*/
|
*/
|
||||||
@ -701,43 +744,38 @@ int x11_send(struct X11Connection *xconn, char *data, int len)
|
|||||||
* If we haven't verified the authorisation, do so now.
|
* If we haven't verified the authorisation, do so now.
|
||||||
*/
|
*/
|
||||||
if (!xconn->verified) {
|
if (!xconn->verified) {
|
||||||
char *err;
|
const char *err;
|
||||||
|
|
||||||
|
assert(!xconn->s);
|
||||||
|
|
||||||
xconn->auth_protocol[xconn->auth_plen] = '\0'; /* ASCIZ */
|
xconn->auth_protocol[xconn->auth_plen] = '\0'; /* ASCIZ */
|
||||||
err = x11_verify(xconn->peer_ip, xconn->peer_port,
|
err = x11_verify(xconn->peer_ip, xconn->peer_port,
|
||||||
xconn->disp, xconn->auth_protocol,
|
xconn->disp, xconn->auth_protocol,
|
||||||
xconn->auth_data, xconn->auth_dlen);
|
xconn->auth_data, xconn->auth_dlen);
|
||||||
|
|
||||||
/*
|
|
||||||
* If authorisation failed, construct and send an error
|
|
||||||
* packet, then terminate the connection.
|
|
||||||
*/
|
|
||||||
if (err) {
|
if (err) {
|
||||||
char *message;
|
x11_send_init_error(xconn, err);
|
||||||
int msglen, msgsize;
|
|
||||||
unsigned char *reply;
|
|
||||||
|
|
||||||
message = dupprintf("%s X11 proxy: %s", appname, err);
|
|
||||||
msglen = strlen(message);
|
|
||||||
reply = snewn(8 + msglen+1 + 4, unsigned char); /* include zero */
|
|
||||||
msgsize = (msglen + 3) & ~3;
|
|
||||||
reply[0] = 0; /* failure */
|
|
||||||
reply[1] = msglen; /* length of reason string */
|
|
||||||
memcpy(reply + 2, xconn->firstpkt + 2, 4); /* major/minor proto vsn */
|
|
||||||
PUT_16BIT(xconn->firstpkt[0], reply + 6, msgsize >> 2);/* data len */
|
|
||||||
memset(reply + 8, 0, msgsize);
|
|
||||||
memcpy(reply + 8, message, msglen);
|
|
||||||
sshfwd_write(xconn->c, (char *)reply, 8 + msgsize);
|
|
||||||
sshfwd_write_eof(xconn->c);
|
|
||||||
sfree(reply);
|
|
||||||
sfree(message);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now we know we're going to accept the connection. Strip
|
* Now we know we're going to accept the connection. Actually
|
||||||
* the fake auth data, and optionally put real auth data in
|
* connect to the X server.
|
||||||
* instead.
|
*/
|
||||||
|
xconn->s = new_connection(sk_addr_dup(xconn->disp->addr),
|
||||||
|
xconn->disp->realhost, xconn->disp->port,
|
||||||
|
0, 1, 0, 0, (Plug) xconn,
|
||||||
|
sshfwd_get_conf(xconn->c));
|
||||||
|
if ((err = sk_socket_error(xconn->s)) != NULL) {
|
||||||
|
char *err_message = dupprintf("unable to connect to"
|
||||||
|
" forwarded X server: %s", err);
|
||||||
|
x11_send_init_error(xconn, err_message);
|
||||||
|
sfree(err_message);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Strip the fake auth data, and optionally put real auth data
|
||||||
|
* in instead.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
char realauthdata[64];
|
char realauthdata[64];
|
||||||
@ -796,5 +834,16 @@ int x11_send(struct X11Connection *xconn, char *data, int len)
|
|||||||
|
|
||||||
void x11_send_eof(struct X11Connection *xconn)
|
void x11_send_eof(struct X11Connection *xconn)
|
||||||
{
|
{
|
||||||
|
if (xconn->s) {
|
||||||
sk_write_eof(xconn->s);
|
sk_write_eof(xconn->s);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* If EOF is received from the X client before we've got to
|
||||||
|
* the point of actually connecting to an X server, then we
|
||||||
|
* should send an EOF back to the client so that the
|
||||||
|
* forwarded channel will be terminated.
|
||||||
|
*/
|
||||||
|
if (xconn->c)
|
||||||
|
sshfwd_write_eof(xconn->c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user