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