]> jfr.im git - irc/quakenet/newserv.git/commitdiff
Add ban overlapping detection logic to permban and tempban.
authorChris Porter <redacted>
Sat, 8 Mar 2008 16:43:28 +0000 (16:43 +0000)
committerChris Porter <redacted>
Sat, 8 Mar 2008 16:43:28 +0000 (16:43 +0000)
chanserv/chancmds/commandlist.c
chanserv/chancmds/permban.c
chanserv/chancmds/tempban.c
chanserv/chanserv.h
chanserv/chanservdb_updates.c
chanserv/database/chanservdb_messages.c

index 598893e6906562b39a2951b0e699fe0eb35a0aae..6533871899ac40d2aa99797ee1fca7018319b84f 100644 (file)
@@ -64,7 +64,7 @@ void _init() {
   chanservaddcommand("giveowner", QCMD_AUTHED, 3, csc_dogiveowner, "Gives total control over a channel to another user.", "Usage: GIVEOWNER <channel> <user> [<code>]\nGives complete control (+n flag) to the named user on the channel.  The new owner\nwill have full control over the channel, including the ability to remove the\nexisting owner(s).  As a precaution the named user must already have master (+m) \naccess on the channel.  Use this command with extreme caution.  Where:\nchannel - channel to use\nuser    - user to give owner to, either a nickname on the network or #accountname.\ncode    - a unique code used to authorize the operation.  If the code is not \n          supplied, the appropriate code will be provided together with a \n          warning about the dangers of this command.  If the wrong code is\n          entered owner access will not be granted.\nGIVEOWNER requires owner (+n) access on the named channel.\n");
   chanservaddcommand("invite", QCMD_AUTHED, 1, csc_doinvite, "Invites you to a channel.", "Usage: INVITE <channel>\nInvites you to the named channel, where:\nchannel - channel to be invited to.\nINVITE requires you to be known (+k) on the named channel.\n");
   chanservaddcommand("op", QCMD_AUTHED, 20, csc_doop, "Ops you or other users on channel(s).", "Usage: OP [<channel> [<user1> [<user2> [...]]]\nOps you on one or more channels, or ops other named users on a given channel.\nThis command cannot be used to op users who are otherwise prevented from getting\nops, e.g. via the +d chanlev flag (see CHANLEV) or bitch mode (see CHANFLAGS).\nWhere:\nchannel - channel to use.  If no channel is specified, you will be given ops on\n          every channel where you have appropriate access and are not already\n          opped.\nuser<n> - user(s) to op instead of yourself.  Each user must be specified as the\n          current nickname of a user on the named channel.\nOP requires operator access (+o) on the named channel.  If this command is used\nto op other users, a notice will be sent to other channel operators on the \nchannel identifying you, unless you have master (+m) access.\n");
-  chanservaddcommand("permban", QCMD_AUTHED, 3, csc_dopermban, "Permanently bans a hostmask on a channel.", "Usage: PERMBAN <channel> <hostmask> [<reason>]\nPermanently bans the provided hostmask on the channel.  If the ban is\nremoved from the channel e.g. by a channel op or the BANTIMER feature, the\nban will be reapplied if a matching user joins the channel.  Bans\nset with the PERMBAN command can be removed via BANCLEAR or BANDEL.  Any users\nmatching the hostmask will be kicked from the channel.\nWhere:\nchannel  - channel to set a ban on\nhostmask - hastmask (nick!user@host) to ban.\nreason   - reason for the ban.  This will be used in kick messages when kicking\n           users matching the ban.  If this is not provided the generic message\n           \"Banned.\" will be used.\nPERMBAN requires master (+m) access on the named channel.\n");
+  chanservaddcommand("permban", QCMD_AUTHED, 3, csc_dopermban, "Permanently bans a hostmask on a channel.", "Usage: PERMBAN <channel> <hostmask> [<reason>]\nPermanently bans the provided hostmask on the channel.  If the ban is\nremoved from the channel e.g. by a channel op or the BANTIMER feature, the\nban will be reapplied if a matching user joins the channel.  Bans\nset with the PERMBAN command can be removed via BANCLEAR or BANDEL.  Any users\nmatching the hostmask will be kicked from the channel.\nWhere:\nchannel  - channel to set a ban on\nhostmask - hostmask (nick!user@host) to ban.\nreason   - reason for the ban.  This will be used in kick messages when kicking\n           users matching the ban.  If this is not provided the generic message\n           \"Banned.\" will be used.\nPERMBAN requires master (+m) access on the named channel.\n");
   chanservaddcommand("recover", QCMD_AUTHED, 1, csc_dorecover, "Recovers a channel (same as deopall, unbanall, clearchan).", "Usage: RECOVER <channel>\nThis command resets the named channel if undesired modes, bans or ops have been\nset.  This has the same effect as DEOPALL followed by UNBANALL followed by\nCLEARCHAN on the channel, where:\nchannel - channel to recover\nRECOVER requires master (+m) access on the named channel.\n");
   chanservaddcommand("rejoin", QCMD_OPER, 1, csc_dorejoin, "Makes the bot rejoin a channel.", "");
   chanservaddcommand("removeuser", QCMD_AUTHED, 20, csc_doremoveuser, "Removes one or more users from a channel.", "Usage: REMOVEUSER <channel> <user1> [<user2> [<user3> [...]]]\nRemoves any flags the named user(s) have on the channel.  This command\ncannot be used to remove owners (+n) from the channel, and cannot be used\nto remove masters (+m) unless the user issuing the command is an owner.\nWhere:\nchannel - channel to use\nuser<n> - a user to remove.  Can either be a nickname on the network\n          or #authname.  Up to 18 users can be specified.\nREMOVEUSER requires master (+m) access on the named channel.\n");
@@ -73,7 +73,7 @@ void _init() {
   chanservaddcommand("settopic", QCMD_AUTHED, 2, csc_dosettopic, "Changes the topic on a channel.", "Usage: SETTOPIC <channel> [<topic>]\nChanges the topic on the channel, where:\nchannel - channel to use\ntopic   - new topic.  If no topic is set, the stored topic will be reset (this\n          feature is useful if some users can no longer see the topic due to a \n          netsplit).\nSETTOPIC requires topic (+t) or master (+m) access on the named channel.\n");
   chanservaddcommand("suspendchan", QCMD_OPER, 2, csc_dosuspendchan, "Suspends a channel from the bot.", "");
   chanservaddcommand("suspendchanlist", QCMD_HELPER, 1, csc_dosuspendchanlist, "Lists suspended channels.", "");
-  chanservaddcommand("tempban", QCMD_AUTHED, 4, csc_dotempban, "Bans a hostmask on a channel for a specified time period.", "Usage: TEMPBAN <channel> <hostmask> <duration> [<reason>]\nTemporarily bans the provided hostmask on the channel.  If the ban is\nremoved from the channel e.g. by a channel op or the BANTIMER feature, the\nban will be reapplied if a matching user joins the channel.  When the time \nexpires the ban will be removed automatically.  Bans set with the PERMBAN \ncommand can be removed via BANCLEAR or BANDEL.  Any users matching the hostmask \nwill be kicked from the channel.\nWhere:\nchannel  - channel to set a ban on\nhostmask - hastmask (nick!user@host) to ban.\nduration - length of time to apply the ban for.  Suffixes m (minutes), h (hours),\n           d (days), w (weeks), M (months) and y (years) can be used to specify \n           the duration, for example 3d, 5h, 1h30m, 1M.\nreason   - reason for the ban.  This will be used in kick messages when kicking\n           users matching the ban.  If this is not provided the generic message\n           \"Banned.\" will be used.\nTEMPBAN requires master (+m) access on the named channel.\n");
+  chanservaddcommand("tempban", QCMD_AUTHED, 4, csc_dotempban, "Bans a hostmask on a channel for a specified time period.", "Usage: TEMPBAN <channel> <hostmask> <duration> [<reason>]\nTemporarily bans the provided hostmask on the channel.  If the ban is\nremoved from the channel e.g. by a channel op or the BANTIMER feature, the\nban will be reapplied if a matching user joins the channel.  When the time \nexpires the ban will be removed automatically.  Bans set with the PERMBAN \ncommand can be removed via BANCLEAR or BANDEL.  Any users matching the hostmask \nwill be kicked from the channel.\nWhere:\nchannel  - channel to set a ban on\nhostmask - hostmask (nick!user@host) to ban.\nduration - length of time to apply the ban for.  Suffixes m (minutes), h (hours),\n           d (days), w (weeks), M (months) and y (years) can be used to specify \n           the duration, for example 3d, 5h, 1h30m, 1M.\nreason   - reason for the ban.  This will be used in kick messages when kicking\n           users matching the ban.  If this is not provided the generic message\n           \"Banned.\" will be used.\nTEMPBAN requires master (+m) access on the named channel.\n");
   chanservaddcommand("unban", QCMD_AUTHED | QCMD_ALIAS, 2, csc_dobandel, "Removes a single ban from a channel.", "");
   chanservaddcommand("unbanall", QCMD_AUTHED, 1, csc_dounbanall, "Removes all bans from a channel.", "Usage: UNBANALL <channel>\nRemoves all the channel bans set on the named channel.  This does not affect\npersistent bans set via the TEMPBAN and PERMBAN commands, see BANCLEAR or\nBANDEL for more information on removing those bans.  Where:\nchannel - channel to use\nUNBANALL requires master (+m) access on the named channel.\n");
   chanservaddcommand("unbanmask", QCMD_AUTHED, 2, csc_dounbanmask, "Removes bans matching a particular mask from a channel.", "Usage: UNBANMASK <channel> <mask>\nRemoves any bans on the channel which are overlapped by the named mask.  Can\nremove both channel bans and registered bans.  Where:\nchannel - channel to use\nmask    - mask to remove.  Any ban subsumed by this mask will be removed.  For\n          example, UNBANMASK *!*@*.isp.net would remove *!*@host1.isp.net and \n          *!*@host2.isp.net and *!user@*.isp.net.\nUNBANMASK requires operator (+o) access on the named channel.\nRemoving registered bans requires master (+m) access on the named channel.\n");
index f85558b23f727d87c3b1cd9ca078bec23b967ed8..fedcf207c6a6f3f84489262a74a9f76db5331523 100644 (file)
@@ -15,7 +15,7 @@
  * CMDHELP: matching the hostmask will be kicked from the channel.
  * CMDHELP: Where:
  * CMDHELP: channel  - channel to set a ban on
- * CMDHELP: hostmask - hastmask (nick!user@host) to ban.
+ * CMDHELP: hostmask - hostmask (nick!user@host) to ban.
  * CMDHELP: reason   - reason for the ban.  This will be used in kick messages when kicking
  * CMDHELP:            users matching the ban.  If this is not provided the generic message
  * CMDHELP:            \"Banned.\" will be used.
 int csc_dopermban(void *source, int cargc, char **cargv) {
   nick *sender=source;
   chanindex *cip;
-  regban *rbp;
+  regban *rbp, *toreplace=NULL;
   regchan *rcp;
   reguser *rup=getreguserfromnick(sender);
+  struct chanban *b;
 
   if (cargc<2) {
     chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "permban");
@@ -50,21 +51,60 @@ int csc_dopermban(void *source, int cargc, char **cargv) {
 
   rcp=cip->exts[chanservext];
 
-  rbp=getregban();
-  rbp->ID=++lastbanID;
-  rbp->cbp=makeban(cargv[1]);
+  b=makeban(cargv[1]);
+
+  for(rbp=rcp->bans;rbp;rbp=rbp->next) {
+    if(banequal(b,rbp->cbp)) { /* if they're equal and one is temporary we just replace it */
+      if(rbp->expiry) {
+        if(toreplace) { /* shouldn't happen */
+          chanservsendmessage(sender, "Internal error, duplicate bans found on banlist.");
+        } else {
+          toreplace=rbp;
+          continue;
+        }
+      } else {
+        chanservstdmessage(sender, QM_PERMBANALREADYSET);
+      }
+    } else if(banoverlap(rbp->cbp,b)) { /* new ban is contained in an already existing one */
+      chanservstdmessage(sender, QM_NEWBANALREADYBANNED, bantostring(rbp->cbp));
+    }else if(banoverlap(b,rbp->cbp)) { /* existing ban is contained in new one */
+      chanservstdmessage(sender, QM_NEWBANOVERLAPS, bantostring(rbp->cbp), cargv[1]);
+    } else {
+      continue;
+    }
+    freechanban(b);
+    return CMD_ERROR;
+  }
+
+  if(toreplace) {
+    freechanban(b);
+    chanservstdmessage(sender, QM_REPLACINGTEMPBAN);
+
+    rbp=toreplace;
+    if(rbp->reason)
+      freesstring(toreplace->reason);
+  } else {
+    rbp=getregban();
+    rbp->ID=++lastbanID;
+    rbp->cbp=b;
+
+    rbp->next=rcp->bans;
+    rcp->bans=rbp;
+  }
+
   rbp->setby=rup->ID;
   rbp->expiry=0;
   if (cargc>2)
     rbp->reason=getsstring(cargv[2],200);
   else
     rbp->reason=NULL;
-  rbp->next=rcp->bans;
-  rcp->bans=rbp;
 
   cs_setregban(cip, rbp);
-  csdb_createban(rcp, rbp);
-  
+  if(toreplace) {
+    csdb_updateban(rcp, rbp);
+  } else {
+    csdb_createban(rcp, rbp);
+  }
   chanservstdmessage(sender, QM_DONE);
   return CMD_OK;
 }
index 0ac86958f1ec9d6a4f03630da476ba7e01e28235..c35a99295bfffdb6a2e57b82a7a719aed8769089 100644 (file)
@@ -16,7 +16,7 @@
  * CMDHELP: will be kicked from the channel.
  * CMDHELP: Where:
  * CMDHELP: channel  - channel to set a ban on
- * CMDHELP: hostmask - hastmask (nick!user@host) to ban.
+ * CMDHELP: hostmask - hostmask (nick!user@host) to ban.
  * CMDHELP: duration - length of time to apply the ban for.  Suffixes m (minutes), h (hours),
  * CMDHELP:            d (days), w (weeks), M (months) and y (years) can be used to specify 
  * CMDHELP:            the duration, for example 3d, 5h, 1h30m, 1M.
@@ -44,6 +44,7 @@ int csc_dotempban(void *source, int cargc, char **cargv) {
   regchan *rcp;
   reguser *rup=getreguserfromnick(sender);
   unsigned int duration;
+  struct chanban *b;
 
   if (cargc<3) {
     chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "tempban");
@@ -61,9 +62,25 @@ int csc_dotempban(void *source, int cargc, char **cargv) {
     return CMD_ERROR;
   }
   
+  b=makeban(cargv[1]);
+  for(rbp=rcp->bans;rbp;rbp=rbp->next) {
+    if(banequal(b,rbp->cbp)) {
+      chanservstdmessage(sender, QM_BANALREADYSET);
+    } else if(banoverlap(rbp->cbp,b)) {
+      chanservstdmessage(sender, QM_NEWBANALREADYBANNED, bantostring(rbp->cbp));
+    } else if(banoverlap(b,rbp->cbp)) {
+      chanservstdmessage(sender, QM_NEWBANOVERLAPS, bantostring(rbp->cbp), cargv[1]);
+    } else {
+      continue;
+    }
+
+    freechanban(b);
+    return CMD_ERROR;
+  }
+  
   rbp=getregban();
   rbp->ID=++lastbanID;
-  rbp->cbp=makeban(cargv[1]);
+  rbp->cbp=b;
   rbp->setby=rup->ID;
   rbp->expiry=time(NULL)+duration;
   if (cargc>3)
index bf7cff89d833cbb34e00f82a2cedfbcb4cd9e7bf..8d0d02069b5f39c11090dbae7ab154ee13836abe 100644 (file)
 #define QM_NOCHALLENGE             145
 #define QM_USEGIVEOWNER            146
 #define QM_NOFLAGSPECIFIED         147
+#define QM_NEWBANALREADYBANNED     148
+#define QM_NEWBANOVERLAPS          149
+#define QM_REPLACINGTEMPBAN        150
+#define QM_PERMBANALREADYSET       151
+#define QM_BANALREADYSET           152
 
 /* List of privileged operations */
 
@@ -831,6 +836,7 @@ void csdb_createuser(reguser *rup);
 void csdb_updateuser(reguser *rup);
 void csdb_createban(regchan *rcp, regban *rbp);
 void csdb_deleteban(regban *rbp);
+void csdb_updateban(regchan *rcp, regban *rbp);
 char *csdb_gethelpstr(char *command, int language);
 void csdb_createmail(reguser *rup, int type);
 void csdb_dohelp(nick *np, Command *cmd);
index 2b49777f5c41591bbfbe5574952bf1dcb7299362..a9ee240a4d611d58dafb01a87c61dbabf3e44ae9 100644 (file)
@@ -313,6 +313,23 @@ void csdb_createban(regchan *rcp, regban *rbp) {
                  rbp->setby, escban, rbp->expiry, escreason);
 }
 
+void csdb_updateban(regchan *rcp, regban *rbp) {
+  char escreason[500];
+  char banstr[100];
+  char escban[200];
+
+  strcpy(banstr,bantostring(rbp->cbp));
+  PQescapeString(escban,banstr,strlen(banstr));
+  
+  if (rbp->reason)
+    PQescapeString(escreason, rbp->reason->content, rbp->reason->length);
+  else
+    escreason[0]='\0';
+
+  pqquery("UPDATE bans set channelID=%u, userID=%u, hostmask='%s', expiry=%lu, reason='%s' "
+                  "WHERE banID=%u", rcp->ID, rbp->setby, escban, rbp->expiry, escreason, rbp->ID);
+}
+
 void csdb_deleteban(regban *rbp) {
   pqquery("DELETE FROM bans WHERE banID=%u", rbp->ID);
 }
index 715ecd419000357720ad6ce1d7e79afeb0deb97f..8f97ba02da30253696aa04389c9118aed6cfd947 100644 (file)
@@ -153,9 +153,14 @@ char *defaultmessages[MAXMESSAGES] = {
   /* 142*/ "Showing %s for last %s.",
   /* 143*/ "Change your nickname to something with none of the following characters: `~^[]{}|_\\",
   /* 144*/ "Invalid digest algorithm.",
-  /* 144*/ "Challenge has either not been requested or has expired.",
-  /* 145*/ "To give the +n flag use GIVEOWNER. Change aborted.",
-  /* 146*/ "You must specify at least one valid flag to add."
+  /* 145*/ "Challenge has either not been requested or has expired.",
+  /* 146*/ "To give the +n flag use GIVEOWNER. Change aborted.",
+  /* 147*/ "You must specify at least one valid flag to add.",
+  /* 148*/ "New ban is already contained within existing ban: %s",
+  /* 149*/ "New ban would replace at least one existing ban (%s), use UNBANMASK %s first if you want to set this ban.",
+  /* 150*/ "A temporary ban with this mask already exists, replacing it.",
+  /* 151*/ "That permanent ban already exists.",
+  /* 152*/ "That ban already exists.",
 };
 
 void initmessages() {