1 | /* |
---|
2 | * xdm - display manager daemon |
---|
3 | * |
---|
4 | * $XConsortium: auth.c,v 1.47 91/11/08 15:18:18 eswu Exp $ |
---|
5 | * |
---|
6 | * Copyright 1988 Massachusetts Institute of Technology |
---|
7 | * |
---|
8 | * Permission to use, copy, modify, and distribute this software and its |
---|
9 | * documentation for any purpose and without fee is hereby granted, provided |
---|
10 | * that the above copyright notice appear in all copies and that both that |
---|
11 | * copyright notice and this permission notice appear in supporting |
---|
12 | * documentation, and that the name of M.I.T. not be used in advertising or |
---|
13 | * publicity pertaining to distribution of the software without specific, |
---|
14 | * written prior permission. M.I.T. makes no representations about the |
---|
15 | * suitability of this software for any purpose. It is provided "as is" |
---|
16 | * without express or implied warranty. |
---|
17 | * |
---|
18 | * Author: Keith Packard, MIT X Consortium |
---|
19 | */ |
---|
20 | |
---|
21 | /* |
---|
22 | * auth.c |
---|
23 | * |
---|
24 | * maintain the authorization generation daemon |
---|
25 | */ |
---|
26 | |
---|
27 | #include "dm.h" |
---|
28 | #include <X11/X.h> |
---|
29 | #include <sys/types.h> |
---|
30 | #include <sys/stat.h> |
---|
31 | #include <sys/socket.h> |
---|
32 | #ifndef ESIX |
---|
33 | # include <sys/ioctl.h> |
---|
34 | #endif /* !ESIX */ |
---|
35 | |
---|
36 | #ifdef TCPCONN |
---|
37 | # include <netinet/in.h> |
---|
38 | #endif |
---|
39 | #ifdef DNETCONN |
---|
40 | # include <netdnet/dn.h> |
---|
41 | # include <netdnet/dnetdb.h> |
---|
42 | #endif |
---|
43 | |
---|
44 | #if (defined(_POSIX_SOURCE) && !defined(AIXV3)) || defined(hpux) || defined(USG) || defined(SVR4) |
---|
45 | #define NEED_UTSNAME |
---|
46 | #include <sys/utsname.h> |
---|
47 | #endif |
---|
48 | |
---|
49 | #if defined(SYSV) && defined(SYSV386) |
---|
50 | # include <sys/stream.h> |
---|
51 | # ifdef ISC |
---|
52 | # include <sys/sioctl.h> |
---|
53 | # endif /* ISC */ |
---|
54 | # ifdef ESIX |
---|
55 | # include <lan/net_ioctl.h> |
---|
56 | # endif /* ESIX */ |
---|
57 | #endif /* SYSV386 */ |
---|
58 | |
---|
59 | #ifdef SVR4 |
---|
60 | # include <netdb.h> |
---|
61 | # include <sys/sockio.h> |
---|
62 | #endif |
---|
63 | #ifdef __convex__ |
---|
64 | # include <sync/queue.h> |
---|
65 | # include <sync/sema.h> |
---|
66 | #endif |
---|
67 | #include <net/if.h> |
---|
68 | |
---|
69 | extern int MitInitAuth (); |
---|
70 | extern Xauth *MitGetAuth (); |
---|
71 | |
---|
72 | #ifdef HASXDMAUTH |
---|
73 | extern int XdmInitAuth (); |
---|
74 | extern Xauth *XdmGetAuth (); |
---|
75 | #ifdef XDMCP |
---|
76 | extern int XdmGetXdmcpAuth (); |
---|
77 | #else |
---|
78 | #define XdmGetXdmcpAuth NULL |
---|
79 | #endif |
---|
80 | #endif |
---|
81 | |
---|
82 | #ifdef SECURE_RPC |
---|
83 | extern int SecureRPCInitAuth (); |
---|
84 | extern Xauth *SecureRPCGetAuth (); |
---|
85 | #endif |
---|
86 | |
---|
87 | struct AuthProtocol { |
---|
88 | unsigned short name_length; |
---|
89 | char *name; |
---|
90 | int (*InitAuth)(); |
---|
91 | Xauth *(*GetAuth)(); |
---|
92 | int (*GetXdmcpAuth)(); |
---|
93 | int inited; |
---|
94 | }; |
---|
95 | |
---|
96 | static struct AuthProtocol AuthProtocols[] = { |
---|
97 | { (unsigned short) 18, "MIT-MAGIC-COOKIE-1", |
---|
98 | MitInitAuth, MitGetAuth, NULL |
---|
99 | }, |
---|
100 | #ifdef HASXDMAUTH |
---|
101 | { (unsigned short) 19, "XDM-AUTHORIZATION-1", |
---|
102 | XdmInitAuth, XdmGetAuth, XdmGetXdmcpAuth, |
---|
103 | }, |
---|
104 | #endif |
---|
105 | #ifdef SECURE_RPC |
---|
106 | { (unsigned short) 9, "SUN-DES-1", |
---|
107 | SecureRPCInitAuth, SecureRPCGetAuth, NULL, |
---|
108 | }, |
---|
109 | #endif |
---|
110 | }; |
---|
111 | |
---|
112 | #define NUM_AUTHORIZATION (sizeof (AuthProtocols) / sizeof (AuthProtocols[0])) |
---|
113 | |
---|
114 | static struct AuthProtocol * |
---|
115 | findProtocol (name_length, name) |
---|
116 | unsigned short name_length; |
---|
117 | char *name; |
---|
118 | { |
---|
119 | int i; |
---|
120 | |
---|
121 | for (i = 0; i < NUM_AUTHORIZATION; i++) |
---|
122 | if (AuthProtocols[i].name_length == name_length && |
---|
123 | bcmp (AuthProtocols[i].name, name, name_length) == 0) |
---|
124 | { |
---|
125 | return &AuthProtocols[i]; |
---|
126 | } |
---|
127 | return (struct AuthProtocol *) 0; |
---|
128 | } |
---|
129 | |
---|
130 | ValidAuthorization (name_length, name) |
---|
131 | unsigned short name_length; |
---|
132 | char *name; |
---|
133 | { |
---|
134 | if (findProtocol (name_length, name)) |
---|
135 | return TRUE; |
---|
136 | return FALSE; |
---|
137 | } |
---|
138 | |
---|
139 | static Xauth * |
---|
140 | GenerateAuthorization (name_length, name) |
---|
141 | unsigned short name_length; |
---|
142 | char *name; |
---|
143 | { |
---|
144 | struct AuthProtocol *a; |
---|
145 | Xauth *auth = 0; |
---|
146 | int i; |
---|
147 | |
---|
148 | Debug ("GenerateAuthorization %*.*s\n", |
---|
149 | name_length, name_length, name); |
---|
150 | a = findProtocol (name_length, name); |
---|
151 | if (a) |
---|
152 | { |
---|
153 | if (!a->inited) |
---|
154 | { |
---|
155 | (*a->InitAuth) (name_length, name); |
---|
156 | a->inited = TRUE; |
---|
157 | } |
---|
158 | auth = (*a->GetAuth) (name_length, name); |
---|
159 | if (auth) |
---|
160 | { |
---|
161 | Debug ("Got 0x%x (%d %*.*s) ", auth, |
---|
162 | auth->name_length, auth->name_length, |
---|
163 | auth->name_length, auth->name); |
---|
164 | for (i = 0; i < (int)auth->data_length; i++) |
---|
165 | Debug (" %02x", auth->data[i] & 0xff); |
---|
166 | Debug ("\n"); |
---|
167 | } |
---|
168 | else |
---|
169 | Debug ("Got (null)\n"); |
---|
170 | } |
---|
171 | else |
---|
172 | { |
---|
173 | Debug ("Unknown authorization %*.*s\n", name_length, name_length, name); |
---|
174 | } |
---|
175 | return auth; |
---|
176 | } |
---|
177 | |
---|
178 | #ifdef XDMCP |
---|
179 | |
---|
180 | SetProtoDisplayAuthorization (pdpy, |
---|
181 | authorizationNameLen, authorizationName) |
---|
182 | struct protoDisplay *pdpy; |
---|
183 | unsigned short authorizationNameLen; |
---|
184 | char *authorizationName; |
---|
185 | { |
---|
186 | struct AuthProtocol *a; |
---|
187 | Xauth *auth; |
---|
188 | |
---|
189 | a = findProtocol (authorizationNameLen, authorizationName); |
---|
190 | pdpy->xdmcpAuthorization = pdpy->fileAuthorization = 0; |
---|
191 | if (a) |
---|
192 | { |
---|
193 | if (!a->inited) |
---|
194 | { |
---|
195 | (*a->InitAuth) (authorizationNameLen, authorizationName); |
---|
196 | a->inited = TRUE; |
---|
197 | } |
---|
198 | if (a->GetXdmcpAuth) |
---|
199 | { |
---|
200 | (*a->GetXdmcpAuth) (pdpy, authorizationNameLen, authorizationName); |
---|
201 | auth = pdpy->xdmcpAuthorization; |
---|
202 | } |
---|
203 | else |
---|
204 | { |
---|
205 | auth = (*a->GetAuth) (authorizationNameLen, authorizationName); |
---|
206 | pdpy->fileAuthorization = auth; |
---|
207 | pdpy->xdmcpAuthorization = 0; |
---|
208 | } |
---|
209 | if (auth) |
---|
210 | Debug ("Got 0x%x (%d %*.*s)\n", auth, |
---|
211 | auth->name_length, auth->name_length, |
---|
212 | auth->name_length, auth->name); |
---|
213 | else |
---|
214 | Debug ("Got (null)\n"); |
---|
215 | } |
---|
216 | } |
---|
217 | |
---|
218 | #endif /* XDMCP */ |
---|
219 | |
---|
220 | static |
---|
221 | CleanUpFileName (src, dst, len) |
---|
222 | char *src, *dst; |
---|
223 | int len; |
---|
224 | { |
---|
225 | while (*src) { |
---|
226 | if (--len <= 0) |
---|
227 | break; |
---|
228 | switch (*src & 0x7f) |
---|
229 | { |
---|
230 | case '/': |
---|
231 | *dst++ = '_'; |
---|
232 | break; |
---|
233 | case '-': |
---|
234 | *dst++ = '.'; |
---|
235 | break; |
---|
236 | default: |
---|
237 | *dst++ = (*src & 0x7f); |
---|
238 | } |
---|
239 | ++src; |
---|
240 | } |
---|
241 | *dst = '\0'; |
---|
242 | } |
---|
243 | |
---|
244 | static |
---|
245 | MakeServerAuthFile (d) |
---|
246 | struct display *d; |
---|
247 | { |
---|
248 | int len; |
---|
249 | #ifdef SYSV |
---|
250 | #define NAMELEN 14 |
---|
251 | #else |
---|
252 | #define NAMELEN 255 |
---|
253 | #endif |
---|
254 | char cleanname[NAMELEN]; |
---|
255 | |
---|
256 | if (d->clientAuthFile && *d->clientAuthFile) |
---|
257 | len = strlen (d->clientAuthFile) + 1; |
---|
258 | else |
---|
259 | { |
---|
260 | CleanUpFileName (d->name, cleanname, NAMELEN - 8); |
---|
261 | len = strlen (authDir) + strlen (cleanname) + 12; |
---|
262 | } |
---|
263 | if (d->authFile) |
---|
264 | free (d->authFile); |
---|
265 | d->authFile = malloc ((unsigned) len); |
---|
266 | if (!d->authFile) |
---|
267 | return FALSE; |
---|
268 | if (d->clientAuthFile && *d->clientAuthFile) |
---|
269 | strcpy (d->authFile, d->clientAuthFile); |
---|
270 | else |
---|
271 | { |
---|
272 | sprintf (d->authFile, "%s/A%s-XXXXXX", authDir, cleanname); |
---|
273 | (void) mktemp (d->authFile); |
---|
274 | } |
---|
275 | return TRUE; |
---|
276 | } |
---|
277 | |
---|
278 | SaveServerAuthorizations (d, auths, count) |
---|
279 | struct display *d; |
---|
280 | Xauth **auths; |
---|
281 | int count; |
---|
282 | { |
---|
283 | FILE *auth_file; |
---|
284 | int mask; |
---|
285 | int ret; |
---|
286 | int i; |
---|
287 | |
---|
288 | mask = umask (0077); |
---|
289 | if (!d->authFile && !MakeServerAuthFile (d)) |
---|
290 | return FALSE; |
---|
291 | (void) unlink (d->authFile); |
---|
292 | auth_file = fopen (d->authFile, "w"); |
---|
293 | umask (mask); |
---|
294 | if (!auth_file) { |
---|
295 | Debug ("Can't creat auth file %s\n", d->authFile); |
---|
296 | LogError ("Cannot open server authorization file %s\n", d->authFile); |
---|
297 | free (d->authFile); |
---|
298 | d->authFile = NULL; |
---|
299 | ret = FALSE; |
---|
300 | } |
---|
301 | else |
---|
302 | { |
---|
303 | Debug ("File: %s auth: %x\n", d->authFile, auths); |
---|
304 | ret = TRUE; |
---|
305 | for (i = 0; i < count; i++) |
---|
306 | { |
---|
307 | if (!XauWriteAuth (auth_file, auths[i]) || |
---|
308 | fflush (auth_file) == EOF) |
---|
309 | { |
---|
310 | LogError ("Cannot write server authorization file %s\n", |
---|
311 | d->authFile); |
---|
312 | ret = FALSE; |
---|
313 | free (d->authFile); |
---|
314 | d->authFile = NULL; |
---|
315 | } |
---|
316 | } |
---|
317 | fclose (auth_file); |
---|
318 | } |
---|
319 | return ret; |
---|
320 | } |
---|
321 | |
---|
322 | SetLocalAuthorization (d) |
---|
323 | struct display *d; |
---|
324 | { |
---|
325 | Xauth *auth, **auths; |
---|
326 | int i, j; |
---|
327 | |
---|
328 | if (d->authorizations) |
---|
329 | { |
---|
330 | for (i = 0; i < d->authNum; i++) |
---|
331 | XauDisposeAuth (d->authorizations[i]); |
---|
332 | free ((char *) d->authorizations); |
---|
333 | d->authorizations = (Xauth **) NULL; |
---|
334 | d->authNum = 0; |
---|
335 | } |
---|
336 | if (!d->authNames) |
---|
337 | return; |
---|
338 | for (i = 0; d->authNames[i]; i++) |
---|
339 | ; |
---|
340 | d->authNameNum = i; |
---|
341 | if (d->authNameLens) |
---|
342 | free ((char *) d->authNameLens); |
---|
343 | d->authNameLens = (unsigned short *) malloc |
---|
344 | (d->authNameNum * sizeof (unsigned short)); |
---|
345 | if (!d->authNameLens) |
---|
346 | return; |
---|
347 | for (i = 0; i < d->authNameNum; i++) |
---|
348 | d->authNameLens[i] = strlen (d->authNames[i]); |
---|
349 | auths = (Xauth **) malloc (d->authNameNum * sizeof (Xauth *)); |
---|
350 | if (!auths) |
---|
351 | return; |
---|
352 | j = 0; |
---|
353 | for (i = 0; i < d->authNameNum; i++) |
---|
354 | { |
---|
355 | auth = GenerateAuthorization (d->authNameLens[i], d->authNames[i]); |
---|
356 | if (auth) |
---|
357 | auths[j++] = auth; |
---|
358 | } |
---|
359 | if (SaveServerAuthorizations (d, auths, j)) |
---|
360 | { |
---|
361 | d->authorizations = auths; |
---|
362 | d->authNum = j; |
---|
363 | } |
---|
364 | else |
---|
365 | { |
---|
366 | for (i = 0; i < j; i++) |
---|
367 | XauDisposeAuth (auths[i]); |
---|
368 | free ((char *) auths); |
---|
369 | } |
---|
370 | } |
---|
371 | |
---|
372 | SetAuthorization (d) |
---|
373 | struct display *d; |
---|
374 | { |
---|
375 | Xauth **auth; |
---|
376 | |
---|
377 | auth = d->authorizations; |
---|
378 | if (auth && *auth) |
---|
379 | XSetAuthorization ((*auth)->name, (int) (*auth)->name_length, |
---|
380 | (*auth)->data, (int) (*auth)->data_length); |
---|
381 | } |
---|
382 | |
---|
383 | static |
---|
384 | openFiles (name, new_name, oldp, newp) |
---|
385 | char *name, *new_name; |
---|
386 | FILE **oldp, **newp; |
---|
387 | { |
---|
388 | int mask; |
---|
389 | |
---|
390 | strcpy (new_name, name); |
---|
391 | strcat (new_name, "-n"); |
---|
392 | mask = umask (0077); |
---|
393 | (void) unlink (new_name); |
---|
394 | *newp = fopen (new_name, "w"); |
---|
395 | (void) umask (mask); |
---|
396 | if (!*newp) { |
---|
397 | Debug ("can't open new file %s\n", new_name); |
---|
398 | return 0; |
---|
399 | } |
---|
400 | *oldp = fopen (name, "r"); |
---|
401 | Debug ("opens succeeded %s %s\n", name, new_name); |
---|
402 | return 1; |
---|
403 | } |
---|
404 | |
---|
405 | static |
---|
406 | binaryEqual (a, b, len) |
---|
407 | char *a, *b; |
---|
408 | unsigned short len; |
---|
409 | { |
---|
410 | while (len-- > 0) |
---|
411 | if (*a++ != *b++) |
---|
412 | return 0; |
---|
413 | return 1; |
---|
414 | } |
---|
415 | |
---|
416 | static |
---|
417 | dumpBytes (len, data) |
---|
418 | unsigned short len; |
---|
419 | char *data; |
---|
420 | { |
---|
421 | unsigned short i; |
---|
422 | |
---|
423 | Debug ("%d: ", len); |
---|
424 | for (i = 0; i < len; i++) |
---|
425 | Debug ("%02x ", data[i] & 0377); |
---|
426 | Debug ("\n"); |
---|
427 | } |
---|
428 | |
---|
429 | static |
---|
430 | dumpAuth (auth) |
---|
431 | Xauth *auth; |
---|
432 | { |
---|
433 | Debug ("family: %d\n", auth->family); |
---|
434 | Debug ("addr: "); |
---|
435 | dumpBytes (auth->address_length, auth->address); |
---|
436 | Debug ("number: "); |
---|
437 | dumpBytes (auth->number_length, auth->number); |
---|
438 | Debug ("name: "); |
---|
439 | dumpBytes (auth->name_length, auth->name); |
---|
440 | Debug ("data: "); |
---|
441 | dumpBytes (auth->data_length, auth->data); |
---|
442 | } |
---|
443 | |
---|
444 | struct addrList { |
---|
445 | unsigned short family; |
---|
446 | unsigned short address_length; |
---|
447 | char *address; |
---|
448 | unsigned short number_length; |
---|
449 | char *number; |
---|
450 | unsigned short name_length; |
---|
451 | char *name; |
---|
452 | struct addrList *next; |
---|
453 | }; |
---|
454 | |
---|
455 | static struct addrList *addrs; |
---|
456 | |
---|
457 | static |
---|
458 | initAddrs () |
---|
459 | { |
---|
460 | addrs = 0; |
---|
461 | } |
---|
462 | |
---|
463 | static |
---|
464 | doneAddrs () |
---|
465 | { |
---|
466 | struct addrList *a, *n; |
---|
467 | for (a = addrs; a; a = n) { |
---|
468 | n = a->next; |
---|
469 | if (a->address) |
---|
470 | free (a->address); |
---|
471 | if (a->number) |
---|
472 | free (a->number); |
---|
473 | free ((char *) a); |
---|
474 | } |
---|
475 | } |
---|
476 | |
---|
477 | static checkEntry (); |
---|
478 | |
---|
479 | static |
---|
480 | saveEntry (auth) |
---|
481 | Xauth *auth; |
---|
482 | { |
---|
483 | struct addrList *new; |
---|
484 | |
---|
485 | new = (struct addrList *) malloc (sizeof (struct addrList)); |
---|
486 | if (!new) { |
---|
487 | LogOutOfMem ("saveEntry"); |
---|
488 | return; |
---|
489 | } |
---|
490 | if ((new->address_length = auth->address_length) > 0) { |
---|
491 | new->address = malloc (auth->address_length); |
---|
492 | if (!new->address) { |
---|
493 | LogOutOfMem ("saveEntry"); |
---|
494 | free ((char *) new); |
---|
495 | return; |
---|
496 | } |
---|
497 | bcopy (auth->address, new->address, (int) auth->address_length); |
---|
498 | } else |
---|
499 | new->address = 0; |
---|
500 | if ((new->number_length = auth->number_length) > 0) { |
---|
501 | new->number = malloc (auth->number_length); |
---|
502 | if (!new->number) { |
---|
503 | LogOutOfMem ("saveEntry"); |
---|
504 | free (new->address); |
---|
505 | free ((char *) new); |
---|
506 | return; |
---|
507 | } |
---|
508 | bcopy (auth->number, new->number, (int) auth->number_length); |
---|
509 | } else |
---|
510 | new->number = 0; |
---|
511 | if ((new->name_length = auth->name_length) > 0) { |
---|
512 | new->name = malloc (auth->name_length); |
---|
513 | if (!new->name) { |
---|
514 | LogOutOfMem ("saveEntry"); |
---|
515 | free (new->number); |
---|
516 | free (new->address); |
---|
517 | free ((char *) new); |
---|
518 | return; |
---|
519 | } |
---|
520 | bcopy (auth->name, new->name, (int) auth->name_length); |
---|
521 | } else |
---|
522 | new->name = 0; |
---|
523 | new->family = auth->family; |
---|
524 | new->next = addrs; |
---|
525 | addrs = new; |
---|
526 | } |
---|
527 | |
---|
528 | static |
---|
529 | checkEntry (auth) |
---|
530 | Xauth *auth; |
---|
531 | { |
---|
532 | struct addrList *a; |
---|
533 | |
---|
534 | for (a = addrs; a; a = a->next) { |
---|
535 | if (a->family == auth->family && |
---|
536 | a->address_length == auth->address_length && |
---|
537 | binaryEqual (a->address, auth->address, auth->address_length) && |
---|
538 | a->number_length == auth->number_length && |
---|
539 | binaryEqual (a->number, auth->number, auth->number_length) && |
---|
540 | a->name_length == auth->name_length && |
---|
541 | binaryEqual (a->name, auth->name, auth->name_length)) |
---|
542 | { |
---|
543 | return 1; |
---|
544 | } |
---|
545 | } |
---|
546 | return 0; |
---|
547 | } |
---|
548 | |
---|
549 | static int doWrite; |
---|
550 | |
---|
551 | static |
---|
552 | writeAuth (file, auth) |
---|
553 | FILE *file; |
---|
554 | Xauth *auth; |
---|
555 | { |
---|
556 | Debug ("writeAuth: doWrite = %d\n", doWrite); |
---|
557 | dumpAuth (auth); /* does Debug only */ |
---|
558 | if (doWrite) |
---|
559 | XauWriteAuth (file, auth); |
---|
560 | } |
---|
561 | |
---|
562 | static |
---|
563 | writeAddr (family, addr_length, addr, file, auth) |
---|
564 | int family; |
---|
565 | int addr_length; |
---|
566 | char *addr; |
---|
567 | FILE *file; |
---|
568 | Xauth *auth; |
---|
569 | { |
---|
570 | auth->family = (unsigned short) family; |
---|
571 | auth->address_length = addr_length; |
---|
572 | auth->address = addr; |
---|
573 | Debug ("writeAddr: writing and saving an entry\n"); |
---|
574 | writeAuth (file, auth); |
---|
575 | saveEntry (auth); |
---|
576 | } |
---|
577 | |
---|
578 | static |
---|
579 | DefineLocal (file, auth) |
---|
580 | FILE *file; |
---|
581 | Xauth *auth; |
---|
582 | { |
---|
583 | char displayname[100]; |
---|
584 | |
---|
585 | /* stolen from xinit.c */ |
---|
586 | |
---|
587 | /* Make sure this produces the same string as _XGetHostname in lib/X/XlibInt.c. |
---|
588 | * Otherwise, Xau will not be able to find your cookies in the Xauthority file. |
---|
589 | * |
---|
590 | * Note: POSIX says that the ``nodename'' member of utsname does _not_ have |
---|
591 | * to have sufficient information for interfacing to the network, |
---|
592 | * and so, you may be better off using gethostname (if it exists). |
---|
593 | */ |
---|
594 | |
---|
595 | #ifdef NEED_UTSNAME |
---|
596 | |
---|
597 | /* hpux: |
---|
598 | * Why not use gethostname()? Well, at least on my system, I've had to |
---|
599 | * make an ugly kernel patch to get a name longer than 8 characters, and |
---|
600 | * uname() lets me access to the whole string (it smashes release, you |
---|
601 | * see), whereas gethostname() kindly truncates it for me. |
---|
602 | */ |
---|
603 | { |
---|
604 | struct utsname name; |
---|
605 | |
---|
606 | uname(&name); |
---|
607 | strcpy(displayname, name.nodename); |
---|
608 | } |
---|
609 | #else |
---|
610 | /* AIXV3: |
---|
611 | * In AIXV3, _POSIX_SOURCE is defined, but uname gives only first |
---|
612 | * field of hostname. Thus, we use gethostname instead. |
---|
613 | */ |
---|
614 | |
---|
615 | gethostname(displayname, sizeof(displayname)); |
---|
616 | #endif |
---|
617 | writeAddr (FamilyLocal, strlen (displayname), displayname, file, auth); |
---|
618 | } |
---|
619 | |
---|
620 | #ifdef STREAMSCONN |
---|
621 | |
---|
622 | #include <tiuser.h> |
---|
623 | |
---|
624 | /* Define this host for access control. Find all the hosts the OS knows about |
---|
625 | * for this fd and add them to the selfhosts list. |
---|
626 | * TLI version, written without sufficient documentation. |
---|
627 | */ |
---|
628 | static |
---|
629 | DefineSelf (fd, file, auth) |
---|
630 | int fd; |
---|
631 | FILE *file; |
---|
632 | Xauth *auth; |
---|
633 | { |
---|
634 | struct netbuf netb; |
---|
635 | char addrret[1024]; /* easier than t_alloc */ |
---|
636 | |
---|
637 | netb.maxlen = sizeof(addrret); |
---|
638 | netb.buf = addrret; |
---|
639 | if (t_getname (fd, &netb, LOCALNAME) == -1) |
---|
640 | t_error ("t_getname"); |
---|
641 | /* what a kludge */ |
---|
642 | writeAddr (FamilyInternet, 4, netb.buf+4, file, auth); |
---|
643 | } |
---|
644 | |
---|
645 | #else /* STREAMSCONN */ |
---|
646 | #ifdef SIOCGIFCONF |
---|
647 | |
---|
648 | /* Define this host for access control. Find all the hosts the OS knows about |
---|
649 | * for this fd and add them to the selfhosts list. |
---|
650 | */ |
---|
651 | static |
---|
652 | DefineSelf (fd, file, auth) |
---|
653 | int fd; |
---|
654 | FILE *file; |
---|
655 | Xauth *auth; |
---|
656 | { |
---|
657 | char buf[2048]; |
---|
658 | struct ifconf ifc; |
---|
659 | register int n; |
---|
660 | int len; |
---|
661 | char *addr; |
---|
662 | int family; |
---|
663 | register struct ifreq *ifr; |
---|
664 | |
---|
665 | ifc.ifc_len = sizeof (buf); |
---|
666 | ifc.ifc_buf = buf; |
---|
667 | if (ioctl (fd, SIOCGIFCONF, (char *) &ifc) < 0) |
---|
668 | LogError ("Trouble getting network interface configuration"); |
---|
669 | for (ifr = ifc.ifc_req, n = ifc.ifc_len / sizeof (struct ifreq); --n >= 0; |
---|
670 | ifr++) |
---|
671 | { |
---|
672 | #ifdef DNETCONN |
---|
673 | /* |
---|
674 | * this is ugly but SIOCGIFCONF returns decnet addresses in |
---|
675 | * a different form from other decnet calls |
---|
676 | */ |
---|
677 | if (ifr->ifr_addr.sa_family == AF_DECnet) { |
---|
678 | len = sizeof (struct dn_naddr); |
---|
679 | addr = (char *)ifr->ifr_addr.sa_data; |
---|
680 | family = FamilyDECnet; |
---|
681 | } else |
---|
682 | #endif |
---|
683 | { |
---|
684 | if (ConvertAddr (&ifr->ifr_addr, &len, &addr) < 0) |
---|
685 | continue; |
---|
686 | if (len == 0) |
---|
687 | { |
---|
688 | Debug ("Skipping zero length address\n"); |
---|
689 | continue; |
---|
690 | } |
---|
691 | /* |
---|
692 | * don't write out 'localhost' entries, as |
---|
693 | * they may conflict with other local entries. |
---|
694 | * DefineLocal will always be called to add |
---|
695 | * the local entry anyway, so this one can |
---|
696 | * be tossed. |
---|
697 | */ |
---|
698 | if (len == 4 && |
---|
699 | addr[0] == 127 && addr[1] == 0 && |
---|
700 | addr[2] == 0 && addr[3] == 1) |
---|
701 | { |
---|
702 | Debug ("Skipping localhost address\n"); |
---|
703 | continue; |
---|
704 | } |
---|
705 | family = FamilyInternet; |
---|
706 | } |
---|
707 | Debug ("DefineSelf: write network address, length %d\n", len); |
---|
708 | writeAddr (family, len, addr, file, auth); |
---|
709 | } |
---|
710 | } |
---|
711 | |
---|
712 | #else /* SIOCGIFCONF */ |
---|
713 | |
---|
714 | /* Define this host for access control. Find all the hosts the OS knows about |
---|
715 | * for this fd and add them to the selfhosts list. |
---|
716 | */ |
---|
717 | static |
---|
718 | DefineSelf (fd, file, auth) |
---|
719 | int fd; |
---|
720 | { |
---|
721 | register int n; |
---|
722 | int len; |
---|
723 | caddr_t addr; |
---|
724 | int family; |
---|
725 | |
---|
726 | struct utsname name; |
---|
727 | register struct hostent *hp; |
---|
728 | |
---|
729 | union { |
---|
730 | struct sockaddr sa; |
---|
731 | struct sockaddr_in in; |
---|
732 | } saddr; |
---|
733 | |
---|
734 | struct sockaddr_in *inetaddr; |
---|
735 | |
---|
736 | /* hpux: |
---|
737 | * Why not use gethostname()? Well, at least on my system, I've had to |
---|
738 | * make an ugly kernel patch to get a name longer than 8 characters, and |
---|
739 | * uname() lets me access to the whole string (it smashes release, you |
---|
740 | * see), whereas gethostname() kindly truncates it for me. |
---|
741 | */ |
---|
742 | uname(&name); |
---|
743 | hp = gethostbyname (name.nodename); |
---|
744 | if (hp != NULL) { |
---|
745 | saddr.sa.sa_family = hp->h_addrtype; |
---|
746 | inetaddr = (struct sockaddr_in *) (&(saddr.sa)); |
---|
747 | bcopy ( (char *) hp->h_addr, (char *) &(inetaddr->sin_addr), (int) hp->h_length); |
---|
748 | family = ConvertAddr ( &(saddr.sa), &len, &addr); |
---|
749 | if ( family >= 0) { |
---|
750 | writeAddr (FamilyInternet, sizeof (inetaddr->sin_addr), |
---|
751 | (char *) (&inetaddr->sin_addr), file, auth); |
---|
752 | } |
---|
753 | } |
---|
754 | } |
---|
755 | |
---|
756 | #endif /* SIOCGIFCONF else */ |
---|
757 | #endif /* STREAMSCONN else */ |
---|
758 | |
---|
759 | static |
---|
760 | setAuthNumber (auth, name) |
---|
761 | Xauth *auth; |
---|
762 | char *name; |
---|
763 | { |
---|
764 | char *colon; |
---|
765 | char *dot, *number; |
---|
766 | |
---|
767 | Debug ("setAuthNumber %s\n", name); |
---|
768 | colon = rindex (name, ':'); |
---|
769 | if (colon) { |
---|
770 | ++colon; |
---|
771 | dot = index (colon, '.'); |
---|
772 | if (dot) |
---|
773 | auth->number_length = dot - colon; |
---|
774 | else |
---|
775 | auth->number_length = strlen (colon); |
---|
776 | number = malloc (auth->number_length + 1); |
---|
777 | if (number) { |
---|
778 | strncpy (number, colon, auth->number_length); |
---|
779 | number[auth->number_length] = '\0'; |
---|
780 | } else { |
---|
781 | LogOutOfMem ("setAuthNumber"); |
---|
782 | auth->number_length = 0; |
---|
783 | } |
---|
784 | auth->number = number; |
---|
785 | Debug ("setAuthNumber: %s\n", number); |
---|
786 | } |
---|
787 | } |
---|
788 | |
---|
789 | static |
---|
790 | writeLocalAuth (file, auth, name) |
---|
791 | FILE *file; |
---|
792 | Xauth *auth; |
---|
793 | char *name; |
---|
794 | { |
---|
795 | int fd; |
---|
796 | |
---|
797 | Debug ("writeLocalAuth: %s %.*s\n", name, auth->name_length, auth->name); |
---|
798 | setAuthNumber (auth, name); |
---|
799 | #ifdef TCPCONN |
---|
800 | fd = socket (AF_INET, SOCK_STREAM, 0); |
---|
801 | DefineSelf (fd, file, auth); |
---|
802 | close (fd); |
---|
803 | #endif |
---|
804 | #ifdef DNETCONN |
---|
805 | fd = socket (AF_DECnet, SOCK_STREAM, 0); |
---|
806 | DefineSelf (fd, file, auth); |
---|
807 | close (fd); |
---|
808 | #endif |
---|
809 | DefineLocal (file, auth); |
---|
810 | } |
---|
811 | |
---|
812 | #ifdef XDMCP |
---|
813 | |
---|
814 | static |
---|
815 | writeRemoteAuth (file, auth, peer, peerlen, name) |
---|
816 | FILE *file; |
---|
817 | Xauth *auth; |
---|
818 | struct sockaddr *peer; |
---|
819 | int peerlen; |
---|
820 | char *name; |
---|
821 | { |
---|
822 | int family = FamilyLocal; |
---|
823 | char *addr; |
---|
824 | |
---|
825 | Debug ("writeRemoteAuth: %s %.*s\n", name, auth->name_length, auth->name); |
---|
826 | if (!peer || peerlen < 2) |
---|
827 | return; |
---|
828 | setAuthNumber (auth, name); |
---|
829 | family = ConvertAddr (peer, &peerlen, &addr); |
---|
830 | Debug ("writeRemoteAuth: family %d\n", family); |
---|
831 | if (family != FamilyLocal) |
---|
832 | { |
---|
833 | Debug ("writeRemoteAuth: %d, %d, %x\n", |
---|
834 | family, peerlen, *(int *)addr); |
---|
835 | writeAddr (family, peerlen, addr, file, auth); |
---|
836 | } |
---|
837 | else |
---|
838 | { |
---|
839 | writeLocalAuth (file, auth, name); |
---|
840 | } |
---|
841 | } |
---|
842 | |
---|
843 | #endif /* XDMCP */ |
---|
844 | |
---|
845 | SetUserAuthorization (d, verify) |
---|
846 | struct display *d; |
---|
847 | struct verify_info *verify; |
---|
848 | { |
---|
849 | FILE *old, *new; |
---|
850 | char home_name[1024], backup_name[1024], new_name[1024]; |
---|
851 | char *name; |
---|
852 | char *home; |
---|
853 | char *envname = 0; |
---|
854 | int lockStatus; |
---|
855 | Xauth *entry, **auths; |
---|
856 | int setenv; |
---|
857 | char **setEnv (), *getEnv (); |
---|
858 | struct stat statb; |
---|
859 | int i; |
---|
860 | int magicCookie; |
---|
861 | |
---|
862 | Debug ("SetUserAuthorization\n"); |
---|
863 | auths = d->authorizations; |
---|
864 | if (auths) { |
---|
865 | home = getEnv (verify->userEnviron, "HOME"); |
---|
866 | lockStatus = LOCK_ERROR; |
---|
867 | if (home) { |
---|
868 | strcpy (home_name, home); |
---|
869 | if (home[strlen(home) - 1] != '/') |
---|
870 | strcat (home_name, "/"); |
---|
871 | strcat (home_name, ".Xauthority"); |
---|
872 | Debug ("XauLockAuth %s\n", home_name); |
---|
873 | lockStatus = XauLockAuth (home_name, 1, 2, 10); |
---|
874 | Debug ("Lock is %d\n", lockStatus); |
---|
875 | if (lockStatus == LOCK_SUCCESS) { |
---|
876 | if (openFiles (home_name, new_name, &old, &new)) { |
---|
877 | name = home_name; |
---|
878 | setenv = 0; |
---|
879 | } else { |
---|
880 | Debug ("openFiles failed\n"); |
---|
881 | XauUnlockAuth (home_name); |
---|
882 | lockStatus = LOCK_ERROR; |
---|
883 | } |
---|
884 | } |
---|
885 | } |
---|
886 | if (lockStatus != LOCK_SUCCESS) { |
---|
887 | sprintf (backup_name, "%s/.XauthXXXXXX", d->userAuthDir); |
---|
888 | (void) mktemp (backup_name); |
---|
889 | lockStatus = XauLockAuth (backup_name, 1, 2, 10); |
---|
890 | Debug ("backup lock is %d\n", lockStatus); |
---|
891 | if (lockStatus == LOCK_SUCCESS) { |
---|
892 | if (openFiles (backup_name, new_name, &old, &new)) { |
---|
893 | name = backup_name; |
---|
894 | setenv = 1; |
---|
895 | } else { |
---|
896 | XauUnlockAuth (backup_name); |
---|
897 | lockStatus = LOCK_ERROR; |
---|
898 | } |
---|
899 | } |
---|
900 | } |
---|
901 | if (lockStatus != LOCK_SUCCESS) { |
---|
902 | Debug ("can't lock auth file %s or backup %s\n", |
---|
903 | home_name, backup_name); |
---|
904 | LogError ("can't lock authorization file %s or backup %s\n", |
---|
905 | home_name, backup_name); |
---|
906 | return; |
---|
907 | } |
---|
908 | initAddrs (); |
---|
909 | doWrite = 1; |
---|
910 | Debug ("%d authorization protocols for %s\n", d->authNum, d->name); |
---|
911 | /* |
---|
912 | * Write MIT-MAGIC-COOKIE-1 authorization first, so that |
---|
913 | * R4 clients which only knew that, and used the first |
---|
914 | * matching entry will continue to function |
---|
915 | */ |
---|
916 | magicCookie = -1; |
---|
917 | for (i = 0; i < d->authNum; i++) |
---|
918 | { |
---|
919 | if (auths[i]->name_length == 18 && |
---|
920 | !strncmp (auths[i]->name, "MIT-MAGIC-COOKIE-1", 18)) |
---|
921 | { |
---|
922 | magicCookie = i; |
---|
923 | if (d->displayType.location == Local) |
---|
924 | writeLocalAuth (new, auths[i], d->name); |
---|
925 | #ifdef XDMCP |
---|
926 | else |
---|
927 | writeRemoteAuth (new, auths[i], d->peer, d->peerlen, d->name); |
---|
928 | #endif |
---|
929 | break; |
---|
930 | } |
---|
931 | } |
---|
932 | /* now write other authorizations */ |
---|
933 | for (i = 0; i < d->authNum; i++) |
---|
934 | { |
---|
935 | if (i != magicCookie) |
---|
936 | { |
---|
937 | if (d->displayType.location == Local) |
---|
938 | writeLocalAuth (new, auths[i], d->name); |
---|
939 | #ifdef XDMCP |
---|
940 | else |
---|
941 | writeRemoteAuth (new, auths[i], d->peer, d->peerlen, d->name); |
---|
942 | #endif |
---|
943 | } |
---|
944 | } |
---|
945 | if (old) { |
---|
946 | if (fstat (fileno (old), &statb) != -1) |
---|
947 | chmod (new_name, (int) (statb.st_mode & 0777)); |
---|
948 | /*SUPPRESS 560*/ |
---|
949 | while (entry = XauReadAuth (old)) { |
---|
950 | if (!checkEntry (entry)) |
---|
951 | { |
---|
952 | Debug ("Writing an entry\n"); |
---|
953 | writeAuth (new, entry); |
---|
954 | } |
---|
955 | XauDisposeAuth (entry); |
---|
956 | } |
---|
957 | fclose (old); |
---|
958 | } |
---|
959 | doneAddrs (); |
---|
960 | fclose (new); |
---|
961 | if (unlink (name) == -1) |
---|
962 | Debug ("unlink %s failed\n", name); |
---|
963 | envname = name; |
---|
964 | if (link (new_name, name) == -1) { |
---|
965 | Debug ("link failed %s %s\n", new_name, name); |
---|
966 | LogError ("Can't move authorization into place\n"); |
---|
967 | setenv = 1; |
---|
968 | envname = new_name; |
---|
969 | } else { |
---|
970 | Debug ("new is in place, go for it!\n"); |
---|
971 | unlink (new_name); |
---|
972 | } |
---|
973 | if (setenv) { |
---|
974 | verify->userEnviron = setEnv (verify->userEnviron, |
---|
975 | "XAUTHORITY", envname); |
---|
976 | verify->systemEnviron = setEnv (verify->systemEnviron, |
---|
977 | "XAUTHORITY", envname); |
---|
978 | } |
---|
979 | XauUnlockAuth (name); |
---|
980 | if (envname) { |
---|
981 | #ifdef NGROUPS_MAX |
---|
982 | chown (envname, verify->uid, verify->groups[0]); |
---|
983 | #else |
---|
984 | chown (envname, verify->uid, verify->gid); |
---|
985 | #endif |
---|
986 | } |
---|
987 | } |
---|
988 | Debug ("done SetUserAuthorization\n"); |
---|
989 | } |
---|
990 | |
---|
991 | RemoveUserAuthorization (d, verify) |
---|
992 | struct display *d; |
---|
993 | struct verify_info *verify; |
---|
994 | { |
---|
995 | char *home; |
---|
996 | Xauth **auths, *entry; |
---|
997 | char name[1024], new_name[1024]; |
---|
998 | int lockStatus; |
---|
999 | FILE *old, *new; |
---|
1000 | struct stat statb; |
---|
1001 | int i; |
---|
1002 | char *getEnv (); |
---|
1003 | |
---|
1004 | if (!(auths = d->authorizations)) |
---|
1005 | return; |
---|
1006 | home = getEnv (verify->userEnviron, "HOME"); |
---|
1007 | if (!home) |
---|
1008 | return; |
---|
1009 | Debug ("RemoveUserAuthorization\n"); |
---|
1010 | strcpy (name, home); |
---|
1011 | if (home[strlen(home) - 1] != '/') |
---|
1012 | strcat (name, "/"); |
---|
1013 | strcat (name, ".Xauthority"); |
---|
1014 | Debug ("XauLockAuth %s\n", name); |
---|
1015 | lockStatus = XauLockAuth (name, 1, 2, 10); |
---|
1016 | Debug ("Lock is %d\n", lockStatus); |
---|
1017 | if (lockStatus != LOCK_SUCCESS) |
---|
1018 | return; |
---|
1019 | if (openFiles (name, new_name, &old, &new)) |
---|
1020 | { |
---|
1021 | initAddrs (); |
---|
1022 | doWrite = 0; |
---|
1023 | for (i = 0; i < d->authNum; i++) |
---|
1024 | { |
---|
1025 | if (d->displayType.location == Local) |
---|
1026 | writeLocalAuth (new, auths[i], d->name); |
---|
1027 | #ifdef XDMCP |
---|
1028 | else |
---|
1029 | writeRemoteAuth (new, auths[i], d->peer, d->peerlen, d->name); |
---|
1030 | #endif |
---|
1031 | } |
---|
1032 | doWrite = 1; |
---|
1033 | if (old) { |
---|
1034 | if (fstat (fileno (old), &statb) != -1) |
---|
1035 | chmod (new_name, (int) (statb.st_mode & 0777)); |
---|
1036 | /*SUPPRESS 560*/ |
---|
1037 | while (entry = XauReadAuth (old)) { |
---|
1038 | if (!checkEntry (entry)) |
---|
1039 | { |
---|
1040 | Debug ("Writing an entry\n"); |
---|
1041 | writeAuth (new, entry); |
---|
1042 | } |
---|
1043 | XauDisposeAuth (entry); |
---|
1044 | } |
---|
1045 | fclose (old); |
---|
1046 | } |
---|
1047 | doneAddrs (); |
---|
1048 | fclose (new); |
---|
1049 | if (unlink (name) == -1) |
---|
1050 | Debug ("unlink %s failed\n", name); |
---|
1051 | if (link (new_name, name) == -1) { |
---|
1052 | Debug ("link failed %s %s\n", new_name, name); |
---|
1053 | LogError ("Can't move authorization into place\n"); |
---|
1054 | } else { |
---|
1055 | Debug ("new is in place, go for it!\n"); |
---|
1056 | unlink (new_name); |
---|
1057 | } |
---|
1058 | } |
---|
1059 | XauUnlockAuth (name); |
---|
1060 | } |
---|