]> jfr.im git - irc/rqf/shadowircd.git/commitdiff
Add propagated xlines, like klines.
authorJilles Tjoelker <redacted>
Tue, 16 Mar 2010 22:05:50 +0000 (23:05 +0100)
committerJilles Tjoelker <redacted>
Tue, 16 Mar 2010 22:05:50 +0000 (23:05 +0100)
doc/reference.conf
help/opers/stats
include/s_conf.h
modules/core/m_ban.c
modules/m_kline.c
modules/m_xline.c
src/s_conf.c

index 33f4a55b42296046b6138ba0c5f69eae4760238e..c46ffa8ed6d848c08b8ae25c80e37e885aa717eb 100755 (executable)
@@ -1198,10 +1198,10 @@ general {
         */
        warn_no_nline = yes;
 
-       /* use propagated bans: KLINE sets fully propagated bans. That means
-        * the klines are part of the netburst and restarted/split servers
-        * will get them, but they will not apply to 3.2 and older servers
-        * at all.
+       /* use propagated bans: KLINE and XLINE set fully propagated bans.
+        * That means the bans are part of the netburst and restarted/split
+        * servers will get them, but they will not apply to 3.2 and older
+        * servers at all.
         */
        use_propagated_bans = yes;
 
index 5d25900da6d60d0aac09b97030ae6e8d36e8b8c3..f20ad564587aeb9cf591589122e923884b382016 100644 (file)
@@ -36,7 +36,7 @@ X f - Shows File Descriptors
 * U - Shows shared blocks (Old U: lines)
   u - Shows server uptime
 ^ v - Shows connected servers and brief status information
-* x - Shows temporary gecos bans
+* x - Shows temporary and global gecos bans
 * X - Shows gecos bans (Old X: lines)
 ^ y - Shows connection classes (Old Y: lines)
 * z - Shows memory stats
index 0ee207a7fa98f0c4479e6ce20e3c142b5d8457f3..31b9a74feaf12f2ac31ca0de3bcd44b135490e88 100644 (file)
@@ -351,6 +351,7 @@ extern void free_conf(struct ConfItem *);
 
 extern rb_dlink_node *find_prop_ban(unsigned int status, const char *user, const char *host);
 extern void deactivate_conf(struct ConfItem *, rb_dlink_node *);
+extern void replace_old_ban(struct ConfItem *);
 
 extern void read_conf_files(int cold);
 
index f61ba0763fd0b55db1216ac5efbaba7b71bfffcf..0efe6ef3eeebe734549167f1b5931b2f676526fc 100644 (file)
@@ -89,6 +89,10 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p
                        ntype = CONF_KILL;
                        stype = "K-Line";
                        break;
+               case 'X':
+                       ntype = CONF_XLINE;
+                       stype = "X-Line";
+                       break;
                default:
                        sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
                                        "Unknown BAN type %s from %s",
@@ -199,10 +203,12 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p
                                       aconf->user ? "@" : "",
                                       aconf->host,
                                       parv[parc - 1]);
-               ilog(L_KLINE, "%s %s %d %s %s %s", parv[1],
+               ilog(L_KLINE, "%s %s %d %s%s%s %s", parv[1],
                                IsServer(source_p) ? source_p->name : get_oper_name(source_p),
                                (hold - rb_current_time()) / 60,
-                               aconf->user, aconf->host,
+                               aconf->user ? aconf->user : "",
+                               aconf->user ? " " : "",
+                               aconf->host,
                                parv[parc - 1]);
                aconf->status &= ~CONF_ILLEGAL;
        }
@@ -217,9 +223,11 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p
                                aconf->host,
                                strcmp(parv[7], "*") ? " on behalf of " : "",
                                strcmp(parv[7], "*") ? parv[7] : "");
-               ilog(L_KLINE, "U%s %s %s %s", parv[1],
+               ilog(L_KLINE, "U%s %s %s%s %s", parv[1],
                                IsServer(source_p) ? source_p->name : get_oper_name(source_p),
-                               aconf->user, aconf->host);
+                               aconf->user ? aconf->user : "",
+                               aconf->user ? " " : "",
+                               aconf->host);
        }
        switch (ntype)
        {
@@ -244,6 +252,15 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p
                                        check_klines();
                        }
                        break;
