Committer  : entrope
CVSROOT    : /cvsroot/undernet-ircu
Module     : ircu2.10
Commit time: 2006-06-29 00:52:51 UTC

Modified files:
     ChangeLog configure doc/example.conf ircd/ircd_parser.y

Log message:

Implement Include restrictions in actions, not the config grammar.

---------------------- diff included ----------------------
Index: ircu2.10/ChangeLog
diff -u ircu2.10/ChangeLog:1.783 ircu2.10/ChangeLog:1.784
--- ircu2.10/ChangeLog:1.783    Wed Jun 28 17:41:28 2006
+++ ircu2.10/ChangeLog  Wed Jun 28 17:52:40 2006
@@ -1,5 +1,23 @@
 2006-06-28  Michael Poole <[EMAIL PROTECTED]>
 
+       * doc/example.conf (Include): Update documentation to reflect
+       these changes.
+
+       * ircd/ircd_parser.y (parse_error): Redefine to yyserror().
+       (ConfigBlock): New enumerated type.
+       (ConfigBlocks): New structure type.
+       (includes): New file-scoped variable.
+       (permitted): Function to check whether a block is permitted and
+       optionally warn when it is not.
+       (*): Check whether a block is permitted before letting it take
+       effect.
+       (includeblock): Rewrite.
+       (blocklimit): New non-terminal with several productions.
+       (blocktypes): Likewise.
+       (blocktype): Likewise.
+
+2006-06-28  Michael Poole <[EMAIL PROTECTED]>
+
        * include/s_conf.h (yyserror): Declare new function.
        (yywarning): Declare new function.
 
Index: ircu2.10/configure
diff -u ircu2.10/configure:1.41 ircu2.10/configure:1.42
--- ircu2.10/configure:1.41     Mon Jun 26 21:46:10 2006
+++ ircu2.10/configure  Wed Jun 28 17:52:40 2006
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.ac Revision: 1.2 .
+# From configure.ac Revision: 1.3 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59 for Undernet IRC Daemon 10.13.alpha.0.
 #
Index: ircu2.10/doc/example.conf
diff -u ircu2.10/doc/example.conf:1.71 ircu2.10/doc/example.conf:1.72
--- ircu2.10/doc/example.conf:1.71      Tue Jun 27 04:29:06 2006
+++ ircu2.10/doc/example.conf   Wed Jun 28 17:52:40 2006
@@ -742,24 +742,21 @@
 #   Include "filename";
 #
 # You can limit the file to certain types of configuration blocks by
-# using the block name.  The following options, and ONLY the following
-# options, are supported:
+# using the block name(s), optionally separated by commas.  For
+# example:
 #
-#   Include class from "filename";
-#   Include client from "filename";
-#   Include jupe from "filename";
-#   Include kill from "filename";
-#   Include linesync from "filename";
-#   Include operator from "filename";
-#   Include quarantine from "filename";
-#   Include uworld from "filename";
-#
-# The linesync option allows UWorld, Jupe, Quarantine, and Kill blocks.
-# If the file includes other blocks, it causes a config syntax error at
-# the Include line.
-#
-# Include client from "clients.conf";
-# Include operator from "opers.conf";
+#   Include uworld, jupe, quarantine, kill from "linesync.conf";
+#   Include operator from "opers.conf";
+#   Include include from "include.conf";
+#
+# The restrictions are transitive across includes.  This means that
+# the last example is not very useful: the only thing include.conf may
+# do is include other include files, and none of them may have any
+# other kind of block!
+#
+# Well-formed but disallowed configuration blocks generate a warning
+# but do not break the file.  The other syntax rules must still be
+# followed, because a syntax error will break the file.
 
 # [features]
 # IRC servers have a large number of options and features.  Most of these
Index: ircu2.10/ircd/ircd_parser.y
diff -u ircu2.10/ircd/ircd_parser.y:1.64 ircu2.10/ircd/ircd_parser.y:1.65
--- ircu2.10/ircd/ircd_parser.y:1.64    Tue Jun 27 04:29:06 2006
+++ ircu2.10/ircd/ircd_parser.y Wed Jun 28 17:52:41 2006
@@ -17,7 +17,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  *  USA.
- * $Id: ircd_parser.y,v 1.64 2006/06/27 11:29:06 entrope Exp $
+ * $Id: ircd_parser.y,v 1.65 2006/06/29 00:52:41 entrope Exp $
  */
 %{
 
@@ -77,13 +77,62 @@
   static struct Privs privs;
   static 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);
