2 * Platform-independent bits of X11 forwarding.
17 unsigned char clientid
[6];
20 typedef struct X11Connection
{
21 unsigned char firstpkt
[12]; /* first X data packet */
23 struct X11Display
*disp
;
25 unsigned char *auth_data
;
26 int data_read
, auth_plen
, auth_psize
, auth_dlen
, auth_dsize
;
29 bool no_data_sent_to_x_client
;
32 SshChannel
*c
; /* channel structure held by SSH backend */
39 static int xdmseen_cmp(void *a
, void *b
)
41 struct XDMSeen
*sa
= a
, *sb
= b
;
42 return sa
->time
> sb
->time
? 1 :
43 sa
->time
< sb
->time
? -1 :
44 memcmp(sa
->clientid
, sb
->clientid
, sizeof(sa
->clientid
));
47 struct X11FakeAuth
*x11_invent_fake_auth(tree234
*authtree
, int authtype
)
49 struct X11FakeAuth
*auth
= snew(struct X11FakeAuth
);
53 * This function has the job of inventing a set of X11 fake auth
54 * data, and adding it to 'authtree'. We must preserve the
55 * property that for any given actual authorisation attempt, _at
56 * most one_ thing in the tree can possibly match it.
58 * For MIT-MAGIC-COOKIE-1, that's not too difficult: the match
59 * criterion is simply that the entire cookie is correct, so we
60 * just have to make sure we don't make up two cookies the same.
61 * (Vanishingly unlikely, but we check anyway to be sure, and go
62 * round again inventing a new cookie if add234 tells us the one
63 * we thought of is already in use.)
65 * For XDM-AUTHORIZATION-1, it's a little more fiddly. The setup
66 * with XA1 is that half the cookie is used as a DES key with
67 * which to CBC-encrypt an assortment of stuff. Happily, the stuff
68 * encrypted _begins_ with the other half of the cookie, and the
69 * IV is always zero, which means that any valid XA1 authorisation
70 * attempt for a given cookie must begin with the same cipher
71 * block, consisting of the DES ECB encryption of the first half
72 * of the cookie using the second half as a key. So we compute
73 * that cipher block here and now, and use it as the sorting key
74 * for distinguishing XA1 entries in the tree.
77 if (authtype
== X11_MIT
) {
78 auth
->proto
= X11_MIT
;
80 /* MIT-MAGIC-COOKIE-1. Cookie size is 128 bits (16 bytes). */
82 auth
->data
= snewn(auth
->datalen
, unsigned char);
83 auth
->xa1_firstblock
= NULL
;
86 random_read(auth
->data
, auth
->datalen
);
87 if (add234(authtree
, auth
) == auth
)
93 assert(authtype
== X11_XDM
);
94 auth
->proto
= X11_XDM
;
96 /* XDM-AUTHORIZATION-1. Cookie size is 16 bytes; byte 8 is zero. */
98 auth
->data
= snewn(auth
->datalen
, unsigned char);
99 auth
->xa1_firstblock
= snewn(8, unsigned char);
100 memset(auth
->xa1_firstblock
, 0, 8);
103 random_read(auth
->data
, 15);
104 auth
->data
[15] = auth
->data
[8];
107 memcpy(auth
->xa1_firstblock
, auth
->data
, 8);
108 des_encrypt_xdmauth(auth
->data
+ 9, auth
->xa1_firstblock
, 8);
109 if (add234(authtree
, auth
) == auth
)
113 auth
->xdmseen
= newtree234(xdmseen_cmp
);
115 auth
->protoname
= dupstr(x11_authnames
[auth
->proto
]);
116 auth
->datastring
= snewn(auth
->datalen
* 2 + 1, char);
117 for (i
= 0; i
< auth
->datalen
; i
++)
118 sprintf(auth
->datastring
+ i
*2, "%02x",
122 auth
->share_cs
= NULL
;
123 auth
->share_chan
= NULL
;
128 void x11_free_fake_auth(struct X11FakeAuth
*auth
)
131 smemclr(auth
->data
, auth
->datalen
);
133 sfree(auth
->protoname
);
134 sfree(auth
->datastring
);
135 sfree(auth
->xa1_firstblock
);
136 if (auth
->xdmseen
!= NULL
) {
137 struct XDMSeen
*seen
;
138 while ((seen
= delpos234(auth
->xdmseen
, 0)) != NULL
)
140 freetree234(auth
->xdmseen
);
145 int x11_authcmp(void *av
, void *bv
)
147 struct X11FakeAuth
*a
= (struct X11FakeAuth
*)av
;
148 struct X11FakeAuth
*b
= (struct X11FakeAuth
*)bv
;
150 if (a
->proto
< b
->proto
)
152 else if (a
->proto
> b
->proto
)
155 if (a
->proto
== X11_MIT
) {
156 if (a
->datalen
< b
->datalen
)
158 else if (a
->datalen
> b
->datalen
)
161 return memcmp(a
->data
, b
->data
, a
->datalen
);
163 assert(a
->proto
== X11_XDM
);
165 return memcmp(a
->xa1_firstblock
, b
->xa1_firstblock
, 8);
169 #define XDM_MAXSKEW 20*60 /* 20 minute clock skew should be OK */
171 static char *x11_verify(unsigned long peer_ip
, int peer_port
,
172 tree234
*authtree
, char *proto
,
173 unsigned char *data
, int dlen
,
174 struct X11FakeAuth
**auth_ret
)
176 struct X11FakeAuth match_dummy
; /* for passing to find234 */
177 struct X11FakeAuth
*auth
;
180 * First, do a lookup in our tree to find the only authorisation
181 * record that _might_ match.
183 if (!strcmp(proto
, x11_authnames
[X11_MIT
])) {
185 * Just look up the whole cookie that was presented to us,
186 * which x11_authcmp will compare against the cookies we
187 * currently believe in.
189 match_dummy
.proto
= X11_MIT
;
190 match_dummy
.datalen
= dlen
;
191 match_dummy
.data
= data
;
192 } else if (!strcmp(proto
, x11_authnames
[X11_XDM
])) {
194 * Look up the first cipher block, against the stored first
195 * cipher blocks for the XDM-AUTHORIZATION-1 cookies we
196 * currently know. (See comment in x11_invent_fake_auth.)
198 match_dummy
.proto
= X11_XDM
;
199 match_dummy
.xa1_firstblock
= data
;
200 } else if (!proto
[0]) {
202 * If the user has attempted to connect to the forwarded X
203 * display with no authority at all, we can give a better
204 * error message than the generic "unsupported protocol". We
205 * at least _recognise_ the null auth protocol, even if we
208 return dupstr("No authorisation provided");
210 return dupprintf("Unsupported authorisation protocol '%s'", proto
);
213 if ((auth
= find234(authtree
, &match_dummy
, 0)) == NULL
)
214 return dupstr("Authorisation not recognised");
217 * If we're using MIT-MAGIC-COOKIE-1, that was all we needed. If
218 * we're doing XDM-AUTHORIZATION-1, though, we have to check the
219 * rest of the auth data.
221 if (auth
->proto
== X11_XDM
) {
225 struct XDMSeen
*seen
, *ret
;
228 return dupprintf("XDM-AUTHORIZATION-1 data was wrong length "
229 "(%d, expected 24)", dlen
);
231 return dupstr("cannot do XDM-AUTHORIZATION-1 without remote "
233 des_decrypt_xdmauth(auth
->data
+9, data
, 24);
235 /* Bitwise-OR together any mismatches in the fixed parts of
236 * the data, to allow checking it all at once */
237 uint32_t mismatches
= 0;
238 /* Check non-key half of auth cookie */
239 for (i
= 0; i
< 8; i
++)
240 mismatches
|= auth
->data
[i
] ^ data
[i
];
241 /* Check IP address and port */
242 mismatches
|= GET_32BIT_MSB_FIRST(data
+8) ^ peer_ip
;
243 mismatches
|= (unsigned short)(GET_16BIT_MSB_FIRST(data
+12) ^
245 /* Check zero padding */
246 for (i
= 18; i
< 24; i
++)
247 mismatches
|= data
[i
];
249 return dupstr("XDM-AUTHORIZATION-1 data failed check");
251 t
= GET_32BIT_MSB_FIRST(data
+14);
253 if (((unsigned long)t
- (unsigned long)tim
254 + XDM_MAXSKEW
) > 2*XDM_MAXSKEW
)
255 return dupstr("XDM-AUTHORIZATION-1 time stamp was too far out");
256 seen
= snew(struct XDMSeen
);
258 memcpy(seen
->clientid
, data
+8, 6);
259 assert(auth
->xdmseen
!= NULL
);
260 ret
= add234(auth
->xdmseen
, seen
);
263 return dupstr("XDM-AUTHORIZATION-1 data replayed");
265 /* While we're here, purge entries too old to be replayed. */
267 seen
= index234(auth
->xdmseen
, 0);
268 assert(seen
!= NULL
);
269 if (t
- seen
->time
<= XDM_MAXSKEW
)
271 sfree(delpos234(auth
->xdmseen
, 0));
274 /* implement other protocols here if ever required */
280 static void x11_log(Plug
*p
, PlugLogType type
, SockAddr
*addr
, int port
,
281 const char *error_msg
, int error_code
)
283 /* We have no interface to the logging module here, so we drop these. */
286 static void x11_send_init_error(struct X11Connection
*conn
,
287 const char *err_message
);
289 static void x11_closing(Plug
*plug
, PlugCloseType type
, const char *error_msg
)
291 struct X11Connection
*xconn
= container_of(
292 plug
, struct X11Connection
, plug
);
294 if (type
!= PLUGCLOSE_NORMAL
) {
296 * Socket error. If we're still at the connection setup stage,
297 * construct an X11 error packet passing on the problem.
299 if (xconn
->no_data_sent_to_x_client
) {
300 char *err_message
= dupprintf("unable to connect to forwarded "
301 "X server: %s", error_msg
);
302 x11_send_init_error(xconn
, err_message
);
307 * Whether we did that or not, now we slam the connection
310 sshfwd_initiate_close(xconn
->c
, error_msg
);
313 * Ordinary EOF received on socket. Send an EOF on the SSH
317 sshfwd_write_eof(xconn
->c
);
321 static void x11_receive(Plug
*plug
, int urgent
, const char *data
, size_t len
)
323 struct X11Connection
*xconn
= container_of(
324 plug
, struct X11Connection
, plug
);
326 xconn
->no_data_sent_to_x_client
= false;
327 sshfwd_write(xconn
->c
, data
, len
);
330 static void x11_sent(Plug
*plug
, size_t bufsize
)
332 struct X11Connection
*xconn
= container_of(
333 plug
, struct X11Connection
, plug
);
335 sshfwd_unthrottle(xconn
->c
, bufsize
);
338 static const PlugVtable X11Connection_plugvt
= {
340 .closing
= x11_closing
,
341 .receive
= x11_receive
,
345 static void x11_chan_free(Channel
*chan
);
346 static size_t x11_send(
347 Channel
*chan
, bool is_stderr
, const void *vdata
, size_t len
);
348 static void x11_send_eof(Channel
*chan
);
349 static void x11_set_input_wanted(Channel
*chan
, bool wanted
);
350 static char *x11_log_close_msg(Channel
*chan
);
352 static const ChannelVtable X11Connection_channelvt
= {
353 .free
= x11_chan_free
,
354 .open_confirmation
= chan_remotely_opened_confirmation
,
355 .open_failed
= chan_remotely_opened_failure
,
357 .send_eof
= x11_send_eof
,
358 .set_input_wanted
= x11_set_input_wanted
,
359 .log_close_msg
= x11_log_close_msg
,
360 .want_close
= chan_default_want_close
,
361 .rcvd_exit_status
= chan_no_exit_status
,
362 .rcvd_exit_signal
= chan_no_exit_signal
,
363 .rcvd_exit_signal_numeric
= chan_no_exit_signal_numeric
,
364 .run_shell
= chan_no_run_shell
,
365 .run_command
= chan_no_run_command
,
366 .run_subsystem
= chan_no_run_subsystem
,
367 .enable_x11_forwarding
= chan_no_enable_x11_forwarding
,
368 .enable_agent_forwarding
= chan_no_enable_agent_forwarding
,
369 .allocate_pty
= chan_no_allocate_pty
,
370 .set_env
= chan_no_set_env
,
371 .send_break
= chan_no_send_break
,
372 .send_signal
= chan_no_send_signal
,
373 .change_window_size
= chan_no_change_window_size
,
374 .request_response
= chan_no_request_response
,
378 * Called to set up the X11Connection structure, though this does not
379 * yet connect to an actual server.
381 Channel
*x11_new_channel(tree234
*authtree
, SshChannel
*c
,
382 const char *peeraddr
, int peerport
,
383 bool connection_sharing_possible
)
385 struct X11Connection
*xconn
;
390 xconn
= snew(struct X11Connection
);
391 xconn
->plug
.vt
= &X11Connection_plugvt
;
392 xconn
->chan
.vt
= &X11Connection_channelvt
;
393 xconn
->chan
.initial_fixed_window_size
=
394 (connection_sharing_possible
? 128 : 0);
395 xconn
->auth_protocol
= NULL
;
396 xconn
->authtree
= authtree
;
397 xconn
->verified
= false;
398 xconn
->data_read
= 0;
399 xconn
->input_wanted
= true;
400 xconn
->no_data_sent_to_x_client
= true;
404 * We don't actually open a local socket to the X server just yet,
405 * because we don't know which one it is. Instead, we'll wait
406 * until we see the incoming authentication data, which may tell
407 * us what display to connect to, or whether we have to divert
408 * this X forwarding channel to a connection-sharing downstream
409 * rather than handling it ourself.
415 * Stash the peer address we were given in its original text form.
417 xconn
->peer_addr
= peeraddr
? dupstr(peeraddr
) : NULL
;
418 xconn
->peer_port
= peerport
;
423 static void x11_chan_free(Channel
*chan
)
425 assert(chan
->vt
== &X11Connection_channelvt
);
426 X11Connection
*xconn
= container_of(chan
, X11Connection
, chan
);
428 if (xconn
->auth_protocol
) {
429 sfree(xconn
->auth_protocol
);
430 sfree(xconn
->auth_data
);
436 sfree(xconn
->peer_addr
);
440 static void x11_set_input_wanted(Channel
*chan
, bool wanted
)
442 assert(chan
->vt
== &X11Connection_channelvt
);
443 X11Connection
*xconn
= container_of(chan
, X11Connection
, chan
);
445 xconn
->input_wanted
= wanted
;
447 sk_set_frozen(xconn
->s
, !xconn
->input_wanted
);
450 static void x11_send_init_error(struct X11Connection
*xconn
,
451 const char *err_message
)
455 unsigned char *reply
;
457 full_message
= dupprintf("%s X11 proxy: %s\n", appname
, err_message
);
459 msglen
= strlen(full_message
);
460 reply
= snewn(8 + msglen
+1 + 4, unsigned char); /* include zero */
461 msgsize
= (msglen
+ 3) & ~3;
462 reply
[0] = 0; /* failure */
463 reply
[1] = msglen
; /* length of reason string */
464 memcpy(reply
+ 2, xconn
->firstpkt
+ 2, 4); /* major/minor proto vsn */
465 PUT_16BIT_X11(xconn
->firstpkt
[0], reply
+ 6, msgsize
>> 2);/* data len */
466 memset(reply
+ 8, 0, msgsize
);
467 memcpy(reply
+ 8, full_message
, msglen
);
468 sshfwd_write(xconn
->c
, reply
, 8 + msgsize
);
469 sshfwd_write_eof(xconn
->c
);
470 xconn
->no_data_sent_to_x_client
= false;
476 * Called to send data down the raw connection.
478 static size_t x11_send(
479 Channel
*chan
, bool is_stderr
, const void *vdata
, size_t len
)
481 assert(chan
->vt
== &X11Connection_channelvt
);
482 X11Connection
*xconn
= container_of(chan
, X11Connection
, chan
);
483 const char *data
= (const char *)vdata
;
486 * Read the first packet.
488 while (len
> 0 && xconn
->data_read
< 12)
489 xconn
->firstpkt
[xconn
->data_read
++] = (unsigned char) (len
--, *data
++);
490 if (xconn
->data_read
< 12)
494 * If we have not allocated the auth_protocol and auth_data
495 * strings, do so now.
497 if (!xconn
->auth_protocol
) {
498 char endian
= xconn
->firstpkt
[0];
499 xconn
->auth_plen
= GET_16BIT_X11(endian
, xconn
->firstpkt
+ 6);
500 xconn
->auth_dlen
= GET_16BIT_X11(endian
, xconn
->firstpkt
+ 8);
501 xconn
->auth_psize
= (xconn
->auth_plen
+ 3) & ~3;
502 xconn
->auth_dsize
= (xconn
->auth_dlen
+ 3) & ~3;
503 /* Leave room for a terminating zero, to make our lives easier. */
504 xconn
->auth_protocol
= snewn(xconn
->auth_psize
+ 1, char);
505 xconn
->auth_data
= snewn(xconn
->auth_dsize
, unsigned char);
509 * Read the auth_protocol and auth_data strings.
512 xconn
->data_read
< 12 + xconn
->auth_psize
)
513 xconn
->auth_protocol
[xconn
->data_read
++ - 12] = (len
--, *data
++);
515 xconn
->data_read
< 12 + xconn
->auth_psize
+ xconn
->auth_dsize
)
516 xconn
->auth_data
[xconn
->data_read
++ - 12 -
517 xconn
->auth_psize
] = (unsigned char) (len
--, *data
++);
518 if (xconn
->data_read
< 12 + xconn
->auth_psize
+ xconn
->auth_dsize
)
522 * If we haven't verified the authorisation, do so now.
524 if (!xconn
->verified
) {
527 struct X11FakeAuth
*auth_matched
= NULL
;
528 unsigned long peer_ip
;
530 int protomajor
, protominor
;
533 unsigned char *socketdata
;
535 char new_peer_addr
[32];
537 char endian
= xconn
->firstpkt
[0];
539 protomajor
= GET_16BIT_X11(endian
, xconn
->firstpkt
+ 2);
540 protominor
= GET_16BIT_X11(endian
, xconn
->firstpkt
+ 4);
544 xconn
->auth_protocol
[xconn
->auth_plen
] = '\0'; /* ASCIZ */
546 peer_ip
= 0; /* placate optimiser */
547 if (x11_parse_ip(xconn
->peer_addr
, &peer_ip
))
548 peer_port
= xconn
->peer_port
;
550 peer_port
= -1; /* signal no peer address data available */
552 errmut
= x11_verify(peer_ip
, peer_port
,
553 xconn
->authtree
, xconn
->auth_protocol
,
554 xconn
->auth_data
, xconn
->auth_dlen
, &auth_matched
);
556 x11_send_init_error(xconn
, errmut
);
560 assert(auth_matched
);
563 * If this auth points to a connection-sharing downstream
564 * rather than an X display we know how to connect to
565 * directly, pass it off to the sharing module now. (This will
566 * have the side effect of freeing xconn.)
568 if (auth_matched
->share_cs
) {
569 sshfwd_x11_sharing_handover(xconn
->c
, auth_matched
->share_cs
,
570 auth_matched
->share_chan
,
571 xconn
->peer_addr
, xconn
->peer_port
,
573 protomajor
, protominor
, data
, len
);
578 * Now we know we're going to accept the connection, and what
579 * X display to connect to. Actually connect to it.
581 xconn
->chan
.initial_fixed_window_size
= 0;
582 sshfwd_window_override_removed(xconn
->c
);
583 xconn
->disp
= auth_matched
->disp
;
584 xconn
->s
= new_connection(sk_addr_dup(xconn
->disp
->addr
),
585 xconn
->disp
->realhost
, xconn
->disp
->port
,
586 false, true, false, false, &xconn
->plug
,
587 sshfwd_get_conf(xconn
->c
), NULL
);
588 if ((err
= sk_socket_error(xconn
->s
)) != NULL
) {
589 char *err_message
= dupprintf("unable to connect to"
590 " forwarded X server: %s", err
);
591 x11_send_init_error(xconn
, err_message
);
597 * Write a new connection header containing our replacement
600 socketdatalen
= 0; /* placate compiler warning */
601 socketdata
= sk_getxdmdata(xconn
->s
, &socketdatalen
);
602 if (socketdata
&& socketdatalen
==6) {
603 sprintf(new_peer_addr
, "%d.%d.%d.%d", socketdata
[0],
604 socketdata
[1], socketdata
[2], socketdata
[3]);
605 new_peer_port
= GET_16BIT_MSB_FIRST(socketdata
+ 4);
607 strcpy(new_peer_addr
, "0.0.0.0");
611 greeting
= x11_make_greeting(xconn
->firstpkt
[0],
612 protomajor
, protominor
,
613 xconn
->disp
->localauthproto
,
614 xconn
->disp
->localauthdata
,
615 xconn
->disp
->localauthdatalen
,
616 new_peer_addr
, new_peer_port
,
619 sk_write(xconn
->s
, greeting
, greeting_len
);
621 smemclr(greeting
, greeting_len
);
627 xconn
->verified
= true;
631 * After initialisation, just copy data simply.
634 return sk_write(xconn
->s
, data
, len
);
637 static void x11_send_eof(Channel
*chan
)
639 assert(chan
->vt
== &X11Connection_channelvt
);
640 X11Connection
*xconn
= container_of(chan
, X11Connection
, chan
);
643 sk_write_eof(xconn
->s
);
646 * If EOF is received from the X client before we've got to
647 * the point of actually connecting to an X server, then we
648 * should send an EOF back to the client so that the
649 * forwarded channel will be terminated.
652 sshfwd_write_eof(xconn
->c
);
656 static char *x11_log_close_msg(Channel
*chan
)
658 return dupstr("Forwarded X11 connection terminated");