+               case CONF_XLINE:
+                       if (aconf->status & CONF_ILLEGAL)
+                               remove_reject_mask(aconf->host, NULL);
+                       else
+                       {
+                               rb_dlinkAddAlloc(aconf, &xline_conf_list);
+                               check_xlines();
+                       }
+                       break;
        }
        sendto_server(client_p, NULL, CAP_BAN|CAP_TS6, NOCAPS,
                        ":%s BAN %s %s %s %s %s %s %s :%s",
index 364c30b0f7f8fdd86782520d9e662941cab1653b..d6e22bc58b51676da0fcf49c0caf27a09a2f6e7c 100644 (file)
@@ -584,32 +584,11 @@ static void
 apply_prop_kline(struct Client *source_p, struct ConfItem *aconf,
             const char *reason, const char *oper_reason, int tkline_time)
 {
-       rb_dlink_node *ptr;
-       struct ConfItem *oldconf;
-
        aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY;
        aconf->hold = rb_current_time() + tkline_time;
        aconf->lifetime = aconf->hold;
 
-       ptr = find_prop_ban(aconf->status, aconf->user, aconf->host);
-       if(ptr != NULL)
-       {
-               oldconf = ptr->data;
-               /* Remember at least as long as the old one. */
-               if(oldconf->lifetime > aconf->lifetime)
-                       aconf->lifetime = oldconf->lifetime;
-               /* Force creation time to increase. */
-               if(oldconf->created >= aconf->created)
-                       aconf->created = oldconf->created + 1;
-               /* Leave at least one second of validity. */
-               if(aconf->hold <= aconf->created)
-                       aconf->hold = aconf->created + 1;
-               if(aconf->lifetime < aconf->hold)
-                       aconf->lifetime = aconf->hold;
-               /* Tell deactivate_conf() to destroy it. */
-               oldconf->lifetime = rb_current_time();
-               deactivate_conf(oldconf, ptr);
-       }
+       replace_old_ban(aconf);
 
        rb_dlinkAddAlloc(aconf, &prop_bans);
        add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf);
index 556ad005c684f9a8358aa0e28df0330fabf9465f..566a36928f15db4a5c3010bf6a2d129ca81f6b7b 100644 (file)
@@ -79,7 +79,7 @@ DECLARE_MODULE_AV1(xline, NULL, NULL, xline_clist, NULL, NULL, "$Revision$");
 
 static int valid_xline(struct Client *, const char *, const char *);
 static void apply_xline(struct Client *client_p, const char *name,
-                       const char *reason, int temp_time);
+                       const char *reason, int temp_time, int propagated);
 static void propagate_xline(struct Client *source_p, const char *target,
                            int temp_time, const char *name, const char *type, const char *reason);
 static void cluster_xline(struct Client *source_p, int temp_time,
@@ -89,7 +89,8 @@ static void handle_remote_xline(struct Client *source_p, int temp_time,
                                const char *name, const char *reason);
 static void handle_remote_unxline(struct Client *source_p, const char *name);
 
-static void remove_xline(struct Client *source_p, const char *name);
+static void remove_xline(struct Client *source_p, const char *name,
+                        int propagated);
 
 
 /* m_xline()
@@ -107,6 +108,7 @@ mo_xline(struct Client *client_p, struct Client *source_p, int parc, const char
        const char *target_server = NULL;
        int temp_time;
        int loc = 1;
+       int propagated = ConfigFileEntry.use_propagated_bans;
 
        if(!IsOperXline(source_p))
        {
@@ -152,8 +154,11 @@ mo_xline(struct Client *client_p, struct Client *source_p, int parc, const char
 
                if(!match(target_server, me.name))
                        return 0;
+
+               /* Set as local-only. */
+               propagated = 0;
        }
