]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - unix/ux_x11.c
61b4f04c8070ddbca161f1a5d81728ff13ec3e99
[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     /*
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 = smalloc(maxsize);
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 }