diff options
Diffstat (limited to 'kdm/kfrontend/kdm_config.c')
-rw-r--r-- | kdm/kfrontend/kdm_config.c | 1477 |
1 files changed, 0 insertions, 1477 deletions
diff --git a/kdm/kfrontend/kdm_config.c b/kdm/kfrontend/kdm_config.c deleted file mode 100644 index 48f316320..000000000 --- a/kdm/kfrontend/kdm_config.c +++ /dev/null @@ -1,1477 +0,0 @@ -/* - -Read options from tdmrc - -Copyright (C) 2001-2005 Oswald Buddenhagen <ossi@kde.org> - - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -*/ - -#include <config.h> - -#include <stdio.h> -#include <unistd.h> -#include <stdarg.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <ctype.h> -#include <errno.h> -#include <netdb.h> -#include <netinet/in.h> -#include <grp.h> -#ifdef _POSIX_PRIORITY_SCHEDULING -# include <sched.h> -#endif - -#include <X11/X.h> -#ifdef FamilyInternet6 -# define IPv6 -#endif - -#include <greet.h> -#include <config.ci> - -/* - * Section/Entry definition structs - */ - -typedef struct Ent { - const char *name; - int id; - void *ptr; - const char *def; -} Ent; - -typedef struct Sect { - const char *name; - Ent *ents; - int numents; -} Sect; - -/* - * Parsed ini file structs - */ - -typedef struct Entry { - struct Entry *next; - const char *val; - Ent *ent; - int vallen; - int line; -} Entry; - -typedef struct Section { - struct Section *next; - Entry *entries; - Sect *sect; - const char *name, *dname, *dhost, *dnum, *dclass; - int nlen, dlen, dhostl, dnuml, dclassl; -} Section; - - -/* - * Split up display-name/-class for fast comparison - */ -typedef struct DSpec { - const char *dhost, *dnum, *dclass; - int dhostl, dnuml, dclassl; -} DSpec; - - -/* - * Config value storage structures - */ - -typedef struct Value { - const char *ptr; - int len; -} Value; - -typedef struct Val { - Value val; - int id; -} Val; - -typedef struct ValArr { - Val *ents; - int nents, esiz, nchars, nptrs; -} ValArr; - - -static void *Malloc( size_t size ); -static void *Realloc( void *ptr, size_t size ); - -#define PRINT_QUOTES -#define LOG_NAME "tdm_config" -#define LOG_DEBUG_MASK DEBUG_CONFIG -#define LOG_PANIC_EXIT 1 -#define STATIC static -#include <printf.c> - - -static void * -Malloc( size_t size ) -{ - void *ret; - - if (!(ret = malloc( size ))) - LogOutOfMem(); - return ret; -} - -static void * -Realloc( void *ptr, size_t size ) -{ - void *ret; - - if (!(ret = realloc( ptr, size )) && size) - LogOutOfMem(); - return ret; -} - - -static void -MkDSpec( DSpec *spec, const char *dname, const char *dclass ) -{ - spec->dhost = dname; - for (spec->dhostl = 0; dname[spec->dhostl] != ':'; spec->dhostl++); - spec->dnum = dname + spec->dhostl + 1; - spec->dnuml = strlen( spec->dnum ); - spec->dclass = dclass; - spec->dclassl = strlen( dclass ); -} - - -static int rfd, wfd; - -static int -Reader( void *buf, int count ) -{ - int ret, rlen; - - for (rlen = 0; rlen < count; ) { - dord: - ret = read( rfd, (void *)((char *)buf + rlen), count - rlen ); - if (ret < 0) { - if (errno == EINTR) - goto dord; - if (errno == EAGAIN) - break; - return -1; - } - if (!ret) - break; - rlen += ret; - } - return rlen; -} - -static void -GRead( void *buf, int count ) -{ - if (Reader( buf, count ) != count) - LogPanic( "Can't read from core\n" ); -} - -static void -GWrite( const void *buf, int count ) -{ - if (write( wfd, buf, count ) != count) - LogPanic( "Can't write to core\n" ); -#ifdef _POSIX_PRIORITY_SCHEDULING - if ((debugLevel & DEBUG_HLPCON)) - sched_yield(); -#endif -} - -static void -GSendInt( int val ) -{ - GWrite( &val, sizeof(val) ); -} - -static void -GSendStr( const char *buf ) -{ - if (buf) { - int len = strlen( buf ) + 1; - GWrite( &len, sizeof(len) ); - GWrite( buf, len ); - } else - GWrite( &buf, sizeof(int)); -} - -static void -GSendNStr( const char *buf, int len ) -{ - int tlen = len + 1; - GWrite( &tlen, sizeof(tlen) ); - GWrite( buf, len ); - GWrite( "", 1 ); -} - -#ifdef XDMCP -static void -GSendArr( int len, const char *data ) -{ - GWrite( &len, sizeof(len) ); - GWrite( data, len ); -} -#endif - -static int -GRecvCmd( int *val ) -{ - if (Reader( val, sizeof(*val) ) != sizeof(*val)) - return 0; - return 1; -} - -static int -GRecvInt() -{ - int val; - - GRead( &val, sizeof(val) ); - return val; -} - -static char * -GRecvStr() -{ - int len; - char *buf; - - len = GRecvInt(); - if (!len) - return 0; - if (!(buf = malloc( len ))) - LogPanic( "No memory for read buffer" ); - GRead( buf, len ); - return buf; -} - - -/* #define WANT_CLOSE 1 */ - -typedef struct File { - char *buf, *eof, *cur; -#if defined(HAVE_MMAP) && defined(WANT_CLOSE) - int ismapped; -#endif -} File; - -static int -readFile( File *file, const char *fn, const char *what ) -{ - int fd; - off_t flen; - - if ((fd = open( fn, O_RDONLY )) < 0) { - LogInfo( "Cannot open %s file %s\n", what, fn ); - return 0; - } - - flen = lseek( fd, 0, SEEK_END ); -#ifdef HAVE_MMAP -# ifdef WANT_CLOSE - file->ismapped = 0; -# endif - file->buf = mmap( 0, flen + 1, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0 ); -# ifdef WANT_CLOSE - if (file->buf) - file->ismapped = 1; - else -# else - if (!file->buf) -# endif -#endif - { - if (!(file->buf = Malloc( flen + 1 ))) { - close( fd ); - return 0; - } - lseek( fd, 0, SEEK_SET ); - if (read( fd, file->buf, flen ) != flen) { - free( file->buf ); - LogError( "Cannot read %s file %s\n", what, fn ); - close( fd ); - return 0; - } - } - file->eof = (file->cur = file->buf) + flen; - close( fd ); - return 1; -} - -#ifdef WANT_CLOSE -static void -freeBuf( File *file ) -{ -# ifdef HAVE_MMAP - if (file->ismapped) - munmap( file->buf, file->eof - file->buf + 1 ); - else -# endif - free( file->buf ); -} -#endif - -CONF_READ_VARS - -#define C_MTYPE_MASK 0x30000000 -# define C_PATH 0x10000000 /* C_TYPE_STR is a path spec */ -# define C_BOOL 0x10000000 /* C_TYPE_INT is a boolean */ -# define C_ENUM 0x20000000 /* C_TYPE_INT is an enum (option) */ -# define C_GRP 0x30000000 /* C_TYPE_INT is a group spec */ -#define C_INTERNAL 0x40000000 /* don't expose to core */ -#define C_CONFIG 0x80000000 /* process only for finding deps */ - -#ifdef XDMCP -static int -PrequestPort( Value *retval ) -{ - if (!VxdmcpEnable.ptr) { - retval->ptr = (char *)0; - return 1; - } - return 0; -} -#endif - -static Value - emptyStr = { "", 1 }, - nullValue = { 0, 0 }, - emptyArgv = { (char *)&nullValue, 0 }; - -static int -PnoPassUsers( Value *retval ) -{ - if (!VnoPassEnable.ptr) { - *retval = emptyArgv; - return 1; - } - return 0; -} - -static int -PautoLoginX( Value *retval ) -{ - if (!VautoLoginEnable.ptr) { - *retval = emptyStr; - return 1; - } - return 0; -} - -CONF_READ_ENTRIES - -static const char *tdmrc = TDMCONF "/tdmrc"; -static const char *tdmrc_dist = TDMCONF "/tdmdistrc"; - -static Section *rootsec; - -static void -ReadConf() -{ - const char *nstr, *dstr, *cstr, *dhost, *dnum, *dclass; - char *s, *e, *st, *en, *ek, *sl, *pt; - Section *cursec; - Entry *curent; - Ent *ce; - int nlen, dlen, clen, dhostl, dnuml, dclassl; - int i, line, sectmoan, restl; - File file; - static int confread; - - if (confread) - return; - confread = 1; - - Debug( "reading config %s ...\n", tdmrc_dist ); - if (!readFile( &file, tdmrc_dist, "master configuration" )) { - Debug( "reading config %s ...\n", tdmrc ); - if (!readFile( &file, tdmrc, "master configuration" )) - return; - } - else { - tdmrc = tdmrc_dist; - } - - for (s = file.buf, line = 0, cursec = 0, sectmoan = 1; s < file.eof; s++) { - line++; - - while ((s < file.eof) && isspace( *s ) && (*s != '\n')) - s++; - - if ((s < file.eof) && ((*s == '\n') || (*s == '#'))) { - sktoeol: - while ((s < file.eof) && (*s != '\n')) - s++; - continue; - } - sl = s; - - if (*s == '[') { - sectmoan = 0; - while ((s < file.eof) && (*s != '\n')) - s++; - e = s - 1; - while ((e > sl) && isspace( *e )) - e--; - if (*e != ']') { - cursec = 0; - LogError( "Invalid section header at %s:%d\n", tdmrc, line ); - continue; - } - nstr = sl + 1; - nlen = e - nstr; - for (cursec = rootsec; cursec; cursec = cursec->next) - if (nlen == cursec->nlen && - !memcmp( nstr, cursec->name, nlen )) - { - LogInfo( "Multiple occurrences of section [%.*s] in %s. " - "Consider merging them.\n", nlen, nstr, tdmrc ); - goto secfnd; - } - if (nstr[0] == 'X' && nstr[1] == '-') { - cstr = nstr + nlen; - clen = 0; - while (++clen, *--cstr != '-'); - if (cstr == nstr + 1) - goto illsec; - dstr = nstr + 2; - dlen = nlen - clen - 2; - dhost = dstr; - dhostl = 0; - for (restl = dlen; restl; restl--) { - if (dhost[dhostl] == ':') { - dnum = dhost + dhostl + 1; - dnuml = 0; - for (restl--; restl; restl--) { - if (dnum[dnuml] == '_') { - dclass = dnum + dnuml + 1; - dclassl = restl; - goto gotall; - } - dnuml++; - } - goto gotnum; - } - dhostl++; - } - dnum = "*"; - dnuml = 1; - gotnum: - dclass = "*"; - dclassl = 1; - gotall: ; - } else { - if (nstr[0] == '-') - goto illsec; - dstr = 0; - dlen = 0; - dhost = 0; - dhostl = 0; - dnum = 0; - dnuml = 0; - dclass = 0; - dclassl = 0; - cstr = nstr; - clen = nlen; - } - for (i = 0; i < as(allSects); i++) - if ((int)strlen( allSects[i]->name ) == clen && - !memcmp( allSects[i]->name, cstr, clen )) - goto newsec; - illsec: - cursec = 0; - LogError( "Unrecognized section name [%.*s] at %s:%d\n", - nlen, nstr, tdmrc, line ); - continue; - newsec: - if (!(cursec = Malloc( sizeof(*cursec) ))) - return; - cursec->name = nstr; - cursec->nlen = nlen; - cursec->dname = dstr; - cursec->dlen = dlen; - cursec->dhost = dhost; - cursec->dhostl = dhostl; - cursec->dnum = dnum; - cursec->dnuml = dnuml; - cursec->dclass = dclass; - cursec->dclassl = dclassl; - cursec->sect = allSects[i]; - cursec->entries = 0; - cursec->next = rootsec; - rootsec = cursec; - /*Debug( "now in section [%.*s], dpy '%.*s', core '%.*s'\n", - nlen, nstr, dlen, dstr, clen, cstr );*/ - secfnd: - continue; - } - - if (!cursec) { - if (sectmoan) { - sectmoan = 0; - LogError( "Entry outside any section at %s:%d", tdmrc, line ); - } - goto sktoeol; - } - - for (; (s < file.eof) && (*s != '\n'); s++) - if (*s == '=') - goto haveeq; - LogError( "Invalid entry (missing '=') at %s:%d\n", tdmrc, line ); - continue; - - haveeq: - for (ek = s - 1; ; ek--) { - if (ek < sl) { - LogError( "Invalid entry (empty key) at %s:%d\n", tdmrc, line ); - goto sktoeol; - } - if (!isspace( *ek )) - break; - } - - s++; - while ((s < file.eof) && isspace( *s ) && (*s != '\n')) - s++; - for (pt = st = en = s; s < file.eof && *s != '\n'; s++) { - if (*s == '\\') { - s++; - if (s >= file.eof || *s == '\n') { - LogError( "Trailing backslash at %s:%d\n", tdmrc, line ); - break; - } - switch (*s) { - case 's': *pt++ = ' '; break; - case 't': *pt++ = '\t'; break; - case 'n': *pt++ = '\n'; break; - case 'r': *pt++ = '\r'; break; - case '\\': *pt++ = '\\'; break; - default: *pt++ = '\\'; *pt++ = *s; break; - } - en = pt; - } else { - *pt++ = *s; - if (*s != ' ' && *s != '\t') - en = pt; - } - } - - nstr = sl; - nlen = ek - sl + 1; - /*Debug( "read entry '%.*s'='%.*s'\n", nlen, nstr, en - st, st );*/ - for (i = 0; i < cursec->sect->numents; i++) { - ce = cursec->sect->ents + i; - if ((int)strlen( ce->name ) == nlen && - !memcmp( ce->name, nstr, nlen )) - goto keyok; - } - LogError( "Unrecognized key '%.*s' in section [%.*s] at %s:%d\n", - nlen, nstr, cursec->nlen, cursec->name, tdmrc, line ); - continue; - keyok: - for (curent = cursec->entries; curent; curent = curent->next) - if (ce == curent->ent) { - LogError( "Multiple occurrences of key '%s' in section [%.*s]" - " of %s\n", - ce->name, cursec->nlen, cursec->name, tdmrc ); - goto keyfnd; - } - if (!(curent = Malloc( sizeof(*curent) ))) - return; - curent->ent = ce; - curent->line = line; - curent->val = st; - curent->vallen = en - st; - curent->next = cursec->entries; - cursec->entries = curent; - keyfnd: - continue; - } -} - -static Entry * -FindGEnt( int id ) -{ - Section *cursec; - Entry *curent; - - for (cursec = rootsec; cursec; cursec = cursec->next) - if (!cursec->dname) - for (curent = cursec->entries; curent; curent = curent->next) - if (curent->ent->id == id) { - Debug( "line %d: %s = %'.*s\n", - curent->line, curent->ent->name, - curent->vallen, curent->val ); - return curent; - } - return 0; -} - -/* Display name match scoring: - * - class (any/exact) -> 0/1 - * - number (any/exact) -> 0/2 - * - host (any/nonempty/trail/exact) -> 0/4/8/12 - */ -static Entry * -FindDEnt( int id, DSpec *dspec ) -{ - Section *cursec, *bestsec; - Entry *curent, *bestent; - int score, bestscore; - - bestscore = -1, bestent = 0; - for (cursec = rootsec; cursec; cursec = cursec->next) - if (cursec->dname) { - score = 0; - if (cursec->dclassl != 1 || cursec->dclass[0] != '*') { - if (cursec->dclassl == dspec->dclassl && - !memcmp( cursec->dclass, dspec->dclass, dspec->dclassl )) - score = 1; - else - continue; - } - if (cursec->dnuml != 1 || cursec->dnum[0] != '*') { - if (cursec->dnuml == dspec->dnuml && - !memcmp( cursec->dnum, dspec->dnum, dspec->dnuml )) - score += 2; - else - continue; - } - if (cursec->dhostl != 1 || cursec->dhost[0] != '*') { - if (cursec->dhostl == 1 && cursec->dhost[0] == '+') { - if (dspec->dhostl) - score += 4; - else - continue; - } else if (cursec->dhost[0] == '.') { - if (cursec->dhostl < dspec->dhostl && - !memcmp( cursec->dhost, - dspec->dhost + dspec->dhostl - cursec->dhostl, - cursec->dhostl )) - score += 8; - else - continue; - } else { - if (cursec->dhostl == dspec->dhostl && - !memcmp( cursec->dhost, dspec->dhost, dspec->dhostl )) - score += 12; - else - continue; - } - } - if (score > bestscore) { - for (curent = cursec->entries; curent; curent = curent->next) - if (curent->ent->id == id) { - bestent = curent; - bestsec = cursec; - bestscore = score; - break; - } - } - } - if (bestent) - Debug( "line %d: %.*s:%.*s_%.*s/%s = %'.*s\n", bestent->line, - bestsec->dhostl, bestsec->dhost, - bestsec->dnuml, bestsec->dnum, - bestsec->dclassl, bestsec->dclass, - bestent->ent->name, bestent->vallen, bestent->val ); - return bestent; -} - -static const char * -CvtValue( Ent *et, Value *retval, int vallen, const char *val, char **eopts ) -{ - Value *ents; - int i, b, e, tlen, nents, esiz; - char buf[80]; - - switch (et->id & C_TYPE_MASK) { - case C_TYPE_INT: - for (i = 0; i < vallen && i < (int)sizeof(buf) - 1; i++) - buf[i] = tolower( val[i] ); - buf[i] = 0; - if ((et->id & C_MTYPE_MASK) == C_BOOL) { - if (!strcmp( buf, "true" ) || - !strcmp( buf, "on" ) || - !strcmp( buf, "yes" ) || - !strcmp( buf, "1" )) - retval->ptr = (char *)1; - else if (!strcmp( buf, "false" ) || - !strcmp( buf, "off" ) || - !strcmp( buf, "no" ) || - !strcmp( buf, "0" )) - retval->ptr = (char *)0; - else - return "boolean"; - return 0; - } else if ((et->id & C_MTYPE_MASK) == C_ENUM) { - for (i = 0; eopts[i]; i++) - if (!memcmp( eopts[i], val, vallen ) && !eopts[i][vallen]) { - retval->ptr = (char *)i; - return 0; - } - return "option"; - } else if ((et->id & C_MTYPE_MASK) == C_GRP) { - struct group *ge; - if ((ge = getgrnam( buf ))) { - retval->ptr = (char *)ge->gr_gid; - return 0; - } - } - retval->ptr = 0; - if (sscanf( buf, "%li", &retval->ptr ) != 1) - return "integer"; - return 0; - case C_TYPE_STR: - retval->ptr = val; - retval->len = vallen + 1; - if ((et->id & C_MTYPE_MASK) == C_PATH) - if (vallen && val[vallen-1] == '/') - retval->len--; - return 0; - case C_TYPE_ARGV: - if (!(ents = Malloc( sizeof(Value) * (esiz = 10) ))) - return 0; - for (nents = 0, tlen = 0, i = 0; ; i++) { - for (; i < vallen && isspace( val[i] ); i++); - for (b = i; i < vallen && val[i] != ','; i++); - if (b == i) - break; - for (e = i; e > b && isspace( val[e - 1] ); e--); - if (esiz < nents + 2) { - Value *entsn = Realloc( ents, - sizeof(Value) * (esiz = esiz * 2 + 1) ); - if (!nents) - break; - ents = entsn; - } - ents[nents].ptr = val + b; - ents[nents].len = e - b; - nents++; - tlen += e - b + 1; - } - ents[nents].ptr = 0; - retval->ptr = (char *)ents; - retval->len = tlen; - return 0; - default: - LogError( "Internal error: unknown value type in id %#x\n", et->id ); - return 0; - } -} - -static void -GetValue( Ent *et, DSpec *dspec, Value *retval, char **eopts ) -{ - Entry *ent; - const char *errs; - -/* Debug( "Getting value %#x\n", et->id );*/ - if (dspec) - ent = FindDEnt( et->id, dspec ); - else - ent = FindGEnt( et->id ); - if (ent) { - if (!(errs = CvtValue( et, retval, ent->vallen, ent->val, eopts ))) - return; - LogError( "Invalid %s value '%.*s' at %s:%d\n", - errs, ent->vallen, ent->val, tdmrc, ent->line ); - } - Debug( "default: %s = %'s\n", et->name, et->def ); - if ((errs = CvtValue( et, retval, strlen( et->def ), et->def, eopts ))) - LogError( "Internal error: invalid default %s value '%s' for key %s\n", - errs, et->def, et->name ); -} - -static int -AddValue( ValArr *va, int id, Value *val ) -{ - int nu; - -/* Debug( "Addig value %#x\n", id );*/ - if (va->nents == va->esiz) { - va->ents = Realloc( va->ents, sizeof(Val) * (va->esiz += 50) ); - if (!va->ents) - return 0; - } - va->ents[va->nents].id = id; - va->ents[va->nents].val = *val; - va->nents++; - switch (id & C_TYPE_MASK) { - case C_TYPE_INT: - break; - case C_TYPE_STR: - va->nchars += val->len; - break; - case C_TYPE_ARGV: - va->nchars += val->len; - for (nu = 0; ((Value *)val->ptr)[nu++].ptr; ); - va->nptrs += nu; - break; - } - return 1; -} - -static void -CopyValues( ValArr *va, Sect *sec, DSpec *dspec, int isconfig ) -{ - Value val; - int i; - - Debug( "getting values for section class [%s]\n", sec->name ); - for (i = 0; i < sec->numents; i++) { -/*Debug ("value %#x\n", sec->ents[i].id);*/ - if ((sec->ents[i].id & (int)C_CONFIG) != isconfig) - ; - else if (sec->ents[i].id & C_INTERNAL) { - GetValue( sec->ents + i, dspec, ((Value *)sec->ents[i].ptr), 0 ); - } else { - if (((sec->ents[i].id & C_MTYPE_MASK) == C_ENUM) || - !sec->ents[i].ptr || - !((int (*)( Value * ))sec->ents[i].ptr)(&val)) { - GetValue( sec->ents + i, dspec, &val, - (char **)sec->ents[i].ptr ); - } - if (!AddValue( va, sec->ents[i].id, &val )) - break; - } - } - return; -} - -static void -SendValues( ValArr *va ) -{ - Value *cst; - int i, nu; - - GSendInt( va->nents ); - GSendInt( va->nptrs ); - GSendInt( 0/*va->nints*/ ); - GSendInt( va->nchars ); - for (i = 0; i < va->nents; i++) { - GSendInt( va->ents[i].id & ~C_PRIVATE ); - switch (va->ents[i].id & C_TYPE_MASK) { - case C_TYPE_INT: - GSendInt( (int)va->ents[i].val.ptr ); - break; - case C_TYPE_STR: - GSendNStr( va->ents[i].val.ptr, va->ents[i].val.len - 1 ); - break; - case C_TYPE_ARGV: - cst = (Value *)va->ents[i].val.ptr; - for (nu = 0; cst[nu].ptr; nu++); - GSendInt( nu ); - for (; cst->ptr; cst++) - GSendNStr( cst->ptr, cst->len ); - break; - } - } -} - - -#ifdef XDMCP -static char * -ReadWord( File *file, int *len, int EOFatEOL ) -{ - char *wordp, *wordBuffer; - int quoted; - char c; - - rest: - wordp = wordBuffer = file->cur; - mloop: - quoted = 0; - qloop: - if (file->cur == file->eof) { - doeow: - if (wordp == wordBuffer) - return 0; - retw: - *wordp = '\0'; - *len = wordp - wordBuffer; - return wordBuffer; - } - c = *file->cur++; - switch (c) { - case '#': - if (quoted) - break; - do { - if (file->cur == file->eof) - goto doeow; - c = *file->cur++; - } while (c != '\n'); - case '\0': - case '\n': - if (EOFatEOL && !quoted) { - file->cur--; - goto doeow; - } - if (wordp != wordBuffer) { - file->cur--; - goto retw; - } - goto rest; - case ' ': - case '\t': - if (wordp != wordBuffer) - goto retw; - goto rest; - case '\\': - if (!quoted) { - quoted = 1; - goto qloop; - } - break; - } - *wordp++ = c; - goto mloop; -} - -#define ALIAS_CHARACTER '%' -#define EQUAL_CHARACTER '=' -#define NEGATE_CHARACTER '!' -#define CHOOSER_STRING "CHOOSER" -#define BROADCAST_STRING "BROADCAST" -#define NOBROADCAST_STRING "NOBROADCAST" -#define LISTEN_STRING "LISTEN" -#define WILDCARD_STRING "*" - -typedef struct hostEntry { - struct hostEntry *next; - int type; - union _hostOrAlias { - char *aliasPattern; - char *hostPattern; - struct _display { - int connectionType; - int hostAddrLen; - char *hostAddress; - } displayAddress; - } entry; -} HostEntry; - -typedef struct listenEntry { - struct listenEntry *next; - int iface; - int mcasts; - int nmcasts; -} ListenEntry; - -typedef struct aliasEntry { - struct aliasEntry *next; - char *name; - HostEntry **pHosts; - int hosts; - int nhosts; - int hasBad; -} AliasEntry; - -typedef struct aclEntry { - struct aclEntry *next; - HostEntry **pEntries; - int entries; - int nentries; - HostEntry **pHosts; - int hosts; - int nhosts; - int flags; -} AclEntry; - - -static int -HasGlobCharacters( char *s ) -{ - for (;;) - switch (*s++) { - case '?': - case '*': - return 1; - case '\0': - return 0; - } -} - -#define PARSE_ALL 0 -#define PARSE_NO_BCAST 1 -#define PARSE_NO_PAT 2 -#define PARSE_NO_ALIAS 4 - -static int -ParseHost( int *nHosts, HostEntry ***hostPtr, int *nChars, - char *hostOrAlias, int len, int parse ) -{ -#if defined(IPv6) && defined(AF_INET6) - struct addrinfo *ai; -#else - struct hostent *hostent; -#endif - void *addr; - int addr_type, addr_len; - - if (!(**hostPtr = (HostEntry *)Malloc( sizeof(HostEntry)))) - return 0; - if (!(parse & PARSE_NO_BCAST) && !strcmp( hostOrAlias, BROADCAST_STRING )) - { - (**hostPtr)->type = HOST_BROADCAST; - } - else if (!(parse & PARSE_NO_ALIAS) && *hostOrAlias == ALIAS_CHARACTER) - { - (**hostPtr)->type = HOST_ALIAS; - (**hostPtr)->entry.aliasPattern = hostOrAlias + 1; - *nChars += len; - } - else if (!(parse & PARSE_NO_PAT) && HasGlobCharacters( hostOrAlias )) - { - (**hostPtr)->type = HOST_PATTERN; - (**hostPtr)->entry.hostPattern = hostOrAlias; - *nChars += len + 1; - } - else - { - (**hostPtr)->type = HOST_ADDRESS; -#if defined(IPv6) && defined(AF_INET6) - if (getaddrinfo( hostOrAlias, NULL, NULL, &ai )) -#else - if (!(hostent = gethostbyname( hostOrAlias ))) -#endif - { - LogWarn( "XDMCP ACL: unresolved host %'s\n", hostOrAlias ); - free( (char *)(**hostPtr) ); - return 0; - } -#if defined(IPv6) && defined(AF_INET6) - addr_type = ai->ai_addr->sa_family; - if (ai->ai_family == AF_INET) { - addr = &((struct sockaddr_in *)ai->ai_addr)->sin_addr; - addr_len = sizeof(struct in_addr); - } else /*if (ai->ai_addr->sa_family == AF_INET6)*/ { - addr = &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr; - addr_len = sizeof(struct in6_addr); - } -#else - addr_type = hostent->h_addrtype; - addr = hostent->h_addr; - addr_len = hostent->h_length; -#endif - if (!((**hostPtr)->entry.displayAddress.hostAddress = - Malloc( addr_len ))) - { -#if defined(IPv6) && defined(AF_INET6) - freeaddrinfo( ai ); -#endif - free( (char *)(**hostPtr) ); - return 0; - } - memcpy( (**hostPtr)->entry.displayAddress.hostAddress, addr, addr_len ); - *nChars += addr_len; - (**hostPtr)->entry.displayAddress.hostAddrLen = addr_len; - (**hostPtr)->entry.displayAddress.connectionType = addr_type; -#if defined(IPv6) && defined(AF_INET6) - freeaddrinfo( ai ); -#endif - } - *hostPtr = &(**hostPtr)->next; - (*nHosts)++; - return 1; -} - -/* Returns non-0 if string is matched by pattern. Does case folding. */ -static int -patternMatch( const char *string, const char *pattern ) -{ - int p, s; - - if (!string) - string = ""; - - for (;;) { - s = *string++; - switch (p = *pattern++) { - case '*': - if (!*pattern) - return 1; - for (string--; *string; string++) - if (patternMatch( string, pattern )) - return 1; - return 0; - case '?': - if (s == '\0') - return 0; - break; - case '\0': - return s == '\0'; - case '\\': - p = *pattern++; - /* fall through */ - default: - if (tolower( p ) != tolower( s )) - return 0; - } - } -} - -#define MAX_DEPTH 32 - -#define CHECK_NOT 1 -#define CHECK_NO_PAT 2 - -static int -checkHostlist( HostEntry **hosts, int nh, AliasEntry *aliases, int na, - int depth, int flags ) -{ - HostEntry *h; - AliasEntry *a; - int hn, an, am; - - for (h = *hosts, hn = 0; hn < nh; hn++, h = h->next) - if (h->type == HOST_ALIAS) { - if (depth == MAX_DEPTH) { - LogError( "XDMCP ACL: alias recursion involving %%%s\n", - h->entry.aliasPattern ); - return 1; - } - for (a = aliases, an = 0, am = 0; an < na; an++, a = a->next) - if (patternMatch( a->name, h->entry.aliasPattern )) { - am = 1; - if ((flags & CHECK_NOT) && a->hasBad) { - LogError( "XDMCP ACL: alias %%%s with unresolved hosts " - "in denying rule\n", a->name ); - return 1; - } - if (checkHostlist( a->pHosts, a->nhosts, aliases, na, - depth + 1, flags )) - return 1; - } - if (!am) { - if (flags & CHECK_NOT) { - LogError( "XDMCP ACL: unresolved alias pattern %%%s " - "in denying rule\n", h->entry.aliasPattern ); - return 1; - } else - LogWarn( "XDMCP ACL: unresolved alias pattern %%%s\n", - h->entry.aliasPattern ); - } - } else if (h->type == HOST_PATTERN && (flags & CHECK_NO_PAT)) - LogWarn( "XDMCP ACL: wildcarded pattern %'s in host-only context\n", - h->entry.hostPattern ); - return 0; -} - -static void -ReadAccessFile( const char *fname ) -{ - HostEntry *hostList, **hostPtr = &hostList; - AliasEntry *aliasList, **aliasPtr = &aliasList; - AclEntry *acList, **acPtr = &acList, *acl; - ListenEntry *listenList, **listenPtr = &listenList; - char *displayOrAlias, *hostOrAlias; - File file; - int nHosts, nAliases, nAcls, nListens, nChars, error, bad; - int i, len; - - nHosts = nAliases = nAcls = nListens = nChars = error = 0; - if (!readFile( &file, fname, "XDMCP access control" )) - goto sendacl; - while ((displayOrAlias = ReadWord( &file, &len, FALSE ))) { - if (*displayOrAlias == ALIAS_CHARACTER) - { - if (!(*aliasPtr = (AliasEntry *)Malloc( sizeof(AliasEntry)))) { - error = 1; - break; - } - (*aliasPtr)->name = displayOrAlias + 1; - nChars += len; - (*aliasPtr)->hosts = nHosts; - (*aliasPtr)->pHosts = hostPtr; - (*aliasPtr)->nhosts = 0; - (*aliasPtr)->hasBad = 0; - while ((hostOrAlias = ReadWord( &file, &len, TRUE ))) { - if (ParseHost( &nHosts, &hostPtr, &nChars, hostOrAlias, len, - PARSE_NO_BCAST )) - (*aliasPtr)->nhosts++; - else - (*aliasPtr)->hasBad = 1; - } - aliasPtr = &(*aliasPtr)->next; - nAliases++; - } - else if (!strcmp( displayOrAlias, LISTEN_STRING )) - { - if (!(*listenPtr = (ListenEntry *)Malloc( sizeof(ListenEntry)))) { - error = 1; - break; - } - (*listenPtr)->iface = nHosts; - if (!(hostOrAlias = ReadWord( &file, &len, TRUE )) || - !strcmp( hostOrAlias, WILDCARD_STRING ) || - !ParseHost( &nHosts, &hostPtr, &nChars, hostOrAlias, len, - PARSE_NO_BCAST|PARSE_NO_PAT|PARSE_NO_ALIAS )) - { - (*listenPtr)->iface = -1; - } - (*listenPtr)->mcasts = nHosts; - (*listenPtr)->nmcasts = 0; - while ((hostOrAlias = ReadWord( &file, &len, TRUE ))) { - if (ParseHost( &nHosts, &hostPtr, &nChars, hostOrAlias, len, - PARSE_NO_BCAST|PARSE_NO_PAT|PARSE_NO_ALIAS )) - (*listenPtr)->nmcasts++; - } - listenPtr = &(*listenPtr)->next; - nListens++; - } - else - { - if (!(*acPtr = (AclEntry *)Malloc( sizeof(AclEntry)))) { - error = 1; - break; - } - (*acPtr)->flags = 0; - if (*displayOrAlias == NEGATE_CHARACTER) { - (*acPtr)->flags |= a_notAllowed; - displayOrAlias++; - } else if (*displayOrAlias == EQUAL_CHARACTER) - displayOrAlias++; - (*acPtr)->entries = nHosts; - (*acPtr)->pEntries = hostPtr; - (*acPtr)->nentries = 1; - if (!ParseHost( &nHosts, &hostPtr, &nChars, displayOrAlias, len, - PARSE_NO_BCAST )) - { - bad = 1; - if ((*acPtr)->flags & a_notAllowed) { - LogError( "XDMCP ACL: unresolved host in denying rule\n" ); - error = 1; - } - } else - bad = 0; - (*acPtr)->hosts = nHosts; - (*acPtr)->pHosts = hostPtr; - (*acPtr)->nhosts = 0; - while ((hostOrAlias = ReadWord( &file, &len, TRUE ))) { - if (!strcmp( hostOrAlias, CHOOSER_STRING )) - (*acPtr)->flags |= a_useChooser; - else if (!strcmp( hostOrAlias, NOBROADCAST_STRING )) - (*acPtr)->flags |= a_notBroadcast; - else { - if (ParseHost( &nHosts, &hostPtr, &nChars, - hostOrAlias, len, PARSE_NO_PAT )) - (*acPtr)->nhosts++; - } - } - if (!bad) { - acPtr = &(*acPtr)->next; - nAcls++; - } - } - } - - if (!nListens) { - if (!(*listenPtr = (ListenEntry *)Malloc( sizeof(ListenEntry)))) - error = 1; - else { - (*listenPtr)->iface = -1; - (*listenPtr)->mcasts = nHosts; - (*listenPtr)->nmcasts = 0; -#if defined(IPv6) && defined(AF_INET6) && defined(XDM_DEFAULT_MCAST_ADDR6) - if (ParseHost( &nHosts, &hostPtr, &nChars, - XDM_DEFAULT_MCAST_ADDR6, - sizeof(XDM_DEFAULT_MCAST_ADDR6)-1, - PARSE_ALL )) - (*listenPtr)->nmcasts++; -#endif - nListens++; - } - } - - for (acl = acList, i = 0; i < nAcls; i++, acl = acl->next) - if (checkHostlist( acl->pEntries, acl->nentries, aliasList, nAliases, - 0, (acl->flags & a_notAllowed) ? CHECK_NOT : 0 ) || - checkHostlist( acl->pHosts, acl->nhosts, aliasList, nAliases, - 0, CHECK_NO_PAT )) - error = 1; - - if (error) { - nHosts = nAliases = nAcls = nListens = nChars = 0; - sendacl: - LogError( "No XDMCP requests will be granted\n" ); - } - GSendInt( nHosts ); - GSendInt( nListens ); - GSendInt( nAliases ); - GSendInt( nAcls ); - GSendInt( nChars ); - for (i = 0; i < nHosts; i++, hostList = hostList->next) { - GSendInt( hostList->type ); - switch (hostList->type) { - case HOST_ALIAS: - GSendStr( hostList->entry.aliasPattern ); - break; - case HOST_PATTERN: - GSendStr( hostList->entry.hostPattern ); - break; - case HOST_ADDRESS: - GSendArr( hostList->entry.displayAddress.hostAddrLen, - hostList->entry.displayAddress.hostAddress ); - GSendInt( hostList->entry.displayAddress.connectionType ); - break; - } - } - for (i = 0; i < nListens; i++, listenList = listenList->next) { - GSendInt( listenList->iface ); - GSendInt( listenList->mcasts ); - GSendInt( listenList->nmcasts ); - } - for (i = 0; i < nAliases; i++, aliasList = aliasList->next) { - GSendStr( aliasList->name ); - GSendInt( aliasList->hosts ); - GSendInt( aliasList->nhosts ); - } - for (i = 0; i < nAcls; i++, acList = acList->next) { - GSendInt( acList->entries ); - GSendInt( acList->nentries ); - GSendInt( acList->hosts ); - GSendInt( acList->nhosts ); - GSendInt( acList->flags ); - } -} -#endif - - -int main( int argc ATTR_UNUSED, char **argv ) -{ - DSpec dspec; - ValArr va; - char *ci, *disp, *dcls, *cfgfile; - int what; - - if (!(ci = getenv( "CONINFO" ))) { - fprintf( stderr, "This program is part of tdm and should not be run manually.\n" ); - return 1; - } - if (sscanf( ci, "%d %d", &rfd, &wfd ) != 2) - return 1; - - InitLog(); - - if ((debugLevel = GRecvInt()) & DEBUG_WCONFIG) - sleep( 100 ); - -/* Debug ("parsing command line\n");*/ - if (**++argv) - tdmrc_dist = tdmrc = *argv; -/* - while (*++argv) { - } -*/ - - for (;;) { -/* Debug ("Awaiting command ...\n");*/ - if (!GRecvCmd( &what )) - break; - switch (what) { - case GC_Files: -/* Debug ("GC_Files\n");*/ - ReadConf(); - CopyValues( 0, &secGeneral, 0, C_CONFIG ); -#ifdef XDMCP - CopyValues( 0, &secXdmcp, 0, C_CONFIG ); - GSendInt( 2 ); -#else - GSendInt( 1 ); -#endif - GSendStr( tdmrc ); - GSendInt( -1 ); -#ifdef XDMCP - GSendNStr( VXaccess.ptr, VXaccess.len - 1 ); - GSendInt( 0 ); -#endif - for (; (what = GRecvInt()) != -1; ) - switch (what) { - case GC_gGlobal: - case GC_gDisplay: - GSendInt( 0 ); - break; -#ifdef XDMCP - case GC_gXaccess: - GSendInt( 1 ); - break; -#endif - default: - GSendInt( -1 ); - break; - } - break; - case GC_GetConf: -/* Debug( "GC_GetConf\n" );*/ - memset( &va, 0, sizeof(va) ); - what = GRecvInt(); - cfgfile = GRecvStr(); - switch (what) { - case GC_gGlobal: -/* Debug( "GC_gGlobal\n" );*/ - Debug( "getting global config\n" ); - ReadConf(); - CopyValues( &va, &secGeneral, 0, 0 ); -#ifdef XDMCP - CopyValues( &va, &secXdmcp, 0, 0 ); -#endif - CopyValues( &va, &secShutdown, 0, 0 ); - SendValues( &va ); - break; - case GC_gDisplay: -/* Debug( "GC_gDisplay\n" );*/ - disp = GRecvStr(); -/* Debug( " Display %s\n", disp );*/ - dcls = GRecvStr(); -/* Debug( " Class %s\n", dcls );*/ - Debug( "getting config for display %s, class %s\n", disp, dcls ); - MkDSpec( &dspec, disp, dcls ? dcls : "" ); - ReadConf(); - CopyValues( &va, &sec_Core, &dspec, 0 ); - CopyValues( &va, &sec_Greeter, &dspec, 0 ); - free( disp ); - if (dcls) - free( dcls ); - SendValues( &va ); - break; -#ifdef XDMCP - case GC_gXaccess: - ReadAccessFile( cfgfile ); - break; -#endif - default: - Debug( "Unsupported config category %#x\n", what ); - } - free( cfgfile ); - break; - default: - Debug( "Unknown config command %#x\n", what ); - } - } - -/* Debug( "Config reader exiting ..." );*/ - return EX_NORMAL; -} |