+#define parse_error yyserror
+
+enum ConfigBlock
+{
+  BLOCK_ADMIN,
+  BLOCK_CLASS,
+  BLOCK_CLIENT,
+  BLOCK_CONNECT,
+  BLOCK_CRULE,
+  BLOCK_FEATURES,
+  BLOCK_GENERAL,
+  BLOCK_IAUTH,
+  BLOCK_INCLUDE,
+  BLOCK_JUPE,
+  BLOCK_KILL,
+  BLOCK_MOTD,
+  BLOCK_OPER,
+  BLOCK_PORT,
+  BLOCK_PSEUDO,
+  BLOCK_QUARANTINE,
+  BLOCK_UWORLD,
+  BLOCK_LAST_BLOCK
+};
+
+struct ConfigBlocks
+{
+  struct ConfigBlocks *cb_parent;
+  unsigned long cb_allowed;
+  char cb_fname[1];
+};
+
+static struct ConfigBlocks *includes;
+
+static int
+permitted(enum ConfigBlock type, int warn)
+{
+  extern int yylineno;
+  static const char *block_names[BLOCK_LAST_BLOCK] = {
+    "Admin", "Class", "Client", "Connect", "CRule", "Features",
+    "General", "IAuth", "Include", "Jupe", "Kill", "Motd", "Oper",
+    "Port", "Pseudo", "Quarantine", "UWorld",
+  };
+
+  if (!includes)
+    return 1;
+  if (includes->cb_allowed & (1 << type))
+    return 1;
+  if (warn)
+  {
+    /* Unfortunately, flex's yylineno is hosed for included files, so
+     * do not try to use it.
+     */
+    yywarning("Forbidden '%s' block at %s.", block_names[type],
+              includes->cb_fname);
+  }
+  return 0;
 }
 
 %}
@@ -171,6 +220,7 @@
 %type <num> sizespec
 %type <num> timespec timefactor factoredtimes factoredtime
 %type <num> expr yesorno privtype
+%type <num> blocklimit blocktypes blocktype
 %left '+' '-'
 %left '*' '/'
 
@@ -257,20 +307,28 @@
                }
                ;
 
