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