Răsfoiți Sursa

Merge branch 'bantype'

* bantype:
  * Cleanup code to avoid constness problems/compile errors
  * Use the channel ban-type for +k/kickban/misc bans in channels
  * cmd_adduser and msd_ident now add hosts with ban-type 0 (*!user@host.com)
  * Add chanint 'ban-type' with a default of 3
  * Bring over bantype patch from eggdrop submitted patch
Bryan Drewery 16 ani în urmă
părinte
comite
fb9772e1c8

+ 1 - 0
doc/UPDATES

@@ -60,6 +60,7 @@
   * Fix cmd_slowjoin not working on backup bots correctly.
   * Fix a crash from long hubnicks.
 * Misc changes
+  * Add new channel setting 'ban-type' which support mIRC style ban types (adapted from recent eggdrop patch)
   * EFnet server list updates (To update yours: .set -YES servers - | .set -YES servers6 -)
   * Give localhubs credit for adding their child bots in 'whois'.
   * Ident lookup timeout is now 5 seconds (will speed up linking / partyline connecting)

+ 17 - 0
doc/help.txt

@@ -380,6 +380,23 @@ See also: link
         $bban-time$b          Set here how long temporary bans will last (in
                           minutes). If you set this setting to 0, the bot will
                           never remove them. (This also requires +dynamicbans)
+        $bban-type$b
+                              This setting defines what type of bans should be
+                          placed. Available types are:
+                              0 *!user@host
+                              1 *!*user@host
+                              2 *!*@host
+                              3 *!*user@*.host
+                              4 *!*@*.host
+                              5 nick!user@host
+                              6 nick!*user@host
+                              7 nick!*@host
+                              8 nick!*user@*.host
+                              9 nick!*@*.host
+                          You can also specify types from 10 to 19 which correspond
+                          to types 0 to 9, with the exception that numbers in hostnames
+                          are replaced with the '?' wildcard, or 20 to 29, which works
+                          like 10 to 19 but using '*' for numbers, instead of '?'.
         $bexempt-time$b       Set here how long temporary exempts will last (in
                           minutes). If you set this setting to 0, the bot will
                           never remove them. The bot will check the exempts

+ 1 - 0
src/chan.h

