X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=ircd%2Fircd_parser.y;h=b3ce75b027f7d35715938496c3b3688b4531eb02;hb=79035436c61e2b58004b47f250ab1e54744a88d6;hp=4e63ff98f3f3c06e6dc6a8a24c77daaa6f76f38b;hpb=5ba09703da9f8f21f3278dc0222cd6fe077cfe31;p=ircu2.10.12-pk.git diff --git a/ircd/ircd_parser.y b/ircd/ircd_parser.y index 4e63ff9..b3ce75b 100644 --- a/ircd/ircd_parser.y +++ b/ircd/ircd_parser.y @@ -1,8 +1,8 @@ /* * ircd_parser.y: A yacc/bison parser for ircd config files. * This is part of ircu, an Internet Relay Chat server. - * The contents of this file are Copyright(C) 2001 by Andrew Miller, the - * ircd-hybrid team and the ircu team. + * The contents of this file are Copyright 2001 Diane Bruce, + * Andrew Miller, the ircd-hybrid team and the ircu team. * 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 @@ -32,6 +32,7 @@ #include "hash.h" #include "ircd.h" #include "ircd_alloc.h" +#include "ircd_auth.h" #include "ircd_chattr.h" #include "ircd_log.h" #include "ircd_reply.h" @@ -55,6 +56,7 @@ #include "support.h" #include "sys.h" #include +#include #include #include #define MAX_STRINGS 80 /* Maximum number of feature params. */ @@ -62,20 +64,34 @@ extern struct DenyConf* denyConfList; extern struct CRuleConf* cruleConfList; extern struct ServerConf* serverConfList; - extern struct qline *GlobalQuarantineList; + extern struct s_map* GlobalServiceMapList; + extern struct qline* GlobalQuarantineList; int yylex(void); /* Now all the globals we need :/... */ - int tping, tconn, maxlinks, sendq, port; + int tping, tconn, maxlinks, sendq, port, invert; int stringno; char *name, *pass, *host; char *stringlist[MAX_STRINGS]; - struct ConnectionClass *class; + struct ConnectionClass *c_class; struct ConfItem *aconf; struct DenyConf *dconf; struct ServerConf *sconf; struct qline *qconf = NULL; + struct s_map *smap; + struct Privs privs; + struct Privs privs_dirty; + +static void parse_error(char *pattern,...) { + static char error_buffer[1024]; + va_list vl; + va_start(vl,pattern); + ircd_vsnprintf(NULL, error_buffer, sizeof(error_buffer), pattern, vl); + va_end(vl); + yyerror(error_buffer); +} + %} %token QSTRING @@ -119,9 +135,7 @@ %token YES %token NO %token OPER -%token PORT %token VHOST -%token MASK %token HIDDEN %token MOTD %token JUPE @@ -139,18 +153,23 @@ %token IP %token FEATURES %token QUARANTINE +%token PSEUDO +%token PREPEND +%token USERMODE +%token IAUTH +%token TIMEOUT /* and now a lot of priviledges... */ -%token TPRIV_CHAN_LIMIT, TPRIV_MODE_LCHAN, TPRIV_DEOP_LCHAN, TPRIV_WALK_LCHAN -%token TPRIV_KILL, TPRIV_LOCAL_KILL, TPRIV_REHASH, TPRIV_RESTART, TPRIV_DIE -%token TPRIV_GLINE, TPRIV_LOCAL_GLINE, TPRIV_JUPE, TPRIV_LOCAL_JUPE -%token TPRIV_LOCAL_OPMODE, TPRIV_OPMODE, TPRIV_SET, TPRIV_WHOX, TPRIV_BADCHAN -%token TPRIV_LOCAL_BADCHAN -%token TPRIV_SEE_CHAN, TPRIV_SHOW_INVIS, TPRIV_SHOW_ALL_INVIS, TPRIV_PROPAGATE -%token TPRIV_UNLIMIT_QUERY, TPRIV_DISPLAY, TPRIV_SEE_OPERS, TPRIV_WIDE_GLINE +%token TPRIV_CHAN_LIMIT TPRIV_MODE_LCHAN TPRIV_DEOP_LCHAN TPRIV_WALK_LCHAN +%token TPRIV_LOCAL_KILL TPRIV_REHASH TPRIV_RESTART TPRIV_DIE +%token TPRIV_GLINE TPRIV_LOCAL_GLINE TPRIV_LOCAL_JUPE TPRIV_LOCAL_BADCHAN +%token TPRIV_LOCAL_OPMODE TPRIV_OPMODE TPRIV_SET TPRIV_WHOX TPRIV_BADCHAN +%token TPRIV_SEE_CHAN TPRIV_SHOW_INVIS TPRIV_SHOW_ALL_INVIS TPRIV_PROPAGATE +%token TPRIV_UNLIMIT_QUERY TPRIV_DISPLAY TPRIV_SEE_OPERS TPRIV_WIDE_GLINE +%token TPRIV_FORCE_OPMODE TPRIV_FORCE_LOCAL_OPMODE /* and some types... */ %type sizespec -%type timespec, timefactor, factoredtimes, factoredtime -%type expr, yesorno, privtype +%type timespec timefactor factoredtimes factoredtime +%type expr yesorno privtype %left '+' '-' %left '*' '/' @@ -164,7 +183,8 @@ blocks: blocks block | block; block: adminblock | generalblock | classblock | connectblock | serverblock | operblock | portblock | jupeblock | clientblock | - killblock | cruleblock | motdblock | featuresblock | quarantineblock; + killblock | cruleblock | motdblock | featuresblock | quarantineblock | + pseudoblock | iauthblock | error; /* The timespec, sizespec and expr was ripped straight from * ircd-hybrid-7. */ @@ -190,51 +210,41 @@ timefactor: SECONDS { $$ = 1; } | DECADES { $$ = 60 * 60 * 24 * 365 * 10; }; -sizespec: expr - = { +sizespec: expr { $$ = $1; } - | expr BYTES - = { + | expr BYTES { $$ = $1; } - | expr KBYTES - = { + | expr KBYTES { $$ = $1 * 1024; } - | expr MBYTES - = { + | expr MBYTES { $$ = $1 * 1024 * 1024; } - | expr GBYTES - = { + | expr GBYTES { $$ = $1 * 1024 * 1024 * 1024; } - | expr TBYTES - = { + | expr TBYTES { $$ = $1 * 1024 * 1024 * 1024; } ; /* this is an arithmatic expression */ expr: NUMBER - = { + { $$ = $1; } - | expr '+' expr - = { + | expr '+' expr { $$ = $1 + $3; } - | expr '-' expr - = { + | expr '-' expr { $$ = $1 - $3; } - | expr '*' expr - = { + | expr '*' expr { $$ = $1 * $3; } - | expr '/' expr - = { + | expr '/' expr { $$ = $1 / $3; } /* leave this out until we find why it makes BSD yacc dump core -larne @@ -242,15 +252,14 @@ expr: NUMBER = { $$ = -$2; } */ - | '(' expr ')' - = { + | '(' expr ')' { $$ = $2; } ; jupeblock: JUPE '{' jupeitems '}' ';' ; jupeitems: jupeitem jupeitems | jupeitem; -jupeitem: jupenick; +jupeitem: jupenick | error; jupenick: NICK '=' QSTRING { addNickJupes(yylval.text); @@ -258,17 +267,23 @@ jupenick: NICK '=' QSTRING generalblock: GENERAL '{' generalitems '}' ';' ; generalitems: generalitem generalitems | generalitem; -generalitem: generalnumeric | generalname | generalvhost | generaldesc; +generalitem: generalnumeric | generalname | generalvhost | generaldesc | error; generalnumeric: NUMERIC '=' NUMBER ';' { if (localConf.numeric == 0) localConf.numeric = yylval.num; + else if (localConf.numeric != yylval.num) + parse_error("Redefinition of server numeric %i (%i)",yylval.num, + localConf.numeric); }; generalname: NAME '=' QSTRING ';' { if (localConf.name == NULL) DupString(localConf.name, yylval.text); + else if (strcmp(localConf.name, yylval.text)) + parse_error("Redefinition of server name %s (%s)",yylval.text, + localConf.name); }; generaldesc: DESCRIPTION '=' QSTRING ';' @@ -295,7 +310,7 @@ adminblock: ADMIN '{' adminitems '}' DupString(localConf.contact, ""); } ';'; adminitems: adminitems adminitem | adminitem; -adminitem: adminlocation | admincontact; +adminitem: adminlocation | admincontact | error; adminlocation: LOCATION '=' QSTRING ';' { if (localConf.location1 == NULL) @@ -317,16 +332,28 @@ classblock: CLASS { tconn = 0; maxlinks = 0; sendq = 0; + pass = NULL; + memset(&privs, 0, sizeof(privs)); + memset(&privs_dirty, 0, sizeof(privs_dirty)); } '{' classitems '}' { if (name != NULL) { - add_class(name, tping, tconn, maxlinks, sendq); + struct ConnectionClass *c_class; + add_class(name, tping, tconn, maxlinks, sendq); + c_class = find_class(name); + c_class->default_umode = pass; + memcpy(&c_class->privs, &privs, sizeof(c_class->privs)); + memcpy(&c_class->privs_dirty, &privs_dirty, sizeof(c_class->privs_dirty)); + } + else { + parse_error("Missing name in class block"); } + pass = NULL; } ';'; classitems: classitem classitems | classitem; classitem: classname | classpingfreq | classconnfreq | classmaxlinks | - classsendq; + classsendq | classusermode | priv | error; classname: NAME '=' QSTRING ';' { MyFree(name); @@ -348,15 +375,21 @@ classsendq: SENDQ '=' sizespec ';' { sendq = yylval.num; }; +classusermode: USERMODE '=' QSTRING ';' +{ + if (pass) + MyFree(pass); + DupString(pass, yylval.text); +}; connectblock: CONNECT { name = pass = host = NULL; - class = NULL; + c_class = NULL; port = 0; } '{' connectitems '}' { - if (name != NULL && pass != NULL && host != NULL && class != NULL && + if (name != NULL && pass != NULL && host != NULL && c_class != NULL && /*ccount < MAXCONFLINKS &&*/ !strchr(host, '*') && !strchr(host, '?')) { @@ -364,7 +397,7 @@ connectblock: CONNECT aconf->status = CONF_SERVER; aconf->name = name; aconf->passwd = pass; - aconf->conn_class = class; + aconf->conn_class = c_class; aconf->port = port; aconf->status = CONF_SERVER; aconf->host = host; @@ -379,11 +412,12 @@ connectblock: CONNECT MyFree(pass); MyFree(host); name = pass = host = NULL; + parse_error("Bad connect block"); } }';'; connectitems: connectitem connectitems | connectitem; connectitem: connectname | connectpass | connectclass | connecthost - | connectport; + | connectport | error; connectname: NAME '=' QSTRING ';' { MyFree(name); @@ -396,7 +430,7 @@ connectpass: PASS '=' QSTRING ';' }; connectclass: CLASS '=' QSTRING ';' { - class = find_class(yylval.text); + c_class = find_class(yylval.text); }; connecthost: HOST '=' QSTRING ';' { @@ -410,7 +444,7 @@ connectport: PORT '=' NUMBER ';' serverblock: SERVER { - aconf = MyMalloc(sizeof(*aconf)); + aconf = (struct ConfItem*) MyMalloc(sizeof(*aconf)); memset(aconf, 0, sizeof(*aconf)); } '{' serveritems '}' { @@ -420,6 +454,7 @@ serverblock: SERVER MyFree(aconf->name); MyFree(aconf); aconf = NULL; + parse_error("Bad server block"); } else { @@ -429,7 +464,7 @@ serverblock: SERVER } ';'; serveritems: serveritem serveritems | serveritem; serveritem: servername | servermask | serverhub | serverleaf | - serveruworld; + serveruworld | error; servername: NAME '=' QSTRING { MyFree(aconf->name); @@ -455,6 +490,8 @@ serverleaf: LEAF '=' YES ';' { if (!(aconf->status & CONF_HUB && aconf->status & CONF_UWORLD)) aconf->status |= CONF_LEAF; + else + parse_error("Server is both leaf and a hub"); } | LEAF '=' NO ';' { @@ -472,13 +509,21 @@ serveruworld: UWORLD '=' YES ';' operblock: OPER { - aconf = MyMalloc(sizeof(*aconf)); + aconf = (struct ConfItem*) MyMalloc(sizeof(*aconf)); memset(aconf, 0, sizeof(*aconf)); + memset(&privs, 0, sizeof(privs)); + memset(&privs_dirty, 0, sizeof(privs_dirty)); aconf->status = CONF_OPERATOR; } '{' operitems '}' ';' { - if (aconf->name != NULL && aconf->passwd != NULL && aconf->host != NULL) + if (aconf->name != NULL && aconf->passwd != NULL && aconf->host != NULL + && aconf->conn_class != NULL) { + memcpy(&aconf->privs, &privs, sizeof(aconf->privs)); + memcpy(&aconf->privs_dirty, &privs_dirty, sizeof(aconf->privs_dirty)); + if (!PrivHas(&privs_dirty, PRIV_PROPAGATE) + && !PrivHas(&aconf->conn_class->privs_dirty, PRIV_PROPAGATE)) + parse_error("Operator block for %s and class %s have no LOCAL setting", aconf->name, aconf->conn_class->cc_name); aconf->next = GlobalConfList; GlobalConfList = aconf; } @@ -493,7 +538,7 @@ operblock: OPER } }; operitems: operitem | operitems operitem; -operitem: opername | operpass | operlocal | operhost | operclass | operpriv; +operitem: opername | operpass | operhost | operclass | priv | error; opername: NAME '=' QSTRING ';' { @@ -507,24 +552,13 @@ operpass: PASS '=' QSTRING ';' DupString(aconf->passwd, yylval.text); }; -operlocal: LOCAL '=' YES ';' -{ - /* XXX it would be good to get rid of local operators and add same - * permission values here. But for now, I am just going with local - * opers... */ - aconf->status = CONF_LOCOP; -} | LOCAL '=' NO ';' -{ - aconf->status = CONF_OPERATOR; -}; - operhost: HOST '=' QSTRING ';' { MyFree(aconf->host); if (!strchr(yylval.text, '@')) { int uh_len; - char *b = MyMalloc((uh_len = strlen(yylval.text)+3)); + char *b = (char*) MyMalloc((uh_len = strlen(yylval.text)+3)); ircd_snprintf(0, b, uh_len, "*@%s", yylval.text); aconf->host = b; } @@ -537,32 +571,28 @@ operclass: CLASS '=' QSTRING ';' aconf->conn_class = find_class(yylval.text); }; -operpriv: privtype '=' yesorno ';' +priv: privtype '=' yesorno ';' { - if ($3 == 1) - { - PrivSet(&aconf->privs_dirty, $1); - PrivSet(&aconf->privs, $1); - } + PrivSet(&privs_dirty, $1); + if (($3 == 1) ^ invert) + PrivSet(&privs, $1); else - { - PrivSet(&aconf->privs_dirty, $1); - PrivClr(&aconf->privs, $1); - } + PrivClr(&privs, $1); + invert = 0; }; privtype: TPRIV_CHAN_LIMIT { $$ = PRIV_CHAN_LIMIT; } | TPRIV_MODE_LCHAN { $$ = PRIV_MODE_LCHAN; } | TPRIV_DEOP_LCHAN { $$ = PRIV_DEOP_LCHAN; } | TPRIV_WALK_LCHAN { $$ = PRIV_WALK_LCHAN; } | - TPRIV_KILL { $$ = PRIV_KILL; } | + KILL { $$ = PRIV_KILL; } | TPRIV_LOCAL_KILL { $$ = PRIV_LOCAL_KILL; } | TPRIV_REHASH { $$ = PRIV_REHASH; } | TPRIV_RESTART { $$ = PRIV_RESTART; } | TPRIV_DIE { $$ = PRIV_DIE; } | TPRIV_GLINE { $$ = PRIV_GLINE; } | TPRIV_LOCAL_GLINE { $$ = PRIV_LOCAL_GLINE; } | - TPRIV_JUPE { $$ = PRIV_JUPE; } | + JUPE { $$ = PRIV_JUPE; } | TPRIV_LOCAL_JUPE { $$ = PRIV_LOCAL_JUPE; } | TPRIV_LOCAL_OPMODE { $$ = PRIV_LOCAL_OPMODE; } | TPRIV_OPMODE { $$ = PRIV_OPMODE; }| @@ -577,7 +607,10 @@ privtype: TPRIV_CHAN_LIMIT { $$ = PRIV_CHAN_LIMIT; } | TPRIV_UNLIMIT_QUERY { $$ = PRIV_UNLIMIT_QUERY; } | TPRIV_DISPLAY { $$ = PRIV_DISPLAY; } | TPRIV_SEE_OPERS { $$ = PRIV_SEE_OPERS; } | - TPRIV_WIDE_GLINE { $$ = PRIV_WIDE_GLINE; }; + TPRIV_WIDE_GLINE { $$ = PRIV_WIDE_GLINE; } | + LOCAL { $$ = PRIV_PROPAGATE; invert = 1; } | + TPRIV_FORCE_OPMODE { $$ = PRIV_FORCE_OPMODE; } | + TPRIV_FORCE_LOCAL_OPMODE { $$ = PRIV_FORCE_LOCAL_OPMODE; }; yesorno: YES { $$ = 1; } | NO { $$ = 0; }; @@ -595,16 +628,17 @@ portblock: PORT { if (port > 0 && port <= 0xFFFF) { add_listener(port, host, pass, tconn, tping); - host = pass = NULL; } else { - MyFree(host); - MyFree(pass); + parse_error("Bad port block"); } + MyFree(host); + MyFree(pass); + host = pass = NULL; }; portitems: portitem portitems | portitem; -portitem: portnumber | portvhost | portmask | portserver | porthidden; +portitem: portnumber | portvhost | portmask | portserver | porthidden | error; portnumber: PORT '=' NUMBER ';' { port = yylval.num; @@ -640,7 +674,7 @@ porthidden: HIDDEN '=' YES ';' clientblock: CLIENT { - aconf = MyMalloc(sizeof(*aconf)); + aconf = (struct ConfItem*) MyMalloc(sizeof(*aconf)); memset(aconf, 0, sizeof(*aconf)); aconf->status = CONF_CLIENT; } '{' clientitems '}' @@ -663,10 +697,11 @@ clientblock: CLIENT MyFree(aconf->passwd); MyFree(aconf); aconf = NULL; + parse_error("Bad client block"); } } ';'; clientitems: clientitem clientitems | clientitem; -clientitem: clienthost | clientclass | clientpass | clientip; +clientitem: clienthost | clientclass | clientpass | clientip | error; clientip: IP '=' QSTRING ';' { MyFree(aconf->host); @@ -692,7 +727,7 @@ clientpass: PASS '=' QSTRING ';' killblock: KILL { - dconf = MyMalloc(sizeof(*dconf)); + dconf = (struct DenyConf*) MyMalloc(sizeof(*dconf)); memset(dconf, 0, sizeof(*dconf)); } '{' killitems '}' { @@ -710,10 +745,11 @@ killblock: KILL MyFree(dconf->message); MyFree(dconf); dconf = NULL; + parse_error("Bad kill block"); } } ';'; killitems: killitem killitems | killitem; -killitem: killuhost | killreal | killreasonfile | killreason; +killitem: killuhost | killreal | killreasonfile | killreason | error; killuhost: HOST '=' QSTRING ';' { char *u, *h; @@ -785,7 +821,7 @@ cruleblock: CRULE struct CRuleNode *node; if (host != NULL && pass != NULL && (node=crule_parse(pass)) != NULL) { - struct CRuleConf *p = MyMalloc(sizeof(*p)); + struct CRuleConf *p = (struct CRuleConf*) MyMalloc(sizeof(*p)); p->hostmask = host; p->rule = pass; p->type = tconn; @@ -797,11 +833,12 @@ cruleblock: CRULE { MyFree(host); MyFree(pass); + parse_error("Bad CRule block"); } } ';'; cruleitems: cruleitem cruleitems | cruleitem; -cruleitem: cruleserver | crulerule | cruleall; +cruleitem: cruleserver | crulerule | cruleall | error; cruleserver: SERVER '=' QSTRING ';' { @@ -836,7 +873,7 @@ motdblock: MOTD { } ';'; motditems: motditem motditems | motditem; -motditem: motdhost | motdfile; +motditem: motdhost | motdfile | error; motdhost: HOST '=' QSTRING ';' { DupString(host, yylval.text); @@ -875,7 +912,7 @@ extrastring: QSTRING quarantineblock: QUARANTINE '{' { if (qconf != NULL) - qconf = MyMalloc(sizeof(*qconf)); + qconf = (struct qline*) MyMalloc(sizeof(*qconf)); else { if (qconf->chname != NULL) @@ -890,7 +927,7 @@ quarantineblock: QUARANTINE '{' { log_write(LS_CONFIG, L_ERROR, 0, "quarantine blocks need a channel name " "and a reason."); - return; + return 0; } qconf->next = GlobalQuarantineList; GlobalQuarantineList = qconf; @@ -904,3 +941,103 @@ quarantineitems: CHANNEL NAME '=' QSTRING ';' { DupString(qconf->reason, yylval.text); }; + +pseudoblock: PSEUDO QSTRING '{' +{ + smap = MyCalloc(1, sizeof(struct s_map)); + DupString(smap->command, $2); +} +pseudoitems '}' ';' +{ + if (!smap->name || !smap->services) + { + log_write(LS_CONFIG, L_ERROR, 0, "pseudo commands need a service name and list of target nicks."); + return 0; + } + if (register_mapping(smap)) + { + smap->next = GlobalServiceMapList; + GlobalServiceMapList = smap; + } + else + { + struct nick_host *nh, *next; + for (nh = smap->services; nh; nh = next) + { + next = nh->next; + MyFree(nh); + } + MyFree(smap->name); + MyFree(smap->command); + MyFree(smap->prepend); + MyFree(smap); + } + smap = NULL; +}; + +pseudoitems: pseudoitem pseudoitems | pseudoitem; +pseudoitem: pseudoname | pseudoprepend | pseudonick | error; +pseudoname: NAME '=' QSTRING ';' +{ + DupString(smap->name, yylval.text); +}; +pseudoprepend: PREPEND '=' QSTRING ';' +{ + DupString(smap->prepend, yylval.text); +}; +pseudonick: NICK '=' QSTRING ';' +{ + char *sep = strchr(yylval.text, '@'); + + if (sep != NULL) { + size_t slen = strlen(yylval.text); + struct nick_host *nh = MyMalloc(sizeof(*nh) + slen); + memcpy(nh->nick, yylval.text, slen + 1); + nh->nicklen = sep - yylval.text; + nh->next = smap->services; + smap->services = nh; + } +}; + +iauthblock: IAUTH '{' +{ + pass = host = NULL; + port = 0; + tconn = 60; + tping = 60; +} iauthitems '}' ';' +{ + if (!name || !host || !port) { + log_write(LS_CONFIG, L_ERROR, 0, "IAuth block needs a server name and port."); + return 0; + } + iauth_connect(host, port, pass, tconn, tping); + MyFree(pass); + MyFree(host); + pass = host = NULL; +}; + +iauthitems: iauthitem iauthitems | iauthitem; +iauthitem: iauthpass | iauthhost | iauthport | iauthconnfreq | iauthtimeout | error; +iauthpass: PASS '=' QSTRING ';' +{ + MyFree(pass); + DupString(pass, yylval.text); +}; +iauthhost: HOST '=' QSTRING ';' +{ + MyFree(host); + DupString(host, yylval.text); +}; +iauthport: PORT '=' NUMBER ';' +{ + port = yylval.num; +}; +iauthconnfreq: CONNECTFREQ '=' timespec ';' +{ + tconn = yylval.num; +}; +iauthtimeout: TIMEOUT '=' timespec ';' +{ + tping = yylval.num; +};