Commit | Line | Data |
---|---|---|
a09e091a JB |
1 | /* |
2 | ||
3 | Copyright 1988, 1998 The Open Group | |
4 | ||
5 | Permission to use, copy, modify, distribute, and sell this software and its | |
6 | documentation for any purpose is hereby granted without fee, provided that | |
7 | the above copyright notice appear in all copies and that both that | |
8 | copyright notice and this permission notice appear in supporting | |
9 | documentation. | |
10 | ||
11 | The above copyright notice and this permission notice shall be included | |
12 | in all copies or substantial portions of the Software. | |
13 | ||
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
15 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
17 | IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
18 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
19 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
20 | OTHER DEALINGS IN THE SOFTWARE. | |
21 | ||
22 | Except as contained in this notice, the name of The Open Group shall | |
23 | not be used in advertising or otherwise to promote the sale, use or | |
24 | other dealings in this Software without prior written authorization | |
25 | from The Open Group. | |
26 | ||
27 | */ | |
28 | ||
29 | /* | |
30 | * authorization hooks for the server | |
31 | * Author: Keith Packard, MIT X Consortium | |
32 | */ | |
33 | ||
34 | #ifdef HAVE_DIX_CONFIG_H | |
35 | #include <dix-config.h> | |
36 | #endif | |
37 | ||
38 | #include <X11/X.h> | |
39 | #include <X11/Xauth.h> | |
40 | #include "misc.h" | |
41 | #include "osdep.h" | |
42 | #include "dixstruct.h" | |
43 | #include <sys/types.h> | |
44 | #include <sys/stat.h> | |
45 | #ifdef WIN32 | |
46 | #include <X11/Xw32defs.h> | |
47 | #endif | |
48 | ||
49 | struct protocol { | |
50 | unsigned short name_length; | |
51 | const char *name; | |
52 | AuthAddCFunc Add; /* new authorization data */ | |
53 | AuthCheckFunc Check; /* verify client authorization data */ | |
54 | AuthRstCFunc Reset; /* delete all authorization data entries */ | |
55 | AuthToIDFunc ToID; /* convert cookie to ID */ | |
56 | AuthFromIDFunc FromID; /* convert ID to cookie */ | |
57 | AuthRemCFunc Remove; /* remove a specific cookie */ | |
58 | #ifdef XCSECURITY | |
59 | AuthGenCFunc Generate; | |
60 | #endif | |
61 | }; | |
62 | ||
63 | static struct protocol protocols[] = { | |
64 | {(unsigned short) 18, "MIT-MAGIC-COOKIE-1", | |
65 | MitAddCookie, MitCheckCookie, MitResetCookie, | |
66 | MitToID, MitFromID, MitRemoveCookie, | |
67 | #ifdef XCSECURITY | |
68 | MitGenerateCookie | |
69 | #endif | |
70 | }, | |
71 | #ifdef HASXDMAUTH | |
72 | {(unsigned short) 19, "XDM-AUTHORIZATION-1", | |
73 | XdmAddCookie, XdmCheckCookie, XdmResetCookie, | |
74 | XdmToID, XdmFromID, XdmRemoveCookie, | |
75 | #ifdef XCSECURITY | |
76 | NULL | |
77 | #endif | |
78 | }, | |
79 | #endif | |
80 | #ifdef SECURE_RPC | |
81 | {(unsigned short) 9, "SUN-DES-1", | |
82 | SecureRPCAdd, SecureRPCCheck, SecureRPCReset, | |
83 | SecureRPCToID, SecureRPCFromID, SecureRPCRemove, | |
84 | #ifdef XCSECURITY | |
85 | NULL | |
86 | #endif | |
87 | }, | |
88 | #endif | |
89 | }; | |
90 | ||
91 | #define NUM_AUTHORIZATION (sizeof (protocols) /\ | |
92 | sizeof (struct protocol)) | |
93 | ||
94 | /* | |
95 | * Initialize all classes of authorization by reading the | |
96 | * specified authorization file | |
97 | */ | |
98 | ||
99 | static char *authorization_file = (char *) NULL; | |
100 | ||
101 | static Bool ShouldLoadAuth = TRUE; | |
102 | ||
103 | void | |
104 | InitAuthorization(char *file_name) | |
105 | { | |
106 | authorization_file = file_name; | |
107 | } | |
108 | ||
109 | static int | |
110 | LoadAuthorization(void) | |
111 | { | |
112 | FILE *f; | |
113 | Xauth *auth; | |
114 | int i; | |
115 | int count = 0; | |
116 | ||
117 | ShouldLoadAuth = FALSE; | |
118 | if (!authorization_file) | |
119 | return 0; | |
120 | ||
121 | f = Fopen(authorization_file, "r"); | |
122 | if (!f) | |
123 | return -1; | |
124 | ||
125 | while ((auth = XauReadAuth(f)) != 0) { | |
126 | for (i = 0; i < NUM_AUTHORIZATION; i++) { | |
127 | if (protocols[i].name_length == auth->name_length && | |
128 | memcmp(protocols[i].name, auth->name, | |
129 | (int) auth->name_length) == 0 && protocols[i].Add) { | |
130 | ++count; | |
131 | (*protocols[i].Add) (auth->data_length, auth->data, | |
132 | FakeClientID(0)); | |
133 | } | |
134 | } | |
135 | XauDisposeAuth(auth); | |
136 | } | |
137 | ||
138 | Fclose(f); | |
139 | return count; | |
140 | } | |
141 | ||
142 | #ifdef XDMCP | |
143 | /* | |
144 | * XdmcpInit calls this function to discover all authorization | |
145 | * schemes supported by the display | |
146 | */ | |
147 | void | |
148 | RegisterAuthorizations(void) | |
149 | { | |
150 | int i; | |
151 | ||
152 | for (i = 0; i < NUM_AUTHORIZATION; i++) | |
153 | XdmcpRegisterAuthorization(protocols[i].name, | |
154 | (int) protocols[i].name_length); | |
155 | } | |
156 | #endif | |
157 | ||
158 | XID | |
159 | CheckAuthorization(unsigned int name_length, | |
160 | const char *name, | |
161 | unsigned int data_length, | |
162 | const char *data, ClientPtr client, const char **reason) | |
163 | { /* failure message. NULL for default msg */ | |
164 | int i; | |
165 | struct stat buf; | |
166 | static time_t lastmod = 0; | |
167 | static Bool loaded = FALSE; | |
168 | ||
169 | if (!authorization_file || stat(authorization_file, &buf)) { | |
170 | if (lastmod != 0) { | |
171 | lastmod = 0; | |
172 | ShouldLoadAuth = TRUE; /* stat lost, so force reload */ | |
173 | } | |
174 | } | |
175 | else if (buf.st_mtime > lastmod) { | |
176 | lastmod = buf.st_mtime; | |
177 | ShouldLoadAuth = TRUE; | |
178 | } | |
179 | if (ShouldLoadAuth) { | |
180 | int loadauth = LoadAuthorization(); | |
181 | ||
182 | /* | |
183 | * If the authorization file has at least one entry for this server, | |
184 | * disable local host access. (loadauth > 0) | |
185 | * | |
186 | * If there are zero entries (either initially or when the | |
187 | * authorization file is later reloaded), or if a valid | |
188 | * authorization file was never loaded, enable local host access. | |
189 | * (loadauth == 0 || !loaded) | |
190 | * | |
191 | * If the authorization file was loaded initially (with valid | |
192 | * entries for this server), and reloading it later fails, don't | |
193 | * change anything. (loadauth == -1 && loaded) | |
194 | */ | |
195 | ||
196 | if (loadauth > 0) { | |
197 | DisableLocalHost(); /* got at least one */ | |
198 | loaded = TRUE; | |
199 | } | |
200 | else if (loadauth == 0 || !loaded) | |
201 | EnableLocalHost(); | |
202 | } | |
203 | if (name_length) { | |
204 | for (i = 0; i < NUM_AUTHORIZATION; i++) { | |
205 | if (protocols[i].name_length == name_length && | |
206 | memcmp(protocols[i].name, name, (int) name_length) == 0) { | |
207 | return (*protocols[i].Check) (data_length, data, client, | |
208 | reason); | |
209 | } | |
210 | *reason = "Protocol not supported by server\n"; | |
211 | } | |
212 | } | |
213 | else | |
214 | *reason = "No protocol specified\n"; | |
215 | return (XID) ~0L; | |
216 | } | |
217 | ||
218 | void | |
219 | ResetAuthorization(void) | |
220 | { | |
221 | int i; | |
222 | ||
223 | for (i = 0; i < NUM_AUTHORIZATION; i++) | |
224 | if (protocols[i].Reset) | |
225 | (*protocols[i].Reset) (); | |
226 | ShouldLoadAuth = TRUE; | |
227 | } | |
228 | ||
229 | int | |
230 | AuthorizationFromID(XID id, | |
231 | unsigned short *name_lenp, | |
232 | const char **namep, unsigned short *data_lenp, char **datap) | |
233 | { | |
234 | int i; | |
235 | ||
236 | for (i = 0; i < NUM_AUTHORIZATION; i++) { | |
237 | if (protocols[i].FromID && | |
238 | (*protocols[i].FromID) (id, data_lenp, datap)) { | |
239 | *name_lenp = protocols[i].name_length; | |
240 | *namep = protocols[i].name; | |
241 | return 1; | |
242 | } | |
243 | } | |
244 | return 0; | |
245 | } | |
246 | ||
247 | int | |
248 | RemoveAuthorization(unsigned short name_length, | |
249 | const char *name, | |
250 | unsigned short data_length, const char *data) | |
251 | { | |
252 | int i; | |
253 | ||
254 | for (i = 0; i < NUM_AUTHORIZATION; i++) { | |
255 | if (protocols[i].name_length == name_length && | |
256 | memcmp(protocols[i].name, name, (int) name_length) == 0 && | |
257 | protocols[i].Remove) { | |
258 | return (*protocols[i].Remove) (data_length, data); | |
259 | } | |
260 | } | |
261 | return 0; | |
262 | } | |
263 | ||
264 | int | |
265 | AddAuthorization(unsigned name_length, const char *name, | |
266 | unsigned data_length, char *data) | |
267 | { | |
268 | int i; | |
269 | ||
270 | for (i = 0; i < NUM_AUTHORIZATION; i++) { | |
271 | if (protocols[i].name_length == name_length && | |
272 | memcmp(protocols[i].name, name, (int) name_length) == 0 && | |
273 | protocols[i].Add) { | |
274 | return (*protocols[i].Add) (data_length, data, FakeClientID(0)); | |
275 | } | |
276 | } | |
277 | return 0; | |
278 | } | |
279 | ||
280 | #ifdef XCSECURITY | |
281 | ||
282 | XID | |
283 | GenerateAuthorization(unsigned name_length, | |
284 | const char *name, | |
285 | unsigned data_length, | |
286 | const char *data, | |
287 | unsigned *data_length_return, char **data_return) | |
288 | { | |
289 | int i; | |
290 | ||
291 | for (i = 0; i < NUM_AUTHORIZATION; i++) { | |
292 | if (protocols[i].name_length == name_length && | |
293 | memcmp(protocols[i].name, name, (int) name_length) == 0 && | |
294 | protocols[i].Generate) { | |
295 | return (*protocols[i].Generate) (data_length, data, | |
296 | FakeClientID(0), | |
297 | data_length_return, data_return); | |
298 | } | |
299 | } | |
300 | return -1; | |
301 | } | |
302 | ||
303 | void | |
304 | GenerateRandomData(int len, char *buf) | |
305 | { | |
306 | int fd; | |
307 | ||
308 | fd = open("/dev/urandom", O_RDONLY); | |
309 | read(fd, buf, len); | |
310 | close(fd); | |
311 | } | |
312 | ||
313 | #endif /* XCSECURITY */ |