-jupeblock: JUPE '{' jupeitems '}' ';' ;
+jupeblock: JUPE '{' {
+  (void)permitted(BLOCK_JUPE, 1);
+} jupeitems '}' ';' ;
 jupeitems: jupeitem jupeitems | jupeitem;
 jupeitem: jupenick;
 jupenick: NICK '=' QSTRING ';'
 {
-  addNickJupes($3);
-  MyFree($3);
+  if (permitted(BLOCK_JUPE, 0))
+  {
+    addNickJupes($3);
+    MyFree($3);
+  }
 };
 
 generalblock: GENERAL
 {
+  if (permitted(BLOCK_GENERAL, 1))
+  {
     /* Zero out the vhost addresses, in case they were removed. */
     memset(&VirtualHost_v4.addr, 0, sizeof(VirtualHost_v4.addr));
     memset(&VirtualHost_v6.addr, 0, sizeof(VirtualHost_v6.addr));
+  }
 } '{' generalitems '}' ';' {
   if (localConf.name == NULL)
     parse_error("Your General block must contain a name.");
@@ -281,7 +339,9 @@
 generalitem: generalnumeric | generalname | generalvhost | generaldesc;
 generalnumeric: NUMERIC '=' NUMBER ';'
 {
-  if (localConf.numeric == 0)
+  if (!permitted(BLOCK_GENERAL, 0))
+    ;
+  else if (localConf.numeric == 0)
     localConf.numeric = $3;
   else if (localConf.numeric != $3)
     parse_error("Redefinition of server numeric %i (%i)", $3,
@@ -290,9 +350,12 @@
 
 generalname: NAME '=' QSTRING ';'
 {
-  if (localConf.name == NULL)
+  if (!permitted(BLOCK_GENERAL, 0))
+    MyFree($3);
+  else if (localConf.name == NULL)
     localConf.name = $3;
-  else {
+  else
+  {
     if (strcmp(localConf.name, $3))
       parse_error("Redefinition of server name %s (%s)", $3,
                   localConf.name);
@@ -302,15 +365,22 @@
 
 generaldesc: DESCRIPTION '=' QSTRING ';'
 {
-  MyFree(localConf.description);
-  localConf.description = $3;
-  ircd_strncpy(cli_info(&me), $3, REALLEN);
+  if (!permitted(BLOCK_GENERAL, 0))
+    MyFree($3);
+  else
+  {
+    MyFree(localConf.description);
+    localConf.description = $3;
+    ircd_strncpy(cli_info(&me), $3, REALLEN);
+  }
 };
 
 generalvhost: VHOST '=' QSTRING ';'
 {
   struct irc_in_addr addr;
-  if (!strcmp($3, "*")) {
+  if (!permitted(BLOCK_GENERAL, 0))
+    ;
+  else if (!strcmp($3, "*")) {
     /* This traditionally meant bind to all interfaces and connect
      * from the default. */
   } else if (!ircd_aton(&addr, $3))
@@ -324,10 +394,13 @@
 
 adminblock: ADMIN
 {
-  MyFree(localConf.location1);
-  MyFree(localConf.location2);
-  MyFree(localConf.contact);
-  localConf.location1 = localConf.location2 = localConf.contact = NULL;
+  if (permitted(BLOCK_ADMIN, 1))
+  {
+    MyFree(localConf.location1);
+    MyFree(localConf.location2);
+    MyFree(localConf.contact);
+    localConf.location1 = localConf.location2 = localConf.contact = NULL;
+  }
 }
 '{' adminitems '}' ';'
 {
@@ -342,7 +415,9 @@
 adminitem: adminlocation | admincontact;
 adminlocation: LOCATION '=' QSTRING ';'
 {
-  if (localConf.location1 == NULL)
+  if (!permitted(BLOCK_ADMIN, 0))
+    MyFree($3);
+  else if (localConf.location1 == NULL)
     localConf.location1 = $3;
   else if (localConf.location2 == NULL)
     localConf.location2 = $3;
@@ -351,15 +426,22 @@
 };
 admincontact: CONTACT '=' QSTRING ';'
 {
- MyFree(localConf.contact);
- localConf.contact = $3;
+  if (!permitted(BLOCK_ADMIN, 0))
+    MyFree($3);
+  else
+  {
+    MyFree(localConf.contact);
+    localConf.contact = $3;
+  }
 };
 
 classblock: CLASS {
   tping = 90;
 } '{' classitems '}' ';'
 {
-  if (name != NULL)
+  if (!permitted(BLOCK_CLASS, 1))
+    ;
+  else if (name != NULL)
   {
     struct ConnectionClass *c_class;
     add_class(name, tping, tconn, maxlinks, sendq);
@@ -417,7 +499,9 @@
 } '{' connectitems '}' ';'
 {
  struct ConfItem *aconf = NULL;
- if (name == NULL)
+ if (!permitted(BLOCK_CONNECT, 1))
+   ;
+ else if (name == NULL)
   parse_error("Missing name in connect block");
  else if (pass == NULL)
   parse_error("Missing password in connect block");
@@ -507,18 +591,23 @@
 connectauto: AUTOCONNECT '=' YES ';' { flags |= CONF_AUTOCONNECT; }
  | AUTOCONNECT '=' NO ';' { flags &= ~CONF_AUTOCONNECT; };
 
-uworldblock: UWORLD '{' uworlditems '}' ';';
+uworldblock: UWORLD '{' {
+  (void)permitted(BLOCK_UWORLD, 1);
+}  uworlditems '}' ';';
 uworlditems: uworlditem uworlditems | uworlditem;
 uworlditem: uworldname;
 uworldname: NAME '=' QSTRING ';'
 {
-  make_conf(CONF_UWORLD)->host = $3;
+  if (permitted(BLOCK_UWORLD, 0))
+    make_conf(CONF_UWORLD)->host = $3;
 };
 
 operblock: OPER '{' operitems '}' ';'
 {
   struct ConfItem *aconf = NULL;
-  if (name == NULL)
+  if (!permitted(BLOCK_OPER, 1))
+    ;
+  else if (name == NULL)
     parse_error("Missing name in operator block");
   else if (pass == NULL)
     parse_error("Missing password in operator block");
@@ -629,7 +718,9 @@
 /* The port block... */
 portblock: PORT '{' portitems '}' ';'
 {
-  if (port > 0 && port <= 0xFFFF)
+  if (!permitted(BLOCK_PORT, 1))
+    ;
+  else if (port > 0 && port <= 0xFFFF)
     add_listener(port, host, pass, tconn, tping);
   else
     parse_error("Port %d is out of range", port);
@@ -684,7 +775,9 @@
   struct irc_in_addr addr;
   unsigned char addrbits = 0;
 
-  if (!c_class)
+  if (!permitted(BLOCK_CLIENT, 1))
+    ;
+  else if (!c_class)
     parse_error("Invalid or missing class in Client block");
   else if (ip && !ipmask_parse(ip, &addr, &addrbits))
     parse_error("Invalid IP address %s in Client block", ip);
@@ -776,7 +869,16 @@
   dconf = (struct DenyConf*) MyCalloc(1, sizeof(*dconf));
 } '{' killitems '}' ';'
 {
-  if (dconf->usermask || dconf->hostmask ||dconf->realmask) {
+  if (!permitted(BLOCK_KILL, 1))
+  {
+    MyFree(dconf->usermask);
+    MyFree(dconf->hostmask);
+    MyFree(dconf->realmask);
+    MyFree(dconf->message);
+    MyFree(dconf);
+  }
+  else if (dconf->usermask || dconf->hostmask ||dconf->realmask)
+  {
     dconf->next = denyConfList;
     denyConfList = dconf;
   }
@@ -844,7 +946,9 @@
 } '{' cruleitems '}' ';'
 {
   struct CRuleNode *node = NULL;
-  if (host == NULL)
+  if (!permitted(BLOCK_CRULE, 1))
+    ;
+  else if (host == NULL)
     parse_error("Missing host in crule block");
   else if (pass == NULL)
     parse_error("Missing rule in crule block");
@@ -895,7 +999,7 @@
 
 motdblock: MOTD '{' motditems '}' ';'
 {
-  if (host != NULL && pass != NULL)
+  if (permitted(BLOCK_MOTD, 1) && host != NULL && pass != NULL)
     motd_add(host, pass);
   MyFree(host);
   MyFree(pass);
@@ -914,7 +1018,9 @@
   pass = $3;
 };
 
-featuresblock: FEATURES '{' featureitems '}' ';';
+featuresblock: FEATURES '{' {
+  (void)permitted(BLOCK_FEATURES, 1);
+} featureitems '}' ';';
 featureitems: featureitems featureitem | featureitem;
 
 featureitem: QSTRING
@@ -923,7 +1029,8 @@
   stringno = 1;
 } '=' stringlist ';' {
   unsigned int ii;
-  feature_set(NULL, (const char * const *)stringlist, stringno);
+  if (permitted(BLOCK_FEATURES, 0))
+    feature_set(NULL, (const char * const *)stringlist, stringno);
   for (ii = 0; ii < stringno; ++ii)
     MyFree(stringlist[ii]);
 };
@@ -937,15 +1044,25 @@
     MyFree($1);
 };
 
-quarantineblock: QUARANTINE '{' quarantineitems '}' ';';
+quarantineblock: QUARANTINE '{' {
+  (void)permitted(BLOCK_QUARANTINE, 1);
+} quarantineitems '}' ';';
 quarantineitems: quarantineitems quarantineitem | quarantineitem;
 quarantineitem: QSTRING '=' QSTRING ';'
 {
-  struct qline *qconf = MyCalloc(1, sizeof(*qconf));
-  qconf->chname = $1;
-  qconf->reason = $3;
-  qconf->next = GlobalQuarantineList;
-  GlobalQuarantineList = qconf;
+  if (!permitted(BLOCK_QUARANTINE, 0))
+  {
+    MyFree($1);
+    MyFree($3);
+  }
+  else
+  {
+    struct qline *qconf = MyCalloc(1, sizeof(*qconf));
+    qconf->chname = $1;
+    qconf->reason = $3;
+    qconf->next = GlobalQuarantineList;
+    GlobalQuarantineList = qconf;
+  }
 };
 
 pseudoblock: PSEUDO QSTRING '{'
@@ -957,7 +1074,9 @@
 {
   int valid = 0;
 
-  if (!smap->name)
+  if (!permitted(BLOCK_PSEUDO, 1))
+    ;
+  else if (!smap->name)
     parse_error("Missing name in pseudo %s block", smap->command);
   else if (!smap->services)
     parse_error("Missing nick in pseudo %s block", smap->command);
@@ -1008,7 +1127,8 @@
 
 iauthblock: IAUTH '{' iauthitems '}' ';'
 {
-  auth_spawn(stringno, stringlist);
+  if (permitted(BLOCK_IAUTH, 1))
+    auth_spawn(stringno, stringlist);
   while (stringno > 0)
     MyFree(stringlist[stringno--]);
 };
@@ -1021,45 +1141,49 @@
     MyFree(stringlist[stringno--]);
 } stringlist ';';
 
-includeblock: INCLUDE QSTRING ';' { lexer_include($2); } blocks TEOF;
+includeblock: INCLUDE blocklimit QSTRING ';' {
+  struct ConfigBlocks *child;
 
-/* These limitations are truly a pain, but making the allowed blocks a
- * function of a list after the INCLUDE means context dependency and
- * making a build-time list of combinations, each one either a token
- * emitted by the lexer (2**N token types, one state each) or a list
- * of token permutations (O(N!) states) -- neither of which is a happy
- * place for the generated parser.
- */
+  child = MyCalloc(1, sizeof(*child) + strlen($3));
+  strcpy(child->cb_fname, $3);
+  child->cb_allowed = $2 & (includes ? includes->cb_allowed : ~0);
+  child->cb_parent = includes;
+  MyFree($3);
+
+  if (permitted(BLOCK_INCLUDE, 1))
+    lexer_include(child->cb_fname);
+  else
+    lexer_include(NULL);
 
-includeblock: INCLUDE LINESYNC FROM QSTRING ';' { lexer_include($4); } 
linesyncblocks2 TEOF;
-linesyncblocks2: linesyncblocks | error;
-linesyncblocks: linesyncblocks linesyncblock | ;
-linesyncblock: uworldblock | jupeblock | quarantineblock | killblock;
-
-includeblock: INCLUDE CLASS FROM QSTRING ';' { lexer_include($4); } 
classblocks2 TEOF;
-classblocks2: classblocks | error;
-classblocks: classblocks classblock | ;
-
-includeblock: INCLUDE UWORLD FROM QSTRING ';' { lexer_include($4); } 
uworldblocks2 TEOF;
-uworldblocks2: uworldblocks | error;
-uworldblocks: uworldblocks uworldblock | ;
-
-includeblock: INCLUDE OPER FROM QSTRING ';' { lexer_include($4); } operblocks2 
TEOF;
-operblocks2: operblocks | error;
-operblocks: operblocks operblock | ;
-
-includeblock: INCLUDE JUPE FROM QSTRING ';' { lexer_include($4); } jupeblocks2 
TEOF;
-jupeblocks2: jupeblocks | error;
-jupeblocks: jupeblocks jupeblock | ;
-
-includeblock: INCLUDE CLIENT FROM QSTRING ';' { lexer_include($4); } 
clientblocks2 TEOF;
-clientblocks2: clientblocks | error;
-clientblocks: clientblocks clientblock | ;
-
-includeblock: INCLUDE KILL FROM QSTRING ';' { lexer_include($4); } killblocks2 
TEOF;
-killblocks2: killblocks | error;
-killblocks: killblocks killblock | ;
-
-includeblock: INCLUDE QUARANTINE FROM QSTRING ';' { lexer_include($4); } 
quarantineblocks2 TEOF;
-quarantineblocks2: quarantineblocks | error;
-quarantineblocks: quarantineblocks quarantineblock | ;
+  includes = child;
+} blocks TEOF {
+  struct ConfigBlocks *parent;
+
+  parent = includes->cb_parent;
+  MyFree(includes);
+  includes = parent;
+};
+
+blocklimit: { $$ = ~0; } ;
+blocklimit: blocktypes FROM;
+blocktypes: blocktypes ',' blocktype { $$ = $1 | $3; };
+blocktypes: blocktype;
+blocktype: ALL { $$ = ~0; }
+  | ADMIN { $$ = 1 << BLOCK_ADMIN; }
+  | CLASS { $$ = 1 << BLOCK_CLASS; }
+  | CLIENT { $$ = 1 << BLOCK_CLIENT; }
+  | CONNECT { $$ = 1 << BLOCK_CONNECT; }
+  | CRULE { $$ = 1 << BLOCK_CRULE; }
+  | FEATURES { $$ = 1 << BLOCK_FEATURES; }
+  | GENERAL { $$ = 1 << BLOCK_GENERAL; }
+  | IAUTH { $$ = 1 << BLOCK_IAUTH; }
+  | INCLUDE { $$ = 1 << BLOCK_INCLUDE; }
+  | JUPE { $$ = 1 << BLOCK_JUPE; }
+  | KILL { $$ = 1 << BLOCK_KILL; }
+  | MOTD { $$ = 1 << BLOCK_MOTD; }
+  | OPER { $$ = 1 << BLOCK_OPER; }
+  | PORT { $$ = 1 << BLOCK_PORT; }
+  | PSEUDO { $$ = 1 << BLOCK_PSEUDO; }
+  | QUARANTINE { $$ = 1 << BLOCK_QUARANTINE; }
+  | UWORLD { $$ = 1 << BLOCK_UWORLD; }
+  ;
----------------------- End of diff -----------------------
_______________________________________________
Patches mailing list
[email protected]
http://undernet.sbg.org/mailman/listinfo/patches

Reply via email to