]> jfr.im git - irc/rqf/shadowircd.git/blobdiff - modules/core/m_ban.c
Fix a minor spelling error in m_kick.
[irc/rqf/shadowircd.git] / modules / core / m_ban.c
index 1fecd3f14ef64179c03df219b996f4f8c811b5dc..ebc5152c87ba1f6495a3c0aa87019b9a6315afad 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "stdinc.h"
 #include "send.h"
+#include "channel.h"
 #include "client.h"
 #include "common.h"
 #include "config.h"
 #include "reject.h"
 #include "hostmask.h"
 
+static int m_ban(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]);
 static int ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]);
 
 struct Message ban_msgtab = {
        "BAN", 0, 0, 0, MFLG_SLOW,
-       {mg_unreg, mg_ignore, {ms_ban, 9}, {ms_ban, 9}, mg_ignore, mg_ignore}
+       {mg_unreg, {m_ban, 0}, {ms_ban, 9}, {ms_ban, 9}, mg_ignore, {m_ban, 0}}
 };
 
 mapi_clist_av1 ban_clist[] =  { &ban_msgtab, NULL };
 DECLARE_MODULE_AV1(ban, NULL, NULL, ban_clist, NULL, NULL, "$Revision: 1349 $");
 
+static int
+m_ban(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
+{
+       sendto_one_notice(source_p, ":The BAN command is not user-accessible.");
+       sendto_one_notice(source_p, ":To ban a user from a channel, see /QUOTE HELP CMODE");
+       if (IsOper(source_p))
+               sendto_one_notice(source_p, ":To ban a user from a server or from the network, see /QUOTE HELP KLINE");
+       return 0;
+}
+
 /* ms_ban()
  *
  * parv[1] - type
@@ -75,6 +87,7 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p
        time_t created, hold, lifetime;
        char *p;
        int act;
+       int valid;
 
        if (strlen(parv[1]) != 1)
        {
@@ -93,6 +106,11 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p
                        ntype = CONF_XLINE;
                        stype = "X-Line";
                        break;
+               case 'R':
+                       ntype = IsChannelName(parv[3]) ? CONF_RESV_CHANNEL :
+                               CONF_RESV_NICK;
+                       stype = "RESV";
+                       break;
                default:
                        sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
                                        "Unknown BAN type %s from %s",
@@ -109,6 +127,7 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p
        ptr = find_prop_ban(ntype, parv[2], parv[3]);
        if (ptr != NULL)
        {
+               /* We already know about this ban mask. */
                aconf = ptr->data;
                if (aconf->created > created ||
                                (aconf->created == created &&
@@ -123,6 +142,11 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p
                                                aconf->host);
                        return 0;
                }
+               /* act indicates if something happened (from the oper's
+                * point of view). This is the case if the ban was
+                * previously active (not deleted) or if the new ban
+                * is not a removal and not already expired.
+                */
                act = !(aconf->status & CONF_ILLEGAL) || (hold != created &&
                                hold > rb_current_time());
                if (lifetime > aconf->lifetime)
@@ -130,6 +154,7 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p
                /* already expired, hmm */
                if (aconf->lifetime <= rb_current_time())
                        return 0;
+               /* Deactivate, it will be reactivated later if appropriate. */
                deactivate_conf(aconf, ptr);
                rb_free(aconf->user);
                aconf->user = NULL;
@@ -144,6 +169,7 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p
        }
        else
        {
+               /* New ban mask. */
                aconf = make_conf();
                aconf->status = CONF_ILLEGAL | ntype;
                aconf->lifetime = lifetime;
@@ -164,14 +190,30 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p
                aconf->passwd = rb_strndup(parv[parc - 1], p - parv[parc - 1] + 1);
                aconf->spasswd = rb_strdup(p + 1);
        }
-       if (act && hold != created &&
-                       !(ntype == CONF_KILL ?
-                               valid_wild_card(aconf->user, aconf->host) :
-                               valid_wild_card_simple(aconf->host)))
+       /* The ban is fully filled in and in the prop_bans list
+        * but still deactivated. Now determine if it should be activated
+        * and send the server notices.
+        */
+       /* We only reject *@* and the like here.
+        * Otherwise malformed bans are fairly harmless and can be removed.
+        */
+       switch (ntype)
+       {
+               case CONF_KILL:
+                       valid = valid_wild_card(aconf->user, aconf->host);
+                       break;
+               case CONF_RESV_CHANNEL:
+                       valid = 1;
+                       break;
+               default:
+                       valid = valid_wild_card_simple(aconf->host);
+                       break;
+       }
+       if (act && hold != created && !valid)
        {
                sendto_realops_snomask(SNO_GENERAL, L_ALL,
                                       "Ignoring global %d min. %s from %s%s%s for [%s%s%s]: too few non-wildcard characters",
-                                      (hold - rb_current_time()) / 60,
+                                      (int)((hold - rb_current_time()) / 60),
                                       stype,
                                       IsServer(source_p) ? source_p->name : get_oper_name(source_p),
                                       strcmp(parv[7], "*") ? " on behalf of " : "",
@@ -194,7 +236,7 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p
                sendto_realops_snomask(SNO_GENERAL, L_ALL,
                                       "%s added global %d min. %s%s%s for [%s%s%s] [%s]",
                                       IsServer(source_p) ? source_p->name : get_oper_name(source_p),
-                                      (hold - rb_current_time()) / 60,
+                                      (int)((hold - rb_current_time()) / 60),
                                       stype,
                                       strcmp(parv[7], "*") ? " from " : "",
                                       strcmp(parv[7], "*") ? parv[7] : "",
@@ -204,7 +246,7 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p
                                       parv[parc - 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,
+                               (int)((hold - rb_current_time()) / 60),
                                aconf->user ? aconf->user : "",
                                aconf->user ? " " : "",
                                aconf->host,
@@ -228,6 +270,11 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p
                                aconf->user ? " " : "",
                                aconf->host);
        }
+       /* If CONF_ILLEGAL is still set at this point, remove entries from the
+        * reject cache (for klines and xlines).
+        * If CONF_ILLEGAL is not set, add the ban to the type-specific data
+        * structure and take action on matched clients/channels.
+        */
        switch (ntype)
        {
                case CONF_KILL:
@@ -260,6 +307,17 @@ ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *p
                                check_xlines();
                        }
                        break;
+               case CONF_RESV_CHANNEL:
+                       if (!(aconf->status & CONF_ILLEGAL))
+                       {
+                               add_to_resv_hash(aconf->host, aconf);
+                               resv_chan_forcepart(aconf->host, aconf->passwd, hold - rb_current_time());
+                       }
+                       break;
+               case CONF_RESV_NICK:
+                       if (!(aconf->status & CONF_ILLEGAL))
+                               rb_dlinkAddAlloc(aconf, &resv_conf_list);
+                       break;
        }
        sendto_server(client_p, NULL, CAP_BAN|CAP_TS6, NOCAPS,
                        ":%s BAN %s %s %s %s %s %s %s :%s",