]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - unix/ux_x11.c
Move MODULE files out of individual project directories into a
[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 <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";