File: | xdm/access.c |
Location: | line 316, column 9 |
Description: | Result of 'malloc' is converted to a pointer of type 'HostEntry', which is incompatible with sizeof operand type 'DisplayEntry' |
1 | /* |
2 | * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. |
3 | * |
4 | * Permission is hereby granted, free of charge, to any person obtaining a |
5 | * copy of this software and associated documentation files (the "Software"), |
6 | * to deal in the Software without restriction, including without limitation |
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
8 | * and/or sell copies of the Software, and to permit persons to whom the |
9 | * Software is furnished to do so, subject to the following conditions: |
10 | * |
11 | * The above copyright notice and this permission notice (including the next |
12 | * paragraph) shall be included in all copies or substantial portions of the |
13 | * Software. |
14 | * |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
21 | * DEALINGS IN THE SOFTWARE. |
22 | */ |
23 | /* |
24 | * |
25 | Copyright 1990, 1998 The Open Group |
26 | |
27 | Permission to use, copy, modify, distribute, and sell this software and its |
28 | documentation for any purpose is hereby granted without fee, provided that |
29 | the above copyright notice appear in all copies and that both that |
30 | copyright notice and this permission notice appear in supporting |
31 | documentation. |
32 | |
33 | The above copyright notice and this permission notice shall be included in |
34 | all copies or substantial portions of the Software. |
35 | |
36 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
37 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
38 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
39 | OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
40 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
41 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
42 | |
43 | Except as contained in this notice, the name of a copyright holder shall not be |
44 | used in advertising or otherwise to promote the sale, use or other dealings |
45 | in this Software without prior written authorization from the copyright holder. |
46 | * |
47 | * Author: Keith Packard, MIT X Consortium |
48 | */ |
49 | |
50 | |
51 | /* |
52 | * Access control for XDMCP - keep a database of allowable display addresses |
53 | * and (potentially) a list of hosts to send ForwardQuery packets to |
54 | */ |
55 | |
56 | #include "dm.h" |
57 | #include "dm_error.h" |
58 | |
59 | #ifdef XDMCP |
60 | |
61 | # include <X11/Xos.h> |
62 | # include <X11/Xdmcp.h> |
63 | # include <X11/X.h> |
64 | # include <stdio.h> |
65 | # include <ctype.h> |
66 | |
67 | # include "dm_socket.h" |
68 | |
69 | # include <netdb.h> |
70 | |
71 | # if defined(IPv61) && defined(AF_INET630) |
72 | # include <arpa/inet.h> |
73 | # endif |
74 | |
75 | # define ALIAS_CHARACTER'%' '%' |
76 | # define NEGATE_CHARACTER'!' '!' |
77 | # define CHOOSER_STRING"CHOOSER" "CHOOSER" |
78 | # define BROADCAST_STRING"BROADCAST" "BROADCAST" |
79 | # define NOBROADCAST_STRING"NOBROADCAST" "NOBROADCAST" |
80 | # define LISTEN_STRING"LISTEN" "LISTEN" |
81 | # define WILDCARD_STRING"*" "*" |
82 | |
83 | # define HOST_ALIAS0 0 |
84 | # define HOST_ADDRESS1 1 |
85 | # define HOST_BROADCAST2 2 |
86 | # define HOST_CHOOSER3 3 |
87 | # define HOST_NOBROADCAST4 4 |
88 | # define HOST_ANYADDR5 5 |
89 | |
90 | typedef struct _hostEntry { |
91 | struct _hostEntry *next; |
92 | int type; |
93 | union _hostOrAlias { |
94 | char *aliasName; |
95 | ARRAY8 hostAddress; |
96 | } entry; |
97 | int hopCount; |
98 | } HostEntry; |
99 | |
100 | # define DISPLAY_ALIAS0 0 |
101 | # define DISPLAY_PATTERN1 1 |
102 | # define DISPLAY_ADDRESS2 2 |
103 | # define DISPLAY_LISTEN3 3 |
104 | |
105 | typedef struct _displayEntry { |
106 | struct _displayEntry *next; |
107 | int type; |
108 | int notAllowed; |
109 | int notBroadcast; |
110 | int chooser; |
111 | union _displayType { |
112 | char *aliasName; |
113 | char *displayPattern; |
114 | struct _display { |
115 | ARRAY8 clientAddress; |
116 | CARD16 connectionType; |
117 | } displayAddress; |
118 | } entry; |
119 | HostEntry *hosts; |
120 | } DisplayEntry; |
121 | |
122 | static DisplayEntry *database; |
123 | |
124 | ARRAY8Ptr |
125 | getLocalAddress (void) |
126 | { |
127 | static ARRAY8 localAddress; |
128 | static int haveLocalAddress; |
129 | |
130 | if (!haveLocalAddress) |
131 | { |
132 | # if defined(IPv61) && defined(AF_INET630) |
133 | struct addrinfo *ai; |
134 | |
135 | if (getaddrinfo(localHostname(), NULL((void*)0), NULL((void*)0), &ai) != 0) { |
136 | if (XdmcpAllocARRAY8 (&localAddress, 4)) { |
137 | localAddress.data[0] = 127; |
138 | localAddress.data[1] = 0; |
139 | localAddress.data[2] = 0; |
140 | localAddress.data[3] = 1; |
141 | haveLocalAddress = 1; |
142 | } |
143 | } else { |
144 | if (ai->ai_addr->sa_family == AF_INET2) { |
145 | if (XdmcpAllocARRAY8 (&localAddress, sizeof(struct in_addr))) { |
146 | memcpy(localAddress.data,__builtin___memcpy_chk (localAddress.data, &((struct sockaddr_in *)ai->ai_addr)->sin_addr, sizeof(struct in_addr), __builtin_object_size (localAddress.data, 0)) |
147 | &((struct sockaddr_in *)ai->ai_addr)->sin_addr,__builtin___memcpy_chk (localAddress.data, &((struct sockaddr_in *)ai->ai_addr)->sin_addr, sizeof(struct in_addr), __builtin_object_size (localAddress.data, 0)) |
148 | sizeof(struct in_addr))__builtin___memcpy_chk (localAddress.data, &((struct sockaddr_in *)ai->ai_addr)->sin_addr, sizeof(struct in_addr), __builtin_object_size (localAddress.data, 0)); |
149 | haveLocalAddress = 1; |
150 | } |
151 | } else if (ai->ai_addr->sa_family == AF_INET630) { |
152 | if (XdmcpAllocARRAY8 (&localAddress, sizeof(struct in6_addr))) |
153 | { |
154 | memcpy(localAddress.data,__builtin___memcpy_chk (localAddress.data, &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr, sizeof(struct in6_addr), __builtin_object_size (localAddress.data, 0)) |
155 | &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr,__builtin___memcpy_chk (localAddress.data, &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr, sizeof(struct in6_addr), __builtin_object_size (localAddress.data, 0)) |
156 | sizeof(struct in6_addr))__builtin___memcpy_chk (localAddress.data, &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr, sizeof(struct in6_addr), __builtin_object_size (localAddress.data, 0)); |
157 | haveLocalAddress = 1; |
158 | } |
159 | } |
160 | freeaddrinfo(ai); |
161 | } |
162 | # else |
163 | struct hostent *hostent; |
164 | |
165 | hostent = gethostbyname (localHostname()); |
166 | if (hostent != NULL((void*)0)) { |
167 | if (XdmcpAllocARRAY8 (&localAddress, hostent->h_length)) { |
168 | memmove(localAddress.data, hostent->h_addr, hostent->h_length)__builtin___memmove_chk (localAddress.data, hostent->h_addr_list [0], hostent->h_length, __builtin_object_size (localAddress .data, 0)); |
169 | haveLocalAddress = 1; |
170 | } |
171 | } else { |
172 | /* Assume 127.0.0.1 */ |
173 | if (XdmcpAllocARRAY8 (&localAddress, 4)) { |
174 | localAddress.data[0] = 127; |
175 | localAddress.data[1] = 0; |
176 | localAddress.data[2] = 0; |
177 | localAddress.data[3] = 1; |
178 | haveLocalAddress = 1; |
179 | } |
180 | } |
181 | # endif |
182 | |
183 | } |
184 | return &localAddress; |
185 | } |
186 | |
187 | static void |
188 | FreeHostEntry (HostEntry *h) |
189 | { |
190 | switch (h->type) { |
191 | case HOST_ALIAS0: |
192 | free (h->entry.aliasName); |
193 | break; |
194 | case HOST_ADDRESS1: |
195 | XdmcpDisposeARRAY8 (&h->entry.hostAddress); |
196 | break; |
197 | case HOST_CHOOSER3: |
198 | break; |
199 | } |
200 | free (h); |
201 | } |
202 | |
203 | static void |
204 | FreeDisplayEntry (DisplayEntry *d) |
205 | { |
206 | HostEntry *h, *next; |
207 | switch (d->type) { |
208 | case DISPLAY_ALIAS0: |
209 | free (d->entry.aliasName); |
210 | break; |
211 | case DISPLAY_PATTERN1: |
212 | free (d->entry.displayPattern); |
213 | break; |
214 | case DISPLAY_ADDRESS2: |
215 | XdmcpDisposeARRAY8 (&d->entry.displayAddress.clientAddress); |
216 | break; |
217 | case DISPLAY_LISTEN3: |
218 | /* do nothing - this case doesn't use the d->entry union */ |
219 | break; |
220 | } |
221 | for (h = d->hosts; h; h = next) { |
222 | next = h->next; |
223 | FreeHostEntry (h); |
224 | } |
225 | free (d); |
226 | } |
227 | |
228 | static void |
229 | FreeAccessDatabase (void) |
230 | { |
231 | DisplayEntry *d, *next; |
232 | |
233 | for (d = database; d; d = next) |
234 | { |
235 | next = d->next; |
236 | FreeDisplayEntry (d); |
237 | } |
238 | database = NULL((void*)0); |
239 | } |
240 | |
241 | # define WORD_LEN256 256 |
242 | static char wordBuffer[WORD_LEN256]; |
243 | static int nextIsEOF; |
244 | |
245 | static char * |
246 | ReadWord (FILE *file, int EOFatEOL) |
247 | { |
248 | int c; |
249 | char *wordp; |
250 | int quoted; |
251 | |
252 | wordp = wordBuffer; |
253 | if (nextIsEOF) |
254 | { |
255 | nextIsEOF = FALSE0; |
256 | return NULL((void*)0); |
257 | } |
258 | quoted = FALSE0; |
259 | for (;wordp - wordBuffer < sizeof(wordBuffer)-2;) { |
260 | c = getc (file); |
261 | switch (c) { |
262 | case '#': |
263 | if (quoted) |
264 | { |
265 | *wordp++ = c; |
266 | break; |
267 | } |
268 | while ((c = getc (file)) != EOF(-1) && c != '\n') |
269 | ; |
270 | case '\n': |
271 | case EOF(-1): |
272 | if (c == EOF(-1) || (EOFatEOL && !quoted)) |
273 | { |
274 | ungetc (c, file); |
275 | if (wordp == wordBuffer) |
276 | return NULL((void*)0); |
277 | *wordp = '\0'; |
278 | nextIsEOF = TRUE1; |
279 | return wordBuffer; |
280 | } |
281 | case ' ': |
282 | case '\t': |
283 | if (wordp != wordBuffer) |
284 | { |
285 | ungetc (c, file); |
286 | *wordp = '\0'; |
287 | return wordBuffer; |
288 | } |
289 | break; |
290 | case '\\': |
291 | if (!quoted) |
292 | { |
293 | quoted = TRUE1; |
294 | continue; |
295 | } |
296 | default: |
297 | if (wordp < &(wordBuffer[WORD_LEN256])) |
298 | *wordp++ = c; |
299 | break; |
300 | } |
301 | quoted = FALSE0; |
302 | } |
303 | return NULL((void*)0); |
304 | } |
305 | |
306 | static HostEntry * |
307 | ReadHostEntry (FILE *file) |
308 | { |
309 | char *hostOrAlias; |
310 | HostEntry *h; |
311 | |
312 | tryagain: |
313 | hostOrAlias = ReadWord (file, TRUE1); |
314 | if (!hostOrAlias) |
315 | return NULL((void*)0); |
316 | h = malloc (sizeof (DisplayEntry)); |
Result of 'malloc' is converted to a pointer of type 'HostEntry', which is incompatible with sizeof operand type 'DisplayEntry' | |
317 | if (!h) |
318 | { |
319 | LogOutOfMem ("ReadHostEntry: DisplayEntry\n"); |
320 | return NULL((void*)0); |
321 | } |
322 | h->hopCount = 1; |
323 | if (*hostOrAlias == ALIAS_CHARACTER'%') |
324 | { |
325 | h->type = HOST_ALIAS0; |
326 | h->entry.aliasName = strdup (hostOrAlias); |
327 | if (!h->entry.aliasName) { |
328 | free (h); |
329 | return NULL((void*)0); |
330 | } |
331 | } |
332 | else if (!strcmp (hostOrAlias, CHOOSER_STRING"CHOOSER")) |
333 | { |
334 | h->type = HOST_CHOOSER3; |
335 | } |
336 | else if (!strcmp (hostOrAlias, BROADCAST_STRING"BROADCAST")) |
337 | { |
338 | h->type = HOST_BROADCAST2; |
339 | } |
340 | else if (!strcmp (hostOrAlias, NOBROADCAST_STRING"NOBROADCAST")) |
341 | { |
342 | h->type = HOST_NOBROADCAST4; |
343 | } |
344 | else if (!strcmp (hostOrAlias, WILDCARD_STRING"*")) |
345 | { |
346 | h->type = HOST_ANYADDR5; |
347 | h->entry.hostAddress.length = 0; |
348 | } |
349 | else |
350 | { |
351 | void *addr=NULL((void*)0); |
352 | size_t addr_length=0; |
353 | # if defined(IPv61) && defined(AF_INET630) |
354 | struct addrinfo *ai = NULL((void*)0); |
355 | # else |
356 | struct hostent *hostent = gethostbyname (hostOrAlias); |
357 | # endif |
358 | char *hops = strrchr(hostOrAlias, '/'); |
359 | |
360 | if (hops) { |
361 | *(hops++) = '\0'; |
362 | h->hopCount = strtol(hops, NULL((void*)0), 10); |
363 | if (h->hopCount < 1) |
364 | h->hopCount = 1; |
365 | } |
366 | |
367 | # if defined(IPv61) && defined(AF_INET630) |
368 | if (getaddrinfo(hostOrAlias, NULL((void*)0), NULL((void*)0), &ai) == 0) { |
369 | if (ai->ai_addr->sa_family == AF_INET2) { |
370 | addr = &((struct sockaddr_in *)ai->ai_addr)->sin_addr; |
371 | addr_length = sizeof(struct in_addr); |
372 | } else if (ai->ai_addr->sa_family == AF_INET630) { |
373 | addr = &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr; |
374 | addr_length = sizeof(struct in6_addr); |
375 | } |
376 | } |
377 | # else |
378 | if (hostent) { |
379 | addr = hostent->h_addrh_addr_list[0]; |
380 | addr_length = hostent->h_length; |
381 | } |
382 | # endif |
383 | h->type = HOST_ADDRESS1; |
384 | |
385 | if (!addr) |
386 | { |
387 | Debug ("No such host %s\n", hostOrAlias); |
388 | LogError ("Access file \"%s\", host \"%s\" not found\n", accessFile, hostOrAlias); |
389 | free (h); |
390 | # if defined(IPv61) && defined(AF_INET630) |
391 | if (ai) |
392 | freeaddrinfo(ai); |
393 | # endif |
394 | goto tryagain; |
395 | } |
396 | if (!XdmcpAllocARRAY8 (&h->entry.hostAddress, addr_length)) |
397 | { |
398 | LogOutOfMem ("ReadHostEntry\n"); |
399 | free (h); |
400 | # if defined(IPv61) && defined(AF_INET630) |
401 | if (ai) |
402 | freeaddrinfo(ai); |
403 | # endif |
404 | return NULL((void*)0); |
405 | } |
406 | memmove( h->entry.hostAddress.data, addr, addr_length)__builtin___memmove_chk (h->entry.hostAddress.data, addr, addr_length , __builtin_object_size (h->entry.hostAddress.data, 0)); |
407 | # if defined(IPv61) && defined(AF_INET630) |
408 | if (ai) |
409 | freeaddrinfo(ai); |
410 | # endif |
411 | } |
412 | return h; |
413 | } |
414 | |
415 | static int |
416 | HasGlobCharacters (char *s) |
417 | { |
418 | for (;;) |
419 | switch (*s++) { |
420 | case '?': |
421 | case '*': |
422 | return 1; |
423 | case '\0': |
424 | return 0; |
425 | } |
426 | } |
427 | |
428 | static DisplayEntry * |
429 | ReadDisplayEntry (FILE *file) |
430 | { |
431 | char *displayOrAlias; |
432 | DisplayEntry *d; |
433 | struct _display *display; |
434 | HostEntry *h, **prev; |
435 | |
436 | tryagain: |
437 | displayOrAlias = ReadWord (file, FALSE0); |
438 | if (!displayOrAlias) |
439 | return NULL((void*)0); |
440 | d = malloc (sizeof (DisplayEntry)); |
441 | if (!d) |
442 | { |
443 | LogOutOfMem ("ReadDisplayEntry: DisplayEntry\n"); |
444 | return NULL((void*)0); |
445 | } |
446 | d->notAllowed = 0; |
447 | d->notBroadcast = 0; |
448 | d->chooser = 0; |
449 | if (*displayOrAlias == ALIAS_CHARACTER'%') |
450 | { |
451 | d->type = DISPLAY_ALIAS0; |
452 | d->entry.aliasName = strdup (displayOrAlias); |
453 | if (!d->entry.aliasName) |
454 | { |
455 | free (d); |
456 | return NULL((void*)0); |
457 | } |
458 | } |
459 | else if (!strcmp(displayOrAlias, LISTEN_STRING"LISTEN")) |
460 | { |
461 | d->type = DISPLAY_LISTEN3; |
462 | } |
463 | else |
464 | { |
465 | if (*displayOrAlias == NEGATE_CHARACTER'!') |
466 | { |
467 | d->notAllowed = 1; |
468 | ++displayOrAlias; |
469 | } |
470 | if (HasGlobCharacters (displayOrAlias)) |
471 | { |
472 | d->type = DISPLAY_PATTERN1; |
473 | d->entry.displayPattern = strdup (displayOrAlias); |
474 | if (!d->entry.displayPattern) |
475 | { |
476 | free (d); |
477 | return NULL((void*)0); |
478 | } |
479 | } |
480 | else |
481 | { |
482 | void *addr = NULL((void*)0); |
483 | size_t addr_length = 0; |
484 | int addrtype = 0; |
485 | |
486 | # if defined(IPv61) && defined(AF_INET630) |
487 | struct addrinfo *ai = NULL((void*)0); |
488 | |
489 | if (getaddrinfo(displayOrAlias, NULL((void*)0), NULL((void*)0), &ai) == 0) { |
490 | addrtype = ai->ai_addr->sa_family; |
491 | if (addrtype == AF_INET2) { |
492 | addr = &((struct sockaddr_in *)ai->ai_addr)->sin_addr; |
493 | addr_length = sizeof(struct in_addr); |
494 | } else if (addrtype == AF_INET630) { |
495 | addr = &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr; |
496 | addr_length = sizeof(struct in6_addr); |
497 | } |
498 | } |
499 | # else |
500 | struct hostent *hostent; |
501 | |
502 | if ((hostent = gethostbyname (displayOrAlias)) != NULL((void*)0)) |
503 | { |
504 | Debug("ReadDisplayEntry: %s\n", displayOrAlias); |
505 | addr = hostent->h_addrh_addr_list[0]; |
506 | addrtype = hostent->h_addrtype; |
507 | addr_length = hostent->h_length; |
508 | } |
509 | # endif |
510 | if (addr == NULL((void*)0)) |
511 | { |
512 | LogError ("Access file %s, display %s unknown\n", accessFile, displayOrAlias); |
513 | free (d); |
514 | # if defined(IPv61) && defined(AF_INET630) |
515 | if (ai) |
516 | freeaddrinfo(ai); |
517 | # endif |
518 | goto tryagain; |
519 | } |
520 | d->type = DISPLAY_ADDRESS2; |
521 | display = &d->entry.displayAddress; |
522 | if (!XdmcpAllocARRAY8 (&display->clientAddress, addr_length)) |
523 | { |
524 | free (d); |
525 | # if defined(IPv61) && defined(AF_INET630) |
526 | if (ai) |
527 | freeaddrinfo(ai); |
528 | # endif |
529 | return NULL((void*)0); |
530 | } |
531 | memmove( display->clientAddress.data, addr, addr_length)__builtin___memmove_chk (display->clientAddress.data, addr , addr_length, __builtin_object_size (display->clientAddress .data, 0)); |
532 | # if defined(IPv61) && defined(AF_INET630) |
533 | if (ai) |
534 | freeaddrinfo(ai); |
535 | # endif |
536 | switch (addrtype) |
537 | { |
538 | # ifdef AF_UNIX1 |
539 | case AF_UNIX1: |
540 | display->connectionType = FamilyLocal(256); |
541 | break; |
542 | # endif |
543 | # ifdef AF_INET2 |
544 | case AF_INET2: |
545 | display->connectionType = FamilyInternet0; |
546 | break; |
547 | # endif |
548 | # if defined(IPv61) && defined(AF_INET630) |
549 | case AF_INET630: |
550 | display->connectionType = FamilyInternet66; |
551 | break; |
552 | # endif |
553 | # ifdef AF_DECnet12 |
554 | case AF_DECnet12: |
555 | display->connectionType = FamilyDECnet1; |
556 | break; |
557 | # endif |
558 | default: |
559 | display->connectionType = FamilyLocal(256); |
560 | break; |
561 | } |
562 | } |
563 | } |
564 | prev = &d->hosts; |
565 | while ((h = ReadHostEntry (file))) |
566 | { |
567 | if (h->type == HOST_CHOOSER3) |
568 | { |
569 | FreeHostEntry (h); |
570 | d->chooser = 1; |
571 | } else if (h->type == HOST_NOBROADCAST4) { |
572 | FreeHostEntry (h); |
573 | d->notBroadcast = 1; |
574 | } else if (h->type == HOST_ANYADDR5) { |
575 | if (d->type == DISPLAY_LISTEN3) { |
576 | *prev = h; |
577 | prev = &h->next; |
578 | } else { |
579 | Debug("Wildcard host specified in Xaccess for type other than LISTEN -- ignoring\n"); |
580 | FreeHostEntry (h); |
581 | } |
582 | } else { |
583 | *prev = h; |
584 | prev = &h->next; |
585 | } |
586 | } |
587 | *prev = NULL((void*)0); |
588 | return d; |
589 | } |
590 | |
591 | static void |
592 | ReadAccessDatabase (FILE *file) |
593 | { |
594 | DisplayEntry *d, **prev; |
595 | |
596 | prev = &database; |
597 | while ((d = ReadDisplayEntry (file))) |
598 | { |
599 | *prev = d; |
600 | prev = &d->next; |
601 | } |
602 | *prev = NULL((void*)0); |
603 | } |
604 | |
605 | int |
606 | ScanAccessDatabase (void) |
607 | { |
608 | FILE *datafile; |
609 | |
610 | FreeAccessDatabase (); |
611 | if (*accessFile) |
612 | { |
613 | datafile = fopen (accessFile, "r"); |
614 | if (!datafile) |
615 | { |
616 | LogError ("Cannot open access control file %s, no XDMCP reqeusts will be granted\n", accessFile); |
617 | return 0; |
618 | } |
619 | ReadAccessDatabase (datafile); |
620 | fclose (datafile); |
621 | } |
622 | return 1; |
623 | } |
624 | |
625 | /* |
626 | * calls the given function for each valid indirect entry. Returns TRUE if |
627 | * the local host exists on any of the lists, else FALSE |
628 | */ |
629 | |
630 | # define MAX_DEPTH32 32 |
631 | |
632 | static int indirectAlias ( |
633 | char *alias, |
634 | ARRAY8Ptr clientAddress, |
635 | CARD16 connectionType, |
636 | ChooserFunc function, |
637 | char *closure, |
638 | int depth, |
639 | int broadcast); |
640 | |
641 | |
642 | static int |
643 | scanHostlist ( |
644 | HostEntry *h, |
645 | ARRAY8Ptr clientAddress, |
646 | CARD16 connectionType, |
647 | ChooserFunc function, |
648 | char *closure, |
649 | int depth, |
650 | int broadcast) |
651 | { |
652 | int haveLocalhost = 0; |
653 | |
654 | for (; h; h = h->next) |
655 | { |
656 | switch (h->type) { |
657 | case HOST_ALIAS0: |
658 | if (indirectAlias (h->entry.aliasName, clientAddress, |
659 | connectionType, function, closure, depth, |
660 | broadcast)) |
661 | haveLocalhost = 1; |
662 | break; |
663 | case HOST_ADDRESS1: |
664 | if (XdmcpARRAY8Equal (getLocalAddress(), &h->entry.hostAddress)) |
665 | haveLocalhost = 1; |
666 | else if (function) |
667 | (*function) (connectionType, &h->entry.hostAddress, closure); |
668 | break; |
669 | case HOST_BROADCAST2: |
670 | if (broadcast) |
671 | { |
672 | ARRAY8 temp; |
673 | |
674 | if (function) |
675 | { |
676 | temp.data = (BYTE *) BROADCAST_STRING"BROADCAST"; |
677 | temp.length = strlen ((char *)temp.data); |
678 | (*function) (connectionType, &temp, closure); |
679 | } |
680 | } |
681 | break; |
682 | } |
683 | } |
684 | return haveLocalhost; |
685 | } |
686 | |
687 | /* Returns non-0 iff string is matched by pattern. Does case folding. |
688 | */ |
689 | static int |
690 | patternMatch (const char *string, char *pattern) |
691 | { |
692 | int p, s; |
693 | |
694 | if (!string) |
695 | string = ""; |
696 | |
697 | for (;;) |
698 | { |
699 | s = *string++; |
700 | switch (p = *pattern++) { |
701 | case '*': |
702 | if (!*pattern) |
703 | return 1; |
704 | for (string--; *string; string++) |
705 | if (patternMatch (string, pattern)) |
706 | return 1; |
707 | return 0; |
708 | case '?': |
709 | if (s == '\0') |
710 | return 0; |
711 | break; |
712 | case '\0': |
713 | return s == '\0'; |
714 | case '\\': |
715 | p = *pattern++; |
716 | /* fall through */ |
717 | default: |
718 | if (isupper(p)) p = tolower(p); |
719 | if (isupper(s)) s = tolower(s); |
720 | if (p != s) |
721 | return 0; |
722 | } |
723 | } |
724 | } |
725 | |
726 | static int |
727 | indirectAlias ( |
728 | char *alias, |
729 | ARRAY8Ptr clientAddress, |
730 | CARD16 connectionType, |
731 | ChooserFunc function, |
732 | char *closure, |
733 | int depth, |
734 | int broadcast) |
735 | { |
736 | DisplayEntry *d; |
737 | int haveLocalhost = 0; |
738 | |
739 | if (depth == MAX_DEPTH32) |
740 | return 0; |
741 | for (d = database; d; d = d->next) |
742 | { |
743 | if (d->type != DISPLAY_ALIAS0 || !patternMatch (alias, d->entry.aliasName)) |
744 | continue; |
745 | if (scanHostlist (d->hosts, clientAddress, connectionType, |
746 | function, closure, depth + 1, broadcast)) |
747 | { |
748 | haveLocalhost = 1; |
749 | } |
750 | } |
751 | return haveLocalhost; |
752 | } |
753 | |
754 | int ForEachMatchingIndirectHost ( |
755 | ARRAY8Ptr clientAddress, |
756 | CARD16 connectionType, |
757 | ChooserFunc function, |
758 | char *closure) |
759 | { |
760 | int haveLocalhost = 0; |
761 | DisplayEntry *d; |
762 | char *clientName = NULL((void*)0); |
763 | |
764 | for (d = database; d; d = d->next) |
765 | { |
766 | switch (d->type) { |
767 | case DISPLAY_ALIAS0: |
768 | case DISPLAY_LISTEN3: |
769 | continue; |
770 | case DISPLAY_PATTERN1: |
771 | if (!clientName) |
772 | clientName = NetworkAddressToHostname (connectionType, |
773 | clientAddress); |
774 | if (!patternMatch (clientName, d->entry.displayPattern)) |
775 | continue; |
776 | break; |
777 | case DISPLAY_ADDRESS2: |
778 | if (d->entry.displayAddress.connectionType != connectionType || |
779 | !XdmcpARRAY8Equal (&d->entry.displayAddress.clientAddress, |
780 | clientAddress)) |
781 | { |
782 | continue; |
783 | } |
784 | break; |
785 | } |
786 | if (!d->hosts) |
787 | continue; |
788 | if (d->notAllowed) |
789 | break; |
790 | if (d->chooser) |
791 | { |
792 | ARRAY8Ptr choice; |
793 | |
794 | choice = IndirectChoice (clientAddress, connectionType); |
795 | if (!choice || XdmcpARRAY8Equal (getLocalAddress(), choice)) |
796 | haveLocalhost = 1; |
797 | else |
798 | (*function) (connectionType, choice, closure); |
799 | } |
800 | else if (scanHostlist (d->hosts, clientAddress, connectionType, |
801 | function, closure, 0, FALSE0)) |
802 | { |
803 | haveLocalhost = 1; |
804 | } |
805 | break; |
806 | } |
807 | free (clientName); |
808 | return haveLocalhost; |
809 | } |
810 | |
811 | int UseChooser ( |
812 | ARRAY8Ptr clientAddress, |
813 | CARD16 connectionType) |
814 | { |
815 | DisplayEntry *d; |
816 | char *clientName = NULL((void*)0); |
817 | |
818 | for (d = database; d; d = d->next) |
819 | { |
820 | switch (d->type) { |
821 | case DISPLAY_ALIAS0: |
822 | case DISPLAY_LISTEN3: |
823 | continue; |
824 | case DISPLAY_PATTERN1: |
825 | if (!clientName) |
826 | clientName = NetworkAddressToHostname (connectionType, |
827 | clientAddress); |
828 | if (!patternMatch (clientName, d->entry.displayPattern)) |
829 | continue; |
830 | break; |
831 | case DISPLAY_ADDRESS2: |
832 | if (d->entry.displayAddress.connectionType != connectionType || |
833 | !XdmcpARRAY8Equal (&d->entry.displayAddress.clientAddress, |
834 | clientAddress)) |
835 | { |
836 | continue; |
837 | } |
838 | break; |
839 | } |
840 | if (!d->hosts) |
841 | continue; |
842 | if (d->notAllowed) |
843 | break; |
844 | if (d->chooser && !IndirectChoice (clientAddress, connectionType)) { |
845 | free (clientName); |
846 | return 1; |
847 | } |
848 | break; |
849 | } |
850 | free (clientName); |
851 | return 0; |
852 | } |
853 | |
854 | void ForEachChooserHost ( |
855 | ARRAY8Ptr clientAddress, |
856 | CARD16 connectionType, |
857 | ChooserFunc function, |
858 | char *closure) |
859 | { |
860 | int haveLocalhost = 0; |
861 | DisplayEntry *d; |
862 | char *clientName = NULL((void*)0); |
863 | |
864 | for (d = database; d; d = d->next) |
865 | { |
866 | switch (d->type) { |
867 | case DISPLAY_ALIAS0: |
868 | case DISPLAY_LISTEN3: |
869 | continue; |
870 | case DISPLAY_PATTERN1: |
871 | if (!clientName) |
872 | clientName = NetworkAddressToHostname (connectionType, |
873 | clientAddress); |
874 | if (!patternMatch (clientName, d->entry.displayPattern)) |
875 | continue; |
876 | break; |
877 | case DISPLAY_ADDRESS2: |
878 | if (d->entry.displayAddress.connectionType != connectionType || |
879 | !XdmcpARRAY8Equal (&d->entry.displayAddress.clientAddress, |
880 | clientAddress)) |
881 | { |
882 | continue; |
883 | } |
884 | break; |
885 | } |
886 | if (!d->hosts) |
887 | continue; |
888 | if (d->notAllowed) |
889 | break; |
890 | if (!d->chooser) |
891 | break; |
892 | if (scanHostlist (d->hosts, clientAddress, connectionType, |
893 | function, closure, 0, TRUE1)) |
894 | { |
895 | haveLocalhost = 1; |
896 | } |
897 | break; |
898 | } |
899 | free (clientName); |
900 | if (haveLocalhost) |
901 | (*function) (connectionType, getLocalAddress(), closure); |
902 | } |
903 | |
904 | /* |
905 | * returns TRUE if the given client is acceptable to the local host. The |
906 | * given display client is acceptable if it occurs without a host list. |
907 | */ |
908 | |
909 | int AcceptableDisplayAddress ( |
910 | ARRAY8Ptr clientAddress, |
911 | CARD16 connectionType, |
912 | xdmOpCode type) |
913 | { |
914 | DisplayEntry *d; |
915 | char *clientName = NULL((void*)0); |
916 | |
917 | if (!*accessFile) |
918 | return 1; |
919 | if (type == INDIRECT_QUERY) |
920 | return 1; |
921 | for (d = database; d; d = d->next) |
922 | { |
923 | if (d->hosts) |
924 | continue; |
925 | switch (d->type) { |
926 | case DISPLAY_ALIAS0: |
927 | case DISPLAY_LISTEN3: |
928 | continue; |
929 | case DISPLAY_PATTERN1: |
930 | if (!clientName) |
931 | clientName = NetworkAddressToHostname (connectionType, |
932 | clientAddress); |
933 | if (!patternMatch (clientName, d->entry.displayPattern)) |
934 | continue; |
935 | break; |
936 | case DISPLAY_ADDRESS2: |
937 | if (d->entry.displayAddress.connectionType != connectionType || |
938 | !XdmcpARRAY8Equal (&d->entry.displayAddress.clientAddress, |
939 | clientAddress)) |
940 | { |
941 | continue; |
942 | } |
943 | break; |
944 | } |
945 | break; |
946 | } |
947 | free (clientName); |
948 | return (d != 0) && (d->notAllowed == 0) |
949 | && (type == BROADCAST_QUERY ? d->notBroadcast == 0 : 1); |
950 | } |
951 | |
952 | void ForEachListenAddr ( |
953 | ListenFunc listenfunction, |
954 | ListenFunc mcastfunction, |
955 | void **closure) |
956 | { |
957 | DisplayEntry *d; |
958 | HostEntry *h; |
959 | int listenFound = 0; |
960 | |
961 | for (d = database; d != NULL((void*)0) ; d = d->next) |
962 | { |
963 | if (d->type == DISPLAY_LISTEN3) { |
964 | listenFound = 1; |
965 | h = d->hosts; |
966 | if (h != NULL((void*)0)) { |
967 | (*listenfunction) (&h->entry.hostAddress, closure); |
968 | for (h = h->next; h != NULL((void*)0); h = h->next) { |
969 | (*mcastfunction) (&h->entry.hostAddress, closure); |
970 | } |
971 | } |
972 | } |
973 | } |
974 | if (!listenFound) { |
975 | (*listenfunction) (NULL((void*)0), closure); |
976 | # if defined(IPv61) && defined(AF_INET630) && defined(XDM_DEFAULT_MCAST_ADDR6"ff02:0:0:0:0:0:0:12b") |
977 | { /* Join default IPv6 Multicast Group */ |
978 | |
979 | static ARRAY8 defaultMcastAddress; |
980 | |
981 | if (defaultMcastAddress.length == 0) { |
982 | struct in6_addr addr6; |
983 | |
984 | if (inet_pton(AF_INET630,XDM_DEFAULT_MCAST_ADDR6"ff02:0:0:0:0:0:0:12b",&addr6) == 1) { |
985 | if (!XdmcpAllocARRAY8 (&defaultMcastAddress, |
986 | sizeof(struct in6_addr))) { |
987 | LogOutOfMem ("ReadHostEntry\n"); |
988 | defaultMcastAddress.length = -1; |
989 | } else { |
990 | memcpy(defaultMcastAddress.data, &addr6,__builtin___memcpy_chk (defaultMcastAddress.data, &addr6, sizeof(struct in6_addr), __builtin_object_size (defaultMcastAddress .data, 0)) |
991 | sizeof(struct in6_addr))__builtin___memcpy_chk (defaultMcastAddress.data, &addr6, sizeof(struct in6_addr), __builtin_object_size (defaultMcastAddress .data, 0)); |
992 | } |
993 | } else { |
994 | defaultMcastAddress.length = -1; |
995 | } |
996 | } |
997 | if ( defaultMcastAddress.length == sizeof(struct in6_addr) ) { |
998 | (*mcastfunction) (&defaultMcastAddress, closure); |
999 | } |
1000 | } |
1001 | # endif |
1002 | } |
1003 | } |
1004 | |
1005 | |
1006 | #endif /* XDMCP */ |