Author: Kev <klmitch@mit.edu>
authorKevin L. Mitchell <klmitch@mit.edu>
Mon, 29 Jan 2001 17:46:31 +0000 (17:46 +0000)
committerKevin L. Mitchell <klmitch@mit.edu>
Mon, 29 Jan 2001 17:46:31 +0000 (17:46 +0000)
Log message:

Fixes for 3 bugs:

1) /mode <nick> -o wasn't propagated; the privileges were being set before
   send_umode_out() could get at them, so the PRIV_PROPAGATE setting went
   away.

2) /mode #channel +b banmask, under certain circumstances, would allow
   multiple bans of the exact same mask to be added to the channel.

3) /mode #channel +b banmask would leak memory if another ban of the exact
   same mask was already present on the channel (and bug #2 wasn't
   triggered).

Testing:

Compiled and ran; unable to duplicate the errors, now.

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

ChangeLog
include/s_user.h
ircd/channel.c
ircd/m_oper.c
ircd/s_user.c

index 88f5d324eaedd0a695fb6bf95e4af50a74c6c70f..6302d7d6ec5fc5472feeea438a0c4fdc5fb0841a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2001-01-29  Kevin L. Mitchell  <klmitch@mit.edu>
+
+       * ircd/channel.c (mode_parse_ban): stopper a tiny leak--if a ban
+       already existed, then the logic would (attempt to) skip it, but
+       would not free the ban string; now the ban string is free'd and
+       the ban count is decremented, releasing the ban for use
+
+       * ircd/s_user.c: make send_umode_out() take a prop argument
+       instead of testing for the PRIV_PROPAGATE privilege itself; fix
+       set_umode() to use this new argument, calculating it before
+       calculating the new privileges for a -o'd user
+
+       * ircd/m_oper.c (m_oper): pass the new prop argument to
+       send_umode_out()
+
+       * ircd/channel.c (mode_parse_ban): turn off MODE_ADD bit in bans
+       that we're not actually going to add because they already exist;
+       test that particular bit before adding to the linked list
+
+       * include/s_user.h: add a prop argument to send_umode_out() to
+       indicate whether or not to propagate the user mode
+
 2001-01-24  Kevin L. Mitchell  <klmitch@mit.edu>
 
        * ircd/msgq.c: ircd_vsnprintf() returns the number of bytes that
index e91de32a7f12adcafc325982b1cf367dba8907e8..c8457add24c2a26ab4986b0cf4f473a0eb701389 100644 (file)
@@ -67,7 +67,8 @@ extern int user_set_away(struct User* user, char* message);
 extern int do_nick_name(char* nick);
 extern int set_nick_name(struct Client* cptr, struct Client* sptr,
                          const char* nick, int parc, char* parv[]);
-extern void send_umode_out(struct Client* cptr, struct Client* sptr, int old);
+extern void send_umode_out(struct Client* cptr, struct Client* sptr, int old,
+                          int prop);
 extern int whisper(struct Client* source, const char* nick,
                    const char* channel, const char* text, int is_notice);
 extern void send_user_info(struct Client* to, char* names, int rpl,
index edb42297baa0546edde0243dbbb946fce6de852d..7ad4534a9b936fa98b8946107dceaf16e97b3d6d 100644 (file)
@@ -2175,16 +2175,18 @@ mode_parse_ban(struct ParseState *state, int *flag_p)
     } else if (state->dir == MODE_ADD) {
       /* if the ban already exists, don't worry about it */
       if (!ircd_strcmp(ban->value.ban.banstr, t_str)) {
+       newban->flags &= ~MODE_ADD; /* don't add ban at all */
+       MyFree(newban->value.ban.banstr); /* stopper a leak */
+       state->numbans--; /* deallocate last ban */
        if (state->done & DONE_BANCLEAN) /* If we're cleaning, finish */
          break;
-       continue;
       } else if (!mmatch(ban->value.ban.banstr, t_str)) {
        if (!(ban->flags & MODE_DEL))
          newban->flags |= CHFL_BAN_OVERLAPPED; /* our ban overlaps */
       } else if (!mmatch(t_str, ban->value.ban.banstr))
        ban->flags |= MODE_DEL; /* mark ban for deletion: overlapping */
 
-      if (!ban->next) {
+      if (!ban->next && (newban->flags & MODE_ADD)) {
        ban->next = newban; /* add our ban with its flags */
        break; /* get out of loop */
       }
index 813e2b3c7c87b0a2626be818e107b3cf518b5647..5bbf215bda1e3e78fd0c8375175171bfdc383d19 100644 (file)
@@ -186,7 +186,7 @@ int m_oper(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 
     set_snomask(sptr, SNO_OPERDEFAULT, SNO_ADD);
     client_set_privs(sptr);
-    send_umode_out(cptr, sptr, old_mode);
+    send_umode_out(cptr, sptr, old_mode, HasPriv(sptr, PRIV_PROPAGATE));
     send_reply(sptr, RPL_YOUREOPER);
 
     sendto_opmask_butone(0, SNO_OLDSNO, "%s (%s@%s) is now operator (%c)",
index 1faaf2a378d059386247d8116b6a7f8257546cc5..b4695ede58b6b27342d0fc91376884920196833d 100644 (file)
@@ -1002,13 +1002,13 @@ int whisper(struct Client* source, const char* nick, const char* channel,
 /*
  * added Sat Jul 25 07:30:42 EST 1992
  */
-void send_umode_out(struct Client *cptr, struct Client *sptr, int old)
+void send_umode_out(struct Client *cptr, struct Client *sptr, int old,
+                   int prop)
 {
   int i;
   struct Client *acptr;
 
-  send_umode(NULL, sptr, old,
-            SEND_UMODES & ~(HasPriv(sptr, PRIV_PROPAGATE) ? 0 : FLAGS_OPER));
+  send_umode(NULL, sptr, old, SEND_UMODES & ~(prop ? 0 : FLAGS_OPER));
 
   for (i = HighestFd; i >= 0; i--) {
     if ((acptr = LocalClientArray[i]) && IsServer(acptr) &&
@@ -1072,6 +1072,7 @@ int set_user_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv
   unsigned int tmpmask = 0;
   int snomask_given = 0;
   char buf[BUFSIZE];
+  int prop = 0;
 
   what = MODE_ADD;
 
@@ -1240,19 +1241,21 @@ int set_user_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv
    * Compare new flags with old flags and send string which
    * will cause servers to update correctly.
    */
-  if ((setflags & FLAGS_OPER) && !IsOper(sptr)) {
-    --UserStats.opers;
-    client_set_privs(sptr);
-  }
-  if (!(setflags & FLAGS_OPER) && IsOper(sptr)) {
+  if (!(setflags & FLAGS_OPER) && IsOper(sptr)) { /* user now oper */
     ++UserStats.opers;
-    client_set_privs(sptr);
+    client_set_privs(sptr); /* may set propagate privilege */
+  }
+  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 */
   }
   if ((setflags & FLAGS_INVISIBLE) && !IsInvisible(sptr))
     --UserStats.inv_clients;
   if (!(setflags & FLAGS_INVISIBLE) && IsInvisible(sptr))
     ++UserStats.inv_clients;
-  send_umode_out(cptr, sptr, setflags);
+  send_umode_out(cptr, sptr, setflags, prop);
 
   return 0;
 }