ux_x11.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. /*
  2. * ux_x11.c: fetch local auth data for X forwarding.
  3. */
  4. #include <ctype.h>
  5. #include <unistd.h>
  6. #include <assert.h>
  7. #include "putty.h"
  8. #include "ssh.h"
  9. void platform_get_x11_auth(char *display, int *protocol,
  10. unsigned char *data, int *datalen)
  11. {
  12. FILE *fp;
  13. char *command;
  14. int maxsize = *datalen;
  15. char *localbuf;
  16. int proto = -1;
  17. display = x11_display(display);
  18. /*
  19. * Normally we should run `xauth list DISPLAYNAME'. However,
  20. * there's an oddity when the display is local: the display
  21. * `localhost:0' (or `:0') should become just `:0'.
  22. */
  23. if (!strncmp(display, "localhost:", 10)
  24. || !strncmp(display, "unix:", 5))
  25. command = dupprintf("xauth list %s 2>/dev/null",
  26. strchr(display, ':'));
  27. else
  28. command = dupprintf("xauth list %s 2>/dev/null", display);
  29. sfree(display);
  30. fp = popen(command, "r");
  31. sfree(command);
  32. if (!fp)
  33. return; /* assume no auth */
  34. localbuf = snewn(maxsize, char);
  35. while (1) {
  36. /*
  37. * Read a line from stdin, and attempt to parse it into a
  38. * display name (ignored), auth protocol, and auth string.
  39. */
  40. int c, i, hexdigit;
  41. char protoname[64];
  42. /* Skip the display name. */
  43. while (c = getc(fp), c != EOF && c != '\n' && !isspace(c));
  44. if (c == EOF) break;
  45. if (c == '\n') continue;
  46. /* Skip white space. */
  47. while (c != EOF && c != '\n' && isspace(c))
  48. c = getc(fp);
  49. if (c == EOF) break;
  50. if (c == '\n') continue;
  51. /* Read the auth protocol name, and see if it matches any we
  52. * know about. */
  53. i = 0;
  54. while (c != EOF && c != '\n' && !isspace(c)) {
  55. if (i < lenof(protoname)-1) protoname[i++] = c;
  56. c = getc(fp);
  57. }
  58. protoname[i] = '\0';
  59. for (i = X11_NO_AUTH; ++i < X11_NAUTHS ;) {
  60. if (!strcmp(protoname, x11_authnames[i]))
  61. break;
  62. }
  63. if (i >= X11_NAUTHS || i <= proto) {
  64. /* Unrecognised protocol name, or a worse one than we already have.
  65. * Skip this line. */
  66. while (c != EOF && c != '\n')
  67. c = getc(fp);
  68. if (c == EOF) break;
  69. }
  70. proto = i;
  71. /* Skip white space. */
  72. while (c != EOF && c != '\n' && isspace(c))
  73. c = getc(fp);
  74. if (c == EOF) break;
  75. if (c == '\n') continue;
  76. /*
  77. * Now grab pairs of hex digits and shove them into `data'.
  78. */
  79. i = 0;
  80. hexdigit = -1;
  81. while (c != EOF && c != '\n') {
  82. int hexval = -1;
  83. if (c >= 'A' && c <= 'F')
  84. hexval = c + 10 - 'A';
  85. if (c >= 'a' && c <= 'f')
  86. hexval = c + 10 - 'a';
  87. if (c >= '0' && c <= '9')
  88. hexval = c - '0';
  89. if (hexval >= 0) {
  90. if (hexdigit >= 0) {
  91. hexdigit = (hexdigit << 4) + hexval;
  92. if (i < maxsize)
  93. localbuf[i++] = hexdigit;
  94. hexdigit = -1;
  95. } else
  96. hexdigit = hexval;
  97. }
  98. c = getc(fp);
  99. }
  100. *datalen = i;
  101. *protocol = proto;
  102. memcpy(data, localbuf, i);
  103. /* Nonetheless, continue looping round; we might find a better one. */
  104. }
  105. pclose(fp);
  106. sfree(localbuf);
  107. }