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