@@ -176,6 +176,7 @@ struct chanset_t {
   int mdop;
   int mop;
   int voice_non_ident;
+  int ban_type;
   interval_t auto_delay;
   int knock_flags;
 /* Chanint template 

+ 112 - 88
src/misc.c

@@ -207,102 +207,126 @@ char *newsplit(char **rest, char delim, bool trim)
   return r;
 }
 
-/* Convert "abc!user@a.b.host" into "*!user@*.b.host"
- * or "abc!user@1.2.3.4" into "*!user@1.2.3.*"
- * or "abc!user@0:0:0:0:0:ffff:1.2.3.4" into "*!user@0:0:0:0:0:ffff:1.2.3.*"
- * or "abc!user@3ffe:604:2:b02e:6174:7265:6964:6573" into
- *    "*!user@3ffe:604:2:b02e:6174:7265:6964:*"
+/* maskhost(), modified to support custom mask types, as defined
+ * by mIRC.
+ * Does not require a proper hostmask in 's'. Accepts any strings,
+ * including empty ones and attempts to provide meaningful results.
+ *
+ * Strings containing no '@' character will be parsed as if the
+ * whole string is a host.
+ * Strings containing no '!' character will be interpreted as if
+ * there is no nick.
+ * '!' as a nick/user separator must precede any '@' characters.
+ * Otherwise it will be considered a part of the host.
+ * Supported types are listed in tcl-commands.doc in the maskhost
+ * command section. Type 3 resembles the older maskhost() most closely.
+ *
+ * Specific examples (with type=3):
+ *
+ * "nick!user@is.the.lamest.bg"  -> *!*user@*.the.lamest.bg (ccTLD)
+ * "nick!user@is.the.lamest.com" -> *!*user@*.lamest.com (gTLD)
+ * "lamest.example"              -> *!*@lamest.example
+ * "whatever@lamest.example"     -> *!*whatever@lamest.example
+ * "com.example@user!nick"       -> *!*com.example@user!nick
+ * "!"                           -> *!*@!
+ * "@"                           -> *!*@*
+ * ""                            -> *!*@*
+ * "abc!user@2001:db8:618:5c0:263:15:dead:babe"
+ * -> *!*user@2001:db8:618:5c0:263:15:dead:*
+ * "abc!user@0:0:0:0:0:ffff:1.2.3.4"
+ * -> *!*user@0:0:0:0:0:ffff:1.2.3.*
  */
-void maskhost(const char *s, char *nw)
+void maskaddr(const char *s, char *nw, int type)
 {
-  register const char *p, *q, *e, *f;
-  int i;
+  int d = type % 5, num = 1;
+  register const char *u = NULL, *h = NULL, *p = NULL;
+
+  /* Look for user and host.. */
+  if ((u = strchr(s, '!')))
+    h = strchr(u, '@');
+
+  if (!h)
+    h = strchr(s, '@');
 
-  *nw++ = '*';
+  /* Print nick if required and available */
+  if (!u || (type % 10) < 5)
+    *nw++ = '*';
+  else {
+    strncpy(nw, s, u - s);
+    nw += u - s;
+  }
   *nw++ = '!';
-  p = (q = strchr(s, '!')) ? q + 1 : s;
-  /* Strip of any nick, if a username is found, use last 8 chars */
-  if ((q = strchr(p, '@'))) {
-    int fl = 0;
-
-    if ((q - p) > 9) {
-      nw[0] = '*';
-      p = q - 7;
-      i = 1;
-    } else
-      i = 0;
-    while (*p != '@') {
-      if (!fl && strchr("~+-^=", *p))
-       nw[i] = '?';
-      else
-        nw[i] = *p;
-      fl++;
-      p++;
-      i++;
+
+  /* Write user if required and available */
+  u = (u ? u + 1 : s);
+  if (!h || (d == 2) || (d == 4))
+    *nw++ = '*';
+  else {
+    if (d) {
+      *nw++ = '*';
+      if (strchr("~+-^=", *u))
+        u++; /* trim leading crap */
     }
-    nw[i++] = '@';
-    q++;
-  } else {
-    nw[0] = '*';
-    nw[1] = '@';
-    i = 2;
-    q = s;
+    strncpy(nw, u, h - u);
+    nw += h - u;
   }
-  nw += i;
-  e = NULL;
-  /* Now q points to the hostname, i point to where to put the mask */
-  if ((!(p = strchr(q, '.')) || !(e = strchr(p + 1, '.'))) && !strchr(q, ':'))
-    /* TLD or 2 part host */
-    strcpy(nw, q);
-  else {
-    if (e == NULL) {		/* IPv6 address?		*/
-      const char *mask_str;
-
-      f = strrchr(q, ':');
-      if (strchr(f, '.')) {	/* IPv4 wrapped in an IPv6?	*/
-	f = strrchr(f, '.');
-	mask_str = ".*";
-      } else 			/* ... no, true IPv6.		*/
-	mask_str = ":*";
-      strncpy(nw, q, f - q);
-      /* No need to nw[f-q] = 0 here, as the strcpy below will
-       * terminate the string for us.
-       */
-      nw += (f - q);
-      strcpy(nw, mask_str);
-    } else {
-      for (f = e; *f; f++)
-        ;
-      f--;
-      if (*f >= '0' && *f <= '9') {	/* Numeric IP address */
-	while (*f != '.')
-	  f--;
-	strncpy(nw, q, f - q);
-	/* No need to nw[f-q] = 0 here, as the strcpy below will
-	 * terminate the string for us.
-	 */
-	nw += (f - q);
-	strcpy(nw, ".*");
-      } else {				/* Normal host >= 3 parts */
-	/*    a.b.c  -> *.b.c
-	 *    a.b.c.d ->  *.b.c.d if tld is a country (2 chars)
-	 *             OR   *.c.d if tld is com/edu/etc (3 chars)
-	 *    a.b.c.d.e -> *.c.d.e   etc
-	 */
-	const char *x = strchr(e + 1, '.');
-
-	if (!x)
-	  x = p;
-	else if (strchr(x + 1, '.'))
-	  x = e;
-	else if (strlen(x) == 3)
-	  x = p;
-	else
-	  x = e;
-	simple_sprintf(nw, "*%s", x);
+  *nw++ = '@';
+
+  /* The rest is for the host */
+  h = (h ? h + 1 : s);
+  for (p = h; *p; p++) /* hostname? */
+    if ((*p > '9' || *p < '0') && *p != '.') {
+      num = 0;
+      break;
+    }
+  p = strrchr(h, ':'); /* IPv6? */
+  /* Mask out after the last colon/dot */
+  if (p && d > 2) {
+    if ((u = strrchr(p, '.')))
+      p = u;
+    strncpy(nw, h, ++p - h);
+    nw += p - h;
+    strcpy(nw, "*");
+  } else if (!p && !num && type >= 10) {
+      /* we have a hostname and type
+       requires us to replace numbers */
+    num = 0;
+    for (p = h; *p; p++) {
+      if (*p < '0' || *p > '9') {
+        *nw++ = *p;
+        num = 0;
+      } else {
+        if (type < 20)
+          *nw++ = '?';
+        else if (!num) {
+          *nw++ = '*';
+          num = 1; /* place only one '*'
+                      per numeric sequence */
+        }
       }
     }
-  }
+    *nw = 0;
+  } else if (d > 2 && (p = strrchr(h, '.'))) {
+    if (num) { /* IPv4 */
+      strncpy(nw, h, p - h);
+      nw += p - h;
+      strcpy(nw, ".*");
+      return;
+    }
+    for (u = h, d = 0; (u = strchr(++u, '.')); d++) ;
+    if (d < 2) { /* types < 2 don't mask the host */
+      strcpy(nw, h);
+      return;
+    }
+    u = strchr(h, '.');
+    if (d > 3 || (d == 3 && strlen(p) > 3))
+      u = strchr(++u, '.'); /* ccTLD or not? Look above. */
+    simple_sprintf(nw, "*%s", u);
+  } else if (!*h) {
+    /* take care if the mask is empty or contains only '@' */
+    strcpy(nw, "*");
+  } else
+    strcpy(nw, h);
 }
 
 

+ 3 - 1
src/misc.h

@@ -28,7 +28,9 @@ int bot_aggressive_to(struct userrec *);
 void readsocks(const char *);
 int updatebin(int, char *, int);
 size_t my_strcpy(char *, const char *);
-void maskhost(const char *, char *);
+void maskaddr(const char *, char *, int);
+#define maskhost(a,b) maskaddr((a),(b),3)
+#define maskban(a,b)  maskaddr((a),(b),3)
 char *stristr(char *, char *);
 void splitc(char *, char *, char);
 void splitcn(char *, char *, char, size_t);

+ 1 - 0
src/mod/channels.mod/cmdschan.c

@@ -1276,6 +1276,7 @@ static void cmd_chaninfo(int idx, char *par)
     SHOW_INT("Auto-delay: ", chan->auto_delay, NULL, "None");
     SHOW_INT("Bad-cookie:" , chan->bad_cookie, P_STR, "Ignore");
     SHOW_INT("Ban-time: ", chan->ban_time, NULL, "Forever");
+    SHOW_INT("Ban-type: ", chan->ban_type, NULL, "3");
     SHOW_INT("Closed-ban: ", chan->closed_ban, NULL, "Don't!");
     SHOW_INT("Closed-invite:", chan->closed_invite, NULL, "Don't!");
     SHOW_INT("Closed-Private:", chan->closed_private, NULL, "Don't!");

+ 9 - 0
src/mod/channels.mod/tclchan.c

@@ -536,6 +536,14 @@ int channel_modify(char *result, struct chanset_t *chan, int items, char **item,
         return ERROR;
       }
       chan->auto_delay = atoi(item[i]);
+    } else if (!strcmp(item[i], "ban-type")) {
+      i++;
+      if (i >= items) {
+        if (result)
+          strlcpy(result, "channel ban-type needs argument", RESULT_LEN);
+        return ERROR;
+      }
+      chan->ban_type = atoi(item[i]);
      
 
 /* Chanint template
@@ -946,6 +954,7 @@ int channel_add(char *result, char *newname, char *options)
     chan->closed_invite = 1;
     chan->voice_non_ident = 1;
     chan->auto_delay = 5;
+    chan->ban_type = 3;
 /* Chanint template
  *  chan->temp = 0;
  */

+ 2 - 1
src/mod/channels.mod/userchan.c

@@ -726,7 +726,7 @@ void write_chans(bd::Stream& stream, int idx)
 
     stream << buf.printf("\
 + channel add %s { chanmode { %s } addedby %s addedts %li \
-bad-cookie %d manop %d mdop %d mop %d limit %d \
+bad-cookie %d manop %d mdop %d mop %d limit %d ban-type %d \
 flood-chan %d:%d flood-ctcp %d:%d flood-join %d:%d \
 flood-kick %d:%d flood-deop %d:%d flood-nick %d:%d flood-mjoin %d:%d \
 closed-ban %d closed-invite %d closed-private %d ban-time %d \
@@ -749,6 +749,7 @@ flood-exempt %d flood-lock-time %d knock %d \
 	chan->mdop,
 	chan->mop,
         chan->limitraise,
+        chan->ban_type,
 	chan->flood_pub_thr, chan->flood_pub_time,
         chan->flood_ctcp_thr, chan->flood_ctcp_time,
         chan->flood_join_thr, chan->flood_join_time,

+ 1 - 1
src/mod/irc.mod/chan.c

@@ -741,7 +741,7 @@ static char *quickban(struct chanset_t *chan, char *uhost)
 {
   static char s1[512] = "";
 
-  maskhost(uhost, s1);
+  maskaddr(uhost, s1, chan->ban_type);
   /* this used to only happen with strict_host == 0 */
   if (strlen(s1) != 1)
     s1[2] = '*';		/* arthur2 */

+ 1 - 1
src/mod/irc.mod/cmdsirc.c

@@ -1778,7 +1778,7 @@ static void cmd_adduser(int idx, char *par)
     return;
   }
   if (!statichost)
-    maskhost(s, s1);
+    maskaddr(s, s1, 0); /* *!user@host.com */
   else {
     strlcpy(s1, s, sizeof s1);
     p1 = strchr(s1, '!');

+ 1 - 1
src/mod/irc.mod/msgcmds.c

@@ -216,7 +216,7 @@ static int msg_ident(char *nick, char *host, struct userrec *u, char *par)
     } else {
       putlog(LOG_CMDS, "*", "(%s!%s) !*! IDENT %s", nick, host, who);
       simple_snprintf(s, sizeof s, "%s!%s", nick, host);
-      maskhost(s, s1);
+      maskaddr(s, s1, 0); /* *!user@host */
       dprintf(DP_HELP, "NOTICE %s :Added hostmask: %s\n", nick, s1);
       addhost_by_handle(who, s1);
       check_this_user(who, 0, NULL);

+ 1 - 1
src/set.c

@@ -40,7 +40,7 @@ int dcc_autoaway;
 bool irc_autoaway;
 bool link_cleartext;
 bool dccauth = 0;
-char *def_chanset = "+enforcebans +dynamicbans +userbans -bitch +cycle -inactive +userexempts -dynamicexempts +userinvites -dynamicinvites -nodesynch -closed -take -voice -private -fastop +meankicks";
+char *def_chanset = "+enforcebans +dynamicbans +userbans -bitch +cycle -inactive +userexempts -dynamicexempts +userinvites -dynamicinvites -nodesynch -closed -take -voice -private -fastop +meankicks ban-type 3";
 int cloak_script = 0;
 rate_t close_threshold;
 int fight_threshold;