-       else if(rb_dlink_list_length(&cluster_conf_list) > 0)
+       else if(!propagated && rb_dlink_list_length(&cluster_conf_list) > 0)
                cluster_xline(source_p, temp_time, name, reason);
 
        if((aconf = find_xline_mask(name)) != NULL)
@@ -166,7 +171,13 @@ mo_xline(struct Client *client_p, struct Client *source_p, int parc, const char
        if(!valid_xline(source_p, name, reason))
                return 0;
 
-       apply_xline(source_p, name, reason, temp_time);
+       if(propagated && temp_time == 0)
+       {
+               sendto_one_notice(source_p, ":Cannot set a permanent global ban");
+               return 0;
+       }
+
+       apply_xline(source_p, name, reason, temp_time, propagated);
 
        return 0;
 }
@@ -226,7 +237,7 @@ handle_remote_xline(struct Client *source_p, int temp_time, const char *name, co
                return;
        }
 
-       apply_xline(source_p, name, reason, temp_time);
+       apply_xline(source_p, name, reason, temp_time, 0);
 }
 
 /* valid_xline()
@@ -270,8 +281,9 @@ valid_xline(struct Client *source_p, const char *gecos, const char *reason)
 }
 
 void
-apply_xline(struct Client *source_p, const char *name, const char *reason, int temp_time)
+apply_xline(struct Client *source_p, const char *name, const char *reason, int temp_time, int propagated)
 {
+       rb_dlink_node *ptr;
        struct ConfItem *aconf;
 
        aconf = make_conf();
@@ -283,7 +295,32 @@ apply_xline(struct Client *source_p, const char *name, const char *reason, int t
 
        aconf->info.oper = operhash_add(get_oper_name(source_p));
 
-       if(temp_time > 0)
+       if(propagated)
+       {
+               aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY;
+               aconf->hold = rb_current_time() + temp_time;
+               aconf->lifetime = aconf->hold;
+
+               replace_old_ban(aconf);
+               rb_dlinkAddAlloc(aconf, &prop_bans);
+
+               sendto_realops_snomask(SNO_GENERAL, L_ALL,
+                                      "%s added global %d min. X-Line for [%s] [%s]",
+                                      get_oper_name(source_p), temp_time / 60,
+                                      aconf->host, reason);
+               ilog(L_KLINE, "X %s %d %s %s",
+                    get_oper_name(source_p), temp_time / 60, name, reason);
+               sendto_one_notice(source_p, ":Added global %d min. X-Line [%s]",
+                                 temp_time / 60, aconf->host);
+               sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS,
+                               ":%s BAN X * %s %lu %d %d * :%s",
+                               source_p->id, aconf->host,
+                               (unsigned long)aconf->created,
+                               (int)(aconf->hold - aconf->created),
+                               (int)(aconf->lifetime - aconf->created),
+                               reason);
+       }
+       else if(temp_time > 0)
        {
                aconf->hold = rb_current_time() + temp_time;
 
@@ -366,6 +403,8 @@ cluster_xline(struct Client *source_p, int temp_time, const char *name, const ch
 static int
 mo_unxline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
 {
+       int propagated = 1;
+
        if(!IsOperXline(source_p))
        {
                sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "xline");
@@ -385,11 +424,12 @@ mo_unxline(struct Client *client_p, struct Client *source_p, int parc, const cha
 
                if(match(parv[3], me.name) == 0)
                        return 0;
+
+               propagated = 0;
        }
-       else if(rb_dlink_list_length(&cluster_conf_list))
-               cluster_generic(source_p, "UNXLINE", SHARED_UNXLINE, CAP_CLUSTER, "%s", parv[1]);
+       /* cluster{} moved to remove_xline */
 
-       remove_xline(source_p, parv[1]);
+       remove_xline(source_p, parv[1], propagated);
 
        return 0;
 }
@@ -434,13 +474,13 @@ handle_remote_unxline(struct Client *source_p, const char *name)
                             source_p->servptr->name, SHARED_UNXLINE))
                return;
 
-       remove_xline(source_p, name);
+       remove_xline(source_p, name, 0);
 
        return;
 }
 
 static void
