Author: Andrew Miller
authorAndrew Miller <a1kmm@amxl.com>
Fri, 5 Apr 2002 11:36:59 +0000 (11:36 +0000)
committerAndrew Miller <a1kmm@amxl.com>
Fri, 5 Apr 2002 11:36:59 +0000 (11:36 +0000)
Log message:
- Allowed specification of the priviledge flags in the config file.
- Fixed a bug in the parser so rehash now works properly.

To do:
- Add documentation to example.conf for the new options.
- Sort out features they still don't seem to work properly.

git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@715 c9e4aea6-c8fd-4c43-8297-357d70d61c8c

ChangeLog
include/client.h
include/s_conf.h
ircd/client.c
ircd/ircd_lexer.l
ircd/ircd_parser.y
ircd/m_oper.c
ircd/s_conf.c
ircd/s_user.c

index 0ab716dfd85c569d031a10aed7cdf8878f991aa6..067ba7d10b844cab9142c23519362b5bed47a9b9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2002-04-05 Andrew Miller <a1kmm@mware.virtualave.net>
+       * ircd/s_conf.c, ircd_parser.y, ircd_lexer.l: Add privilege
+       specification.
+        * Fix a minor parser bug that meant rehash didn't always
+       work correctly.
+
 2002-04-03  Alex Badea  <vampire@p16.pub.ro>
 
        * include/channel.h: fix compiler warnings (paratheses around &&)
index ffbaf548d3ee04062c09b1a9279c26983e7171f2..3522c40ee3efb7f0cb8bbc45a87f878bfff7dbe5 100644 (file)
@@ -515,7 +515,7 @@ extern int client_get_ping(const struct Client* local_client);
 extern void client_drop_sendq(struct Connection* con);
 extern void client_add_sendq(struct Connection* con,
                             struct Connection** con_p);
-extern void client_set_privs(struct Client* client);
+extern void client_set_privs(struct Client *client, struct ConfItem *oper);
 extern int client_report_privs(struct Client* to, struct Client* client);
 
 #endif /* INCLUDED_client_h */
index 6a89ab9142a64386fcc331229190ef1b05594dfb..14f6df61f1afed936393b36f5a7f6a9f8a06d639 100644 (file)
@@ -17,6 +17,7 @@
 #include <netinet/in.h>        /* struct in_addr */
 #define INCLUDED_netinet_in_h
 #endif
+#include "client.h"
 
 struct Client;
 struct SLink;
@@ -50,19 +51,21 @@ struct TRecord;
  * Structures
  */
 
-struct ConfItem {
-  struct ConfItem*         next;
-  unsigned int             status;      /* If CONF_ILLEGAL, delete when no clients */
-  unsigned int             clients;     /* Number of *LOCAL* clients using this */
-  struct ConnectionClass*  conn_class;  /* Class of connection */
-  struct in_addr           ipnum;       /* ip number of host field */
-  char*                    host;
-  char*                    passwd;
-  char*                    name;
-  time_t                   hold;        /* Hold until this time (calendar time) */
-  int                      dns_pending; /* a dns request is pending */
-  unsigned short           port;
-  char                            bits;        /* Number of bits for ipkills */
+struct ConfItem
+{
+  struct ConfItem *next;
+  unsigned int status;      /* If CONF_ILLEGAL, delete when no clients */
+  unsigned int clients;     /* Number of *LOCAL* clients using this */
+  struct ConnectionClass *conn_class;  /* Class of connection */
+  struct in_addr ipnum;       /* ip number of host field */
+  char *host;
+  char *passwd;
+  char *name;
+  time_t hold; /* Hold until this time (calendar time) */
+  int dns_pending; /* a dns request is pending */
+  unsigned short port;
+  unsigned char bits; /* Number of bits for ipkills. */
+  struct Privs privs; /* Priviledges for opers. */
 };
 
 struct ServerConf {
@@ -190,6 +193,8 @@ extern int find_kill(struct Client *cptr);
 extern int find_restrict(struct Client *cptr);
 extern struct MotdItem* read_motd(const char* motdfile);
 
+extern void set_initial_oper_privs(struct ConfItem *oper, int flags);
+
 extern void yyerror(const char *msg);
 
 #endif /* INCLUDED_s_conf_h */
index c313d78c9b8a8f8a367e47600424086cb525f861..fc4dd9c7ee0bbdc836ce95d04144e8cb402ed8f0 100644 (file)
@@ -101,121 +101,121 @@ void client_add_sendq(struct Connection* con, struct Connection** con_p)
   }
 }
 
