1 /*
3 Copyright 1988, 1998 The Open Group
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.
11 The above copyright notice and this permission notice shall be included
12 in all copies or substantial portions of the Software.
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.
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.
27 */
29 /*
30 * authorization hooks for the server
31 * Author: Keith Packard, MIT X Consortium
32 */
34 #ifdef HAVE_DIX_CONFIG_H
35 #include <dix-config.h>
36 #endif
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
49 struct protocol {
50 unsigned short name_length;
51 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 };
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 };
91 # define NUM_AUTHORIZATION (sizeof (protocols) /\
92 sizeof (struct protocol))
94 /*
95 * Initialize all classes of authorization by reading the
96 * specified authorization file
97 */
99 static char *authorization_file = (char *)NULL;
101 static Bool ShouldLoadAuth = TRUE;
103 void
104 InitAuthorization (char *file_name)
105 {
106 authorization_file = file_name;
107 }
109 static int
110 LoadAuthorization (void)
111 {
112 FILE *f;
113 Xauth *auth;
114 int i;
115 int count = 0;
117 ShouldLoadAuth = FALSE;
118 if (!authorization_file)
119 return 0;
121 f = Fopen (authorization_file, "r");
122 if (!f)
123 return -1;
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, (int) auth->name_length) == 0 &&
129 protocols[i].Add)
130 {
131 ++count;
132 (*protocols[i].Add) (auth->data_length, auth->data,
133 FakeClientID(0));
134 }
135 }
136 XauDisposeAuth (auth);
137 }
139 Fclose (f);
140 return count;
141 }
143 #ifdef XDMCP
144 /*
145 * XdmcpInit calls this function to discover all authorization
146 * schemes supported by the display
147 */
148 void
149 RegisterAuthorizations (void)
150 {
151 int i;
153 for (i = 0; i < NUM_AUTHORIZATION; i++)
154 XdmcpRegisterAuthorization (protocols[i].name,
155 (int)protocols[i].name_length);
156 }
157 #endif
159 XID
160 CheckAuthorization (
161 unsigned int name_length,
162 const char *name,
163 unsigned int data_length,
164 const char *data,
165 ClientPtr client,
166 char **reason) /* failure message. NULL for default msg */
167 {
168 int i;
169 struct stat buf;
170 static time_t lastmod = 0;
171 static Bool loaded = FALSE;
173 if (!authorization_file || stat(authorization_file, &buf))
174 {
175 if (lastmod != 0) {
176 lastmod = 0;
177 ShouldLoadAuth = TRUE; /* stat lost, so force reload */
178 }
179 }
180 else if (buf.st_mtime > lastmod)
181 {
182 lastmod = buf.st_mtime;
183 ShouldLoadAuth = TRUE;
184 }
185 if (ShouldLoadAuth)
186 {
187 int loadauth = LoadAuthorization();
189 /*
190 * If the authorization file has at least one entry for this server,
191 * disable local host access. (loadauth > 0)
192 *
193 * If there are zero entries (either initially or when the
194 * authorization file is later reloaded), or if a valid
195 * authorization file was never loaded, enable local host access.
196 * (loadauth == 0 || !loaded)
197 *
198 * If the authorization file was loaded initially (with valid
199 * entries for this server), and reloading it later fails, don't
200 * change anything. (loadauth == -1 && loaded)
201 */
203 if (loadauth > 0)
204 {
205 DisableLocalHost(); /* got at least one */
206 loaded = TRUE;
207 }
208 else if (loadauth == 0 || !loaded)
209 EnableLocalHost ();
210 }
211 if (name_length) {
212 for (i = 0; i < NUM_AUTHORIZATION; i++) {
213 if (protocols[i].name_length == name_length &&
214 memcmp (protocols[i].name, name, (int) name_length) == 0)
215 {
216 return (*protocols[i].Check) (data_length, data, client, reason);
217 }
218 *reason = "Protocol not supported by server\n";
219 }
220 } else *reason = "No protocol specified\n";
221 return (XID) ~0L;
222 }
224 void
225 ResetAuthorization (void)
226 {
227 int i;
229 for (i = 0; i < NUM_AUTHORIZATION; i++)
230 if (protocols[i].Reset)
231 (*protocols[i].Reset)();
232 ShouldLoadAuth = TRUE;
233 }
235 int
236 AuthorizationFromID (
237 XID id,
238 unsigned short *name_lenp,
239 char **namep,
240 unsigned short *data_lenp,
241 char **datap)
242 {
243 int i;
245 for (i = 0; i < NUM_AUTHORIZATION; i++) {
246 if (protocols[i].FromID &&
247 (*protocols[i].FromID) (id, data_lenp, datap)) {
248 *name_lenp = protocols[i].name_length;
249 *namep = protocols[i].name;
250 return 1;
251 }
252 }
253 return 0;
254 }
256 int
257 RemoveAuthorization (
258 unsigned short name_length,
259 const char *name,
260 unsigned short data_length,
261 const char *data)
262 {
263 int i;
265 for (i = 0; i < NUM_AUTHORIZATION; i++) {
266 if (protocols[i].name_length == name_length &&
267 memcmp (protocols[i].name, name, (int) name_length) == 0 &&
268 protocols[i].Remove)
269 {
270 return (*protocols[i].Remove) (data_length, data);
271 }
272 }
273 return 0;
274 }
276 int
277 AddAuthorization (unsigned name_length, const char *name,
278 unsigned data_length, char *data)
279 {
280 int i;
282 for (i = 0; i < NUM_AUTHORIZATION; i++) {
283 if (protocols[i].name_length == name_length &&
284 memcmp (protocols[i].name, name, (int) name_length) == 0 &&
285 protocols[i].Add)
286 {
287 return (*protocols[i].Add) (data_length, data, FakeClientID(0));
288 }
289 }
290 return 0;
291 }
293 #ifdef XCSECURITY
295 XID
296 GenerateAuthorization(
297 unsigned name_length,
298 const char *name,
299 unsigned data_length,
300 const char *data,
301 unsigned *data_length_return,
302 char **data_return)
303 {
304 int i;
306 for (i = 0; i < NUM_AUTHORIZATION; i++) {
307 if (protocols[i].name_length == name_length &&
308 memcmp (protocols[i].name, name, (int) name_length) == 0 &&
309 protocols[i].Generate)
310 {
311 return (*protocols[i].Generate) (data_length, data,
312 FakeClientID(0), data_length_return, data_return);
313 }
314 }
315 return -1;
316 }
318 void
319 GenerateRandomData (int len, char *buf)
320 {
321 int fd;
323 fd = open("/dev/urandom", O_RDONLY);
324 read(fd, buf, len);
325 close(fd);
326 }
328 #endif /* XCSECURITY */