-remove_xline(struct Client *source_p, const char *name)
+remove_xline(struct Client *source_p, const char *name, int propagated)
 {
        struct ConfItem *aconf;
        rb_dlink_node *ptr;
@@ -451,6 +491,41 @@ remove_xline(struct Client *source_p, const char *name)
 
                if(!irccmp(aconf->host, name))
                {
+                       if(aconf->lifetime)
+                       {
+                               if(!propagated)
+                               {
+                                       sendto_one_notice(source_p, ":Cannot remove global X-Line %s on specific servers", name);
+                                       return;
+                               }
+                               ptr = rb_dlinkFind(aconf, &prop_bans);
+                               if(ptr == NULL)
+                                       return;
+                               sendto_one_notice(source_p, ":X-Line for [%s] is removed", name);
+                               sendto_realops_snomask(SNO_GENERAL, L_ALL,
+                                                      "%s has removed the global X-Line for: [%s]",
+                                                      get_oper_name(source_p), name);
+                               ilog(L_KLINE, "UX %s %s", get_oper_name(source_p), name);
+                               if(aconf->created < rb_current_time())
+                                       aconf->created = rb_current_time();
+                               else
+                                       aconf->created++;
+                               aconf->hold = aconf->created;
+                               operhash_delete(aconf->info.oper);
+                               aconf->info.oper = operhash_add(get_oper_name(source_p));
+                               aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY;
+                               sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS,
+                                               ":%s BAN X * %s %lu %d %d * :*",
+                                               source_p->id, aconf->host,
+                                               (unsigned long)aconf->created,
+                                               0,
+                                               (int)(aconf->lifetime - aconf->created));
+                               remove_reject_mask(aconf->host, NULL);
+                               deactivate_conf(aconf, ptr);
+                               return;
+                       }
+                       else if(MyClient(source_p) && rb_dlink_list_length(&cluster_conf_list))
+                               cluster_generic(source_p, "UNXLINE", SHARED_UNXLINE, CAP_CLUSTER, "%s", name);
                        if(!aconf->hold)
                        {
                                bandb_del(BANDB_XLINE, aconf->host, NULL);
@@ -477,6 +552,9 @@ remove_xline(struct Client *source_p, const char *name)
                }
        }
 
+       if(MyClient(source_p) && rb_dlink_list_length(&cluster_conf_list))
+               cluster_generic(source_p, "UNXLINE", SHARED_UNXLINE, CAP_CLUSTER, "%s", name);
+
        sendto_one_notice(source_p, ":No X-Line for %s", name);
 
        return;
index 3f4608890272a6a8bca7115689d798321d900ac2..768ae2fb31df2edc5d1768eb5c748c38022c0db4 100644 (file)
@@ -1133,6 +1133,36 @@ deactivate_conf(struct ConfItem *aconf, rb_dlink_node *ptr)
        }
 }
 
+/* Given a new ban ConfItem, look for any matching ban, update the lifetime
+ * from it and delete it.
+ */
+void
+replace_old_ban(struct ConfItem *aconf)
+{
+       rb_dlink_node *ptr;
+       struct ConfItem *oldconf;
+
+       ptr = find_prop_ban(aconf->status, aconf->user, aconf->host);
+       if(ptr != NULL)
+       {
+               oldconf = ptr->data;
+               /* Remember at least as long as the old one. */
+               if(oldconf->lifetime > aconf->lifetime)
+                       aconf->lifetime = oldconf->lifetime;
+               /* Force creation time to increase. */
+               if(oldconf->created >= aconf->created)
+                       aconf->created = oldconf->created + 1;
+               /* Leave at least one second of validity. */
+               if(aconf->hold <= aconf->created)
+                       aconf->hold = aconf->created + 1;
+               if(aconf->lifetime < aconf->hold)
+                       aconf->lifetime = aconf->hold;
+               /* Tell deactivate_conf() to destroy it. */
+               oldconf->lifetime = rb_current_time();
+               deactivate_conf(oldconf, ptr);
+       }
+}
+
 static void
 expire_prop_bans(void *list)
 {