-static struct {
+static struct
+{
   unsigned int priv;
   enum Feature feat;
   unsigned int flag;
-} feattab[] = {
-  { PRIV_WHOX, FEAT_LAST_F, (FLAGS_OPER | FLAGS_LOCOP) },
-  { PRIV_DISPLAY, FEAT_LAST_F, (FLAGS_OPER | FLAGS_LOCOP) },
-  { PRIV_CHAN_LIMIT, FEAT_OPER_NO_CHAN_LIMIT, (FLAGS_OPER | FLAGS_LOCOP) },
-  { PRIV_MODE_LCHAN, FEAT_OPER_MODE_LCHAN, (FLAGS_OPER | FLAGS_LOCOP) },
-  { PRIV_LOCAL_OPMODE, FEAT_OPER_MODE_LCHAN, (FLAGS_OPER | FLAGS_LOCOP) },
-  { PRIV_WALK_LCHAN, FEAT_OPER_WALK_THROUGH_LMODES,
-    (FLAGS_OPER | FLAGS_LOCOP) },
-  { PRIV_DEOP_LCHAN, FEAT_NO_OPER_DEOP_LCHAN, (FLAGS_OPER | FLAGS_LOCOP) },
-  { PRIV_SHOW_INVIS, FEAT_SHOW_INVISIBLE_USERS, (FLAGS_OPER | FLAGS_LOCOP) },
-  { PRIV_SHOW_ALL_INVIS, FEAT_SHOW_ALL_INVISIBLE_USERS,
-    (FLAGS_OPER | FLAGS_LOCOP) },
-  { PRIV_UNLIMIT_QUERY, FEAT_UNLIMIT_OPER_QUERY, (FLAGS_OPER | FLAGS_LOCOP) },
-  { PRIV_LIST_CHAN, FEAT_LIST_CHAN, (FLAGS_OPER | FLAGS_LOCOP) },
-
-  { PRIV_KILL, FEAT_LOCAL_KILL_ONLY, 0 },
-  { PRIV_GLINE, FEAT_CONFIG_OPERCMDS, ~0 },
-  { PRIV_JUPE, FEAT_CONFIG_OPERCMDS, ~0 },
-  { PRIV_OPMODE, FEAT_CONFIG_OPERCMDS, ~0 },
-  { PRIV_BADCHAN, FEAT_CONFIG_OPERCMDS, ~0 },
-
-  { PRIV_PROPAGATE, FEAT_LAST_F, FLAGS_OPER },
-  { PRIV_SEE_OPERS, FEAT_LAST_F, FLAGS_OPER },
-  { PRIV_KILL, FEAT_OPER_KILL, FLAGS_OPER },
-  { PRIV_LOCAL_KILL, FEAT_OPER_KILL, FLAGS_OPER },
-  { PRIV_REHASH, FEAT_OPER_REHASH, FLAGS_OPER },
-  { PRIV_RESTART, FEAT_OPER_RESTART, FLAGS_OPER },
-  { PRIV_DIE, FEAT_OPER_DIE, FLAGS_OPER },
-  { PRIV_GLINE, FEAT_OPER_GLINE, FLAGS_OPER },
-  { PRIV_LOCAL_GLINE, FEAT_OPER_LGLINE, FLAGS_OPER },
-  { PRIV_JUPE, FEAT_OPER_JUPE, FLAGS_OPER },
-  { PRIV_LOCAL_JUPE, FEAT_OPER_LJUPE, FLAGS_OPER },
-  { PRIV_OPMODE, FEAT_OPER_OPMODE, FLAGS_OPER },
-  { PRIV_LOCAL_OPMODE, FEAT_OPER_LOPMODE, FLAGS_OPER },
-  { PRIV_BADCHAN, FEAT_OPER_BADCHAN, FLAGS_OPER },
-  { PRIV_LOCAL_BADCHAN, FEAT_OPER_LBADCHAN, FLAGS_OPER },
-  { PRIV_SET, FEAT_OPER_SET, FLAGS_OPER },
-  { PRIV_SEE_CHAN, FEAT_OPERS_SEE_IN_SECRET_CHANNELS, FLAGS_OPER },
-  { PRIV_WIDE_GLINE, FEAT_OPER_WIDE_GLINE, FLAGS_OPER },
-  { PRIV_LIST_CHAN, FEAT_OPER_LIST_CHAN, FLAGS_OPER },
+} feattab[] =
+  {
+    { PRIV_WHOX, FEAT_LAST_F, (FLAGS_OPER | FLAGS_LOCOP) },
+    { PRIV_DISPLAY, FEAT_LAST_F, (FLAGS_OPER | FLAGS_LOCOP) },
+    { PRIV_CHAN_LIMIT, FEAT_OPER_NO_CHAN_LIMIT, (FLAGS_OPER | FLAGS_LOCOP) },
+    { PRIV_MODE_LCHAN, FEAT_OPER_MODE_LCHAN, (FLAGS_OPER | FLAGS_LOCOP) },
+    { PRIV_LOCAL_OPMODE, FEAT_OPER_MODE_LCHAN, (FLAGS_OPER | FLAGS_LOCOP) },
+    { PRIV_WALK_LCHAN, FEAT_OPER_WALK_THROUGH_LMODES,
+      (FLAGS_OPER | FLAGS_LOCOP) },
+    { PRIV_DEOP_LCHAN, FEAT_NO_OPER_DEOP_LCHAN, (FLAGS_OPER | FLAGS_LOCOP) },
+    { PRIV_SHOW_INVIS, FEAT_SHOW_INVISIBLE_USERS, (FLAGS_OPER | FLAGS_LOCOP) },
+    { PRIV_SHOW_ALL_INVIS, FEAT_SHOW_ALL_INVISIBLE_USERS,
+      (FLAGS_OPER | FLAGS_LOCOP) },
+    { PRIV_UNLIMIT_QUERY, FEAT_UNLIMIT_OPER_QUERY,
+      (FLAGS_OPER | FLAGS_LOCOP) },
+    { PRIV_LIST_CHAN, FEAT_LIST_CHAN, (FLAGS_OPER | FLAGS_LOCOP) },
+    { PRIV_KILL, FEAT_LOCAL_KILL_ONLY, 0 },
+    { PRIV_GLINE, FEAT_CONFIG_OPERCMDS, ~0 },
+    { PRIV_JUPE, FEAT_CONFIG_OPERCMDS, ~0 },
+    { PRIV_OPMODE, FEAT_CONFIG_OPERCMDS, ~0 },
+    { PRIV_BADCHAN, FEAT_CONFIG_OPERCMDS, ~0 },
+    { PRIV_PROPAGATE, FEAT_LAST_F, FLAGS_OPER },
+    { PRIV_SEE_OPERS, FEAT_LAST_F, FLAGS_OPER },
+    { PRIV_KILL, FEAT_OPER_KILL, FLAGS_OPER },
+    { PRIV_LOCAL_KILL, FEAT_OPER_KILL, FLAGS_OPER },
+    { PRIV_REHASH, FEAT_OPER_REHASH, FLAGS_OPER },
+    { PRIV_RESTART, FEAT_OPER_RESTART, FLAGS_OPER },
+    { PRIV_DIE, FEAT_OPER_DIE, FLAGS_OPER },
+    { PRIV_GLINE, FEAT_OPER_GLINE, FLAGS_OPER },
+    { PRIV_LOCAL_GLINE, FEAT_OPER_LGLINE, FLAGS_OPER },
+    { PRIV_JUPE, FEAT_OPER_JUPE, FLAGS_OPER },
+    { PRIV_LOCAL_JUPE, FEAT_OPER_LJUPE, FLAGS_OPER },
+    { PRIV_OPMODE, FEAT_OPER_OPMODE, FLAGS_OPER },
+    { PRIV_LOCAL_OPMODE, FEAT_OPER_LOPMODE, FLAGS_OPER },
+    { PRIV_BADCHAN, FEAT_OPER_BADCHAN, FLAGS_OPER },
+    { PRIV_LOCAL_BADCHAN, FEAT_OPER_LBADCHAN, FLAGS_OPER },
+    { PRIV_SET, FEAT_OPER_SET, FLAGS_OPER },
+    { PRIV_SEE_CHAN, FEAT_OPERS_SEE_IN_SECRET_CHANNELS, FLAGS_OPER },
+    { PRIV_WIDE_GLINE, FEAT_OPER_WIDE_GLINE, FLAGS_OPER },
+    { PRIV_LIST_CHAN, FEAT_OPER_LIST_CHAN, FLAGS_OPER },
+    { PRIV_LOCAL_KILL, FEAT_LOCOP_KILL, FLAGS_LOCOP },
+    { PRIV_REHASH, FEAT_LOCOP_REHASH, FLAGS_LOCOP },
+    { PRIV_RESTART, FEAT_LOCOP_RESTART, FLAGS_LOCOP },
+    { PRIV_DIE, FEAT_LOCOP_DIE, FLAGS_LOCOP },
+    { PRIV_LOCAL_GLINE, FEAT_LOCOP_LGLINE, FLAGS_LOCOP },
+    { PRIV_LOCAL_JUPE, FEAT_LOCOP_LJUPE, FLAGS_LOCOP },
+    { PRIV_LOCAL_OPMODE, FEAT_LOCOP_LOPMODE, FLAGS_LOCOP },
+    { PRIV_LOCAL_BADCHAN, FEAT_LOCOP_LBADCHAN, FLAGS_LOCOP },
+    { PRIV_SET, FEAT_LOCOP_SET, FLAGS_LOCOP },
+    { PRIV_SEE_CHAN, FEAT_LOCOP_SEE_IN_SECRET_CHANNELS, FLAGS_LOCOP },
+    { PRIV_WIDE_GLINE, FEAT_LOCOP_WIDE_GLINE, FLAGS_LOCOP },
+    { PRIV_LIST_CHAN, FEAT_LOCOP_LIST_CHAN, FLAGS_LOCOP },
+    { 0, FEAT_LAST_F, 0 }
+  };
 
-  { PRIV_LOCAL_KILL, FEAT_LOCOP_KILL, FLAGS_LOCOP },
-  { PRIV_REHASH, FEAT_LOCOP_REHASH, FLAGS_LOCOP },
-  { PRIV_RESTART, FEAT_LOCOP_RESTART, FLAGS_LOCOP },
-  { PRIV_DIE, FEAT_LOCOP_DIE, FLAGS_LOCOP },
-  { PRIV_LOCAL_GLINE, FEAT_LOCOP_LGLINE, FLAGS_LOCOP },
-  { PRIV_LOCAL_JUPE, FEAT_LOCOP_LJUPE, FLAGS_LOCOP },
-  { PRIV_LOCAL_OPMODE, FEAT_LOCOP_LOPMODE, FLAGS_LOCOP },
-  { PRIV_LOCAL_BADCHAN, FEAT_LOCOP_LBADCHAN, FLAGS_LOCOP },
-  { PRIV_SET, FEAT_LOCOP_SET, FLAGS_LOCOP },
-  { PRIV_SEE_CHAN, FEAT_LOCOP_SEE_IN_SECRET_CHANNELS, FLAGS_LOCOP },
-  { PRIV_WIDE_GLINE, FEAT_LOCOP_WIDE_GLINE, FLAGS_LOCOP },
-  { PRIV_LIST_CHAN, FEAT_LOCOP_LIST_CHAN, FLAGS_LOCOP },
-  { 0, FEAT_LAST_F, 0 }
-};
+void
+set_initial_oper_privs(struct ConfItem *oper, int flags)
+{
+  int i;
+  memset(&oper->privs, 0, sizeof(oper->privs));
+  for (i = 0; feattab[i].priv; i++)
+    if ((feattab[i].flag | flags) != 0 && feattab[i].flag != ~0)
+      PrivSet(&oper->privs, feattab[i].priv);
+}
 
 /* client_set_privs(struct Client* client)
  *
  * Sets the privileges for opers.
  */
 void
