X11FWD.C 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. /*
  2. * Platform-independent bits of X11 forwarding.
  3. */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <assert.h>
  7. #include <time.h>
  8. #include "putty.h"
  9. #include "ssh.h"
  10. #include "tree234.h"
  11. #define GET_16BIT(endian, cp) \
  12. (endian=='B' ? GET_16BIT_MSB_FIRST(cp) : GET_16BIT_LSB_FIRST(cp))
  13. #define PUT_16BIT(endian, cp, val) \
  14. (endian=='B' ? PUT_16BIT_MSB_FIRST(cp, val) : PUT_16BIT_LSB_FIRST(cp, val))
  15. const char *const x11_authnames[] = {
  16. "", "MIT-MAGIC-COOKIE-1", "XDM-AUTHORIZATION-1"
  17. };
  18. struct XDMSeen {
  19. unsigned int time;
  20. unsigned char clientid[6];
  21. };
  22. struct X11Auth {
  23. unsigned char fakedata[64], realdata[64];
  24. int fakeproto, realproto;
  25. int fakelen, reallen;
  26. tree234 *xdmseen;
  27. };
  28. struct X11Private {
  29. const struct plug_function_table *fn;
  30. /* the above variable absolutely *must* be the first in this structure */
  31. unsigned char firstpkt[12]; /* first X data packet */
  32. struct X11Auth *auth;
  33. char *auth_protocol;
  34. unsigned char *auth_data;
  35. int data_read, auth_plen, auth_psize, auth_dlen, auth_dsize;
  36. int verified;
  37. int throttled, throttle_override;
  38. unsigned long peer_ip;
  39. int peer_port;
  40. void *c; /* data used by ssh.c */
  41. Socket s;
  42. };
  43. static int xdmseen_cmp(void *a, void *b)
  44. {
  45. struct XDMSeen *sa = a, *sb = b;
  46. return sa->time > sb->time ? 1 :
  47. sa->time < sb->time ? -1 :
  48. memcmp(sa->clientid, sb->clientid, sizeof(sa->clientid));
  49. }
  50. void *x11_invent_auth(char *proto, int protomaxlen,
  51. char *data, int datamaxlen, int proto_id)
  52. {
  53. struct X11Auth *auth = snew(struct X11Auth);
  54. char ourdata[64];
  55. int i;
  56. if (proto_id == X11_MIT) {
  57. auth->fakeproto = X11_MIT;
  58. /* MIT-MAGIC-COOKIE-1. Cookie size is 128 bits (16 bytes). */
  59. auth->fakelen = 16;
  60. for (i = 0; i < 16; i++)
  61. auth->fakedata[i] = random_byte();
  62. auth->xdmseen = NULL;
  63. } else {
  64. assert(proto_id == X11_XDM);
  65. auth->fakeproto = X11_XDM;
  66. /* XDM-AUTHORIZATION-1. Cookie size is 16 bytes; byte 8 is zero. */
  67. auth->fakelen = 16;
  68. for (i = 0; i < 16; i++)
  69. auth->fakedata[i] = (i == 8 ? 0 : random_byte());
  70. auth->xdmseen = newtree234(xdmseen_cmp);
  71. }
  72. /* Now format for the recipient. */
  73. strncpy(proto, x11_authnames[auth->fakeproto], protomaxlen);
  74. ourdata[0] = '\0';
  75. for (i = 0; i < auth->fakelen; i++)
  76. sprintf(ourdata + strlen(ourdata), "%02x", auth->fakedata[i]);
  77. strncpy(data, ourdata, datamaxlen);
  78. return auth;
  79. }
  80. void x11_free_auth(void *authv)
  81. {
  82. struct X11Auth *auth = (struct X11Auth *)authv;
  83. struct XDMSeen *seen;
  84. if (auth->xdmseen != NULL) {
  85. while ((seen = delpos234(auth->xdmseen, 0)) != NULL)
  86. sfree(seen);
  87. freetree234(auth->xdmseen);
  88. }
  89. sfree(auth);
  90. }
  91. /*
  92. * Fetch the real auth data for a given display string, and store
  93. * it in an X11Auth structure. Returns NULL on success, or an error
  94. * string.
  95. */
  96. void x11_get_real_auth(void *authv, char *display)
  97. {
  98. struct X11Auth *auth = (struct X11Auth *)authv;
  99. auth->realproto = X11_NO_AUTH; /* in case next call does nothing */
  100. auth->reallen = sizeof(auth->realdata);
  101. platform_get_x11_auth(display, &auth->realproto,
  102. auth->realdata, &auth->reallen);
  103. }
  104. #define XDM_MAXSKEW 20*60 /* 20 minute clock skew should be OK */
  105. static char *x11_verify(unsigned long peer_ip, int peer_port,
  106. struct X11Auth *auth, char *proto,
  107. unsigned char *data, int dlen)
  108. {
  109. if (strcmp(proto, x11_authnames[auth->fakeproto]) != 0)
  110. return "wrong authentication protocol attempted";
  111. if (auth->fakeproto == X11_MIT) {
  112. if (dlen != auth->fakelen)
  113. return "MIT-MAGIC-COOKIE-1 data was wrong length";
  114. if (memcmp(auth->fakedata, data, dlen) != 0)
  115. return "MIT-MAGIC-COOKIE-1 data did not match";
  116. }
  117. if (auth->fakeproto == X11_XDM) {
  118. unsigned long t;
  119. time_t tim;
  120. int i;
  121. struct XDMSeen *seen, *ret;
  122. if (dlen != 24)
  123. return "XDM-AUTHORIZATION-1 data was wrong length";
  124. if (peer_port == -1)
  125. return "cannot do XDM-AUTHORIZATION-1 without remote address data";
  126. des_decrypt_xdmauth(auth->fakedata+9, data, 24);
  127. if (memcmp(auth->fakedata, data, 8) != 0)
  128. return "XDM-AUTHORIZATION-1 data failed check"; /* cookie wrong */
  129. if (GET_32BIT_MSB_FIRST(data+8) != peer_ip)
  130. return "XDM-AUTHORIZATION-1 data failed check"; /* IP wrong */
  131. if ((int)GET_16BIT_MSB_FIRST(data+12) != peer_port)
  132. return "XDM-AUTHORIZATION-1 data failed check"; /* port wrong */
  133. t = GET_32BIT_MSB_FIRST(data+14);
  134. for (i = 18; i < 24; i++)
  135. if (data[i] != 0) /* zero padding wrong */
  136. return "XDM-AUTHORIZATION-1 data failed check";
  137. tim = time(NULL);
  138. if (abs(t - tim) > XDM_MAXSKEW)
  139. return "XDM-AUTHORIZATION-1 time stamp was too far out";
  140. seen = snew(struct XDMSeen);
  141. seen->time = t;
  142. memcpy(seen->clientid, data+8, 6);
  143. assert(auth->xdmseen != NULL);
  144. ret = add234(auth->xdmseen, seen);
  145. if (ret != seen) {
  146. sfree(seen);
  147. return "XDM-AUTHORIZATION-1 data replayed";
  148. }
  149. /* While we're here, purge entries too old to be replayed. */
  150. for (;;) {
  151. seen = index234(auth->xdmseen, 0);
  152. assert(seen != NULL);
  153. if (t - seen->time <= XDM_MAXSKEW)
  154. break;
  155. sfree(delpos234(auth->xdmseen, 0));
  156. }
  157. }
  158. /* implement other protocols here if ever required */
  159. return NULL;
  160. }
  161. static void x11_log(Plug p, int type, SockAddr addr, int port,
  162. const char *error_msg, int error_code)
  163. {
  164. /* We have no interface to the logging module here, so we drop these. */
  165. }
  166. static int x11_closing(Plug plug, const char *error_msg, int error_code,
  167. int calling_back)
  168. {
  169. struct X11Private *pr = (struct X11Private *) plug;
  170. /*
  171. * We have no way to communicate down the forwarded connection,
  172. * so if an error occurred on the socket, we just ignore it
  173. * and treat it like a proper close.
  174. */
  175. sshfwd_close(pr->c);
  176. x11_close(pr->s);
  177. return 1;
  178. }
  179. static int x11_receive(Plug plug, int urgent, char *data, int len)
  180. {
  181. struct X11Private *pr = (struct X11Private *) plug;
  182. if (sshfwd_write(pr->c, data, len) > 0) {
  183. pr->throttled = 1;
  184. sk_set_frozen(pr->s, 1);
  185. }
  186. return 1;
  187. }
  188. static void x11_sent(Plug plug, int bufsize)
  189. {
  190. struct X11Private *pr = (struct X11Private *) plug;
  191. sshfwd_unthrottle(pr->c, bufsize);
  192. }
  193. /*
  194. * When setting up X forwarding, we should send the screen number
  195. * from the specified local display. This function extracts it from
  196. * the display string.
  197. */
  198. int x11_get_screen_number(char *display)
  199. {
  200. int n;
  201. n = strcspn(display, ":");
  202. if (!display[n])
  203. return 0;
  204. n = strcspn(display, ".");
  205. if (!display[n])
  206. return 0;
  207. return atoi(display + n + 1);
  208. }
  209. /* Find the right display, returns an allocated string */
  210. char *x11_display(const char *display) {
  211. char *ret;
  212. if(!display || !*display) {
  213. /* try to find platform-specific local display */
  214. if((ret = platform_get_x_display())==0 || !*ret)
  215. /* plausible default for all platforms */
  216. ret = dupstr(":0");
  217. } else
  218. ret = dupstr(display);
  219. if(ret[0] == ':') {
  220. /* no transport specified, use whatever we think is best */
  221. char *s = dupcat(platform_x11_best_transport, ret, (char *)0);
  222. sfree(ret);
  223. return s;
  224. } else
  225. return ret;
  226. }
  227. /*
  228. * Called to set up the raw connection.
  229. *
  230. * Returns an error message, or NULL on success.
  231. * also, fills the SocketsStructure
  232. */
  233. const char *x11_init(Socket * s, char *display, void *c, void *auth,
  234. const char *peeraddr, int peerport, const Config *cfg)
  235. {
  236. static const struct plug_function_table fn_table = {
  237. x11_log,
  238. x11_closing,
  239. x11_receive,
  240. x11_sent,
  241. NULL
  242. };
  243. SockAddr addr;
  244. int port;
  245. const char *err;
  246. char *dummy_realhost;
  247. char host[128];
  248. int n, displaynum;
  249. struct X11Private *pr;
  250. /* default display */
  251. display = x11_display(display);
  252. /*
  253. * Split up display name into host and display-number parts.
  254. */
  255. n = strcspn(display, ":");
  256. assert(n != 0); /* x11_display() promises this */
  257. if (display[n])
  258. displaynum = atoi(display + n + 1);
  259. else
  260. displaynum = 0; /* sensible default */
  261. if (n > sizeof(host) - 1)
  262. n = sizeof(host) - 1;
  263. strncpy(host, display, n);
  264. host[n] = '\0';
  265. sfree(display);
  266. if(!strcmp(host, "unix")) {
  267. /* use AF_UNIX sockets (doesn't make sense on all platforms) */
  268. addr = platform_get_x11_unix_address(displaynum,
  269. &dummy_realhost);
  270. port = 0; /* to show we are not confused */
  271. } else {
  272. port = 6000 + displaynum;
  273. /*
  274. * Try to find host.
  275. */
  276. addr = name_lookup(host, port, &dummy_realhost, cfg, ADDRTYPE_UNSPEC);
  277. if ((err = sk_addr_error(addr)) != NULL) {
  278. sk_addr_free(addr);
  279. return err;
  280. }
  281. }
  282. /*
  283. * Open socket.
  284. */
  285. pr = snew(struct X11Private);
  286. pr->fn = &fn_table;
  287. pr->auth_protocol = NULL;
  288. pr->auth = (struct X11Auth *)auth;
  289. pr->verified = 0;
  290. pr->data_read = 0;
  291. pr->throttled = pr->throttle_override = 0;
  292. pr->c = c;
  293. pr->s = *s = new_connection(addr, dummy_realhost, port,
  294. 0, 1, 0, 0, (Plug) pr, cfg);
  295. if ((err = sk_socket_error(*s)) != NULL) {
  296. sfree(pr);
  297. return err;
  298. }
  299. /*
  300. * See if we can make sense of the peer address we were given.
  301. */
  302. {
  303. int i[4];
  304. if (peeraddr &&
  305. 4 == sscanf(peeraddr, "%d.%d.%d.%d", i+0, i+1, i+2, i+3)) {
  306. pr->peer_ip = (i[0] << 24) | (i[1] << 16) | (i[2] << 8) | i[3];
  307. pr->peer_port = peerport;
  308. } else {
  309. pr->peer_ip = 0;
  310. pr->peer_port = -1;
  311. }
  312. }
  313. sk_set_private_ptr(*s, pr);
  314. return NULL;
  315. }
  316. void x11_close(Socket s)
  317. {
  318. struct X11Private *pr;
  319. if (!s)
  320. return;
  321. pr = (struct X11Private *) sk_get_private_ptr(s);
  322. if (pr->auth_protocol) {
  323. sfree(pr->auth_protocol);
  324. sfree(pr->auth_data);
  325. }
  326. sfree(pr);
  327. sk_close(s);
  328. }
  329. void x11_unthrottle(Socket s)
  330. {
  331. struct X11Private *pr;
  332. if (!s)
  333. return;
  334. pr = (struct X11Private *) sk_get_private_ptr(s);
  335. pr->throttled = 0;
  336. sk_set_frozen(s, pr->throttled || pr->throttle_override);
  337. }
  338. void x11_override_throttle(Socket s, int enable)
  339. {
  340. struct X11Private *pr;
  341. if (!s)
  342. return;
  343. pr = (struct X11Private *) sk_get_private_ptr(s);
  344. pr->throttle_override = enable;
  345. sk_set_frozen(s, pr->throttled || pr->throttle_override);
  346. }
  347. /*
  348. * Called to send data down the raw connection.
  349. */
  350. int x11_send(Socket s, char *data, int len)
  351. {
  352. struct X11Private *pr;
  353. if (!s)
  354. return 0;
  355. pr = (struct X11Private *) sk_get_private_ptr(s);
  356. /*
  357. * Read the first packet.
  358. */
  359. while (len > 0 && pr->data_read < 12)
  360. pr->firstpkt[pr->data_read++] = (unsigned char) (len--, *data++);
  361. if (pr->data_read < 12)
  362. return 0;
  363. /*
  364. * If we have not allocated the auth_protocol and auth_data
  365. * strings, do so now.
  366. */
  367. if (!pr->auth_protocol) {
  368. pr->auth_plen = GET_16BIT(pr->firstpkt[0], pr->firstpkt + 6);
  369. pr->auth_dlen = GET_16BIT(pr->firstpkt[0], pr->firstpkt + 8);
  370. pr->auth_psize = (pr->auth_plen + 3) & ~3;
  371. pr->auth_dsize = (pr->auth_dlen + 3) & ~3;
  372. /* Leave room for a terminating zero, to make our lives easier. */
  373. pr->auth_protocol = snewn(pr->auth_psize + 1, char);
  374. pr->auth_data = snewn(pr->auth_dsize, unsigned char);
  375. }
  376. /*
  377. * Read the auth_protocol and auth_data strings.
  378. */
  379. while (len > 0 && pr->data_read < 12 + pr->auth_psize)
  380. pr->auth_protocol[pr->data_read++ - 12] = (len--, *data++);
  381. while (len > 0 && pr->data_read < 12 + pr->auth_psize + pr->auth_dsize)
  382. pr->auth_data[pr->data_read++ - 12 -
  383. pr->auth_psize] = (unsigned char) (len--, *data++);
  384. if (pr->data_read < 12 + pr->auth_psize + pr->auth_dsize)
  385. return 0;
  386. /*
  387. * If we haven't verified the authentication, do so now.
  388. */
  389. if (!pr->verified) {
  390. char *err;
  391. pr->auth_protocol[pr->auth_plen] = '\0'; /* ASCIZ */
  392. err = x11_verify(pr->peer_ip, pr->peer_port,
  393. pr->auth, pr->auth_protocol,
  394. pr->auth_data, pr->auth_dlen);
  395. /*
  396. * If authentication failed, construct and send an error
  397. * packet, then terminate the connection.
  398. */
  399. if (err) {
  400. char *message;
  401. int msglen, msgsize;
  402. unsigned char *reply;
  403. message = dupprintf("PuTTY X11 proxy: %s", err);
  404. msglen = strlen(message);
  405. reply = snewn(8 + msglen+1 + 4, unsigned char); /* include zero */
  406. msgsize = (msglen + 3) & ~3;
  407. reply[0] = 0; /* failure */
  408. reply[1] = msglen; /* length of reason string */
  409. memcpy(reply + 2, pr->firstpkt + 2, 4); /* major/minor proto vsn */
  410. PUT_16BIT(pr->firstpkt[0], reply + 6, msgsize >> 2);/* data len */
  411. memset(reply + 8, 0, msgsize);
  412. memcpy(reply + 8, message, msglen);
  413. sshfwd_write(pr->c, (char *)reply, 8 + msgsize);
  414. sshfwd_close(pr->c);
  415. x11_close(s);
  416. sfree(reply);
  417. sfree(message);
  418. return 0;
  419. }
  420. /*
  421. * Now we know we're going to accept the connection. Strip
  422. * the fake auth data, and optionally put real auth data in
  423. * instead.
  424. */
  425. {
  426. char realauthdata[64];
  427. int realauthlen = 0;
  428. int authstrlen = strlen(x11_authnames[pr->auth->realproto]);
  429. int buflen = 0; /* initialise to placate optimiser */
  430. static const char zeroes[4] = { 0,0,0,0 };
  431. void *buf;
  432. if (pr->auth->realproto == X11_MIT) {
  433. assert(pr->auth->reallen <= lenof(realauthdata));
  434. realauthlen = pr->auth->reallen;
  435. memcpy(realauthdata, pr->auth->realdata, realauthlen);
  436. } else if (pr->auth->realproto == X11_XDM &&
  437. pr->auth->reallen == 16 &&
  438. ((buf = sk_getxdmdata(s, &buflen))!=0)) {
  439. time_t t;
  440. realauthlen = (buflen+12+7) & ~7;
  441. assert(realauthlen <= lenof(realauthdata));
  442. memset(realauthdata, 0, realauthlen);
  443. memcpy(realauthdata, pr->auth->realdata, 8);
  444. memcpy(realauthdata+8, buf, buflen);
  445. t = time(NULL);
  446. PUT_32BIT_MSB_FIRST(realauthdata+8+buflen, t);
  447. des_encrypt_xdmauth(pr->auth->realdata+9,
  448. (unsigned char *)realauthdata,
  449. realauthlen);
  450. sfree(buf);
  451. }
  452. /* implement other auth methods here if required */
  453. PUT_16BIT(pr->firstpkt[0], pr->firstpkt + 6, authstrlen);
  454. PUT_16BIT(pr->firstpkt[0], pr->firstpkt + 8, realauthlen);
  455. sk_write(s, (char *)pr->firstpkt, 12);
  456. if (authstrlen) {
  457. sk_write(s, x11_authnames[pr->auth->realproto], authstrlen);
  458. sk_write(s, zeroes, 3 & (-authstrlen));
  459. }
  460. if (realauthlen) {
  461. sk_write(s, realauthdata, realauthlen);
  462. sk_write(s, zeroes, 3 & (-realauthlen));
  463. }
  464. }
  465. pr->verified = 1;
  466. }
  467. /*
  468. * After initialisation, just copy data simply.
  469. */
  470. return sk_write(s, data, len);
  471. }