]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - unix/ux_x11.c
Introduce framework for authenticating with the local X server.
[PuTTY.git] / 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 }