-client_set_privs(struct Client* client)
+client_set_privs(struct Client *client, struct ConfItem *oper)
 {
-  struct Privs privs;
-  struct Privs antiprivs;
   int i;
 
-  memset(&privs, 0, sizeof(struct Privs));
-  memset(&antiprivs, 0, sizeof(struct Privs));
+  memset(&(cli_privs(client)), 0, sizeof(struct Privs));
 
-  if (!IsAnOper(client)) { /* clear privilege mask */
-    memset(&(cli_privs(client)), 0, sizeof(struct Privs));
+  if (!IsAnOper(client))
     return;
-  } else if (!MyConnect(client)) {
+  else if (!MyConnect(client))
+  {
     memset(&(cli_privs(client)), 255, sizeof(struct Privs));
     PrivClr(&(cli_privs(client)), PRIV_SET);
     return;
   }
+  else if (oper == NULL)
+    return;
 
-  /* This sequence is temporary until the .conf is carefully rewritten */
+  /* Copy across privs from the config. */
+  cli_privs(client) = oper->privs;
 
-  for (i = 0; feattab[i].priv; i++) {
-    if (feattab[i].flag == 0) {
-      if (feature_bool(feattab[i].feat))
-       PrivSet(&antiprivs, feattab[i].priv);
-    } else if (feattab[i].flag == ~0) {
-      if (!feature_bool(feattab[i].feat))
-       PrivSet(&antiprivs, feattab[i].priv);
-    } else if (cli_flags(client) & feattab[i].flag) {
-      if (feattab[i].feat == FEAT_LAST_F ||
-         feature_bool(feattab[i].feat))
-       PrivSet(&privs, feattab[i].priv);
-    }
-  }
+  /* Remove privileges disallowed by features... */
+  for (i = 0; feattab[i].priv; i++)
+    if (feattab[i].flag == 0 && feature_bool(feattab[i].feat))      
+      PrivClr(&cli_privs(client), feattab[i].priv);
+    else if (feattab[i].flag == ~0 && !feature_bool(feattab[i].feat))
+      PrivClr(&cli_privs(client), feattab[i].priv);
 
-  /* This is the end of the gross section */
-
-  if (PrivHas(&privs, PRIV_PROPAGATE))
-    PrivSet(&privs, PRIV_DISPLAY); /* force propagating opers to display */
-  else { /* if they don't propagate oper status, prevent desyncs */
-    PrivSet(&antiprivs, PRIV_KILL);
-    PrivSet(&antiprivs, PRIV_GLINE);
-    PrivSet(&antiprivs, PRIV_JUPE);
-    PrivSet(&antiprivs, PRIV_OPMODE);
-    PrivSet(&antiprivs, PRIV_BADCHAN);
+  /* This should be handled in the config, but lets be sure... */
+  if (PrivHas(&cli_privs(client), PRIV_PROPAGATE))
+    /* force propagating opers to display */
+    PrivSet(&cli_privs(client), PRIV_DISPLAY);
+  else
+  {
+    /* if they don't propagate oper status, prevent desyncs */
+    PrivClr(&cli_privs(client), PRIV_KILL);
+    PrivClr(&cli_privs(client), PRIV_GLINE);
+    PrivClr(&cli_privs(client), PRIV_JUPE);
+    PrivClr(&cli_privs(client), PRIV_OPMODE);
+    PrivClr(&cli_privs(client), PRIV_BADCHAN);
   }
-
-  for (i = 0; i <= _PRIV_IDX(PRIV_LAST_PRIV); i++)
-    privs.priv_mask[i] &= ~antiprivs.priv_mask[i];
-
-  cli_privs(client) = privs;
 }
 
 static struct {
index ea9ccb89b70cdb3ee73125fec3bb60e48165eca5..f3d893b34e83f35cab0b67a611b1a2ae8fcf1d80 100644 (file)
  */
 
 %{
-extern int conf_fd, lineno;
 #include <unistd.h>
+#include <stdio.h>
+#include "ircd.h"
 #include "y.tab.h"
-#undef YY_INPUT
-/* Just stop the lexer at EOF or error. */
-#define YY_INPUT(buf,result,max_size) \
-          if ((result = read(conf_fd, buf, max_size)) <= 0) \
-            result = 0;
+
+extern int lineno;
+
+void
+init_lexer(void)
+{
+  yyin = fopen(configfile, "r");
+  if (yyin == NULL)
+    yy_fatal_error("Could not open the configuration file.");
+  YY_NEW_FILE;
+  lineno = 1;
+}
+
 %}
 %option noyywrap
 %option case-insensitive
 %option nounput
 
+
 WHITE [ \t\r]+
 SHCOMMENT #[^\n]*
 NUMBER [0-9]+
@@ -111,5 +121,31 @@ ip return IP;
 crule return CRULE;
 kill return KILL;
 features return FEATURES;
+bypass_local_channel_limits return TPRIV_CHAN_LIMIT;
+set_local_channel_modes return TPRIV_MODE_LCHAN;
+protected_local_channel return TPRIV_DEOP_LCHAN;
+bypass_join_local_channels return TPRIV_WALK_LCHAN;
+global_kill return TPRIV_KILL;
+local_kill return TPRIV_LOCAL_KILL;
+rehash return TPRIV_REHASH;
+restart return TPRIV_RESTART;
+die return TPRIV_DIE;
+gline return TPRIV_GLINE;
+local_gline return TPRIV_LOCAL_GLINE;
+jupe_server return TPRIV_JUPE;
+local_jupe_server return TPRIV_LOCAL_JUPE;
+hack_channel_modes return TPRIV_OPMODE;
+change_settings return TPRIV_SET;
+extended_who_information return TPRIV_WHOX;
+gline_channels return TPRIV_BADCHAN;
+local_gline_channels return TPRIV_LOCAL_BADCHAN;
+see_private_channels return TPRIV_SEE_CHAN;
+see_invisible_users return TPRIV_SHOW_INVIS;
+list_all_invisible_users return TPRIV_SHOW_ALL_INVIS;
+globally_opered return TPRIV_PROPAGATE;
+unlimited_who_queries return TPRIV_UNLIMIT_QUERY;
+oper_status_display return TPRIV_DISPLAY;
+see_other_opers return TPRIV_SEE_OPERS;
+wide_glines return TPRIV_WIDE_GLINE;
 \n lineno++;
 . return yytext[0];
index d49ab339b3bb0fdfcce753fc3933274f6d9ffb50..81a15fe4f478649c0c5264db20b3852e6d5145a4 100644 (file)
 %token ALL
 %token IP
 %token FEATURES
+/* 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
+/* and some types... */
 %type <num> sizespec
 %type <num> timespec, timefactor, factoredtimes, factoredtime
-%type <num> expr
+%type <num> expr, yesorno, privtype
 %left '+' '-'
 %left '*' '/'
 
@@ -459,24 +468,27 @@ operblock: OPER
   aconf = MyMalloc(sizeof(*aconf));
   memset(aconf, 0, sizeof(*aconf));
   aconf->status = CONF_OPERATOR;
+  set_initial_oper_privs(aconf, (FLAGS_OPER | FLAGS_LOCOP));
 } '{' operitems '}' ';'
 {
   if (aconf->name != NULL && aconf->passwd != NULL && aconf->host != NULL)
   {
-   aconf->next = GlobalConfList;
-   GlobalConfList = aconf;
+    log_write(LS_CONFIG, L_ERROR, 0, "added an oper block for host %s", aconf->host);
+    aconf->next = GlobalConfList;
+    GlobalConfList = aconf;
   }
   else
   {
-   MyFree(aconf->name);
-   MyFree(aconf->passwd);
-   MyFree(aconf->host);
-   MyFree(aconf);
-   aconf = NULL;
+    log_write(LS_CONFIG, L_ERROR, 0, "operator blocks need a name, password, and host.");
+    MyFree(aconf->name);
+    MyFree(aconf->passwd);
+    MyFree(aconf->host);
+    MyFree(aconf);
+    aconf = NULL;
   }
 };
 operitems: operitem | operitems operitem;
-operitem: opername | operpass | operlocal | operhost | operclass;
+operitem: opername | operpass | operlocal | operhost | operclass | operpriv;
 
 opername: NAME '=' QSTRING ';'
 {
@@ -496,8 +508,12 @@ operlocal: LOCAL '=' YES ';'
    * permission values here. But for now, I am just going with local 
    * opers... */
   aconf->status = CONF_LOCOP;
+  /* XXX blow away existing priviledges. */
+  set_initial_oper_privs(aconf, FLAGS_LOCOP);
 } | LOCAL '=' NO ';'
 {
+  /* XXX blow away existing priviledges. */
+  set_initial_oper_privs(aconf, (FLAGS_OPER|FLAGS_LOCOP));
   aconf->status = CONF_OPERATOR;
 };
 
@@ -520,6 +536,44 @@ operclass: CLASS '=' QSTRING ';'
  aconf->conn_class = find_class(yylval.text);
 };
 
+operpriv: privtype '=' yesorno ';'
+{
+  if ($3 == 1)
+    PrivSet(&aconf->privs, $1);
+  else
+    PrivClr(&aconf->privs, $1);
+};
+
+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; } |
+          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; } |
+          TPRIV_LOCAL_JUPE { $$ = PRIV_LOCAL_JUPE; } |
+          TPRIV_LOCAL_OPMODE { $$ = PRIV_LOCAL_OPMODE; } |
+          TPRIV_OPMODE { $$ = PRIV_OPMODE; }|
+          TPRIV_SET { $$ = PRIV_SET; } |
+          TPRIV_WHOX { $$ = PRIV_WHOX; } |
+          TPRIV_BADCHAN { $$ = PRIV_BADCHAN; } |
+          TPRIV_LOCAL_BADCHAN { $$ = TPRIV_LOCAL_BADCHAN; } |
+          TPRIV_SEE_CHAN { $$ = PRIV_SEE_CHAN; } |
+          TPRIV_SHOW_INVIS { $$ = PRIV_SHOW_INVIS; } |
+          TPRIV_SHOW_ALL_INVIS { $$ = PRIV_SHOW_ALL_INVIS; } |
+          TPRIV_PROPAGATE { $$ = PRIV_PROPAGATE; } |
+          TPRIV_UNLIMIT_QUERY { $$ = PRIV_UNLIMIT_QUERY; } |
+          TPRIV_DISPLAY { $$ = PRIV_DISPLAY; } |
+          TPRIV_SEE_OPERS { $$ = PRIV_SEE_OPERS; } |
+          TPRIV_WIDE_GLINE { $$ = PRIV_WIDE_GLINE; };
+
+yesorno: YES { $$ = 1; } | NO { $$ = 0; };
+
 /* The port block... */
 portblock: PORT {
   port = 0;
@@ -797,7 +851,8 @@ featureitem: QSTRING
 stringlist: QSTRING
 {
   stringlist[0] = $1;
-  stringno = 1;
+  stringlist[1] = $1;
+  stringno = 2;
 } posextrastrings
 {
   feature_set(NULL, (const char * const *)stringlist, stringno);
index 767b52da0ac0f6810f42092bb767c37f7167facb..1166840c5e77ae41993503721a51f6d59d7662c8 100644 (file)
@@ -179,7 +179,7 @@ int m_oper(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
     cli_flags(sptr) |= (FLAGS_WALLOP | FLAGS_SERVNOTICE | FLAGS_DEBUG);
 
     set_snomask(sptr, SNO_OPERDEFAULT, SNO_ADD);
-    client_set_privs(sptr);
+    client_set_privs(sptr, aconf);
     cli_max_sendq(sptr) = 0; /* Get the sendq from the oper's class */
     send_umode_out(cptr, sptr, old_mode, HasPriv(sptr, PRIV_PROPAGATE));
     send_reply(sptr, RPL_YOUREOPER);
index d1677b1abb44d330302af9f78036db268a602d3f..21fa6aca7c8e904a09928dc23f973bbc3d2d0e1d 100644 (file)
@@ -63,6 +63,7 @@
 #include <string.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <stdio.h>
 
 #ifndef INADDR_NONE
 #define INADDR_NONE 0xffffffff
@@ -932,301 +933,17 @@ const struct DenyConf* conf_get_deny_list(void)
 
 #define MAXCONFLINKS 150
 
+extern FILE *yyin;
+void init_lexer(void);
+
 int read_configuration_file(void)
 {
   feature_unmark(); /* unmark all features for resetting later */
   /* Now just open an fd. The buffering isn't really needed... */
-  if ((conf_fd = open(configfile, O_RDONLY)) < 0)
-   return 0;
-  lineno = 1;
+  init_lexer();
   yyparse();
-  close(conf_fd);
-#if 0
-  while (fbgets(line, sizeof(line) - 1, file)) {
-    if ('#' == *line || IsSpace(*line))
-      continue;
-
-    if ((src = strchr(line, '\n')))
-      *src = '\0';
-    
-    if (':' != line[1]) {
-      Debug((DEBUG_ERROR, "Bad config line: %s", line));
-      sendto_opmask_butone(0, SNO_OLDSNO,"Bad Config line");
-      continue;
-    }
-
-    /*
-     * do escapes, quoting, comments, and field breakup in place
-     * in one pass with a poor mans state machine
-     */
-    field_vector[0] = line;
-    field_count = 1;
-    quoted = 0;
-
-    for (src = line, dest = line; *src; ) {
-      switch (*src) {
-      case '\\':
-        ++src;
-        switch (*src) {
-        case 'b':
-          *dest++ = '\b';
-          ++src;
-          break;
-        case 'f':
-          *dest++ = '\f';
-          ++src;
-          break;
-        case 'n':
-          *dest++ = '\n';
-          ++src;
-          break;
-        case 'r':
-          *dest++ = '\r';      
-          ++src;
-          break;
-        case 't':
-          *dest++ = '\t';
-          ++src;
-          break;
-        case 'v':
-          *dest++ = '\v';
-          ++src;
-          break;
-        case '\\':
-          *dest++ = '\\';
-          ++src;
-          break;
-        case '\0':
-          break;
-        default:
-          *dest++ = *src++;
-          break;
-        }
-        break;
-      case '"':
-        if (quoted)
-          quoted = 0;
-        else
-          quoted = 1;
-        /*
-         * strip quotes
-         */
-        ++src;
-        break;
-      case ':':
-        if (quoted)
-          *dest++ = *src++;
-        else {
-          *dest++ = '\0';
-          field_vector[field_count++] = dest;
-          if (field_count > MAX_FIELDS)
-            *src = '\0';
-          else  
-            ++src;
-        }
-        break;
-      case '#':
-        *src = '\0';
-        break;
-      default:
-        *dest++ = *src++;
-        break;
-      }
-    }
-    *dest = '\0';
-
-    if (field_count < 2 || EmptyString(field_vector[0]))
-      continue;
-
-    if (aconf)
-      free_conf(aconf);
-
-    aconf = make_conf();
-
-    switch (*field_vector[0]) {
-    case 'A':                /* Name, e-mail address of administrator */
-    case 'a':                /* of this server. CONF_ADMIN */
-      conf_add_admin(field_vector, field_count);
-      aconf->status = CONF_ILLEGAL;
-      break;
-    case 'C':                /* Server where I should try to connect */
-    case 'c':                /* in case of lp failures             */
-      ++ccount;
-      aconf->status = CONF_SERVER;
-      break;
-      /* Connect rule */
-    case 'D':  /* CONF_CRULEALL */
-      conf_add_crule(field_vector, field_count, CRULE_ALL);
-      aconf->status = CONF_ILLEGAL;
-      break;
-      /* Connect rule - autos only */
-    case 'd':  /* CONF_CRULEAUTO */
-      conf_add_crule(field_vector, field_count, CRULE_AUTO);
-      aconf->status = CONF_ILLEGAL;
-      break;
-    case 'F':                /* Feature line */
-    case 'f':
-      feature_set(0, &field_vector[1], field_count - 1);
-      aconf->status = CONF_ILLEGAL;
-      break;
-    case 'H':                /* Hub server line */
-    case 'h':
-      aconf->status = CONF_HUB;
-      break;
-    case 'I':                /* Just plain normal irc client trying  */
-    case 'i':                /* to connect me */
-      aconf->status = CONF_CLIENT;
-      break;
-    case 'K':                /* Kill user line on irc.conf           */
-      conf_add_deny(field_vector, field_count, 0);
-      aconf->status = CONF_ILLEGAL;
-      break;
-    case 'k':                /* Kill user line based on IP in ircd.conf */
-      conf_add_deny(field_vector, field_count, 1);
-      aconf->status = CONF_ILLEGAL;
-      break;
-      /* Operator. Line should contain at least */
-      /* password and host where connection is  */
-    case 'L':                /* guaranteed leaf server */
-    case 'l':
-      aconf->status = CONF_LEAF;
-      break;
-      /* Me. Host field is name used for this host */
-      /* and port number is the number of the port */
-    case 'M':
-    case 'm':        /* CONF_ME */
-      conf_add_local(field_vector, field_count);
-      aconf->status = CONF_ILLEGAL;
-      break;
-    case 'O':
-      aconf->status = CONF_OPERATOR;
-      break;
-      /* Local Operator, (limited privs --SRB) */
-    case 'o':
-      aconf->status = CONF_LOCOP;
-      break;
-    case 'P':                /* listen port line */
-    case 'p':        /* CONF_LISTEN_PORT */
-      conf_add_listener(field_vector, field_count);
-      aconf->status = CONF_ILLEGAL;
-      break;
-    case 'T':                /* print out different motd's */
-    case 't':                /* based on hostmask - CONF_TLINES */
-      motd_add(field_vector[1], field_vector[2]);
-      aconf->status = CONF_ILLEGAL;
-      break;
-    case 'U':      /* Underworld server, allowed to hack modes */
-    case 'u':      /* *Every* server on the net must define the same !!! */
-      aconf->status = CONF_UWORLD;
-      break;
-    case 'Y':
-    case 'y':      /* CONF_CLASS */
-      conf_add_class(field_vector, field_count);
-      aconf->status = CONF_ILLEGAL;
-      break;
-    default:
-      Debug((DEBUG_ERROR, "Error in config file: %s", line));
-      sendto_opmask_butone(0, SNO_OLDSNO, "Unknown prefix in config file: %c",
-                          *field_vector[0]);
-      aconf->status = CONF_ILLEGAL;
-      break;
-    }
-    if (IsIllegal(aconf))
-      continue;
-
-    if (!EmptyString(field_vector[1]))
-      DupString(aconf->host, field_vector[1]);
-
-    if (!EmptyString(field_vector[2]))
-      DupString(aconf->passwd, field_vector[2]);
-
-    if (field_count > 3 && !EmptyString(field_vector[3]))
-        DupString(aconf->name, field_vector[3]);
-
-    if (field_count > 4 && !EmptyString(field_vector[4]))
-        aconf->port = atoi(field_vector[4]); 
-
-    if (field_count > 5 && !EmptyString(field_vector[5]))
-      aconf->conn_class = find_class(atoi(field_vector[5]));
-
-    /*
-     * Associate each conf line with a class by using a pointer
-     * to the correct class record. -avalon
-     */
-    if (aconf->status & CONF_CLIENT_MASK) {
-      if (aconf->conn_class == 0)
-        aconf->conn_class = find_class(0);
-    }
-    if (aconf->status & CONF_CLIENT) {
-      struct ConfItem *bconf;
-
-      if ((bconf = find_conf_entry(aconf, aconf->status))) {
-        delist_conf(bconf);
-        bconf->status &= ~CONF_ILLEGAL;
-        if (aconf->status == CONF_CLIENT) {
-          /*
-           * copy the password field in case it changed
-           */
-          MyFree(bconf->passwd);
-          bconf->passwd = aconf->passwd;
-          aconf->passwd = 0;
-
-          ConfLinks(bconf) -= bconf->clients;
-          bconf->conn_class = aconf->conn_class;
-          if (bconf->conn_class)
-            ConfLinks(bconf) += bconf->clients;
-        }
-        free_conf(aconf);
-        aconf = bconf;
-      }
-    }
-    if (aconf->status & CONF_SERVER) {
-      if (ccount > MAXCONFLINKS || !aconf->host || strchr(aconf->host, '*') ||
-          strchr(aconf->host, '?') || !aconf->name)
-        continue;
-    }
-    if (aconf->status & (CONF_LOCOP | CONF_OPERATOR)) {
-      if (!strchr(aconf->host, '@')) {
-        char* newhost;
-        int len = 3;                /* *@\0 = 3 */
-
-        len += strlen(aconf->host);
-        newhost = (char*) MyMalloc(len);
-        assert(0 != newhost);
-        ircd_snprintf(0, newhost, len, "*@%s", aconf->host);
-        MyFree(aconf->host);
-        aconf->host = newhost;
-      }
-    }
-    if (aconf->status & CONF_SERVER) {
-      if (EmptyString(aconf->passwd))
-        continue;
-      lookup_confhost(aconf);
-    }
-    /*
-     * Juped nicks are listed in the 'password' field of U:lines,
-     * the list is comma separated and might be empty and/or contain
-     * empty elements... the only limit is that it MUST be shorter
-     * than 512 chars, or they will be cutted out :)
-     */
-    if ((aconf->status == CONF_UWORLD) && (aconf->passwd) && (*aconf->passwd))
-      addNickJupes(aconf->passwd);
-
-    collapse(aconf->host);
-    collapse(aconf->name);
-    Debug((DEBUG_NOTICE,
-        "Read Init: (%d) (%s) (%s) (%s) (%u) (%p)",
-        aconf->status, aconf->host, aconf->passwd,
-        aconf->name, aconf->port, aconf->conn_class));
-    aconf->next = GlobalConfList;
-    GlobalConfList = aconf;
-    aconf = NULL;
-  }
-  if (aconf)
-    free_conf(aconf);
-  fbclose(file);
-/*    nextping = nextconnect = CurrentTime; */
-#endif
+  fclose(yyin);
+  yyin = NULL;
   feature_mark(); /* reset unmarked features */
   return 1;
 }
index 467bea6a370ce4045b8984160a4383472af205c9..52d55a85108fb50d284c85600f9b3d41faa1165a 100644 (file)
@@ -690,7 +690,7 @@ int set_nick_name(struct Client* cptr, struct Client* sptr,
         }
       }
     }
-    client_set_privs(new_client); /* set privs on user */
+    client_set_privs(new_client, NULL); /* set privs on user */
     /*
      * Set new nick name.
      */
@@ -1299,13 +1299,13 @@ int set_user_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv
    */
   if (!(setflags & FLAGS_OPER) && IsOper(sptr)) { /* user now oper */
     ++UserStats.opers;
-    client_set_privs(sptr); /* may set propagate privilege */
+    client_set_privs(sptr, NULL);
   }
   if (HasPriv(sptr, PRIV_PROPAGATE)) /* remember propagate privilege setting */
     prop = 1;
   if ((setflags & FLAGS_OPER) && !IsOper(sptr)) { /* user no longer oper */
     --UserStats.opers;
-    client_set_privs(sptr); /* will clear propagate privilege */
+    client_set_privs(sptr, NULL); /* will clear propagate privilege */
   }
   if ((setflags & FLAGS_INVISIBLE) && !IsInvisible(sptr))
     --UserStats.inv_clients;