3 Read options from kdmrc
5 Copyright (C) 2001-2005 Oswald Buddenhagen <ossi@kde.org>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 #include <config-workspace.h>
35 #include <netinet/in.h>
37 #ifdef _POSIX_PRIORITY_SCHEDULING
42 #ifdef FamilyInternet6
48 #define WANT_CONF_READ
52 * Section/Entry definition structs
69 * Parsed ini file structs
72 typedef struct Entry
{
80 typedef struct Section
{
84 const char *name
, *dname
, *dhost
, *dnum
, *dclass
;
85 int nlen
, dlen
, dhostl
, dnuml
, dclassl
;
90 * Split up display-name/-class for fast comparison
92 typedef struct DSpec
{
93 const char *dhost
, *dnum
, *dclass
;
94 int dhostl
, dnuml
, dclassl
;
99 * Config value storage structures
102 typedef union Value
{
105 int len
; /* including 0-terminator */
109 int totlen
; /* summed up length of all contained strings */
119 typedef struct ValArr
{
121 int nents
, esiz
, nchars
, nptrs
;
125 static void *Malloc( size_t size
);
126 static void *Realloc( void *ptr
, size_t size
);
129 #define LOG_NAME "kdm_config"
130 #define LOG_DEBUG_MASK DEBUG_CONFIG
131 #define LOG_PANIC_EXIT 1
132 #define STATIC static
137 Malloc( size_t size
)
141 if (!(ret
= malloc( size
)))
147 Realloc( void *ptr
, size_t size
)
151 if (!(ret
= realloc( ptr
, size
)) && size
)
158 mkDSpec( DSpec
*spec
, const char *dname
, const char *dclass
)
161 for (spec
->dhostl
= 0; dname
[spec
->dhostl
] != ':'; spec
->dhostl
++);
162 spec
->dnum
= dname
+ spec
->dhostl
+ 1;
163 spec
->dnuml
= strlen( spec
->dnum
);
164 spec
->dclass
= dclass
;
165 spec
->dclassl
= strlen( dclass
);
172 reader( void *buf
, int count
)
176 for (rlen
= 0; rlen
< count
; ) {
178 ret
= read( rfd
, (void *)((char *)buf
+ rlen
), count
- rlen
);
194 gRead( void *buf
, int count
)
196 if (reader( buf
, count
) != count
)
197 logPanic( "Cannot read from core\n" );
201 gWrite( const void *buf
, int count
)
203 if (write( wfd
, buf
, count
) != count
)
204 logPanic( "Cannot write to core\n" );
205 #ifdef _POSIX_PRIORITY_SCHEDULING
206 if ((debugLevel
& DEBUG_HLPCON
))
214 gWrite( &val
, sizeof(val
) );
218 gSendStr( const char *buf
)
221 int len
= strlen( buf
) + 1;
222 gWrite( &len
, sizeof(len
) );
225 gWrite( &buf
, sizeof(int) );
229 gSendNStr( const char *buf
, int len
)
232 gWrite( &tlen
, sizeof(tlen
) );
239 gSendArr( int len
, const char *data
)
241 gWrite( &len
, sizeof(len
) );
249 if (reader( val
, sizeof(*val
) ) != sizeof(*val
))
259 gRead( &val
, sizeof(val
) );
272 if (!(buf
= malloc( len
)))
273 logPanic( "No memory for read buffer" );
279 /* #define WANT_CLOSE 1 */
281 typedef struct File
{
282 char *buf
, *eof
, *cur
;
283 #if defined(HAVE_MMAP) && defined(WANT_CLOSE)
289 readFile( File
*file
, const char *fn
, const char *what
)
294 if ((fd
= open( fn
, O_RDONLY
)) < 0) {
295 logInfo( "Cannot open %s file %s\n", what
, fn
);
299 flen
= lseek( fd
, 0, SEEK_END
);
302 file
->ismapped
= False
;
304 file
->buf
= mmap( 0, flen
+ 1, PROT_READ
| PROT_WRITE
, MAP_PRIVATE
, fd
, 0 );
307 file
->ismapped
= True
;
314 if (!(file
->buf
= Malloc( flen
+ 1 ))) {
318 lseek( fd
, 0, SEEK_SET
);
319 if (read( fd
, file
->buf
, flen
) != flen
) {
321 logError( "Cannot read %s file %s\n", what
, fn
);
326 file
->eof
= (file
->cur
= file
->buf
) + flen
;
333 freeBuf( File
*file
)
337 munmap( file
->buf
, file
->eof
- file
->buf
+ 1 );
346 #define C_MTYPE_MASK 0x30000000
347 # define C_PATH 0x10000000 /* C_TYPE_STR is a path spec */
348 # define C_BOOL 0x10000000 /* C_TYPE_INT is a boolean */
349 # define C_ENUM 0x20000000 /* C_TYPE_INT is an enum (option) */
350 # define C_GRP 0x30000000 /* C_TYPE_INT is a group spec */
351 #define C_INTERNAL 0x40000000 /* don't expose to core */
352 #define C_CONFIG 0x80000000 /* process only for finding deps */
356 PrequestPort( Value
*retval
)
358 if (!VxdmcpEnable
.num
) {
367 emptyStr
= { { "", 1 } },
368 nullValue
= { { 0, 0 } },
369 emptyArgv
= { { (char *)&nullValue
, 0 } };
372 PnoPassUsers( Value
*retval
)
374 if (!VnoPassEnable
.num
) {
382 PautoLoginX( Value
*retval
)
384 if (!VautoLoginEnable
.num
) {
393 static const char *kdmrc
= KDMCONF
"/kdmrc";
395 static Section
*rootsec
;
400 const char *nstr
, *dstr
, *cstr
, *dhost
, *dnum
, *dclass
;
401 char *s
, *e
, *st
, *en
, *ek
, *sl
, *pt
;
405 int nlen
, dlen
, clen
, dhostl
, dnuml
, dclassl
;
406 int i
, line
, sectmoan
, restl
;
414 debug( "reading config %s ...\n", kdmrc
);
415 if (!readFile( &file
, kdmrc
, "master configuration" ))
418 for (s
= file
.buf
, line
= 0, cursec
= 0, sectmoan
= 1; s
< file
.eof
; s
++) {
421 while ((s
< file
.eof
) && isspace( *s
) && (*s
!= '\n'))
424 if ((s
< file
.eof
) && ((*s
== '\n') || (*s
== '#'))) {
426 while ((s
< file
.eof
) && (*s
!= '\n'))
434 while ((s
< file
.eof
) && (*s
!= '\n'))
437 while ((e
> sl
) && isspace( *e
))
441 logError( "Invalid section header at %s:%d\n", kdmrc
, line
);
446 for (cursec
= rootsec
; cursec
; cursec
= cursec
->next
)
447 if (nlen
== cursec
->nlen
&&
448 !memcmp( nstr
, cursec
->name
, nlen
))
450 logInfo( "Multiple occurrences of section [%.*s] in %s. "
451 "Consider merging them.\n", nlen
, nstr
, kdmrc
);
454 if (nstr
[0] == 'X' && nstr
[1] == '-') {
457 while (++clen
, *--cstr
!= '-');
458 if (cstr
== nstr
+ 1)
461 dlen
= nlen
- clen
- 2;
464 for (restl
= dlen
; restl
; restl
--) {
465 if (dhost
[dhostl
] == ':') {
466 dnum
= dhost
+ dhostl
+ 1;
468 for (restl
--; restl
; restl
--) {
469 if (dnum
[dnuml
] == '_') {
470 dclass
= dnum
+ dnuml
+ 1;
500 for (i
= 0; i
< as(allSects
); i
++)
501 if ((int)strlen( allSects
[i
]->name
) == clen
&&
502 !memcmp( allSects
[i
]->name
, cstr
, clen
))
506 logError( "Unrecognized section name [%.*s] at %s:%d\n",
507 nlen
, nstr
, kdmrc
, line
);
510 if (!(cursec
= Malloc( sizeof(*cursec
) )))
514 cursec
->dname
= dstr
;
516 cursec
->dhost
= dhost
;
517 cursec
->dhostl
= dhostl
;
519 cursec
->dnuml
= dnuml
;
520 cursec
->dclass
= dclass
;
521 cursec
->dclassl
= dclassl
;
522 cursec
->sect
= allSects
[i
];
524 cursec
->next
= rootsec
;
526 /*debug( "now in section [%.*s], dpy '%.*s', core '%.*s'\n",
527 nlen, nstr, dlen, dstr, clen, cstr );*/
535 logError( "Entry outside any section at %s:%d", kdmrc
, line
);
540 for (; (s
< file
.eof
) && (*s
!= '\n'); s
++)
543 logError( "Invalid entry (missing '=') at %s:%d\n", kdmrc
, line
);
547 for (ek
= s
- 1; ; ek
--) {
549 logError( "Invalid entry (empty key) at %s:%d\n", kdmrc
, line
);
557 while ((s
< file
.eof
) && isspace( *s
) && (*s
!= '\n'))
559 for (pt
= st
= en
= s
; s
< file
.eof
&& *s
!= '\n'; s
++) {
562 if (s
>= file
.eof
|| *s
== '\n') {
563 logError( "Trailing backslash at %s:%d\n", kdmrc
, line
);
567 case 's': *pt
++ = ' '; break;
568 case 't': *pt
++ = '\t'; break;
569 case 'n': *pt
++ = '\n'; break;
570 case 'r': *pt
++ = '\r'; break;
571 case '\\': *pt
++ = '\\'; break;
572 default: *pt
++ = '\\'; *pt
++ = *s
; break;
577 if (*s
!= ' ' && *s
!= '\t')
584 /*debug( "read entry '%.*s'='%.*s'\n", nlen, nstr, en - st, st );*/
585 for (i
= 0; i
< cursec
->sect
->numents
; i
++) {
586 ce
= cursec
->sect
->ents
+ i
;
587 if ((int)strlen( ce
->name
) == nlen
&&
588 !memcmp( ce
->name
, nstr
, nlen
))
591 logError( "Unrecognized key '%.*s' in section [%.*s] at %s:%d\n",
592 nlen
, nstr
, cursec
->nlen
, cursec
->name
, kdmrc
, line
);
595 for (curent
= cursec
->entries
; curent
; curent
= curent
->next
)
596 if (ce
== curent
->ent
) {
597 logError( "Multiple occurrences of key '%s' in section [%.*s]"
599 ce
->name
, cursec
->nlen
, cursec
->name
, kdmrc
);
602 if (!(curent
= Malloc( sizeof(*curent
) )))
607 curent
->vallen
= en
- st
;
608 curent
->next
= cursec
->entries
;
609 cursec
->entries
= curent
;
621 for (cursec
= rootsec
; cursec
; cursec
= cursec
->next
)
623 for (curent
= cursec
->entries
; curent
; curent
= curent
->next
)
624 if (curent
->ent
->id
== id
) {
625 debug( "line %d: %s = %'.*s\n",
626 curent
->line
, curent
->ent
->name
,
627 curent
->vallen
, curent
->val
);
633 /* Display name match scoring:
634 * - class (any/exact) -> 0/1
635 * - number (any/exact) -> 0/2
636 * - host (any/nonempty/trail/exact) -> 0/4/8/12
639 findDEnt( int id
, DSpec
*dspec
)
641 Section
*cursec
, *bestsec
= 0;
642 Entry
*curent
, *bestent
;
643 int score
, bestscore
;
645 bestscore
= -1, bestent
= 0;
646 for (cursec
= rootsec
; cursec
; cursec
= cursec
->next
)
649 if (cursec
->dclassl
!= 1 || cursec
->dclass
[0] != '*') {
650 if (cursec
->dclassl
== dspec
->dclassl
&&
651 !memcmp( cursec
->dclass
, dspec
->dclass
, dspec
->dclassl
))
656 if (cursec
->dnuml
!= 1 || cursec
->dnum
[0] != '*') {
657 if (cursec
->dnuml
== dspec
->dnuml
&&
658 !memcmp( cursec
->dnum
, dspec
->dnum
, dspec
->dnuml
))
663 if (cursec
->dhostl
!= 1 || cursec
->dhost
[0] != '*') {
664 if (cursec
->dhostl
== 1 && cursec
->dhost
[0] == '+') {
669 } else if (cursec
->dhost
[0] == '.') {
670 if (cursec
->dhostl
< dspec
->dhostl
&&
671 !memcmp( cursec
->dhost
,
672 dspec
->dhost
+ dspec
->dhostl
- cursec
->dhostl
,
678 if (cursec
->dhostl
== dspec
->dhostl
&&
679 !memcmp( cursec
->dhost
, dspec
->dhost
, dspec
->dhostl
))
685 if (score
> bestscore
) {
686 for (curent
= cursec
->entries
; curent
; curent
= curent
->next
)
687 if (curent
->ent
->id
== id
) {
696 debug( "line %d: %.*s:%.*s_%.*s/%s = %'.*s\n", bestent
->line
,
697 bestsec
->dhostl
, bestsec
->dhost
,
698 bestsec
->dnuml
, bestsec
->dnum
,
699 bestsec
->dclassl
, bestsec
->dclass
,
700 bestent
->ent
->name
, bestent
->vallen
, bestent
->val
);
705 convertValue( Ent
*et
, Value
*retval
, int vallen
, const char *val
, char **eopts
)
708 int i
, b
, e
, tlen
, nents
, esiz
;
711 switch (et
->id
& C_TYPE_MASK
) {
713 for (i
= 0; i
< vallen
&& i
< (int)sizeof(buf
) - 1; i
++)
714 buf
[i
] = tolower( val
[i
] );
716 if ((et
->id
& C_MTYPE_MASK
) == C_BOOL
) {
717 if (!strcmp( buf
, "true" ) ||
718 !strcmp( buf
, "on" ) ||
719 !strcmp( buf
, "yes" ) ||
722 else if (!strcmp( buf
, "false" ) ||
723 !strcmp( buf
, "off" ) ||
724 !strcmp( buf
, "no" ) ||
730 } else if ((et
->id
& C_MTYPE_MASK
) == C_ENUM
) {
731 for (i
= 0; eopts
[i
]; i
++)
732 if (!memcmp( eopts
[i
], val
, vallen
) && !eopts
[i
][vallen
]) {
737 } else if ((et
->id
& C_MTYPE_MASK
) == C_GRP
) {
739 if ((ge
= getgrnam( buf
))) {
740 retval
->num
= ge
->gr_gid
;
744 if (sscanf( buf
, "%i", &retval
->num
) != 1)
748 retval
->str
.ptr
= val
;
749 retval
->str
.len
= vallen
+ 1;
750 if ((et
->id
& C_MTYPE_MASK
) == C_PATH
)
751 if (vallen
&& val
[vallen
-1] == '/')
755 if (!(ents
= Malloc( sizeof(Value
) * (esiz
= 10) )))
757 for (nents
= 0, tlen
= 0, i
= 0; ; i
++) {
758 for (; i
< vallen
&& isspace( val
[i
] ); i
++);
759 for (b
= i
; i
< vallen
&& val
[i
] != ','; i
++);
762 for (e
= i
; e
> b
&& isspace( val
[e
- 1] ); e
--);
763 if (esiz
< nents
+ 2) {
764 Value
*entsn
= Realloc( ents
,
765 sizeof(Value
) * (esiz
= esiz
* 2 + 1) );
770 ents
[nents
].str
.ptr
= val
+ b
;
771 ents
[nents
].str
.len
= e
- b
;
775 ents
[nents
].str
.ptr
= 0;
776 retval
->argv
.ptr
= ents
;
777 retval
->argv
.totlen
= tlen
;
780 logError( "Internal error: unknown value type in id %#x\n", et
->id
);
786 getValue( Ent
*et
, DSpec
*dspec
, Value
*retval
, char **eopts
)
791 /* debug( "Getting value %#x\n", et->id );*/
793 ent
= findDEnt( et
->id
, dspec
);
795 ent
= findGEnt( et
->id
);
797 if (!(errs
= convertValue( et
, retval
, ent
->vallen
, ent
->val
, eopts
)))
799 logError( "Invalid %s value '%.*s' at %s:%d\n",
800 errs
, ent
->vallen
, ent
->val
, kdmrc
, ent
->line
);
802 debug( "default: %s = %'s\n", et
->name
, et
->def
);
803 if ((errs
= convertValue( et
, retval
, strlen( et
->def
), et
->def
, eopts
)))
804 logError( "Internal error: invalid default %s value '%s' for key %s\n",
805 errs
, et
->def
, et
->name
);
809 addValue( ValArr
*va
, int id
, Value
*val
)
813 /* debug( "Addig value %#x\n", id );*/
814 if (va
->nents
== va
->esiz
) {
815 va
->ents
= Realloc( va
->ents
, sizeof(Val
) * (va
->esiz
+= 50) );
819 va
->ents
[va
->nents
].id
= id
;
820 va
->ents
[va
->nents
].val
= *val
;
822 switch (id
& C_TYPE_MASK
) {
826 va
->nchars
+= val
->str
.len
;
829 va
->nchars
+= val
->argv
.totlen
;
830 for (nu
= 0; val
->argv
.ptr
[nu
++].str
.ptr
; );
838 copyValues( ValArr
*va
, Sect
*sec
, DSpec
*dspec
, int isconfig
)
843 debug( "getting values for section class [%s]\n", sec
->name
);
844 for (i
= 0; i
< sec
->numents
; i
++) {
845 /*debug ("value %#x\n", sec->ents[i].id);*/
846 if ((sec
->ents
[i
].id
& (int)C_CONFIG
) != isconfig
)
848 else if (sec
->ents
[i
].id
& C_INTERNAL
) {
849 getValue( sec
->ents
+ i
, dspec
, ((Value
*)sec
->ents
[i
].ptr
), 0 );
851 if (((sec
->ents
[i
].id
& C_MTYPE_MASK
) == C_ENUM
) ||
853 !((int (*)( Value
* ))sec
->ents
[i
].ptr
)(&val
)) {
854 getValue( sec
->ents
+ i
, dspec
, &val
,
855 (char **)sec
->ents
[i
].ptr
);
857 if (!addValue( va
, sec
->ents
[i
].id
, &val
))
865 sendValues( ValArr
*va
)
870 gSendInt( va
->nents
);
871 gSendInt( va
->nptrs
);
872 gSendInt( 0/*va->nints*/ );
873 gSendInt( va
->nchars
);
874 for (i
= 0; i
< va
->nents
; i
++) {
875 gSendInt( va
->ents
[i
].id
& ~C_PRIVATE
);
876 switch (va
->ents
[i
].id
& C_TYPE_MASK
) {
878 gSendInt( va
->ents
[i
].val
.num
);
881 gSendNStr( va
->ents
[i
].val
.str
.ptr
, va
->ents
[i
].val
.str
.len
- 1 );
884 cst
= va
->ents
[i
].val
.argv
.ptr
;
885 for (nu
= 0; cst
[nu
].str
.ptr
; nu
++);
887 for (; cst
->str
.ptr
; cst
++)
888 gSendNStr( cst
->str
.ptr
, cst
->str
.len
);
897 readWord( File
*file
, int *len
, int EOFatEOL
)
899 char *wordp
, *wordBuffer
;
904 wordp
= wordBuffer
= file
->cur
;
908 if (file
->cur
== file
->eof
) {
910 if (wordp
== wordBuffer
)
914 *len
= wordp
- wordBuffer
;
923 if (file
->cur
== file
->eof
)
929 if (EOFatEOL
&& !quoted
) {
933 if (wordp
!= wordBuffer
) {
940 if (wordp
!= wordBuffer
)
954 #define ALIAS_CHARACTER '%'
955 #define EQUAL_CHARACTER '='
956 #define NEGATE_CHARACTER '!'
957 #define CHOOSER_STRING "CHOOSER"
958 #define BROADCAST_STRING "BROADCAST"
959 #define NOBROADCAST_STRING "NOBROADCAST"
960 #define LISTEN_STRING "LISTEN"
961 #define WILDCARD_STRING "*"
963 typedef struct _HostEntry
{
964 struct _HostEntry
*next
;
977 typedef struct _ListenEntry
{
978 struct _ListenEntry
*next
;
984 typedef struct _AliasEntry
{
985 struct _AliasEntry
*next
;
993 typedef struct _AclEntry
{
994 struct _AclEntry
*next
;
995 HostEntry
**pEntries
;
1006 hasGlobCharacters( char *s
)
1019 #define PARSE_NO_BCAST 1
1020 #define PARSE_NO_PAT 2
1021 #define PARSE_NO_ALIAS 4
1024 parseHost( int *nHosts
, HostEntry
***hostPtr
, int *nChars
,
1025 char *hostOrAlias
, int len
, int parse
)
1027 #if defined(IPv6) && defined(AF_INET6)
1028 struct addrinfo
*ai
;
1030 struct hostent
*hostent
;
1033 int addr_type
, addr_len
;
1035 if (!(**hostPtr
= (HostEntry
*)Malloc( sizeof(HostEntry
) )))
1037 if (!(parse
& PARSE_NO_BCAST
) && !strcmp( hostOrAlias
, BROADCAST_STRING
))
1039 (**hostPtr
)->type
= HOST_BROADCAST
;
1041 else if (!(parse
& PARSE_NO_ALIAS
) && *hostOrAlias
== ALIAS_CHARACTER
)
1043 (**hostPtr
)->type
= HOST_ALIAS
;
1044 (**hostPtr
)->entry
.aliasPattern
= hostOrAlias
+ 1;
1047 else if (!(parse
& PARSE_NO_PAT
) && hasGlobCharacters( hostOrAlias
))
1049 (**hostPtr
)->type
= HOST_PATTERN
;
1050 (**hostPtr
)->entry
.hostPattern
= hostOrAlias
;
1055 (**hostPtr
)->type
= HOST_ADDRESS
;
1056 #if defined(IPv6) && defined(AF_INET6)
1057 if (getaddrinfo( hostOrAlias
, NULL
, NULL
, &ai
))
1059 if (!(hostent
= gethostbyname( hostOrAlias
)))
1062 logWarn( "XDMCP ACL: unresolved host %'s\n", hostOrAlias
);
1063 free( (char *)(**hostPtr
) );
1066 #if defined(IPv6) && defined(AF_INET6)
1067 addr_type
= ai
->ai_addr
->sa_family
;
1068 if (ai
->ai_family
== AF_INET
) {
1069 addr
= &((struct sockaddr_in
*)ai
->ai_addr
)->sin_addr
;
1070 addr_len
= sizeof(struct in_addr
);
1071 } else /*if (ai->ai_addr->sa_family == AF_INET6)*/ {
1072 addr
= &((struct sockaddr_in6
*)ai
->ai_addr
)->sin6_addr
;
1073 addr_len
= sizeof(struct in6_addr
);
1076 addr_type
= hostent
->h_addrtype
;
1077 addr
= hostent
->h_addr
;
1078 addr_len
= hostent
->h_length
;
1080 if (!((**hostPtr
)->entry
.displayAddress
.hostAddress
=
1081 Malloc( addr_len
)))
1083 #if defined(IPv6) && defined(AF_INET6)
1086 free( (char *)(**hostPtr
) );
1089 memcpy( (**hostPtr
)->entry
.displayAddress
.hostAddress
, addr
, addr_len
);
1090 *nChars
+= addr_len
;
1091 (**hostPtr
)->entry
.displayAddress
.hostAddrLen
= addr_len
;
1092 (**hostPtr
)->entry
.displayAddress
.connectionType
= addr_type
;
1093 #if defined(IPv6) && defined(AF_INET6)
1097 *hostPtr
= &(**hostPtr
)->next
;
1102 /* Returns True if string is matched by pattern. Does case folding. */
1104 patternMatch( const char *string
, const char *pattern
)
1113 switch (p
= *pattern
++) {
1117 for (string
--; *string
; string
++)
1118 if (patternMatch( string
, pattern
))
1131 if (tolower( p
) != tolower( s
))
1137 #define MAX_DEPTH 32
1140 #define CHECK_NO_PAT 2
1143 checkHostlist( HostEntry
**hosts
, int nh
, AliasEntry
*aliases
, int na
,
1144 int depth
, int flags
)
1150 for (h
= *hosts
, hn
= 0; hn
< nh
; hn
++, h
= h
->next
)
1151 if (h
->type
== HOST_ALIAS
) {
1152 if (depth
== MAX_DEPTH
) {
1153 logError( "XDMCP ACL: alias recursion involving %%%s\n",
1154 h
->entry
.aliasPattern
);
1157 for (a
= aliases
, an
= 0, am
= False
; an
< na
; an
++, a
= a
->next
)
1158 if (patternMatch( a
->name
, h
->entry
.aliasPattern
)) {
1160 if ((flags
& CHECK_NOT
) && a
->hasBad
) {
1161 logError( "XDMCP ACL: alias %%%s with unresolved hosts "
1162 "in denying rule\n", a
->name
);
1165 if (checkHostlist( a
->pHosts
, a
->nhosts
, aliases
, na
,
1170 if (flags
& CHECK_NOT
) {
1171 logError( "XDMCP ACL: unresolved alias pattern %%%s "
1172 "in denying rule\n", h
->entry
.aliasPattern
);
1175 logWarn( "XDMCP ACL: unresolved alias pattern %%%s\n",
1176 h
->entry
.aliasPattern
);
1178 } else if (h
->type
== HOST_PATTERN
&& (flags
& CHECK_NO_PAT
))
1179 logWarn( "XDMCP ACL: wildcarded pattern %'s in host-only context\n",
1180 h
->entry
.hostPattern
);
1185 readAccessFile( const char *fname
)
1187 HostEntry
*hostList
, **hostPtr
= &hostList
;
1188 AliasEntry
*aliasList
, **aliasPtr
= &aliasList
;
1189 AclEntry
*acList
, **acPtr
= &acList
, *acl
;
1190 ListenEntry
*listenList
, **listenPtr
= &listenList
;
1191 char *displayOrAlias
, *hostOrAlias
;
1193 int nHosts
, nAliases
, nAcls
, nListens
, nChars
, error
, bad
;
1196 nHosts
= nAliases
= nAcls
= nListens
= nChars
= 0;
1198 if (!readFile( &file
, fname
, "XDMCP access control" ))
1200 while ((displayOrAlias
= readWord( &file
, &len
, False
))) {
1201 if (*displayOrAlias
== ALIAS_CHARACTER
)
1203 if (!(*aliasPtr
= (AliasEntry
*)Malloc( sizeof(AliasEntry
) ))) {
1207 (*aliasPtr
)->name
= displayOrAlias
+ 1;
1209 (*aliasPtr
)->hosts
= nHosts
;
1210 (*aliasPtr
)->pHosts
= hostPtr
;
1211 (*aliasPtr
)->nhosts
= 0;
1212 (*aliasPtr
)->hasBad
= False
;
1213 while ((hostOrAlias
= readWord( &file
, &len
, True
))) {
1214 if (parseHost( &nHosts
, &hostPtr
, &nChars
, hostOrAlias
, len
,
1216 (*aliasPtr
)->nhosts
++;
1218 (*aliasPtr
)->hasBad
= True
;
1220 aliasPtr
= &(*aliasPtr
)->next
;
1223 else if (!strcmp( displayOrAlias
, LISTEN_STRING
))
1225 if (!(*listenPtr
= (ListenEntry
*)Malloc( sizeof(ListenEntry
) ))) {
1229 (*listenPtr
)->iface
= nHosts
;
1230 if (!(hostOrAlias
= readWord( &file
, &len
, True
)) ||
1231 !strcmp( hostOrAlias
, WILDCARD_STRING
) ||
1232 !parseHost( &nHosts
, &hostPtr
, &nChars
, hostOrAlias
, len
,
1233 PARSE_NO_BCAST
|PARSE_NO_PAT
|PARSE_NO_ALIAS
))
1235 (*listenPtr
)->iface
= -1;
1237 (*listenPtr
)->mcasts
= nHosts
;
1238 (*listenPtr
)->nmcasts
= 0;
1239 while ((hostOrAlias
= readWord( &file
, &len
, True
))) {
1240 if (parseHost( &nHosts
, &hostPtr
, &nChars
, hostOrAlias
, len
,
1241 PARSE_NO_BCAST
|PARSE_NO_PAT
|PARSE_NO_ALIAS
))
1242 (*listenPtr
)->nmcasts
++;
1244 listenPtr
= &(*listenPtr
)->next
;
1249 if (!(*acPtr
= (AclEntry
*)Malloc( sizeof(AclEntry
) ))) {
1253 (*acPtr
)->flags
= 0;
1254 if (*displayOrAlias
== NEGATE_CHARACTER
) {
1255 (*acPtr
)->flags
|= a_notAllowed
;
1257 } else if (*displayOrAlias
== EQUAL_CHARACTER
)
1259 (*acPtr
)->entries
= nHosts
;
1260 (*acPtr
)->pEntries
= hostPtr
;
1261 (*acPtr
)->nentries
= 1;
1262 if (!parseHost( &nHosts
, &hostPtr
, &nChars
, displayOrAlias
, len
,
1266 if ((*acPtr
)->flags
& a_notAllowed
) {
1267 logError( "XDMCP ACL: unresolved host in denying rule\n" );
1272 (*acPtr
)->hosts
= nHosts
;
1273 (*acPtr
)->pHosts
= hostPtr
;
1274 (*acPtr
)->nhosts
= 0;
1275 while ((hostOrAlias
= readWord( &file
, &len
, True
))) {
1276 if (!strcmp( hostOrAlias
, CHOOSER_STRING
))
1277 (*acPtr
)->flags
|= a_useChooser
;
1278 else if (!strcmp( hostOrAlias
, NOBROADCAST_STRING
))
1279 (*acPtr
)->flags
|= a_notBroadcast
;
1281 if (parseHost( &nHosts
, &hostPtr
, &nChars
,
1282 hostOrAlias
, len
, PARSE_NO_PAT
))
1287 acPtr
= &(*acPtr
)->next
;
1294 if (!(*listenPtr
= (ListenEntry
*)Malloc( sizeof(ListenEntry
) )))
1297 (*listenPtr
)->iface
= -1;
1298 (*listenPtr
)->mcasts
= nHosts
;
1299 (*listenPtr
)->nmcasts
= 0;
1300 #if defined(IPv6) && defined(AF_INET6) && defined(XDM_DEFAULT_MCAST_ADDR6)
1301 if (parseHost( &nHosts
, &hostPtr
, &nChars
,
1302 XDM_DEFAULT_MCAST_ADDR6
,
1303 sizeof(XDM_DEFAULT_MCAST_ADDR6
)-1,
1305 (*listenPtr
)->nmcasts
++;
1311 for (acl
= acList
, i
= 0; i
< nAcls
; i
++, acl
= acl
->next
)
1312 if (checkHostlist( acl
->pEntries
, acl
->nentries
, aliasList
, nAliases
,
1313 0, (acl
->flags
& a_notAllowed
) ? CHECK_NOT
: 0 ) ||
1314 checkHostlist( acl
->pHosts
, acl
->nhosts
, aliasList
, nAliases
,
1319 nHosts
= nAliases
= nAcls
= nListens
= nChars
= 0;
1321 logError( "No XDMCP requests will be granted\n" );
1324 gSendInt( nListens
);
1325 gSendInt( nAliases
);
1328 for (i
= 0; i
< nHosts
; i
++, hostList
= hostList
->next
) {
1329 gSendInt( hostList
->type
);
1330 switch (hostList
->type
) {
1332 gSendStr( hostList
->entry
.aliasPattern
);
1335 gSendStr( hostList
->entry
.hostPattern
);
1338 gSendArr( hostList
->entry
.displayAddress
.hostAddrLen
,
1339 hostList
->entry
.displayAddress
.hostAddress
);
1340 gSendInt( hostList
->entry
.displayAddress
.connectionType
);
1344 for (i
= 0; i
< nListens
; i
++, listenList
= listenList
->next
) {
1345 gSendInt( listenList
->iface
);
1346 gSendInt( listenList
->mcasts
);
1347 gSendInt( listenList
->nmcasts
);
1349 for (i
= 0; i
< nAliases
; i
++, aliasList
= aliasList
->next
) {
1350 gSendStr( aliasList
->name
);
1351 gSendInt( aliasList
->hosts
);
1352 gSendInt( aliasList
->nhosts
);
1354 for (i
= 0; i
< nAcls
; i
++, acList
= acList
->next
) {
1355 gSendInt( acList
->entries
);
1356 gSendInt( acList
->nentries
);
1357 gSendInt( acList
->hosts
);
1358 gSendInt( acList
->nhosts
);
1359 gSendInt( acList
->flags
);
1365 int main( int argc ATTR_UNUSED
, char **argv
)
1369 char *ci
, *disp
, *dcls
, *cfgfile
;
1372 if (!(ci
= getenv( "CONINFO" ))) {
1373 fprintf( stderr
, "This program is part of kdm and should not be run manually.\n" );
1376 if (sscanf( ci
, "%d %d", &rfd
, &wfd
) != 2)
1381 if ((debugLevel
= gRecvInt()) & DEBUG_WCONFIG
)
1384 /* debug ("parsing command line\n");*/
1393 /* debug ("Awaiting command ...\n");*/
1394 if (!gRecvCmd( &what
))
1398 /* debug ("GC_Files\n");*/
1400 copyValues( 0, &secGeneral
, 0, C_CONFIG
);
1402 copyValues( 0, &secXdmcp
, 0, C_CONFIG
);
1410 gSendNStr( VXaccess
.str
.ptr
, VXaccess
.str
.len
- 1 );
1413 for (; (what
= gRecvInt()) != -1; )
1430 /* debug( "GC_GetConf\n" );*/
1431 memset( &va
, 0, sizeof(va
) );
1433 cfgfile
= gRecvStr();
1436 /* debug( "GC_gGlobal\n" );*/
1437 debug( "getting global config\n" );
1439 copyValues( &va
, &secGeneral
, 0, 0 );
1441 copyValues( &va
, &secXdmcp
, 0, 0 );
1443 copyValues( &va
, &secShutdown
, 0, 0 );
1447 /* debug( "GC_gDisplay\n" );*/
1449 /* debug( " Display %s\n", disp );*/
1451 /* debug( " Class %s\n", dcls );*/
1452 debug( "getting config for display %s, class %s\n", disp
, dcls
);
1453 mkDSpec( &dspec
, disp
, dcls
? dcls
: "" );
1455 copyValues( &va
, &sec_Core
, &dspec
, 0 );
1456 copyValues( &va
, &sec_Greeter
, &dspec
, 0 );
1464 readAccessFile( cfgfile
);
1468 debug( "Unsupported config category %#x\n", what
);
1473 debug( "Unknown config command %#x\n", what
);
1477 /* debug( "Config reader exiting ..." );*/