x11fwd.c 14 KB

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