67c76f839ee713476cd3ccd3a2457d45ab4fb74e
[u/mdw/putty] / unix / ux_x11.c
1 /*
2 * ux_x11.c: fetch local auth data for X forwarding.
3 */
4
5 #include <ctype.h>
6 #include <unistd.h>
7 #include "putty.h"
8
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
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 command = dupprintf("xauth list %s 2>/dev/null", display+9);
25 else
26 command = dupprintf("xauth list %s 2>/dev/null", display);
27 fp = popen(command, "r");
28 sfree(command);
29
30 if (!fp)
31 return; /* assume no auth */
32
33 localbuf = snewn(maxsize, char);
34
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
43 /* Skip the display name. */
44 while (c = getc(fp), c != EOF && c != '\n' && !isspace(c));
45 if (c == EOF) break;
46 if (c == '\n') continue;
47
48 /* Skip white space. */
49 while (c != EOF && c != '\n' && isspace(c))
50 c = getc(fp);
51 if (c == EOF) break;
52 if (c == '\n') continue;
53
54 /* Read the auth protocol name, and see if it matches any we
55 * know about. */
56 i = 0;
57 while (c != EOF && c != '\n' && !isspace(c)) {
58 if (i < lenof(protoname)-1) protoname[i++] = c;
59 c = getc(fp);
60 }
61 protoname[i] = '\0';
62
63 for (i = X11_NO_AUTH; ++i < X11_NAUTHS ;) {
64 if (!strcmp(protoname, x11_authnames[i]))
65 break;
66 }
67 if (i >= X11_NAUTHS || i <= proto) {
68 /* Unrecognised protocol name, or a worse one than we already have.
69 * Skip this line. */
70 while (c != EOF && c != '\n')
71 c = getc(fp);
72 if (c == EOF) break;
73 }
74 proto = i;
75
76 /* Skip white space. */
77 while (c != EOF && c != '\n' && isspace(c))
78 c = getc(fp);
79 if (c == EOF) break;
80 if (c == '\n') continue;
81
82 /*
83 * Now grab pairs of hex digits and shove them into `data'.
84 */
85 i = 0;
86 hexdigit = -1;
87 while (c != EOF && c != '\n') {
88 int hexval = -1;
89 if (c >= 'A' && c <= 'F')
90 hexval = c + 10 - 'A';
91 if (c >= 'a' && c <= 'f')
92 hexval = c + 10 - 'a';
93 if (c >= '0' && c <= '9')
94 hexval = c - '0';
95 if (hexval >= 0) {
96 if (hexdigit >= 0) {
97 hexdigit = (hexdigit << 4) + hexval;
98 if (i < maxsize)
99 localbuf[i++] = hexdigit;
100 hexdigit = -1;
101 } else
102 hexdigit = hexval;
103 }
104 c = getc(fp);
105 }
106
107 *datalen = i;
108 *protocol = proto;
109 memcpy(data, localbuf, i);
110
111 /* Nonetheless, continue looping round; we might find a better one. */
112 }
113 pclose(fp);
114 sfree(localbuf);
115 }