1
0
mirror of https://github.com/unrealircd/unrealircd.git synced 2026-07-08 04:03:12 +02:00

Support ::destination and ::exclude-destination in security groups / mask items

at selected places (there needs to be explicit code in place to handle this).
At the moment it is supported at two places only:
* For spamfilters (was already possible via crules via ::rule with
  a destination('xyz') but now non-crule destination "#xyz"; works as well, eg:
  spamfilter {
          ...
          except {
                  destination "#main";
          }
  }
  Note that if you want to exempt a destination in all spamfilters,
  we already have set::spamfilter::except for that!
* In restrict commands for like channel-message and such:
  set {
          restrict-commands {
                  channel-message {
                          except {
                                  connect-time 600;
                                  destination "#test";
                          }
                  }
           }
  }

Allow passing a crule_context via user_allowed_by_security_group_context()
and make user_allowed_by_security_group() call that.

Actually document spamfilter::except online in the docs (yeah you
won't see it in this commit, just mentioning...)

And yeah, by now i wonder if we should really call it crule_context
since it is more like a security group matching context, but.. whatever.
This commit is contained in:
Bram Matthys
2024-07-06 09:03:49 +02:00
parent a804b24150
commit e03a5dfd5f
5 changed files with 71 additions and 36 deletions
+28 -14
View File
@@ -49,8 +49,8 @@ int rcmd_configrun(ConfigFile *cf, ConfigEntry *ce, int type);
int rcmd_can_send_to_channel(Client *client, Channel *channel, Membership *lp, const char **msg, const char **errmsg, SendType sendtype);
int rcmd_can_send_to_user(Client *client, Client *target, const char **text, const char **errmsg, SendType sendtype);
int rcmd_can_join(Client *client, Channel *channel, const char *key, char **errmsg);
int rcmd_block_message(Client *client, const char *text, SendType sendtype, const char **errmsg, const char *display, const char *conftag);
int rcmd_block_join(Client *client, const char **errmsg);
int rcmd_block_message(Client *client, const char *destination, const char *text, SendType sendtype, const char **errmsg, const char *display, const char *conftag);
int rcmd_block_join(Client *client, Channel *channel, const char **errmsg);
CMD_OVERRIDE_FUNC(rcmd_override);
// Globals
@@ -298,7 +298,7 @@ int rcmd_configrun(ConfigFile *cf, ConfigEntry *ce, int type)
rcmd->except->identified = config_checkval(cep2->value, CFG_YESNO);
continue;
}
if (!strcmp(cep2->name, "exempt-webirc"))
{
rcmd->except->webirc = config_checkval(cep2->value, CFG_YESNO);
@@ -323,18 +323,18 @@ int rcmd_configrun(ConfigFile *cf, ConfigEntry *ce, int type)
return 1;
}
int rcmd_canbypass(Client *client, RestrictedCommand *rcmd)
int rcmd_canbypass(Client *client, RestrictedCommand *rcmd, crule_context *context)
{
if (!client || !rcmd)
return 1;
if (user_allowed_by_security_group(client, rcmd->except))
if (user_allowed_by_security_group_context(client, rcmd->except, context))
return 1;
return 0;
}
int rcmd_can_send_to_channel(Client *client, Channel *channel, Membership *lp, const char **msg, const char **errmsg, SendType sendtype)
{
if (rcmd_block_message(client, *msg, sendtype, errmsg, "channel", (sendtype == SEND_TYPE_NOTICE ? "channel-notice" : "channel-message")))
if (rcmd_block_message(client, channel->name, *msg, sendtype, errmsg, "channel", (sendtype == SEND_TYPE_NOTICE ? "channel-notice" : "channel-message")))
return HOOK_DENY;
return HOOK_CONTINUE;
@@ -346,14 +346,15 @@ int rcmd_can_send_to_user(Client *client, Client *target, const char **text, con
if ((client == target) || IsULine(target))
return HOOK_CONTINUE; /* bypass/exempt */
if (rcmd_block_message(client, *text, sendtype, errmsg, "user", (sendtype == SEND_TYPE_NOTICE ? "private-notice" : "private-message")))
if (rcmd_block_message(client, target->name, *text, sendtype, errmsg, "user", (sendtype == SEND_TYPE_NOTICE ? "private-notice" : "private-message")))
return HOOK_DENY;
return HOOK_CONTINUE;
}
int rcmd_block_message(Client *client, const char *text, SendType sendtype, const char **errmsg, const char *display, const char *conftag)
int rcmd_block_message(Client *client, const char *destination, const char *text, SendType sendtype, const char **errmsg, const char *display, const char *conftag)
{
crule_context context;
RestrictedCommand *rcmd;
static char errbuf[256];
@@ -361,8 +362,12 @@ int rcmd_block_message(Client *client, const char *text, SendType sendtype, cons
if (!MyUser(client) || !client->local || IsOper(client) || IsULine(client))
return 0;
memset(&context, 0, sizeof(context));
context.client = client;
context.destination = destination;
rcmd = find_restrictions_byconftag(conftag);
if (rcmd && !rcmd_canbypass(client, rcmd))
if (rcmd && !rcmd_canbypass(client, rcmd, &context))
{
int notice = (sendtype == SEND_TYPE_NOTICE ? 1 : 0); // temporary hack FIXME !!!
if (rcmd->except->connect_time)
@@ -386,6 +391,7 @@ int rcmd_block_message(Client *client, const char *text, SendType sendtype, cons
CMD_OVERRIDE_FUNC(rcmd_override)
{
RestrictedCommand *rcmd;
crule_context context;
if (!MyUser(client) || !client->local || IsOper(client) || IsULine(client))
{
@@ -393,8 +399,11 @@ CMD_OVERRIDE_FUNC(rcmd_override)
return;
}
memset(&context, 0, sizeof(context));
context.client = client;
rcmd = find_restrictions_bycmd(ovr->command->cmd);
if (rcmd && !rcmd_canbypass(client, rcmd))
if (rcmd && !rcmd_canbypass(client, rcmd, &context))
{
if (rcmd->except->connect_time)
{
@@ -422,27 +431,32 @@ int rcmd_can_join(Client *client, Channel *channel, const char *key, char **errm
if (channel->users || has_channel_mode(channel, 'P'))
return 0;
else if (rcmd_block_join(client, &join_err))
else if (rcmd_block_join(client, channel, &join_err))
{
static char formatted_errmsg[512];
snprintf(formatted_errmsg, sizeof(formatted_errmsg), "JOIN :%s", join_err);
*errmsg = formatted_errmsg;
return ERR_CANNOTDOCOMMAND;
}
return 0;
}
int rcmd_block_join(Client *client, const char **errmsg)
int rcmd_block_join(Client *client, Channel *channel, const char **errmsg)
{
RestrictedCommand *rcmd;
crule_context context;
static char errbuf[256];
if (!MyUser(client) || !client->local || IsOper(client) || IsULine(client))
return 0;
memset(&context, 0, sizeof(context));
context.client = client;
context.destination = channel->name;
rcmd = find_restrictions_byconftag("channel-create");
if (rcmd && !rcmd_canbypass(client, rcmd))
if (rcmd && !rcmd_canbypass(client, rcmd, &context))
{
if (rcmd->except->connect_time)
{
+8 -8
View File
@@ -5362,6 +5362,7 @@ int _match_spamfilter(Client *client, const char *str_in, int target, const char
int stop_processing_general_spamfilters = 0;
int stop_processing_central_spamfilters = 0;
int content_revealed = 0;
crule_context context;
if (rettkl)
*rettkl = NULL; /* initialize to NULL */
@@ -5380,13 +5381,18 @@ int _match_spamfilter(Client *client, const char *str_in, int target, const char
if (!client->user || ValidatePermissionsForPath("immune:server-ban:spamfilter",client,NULL,NULL,NULL) || IsULine(client))
return 0;
memset(&context, 0, sizeof(context));
context.client = client;
context.text = str_in;
context.destination = destination;
/* Client exempt from spamfilter checking?
* Let's check that early: going through elines is likely faster than running the regex(es).
*/
if (find_tkl_exception(TKL_SPAMF, client))
user_is_exempt_general = 1;
if (user_allowed_by_security_group(client, iConf.central_spamfilter_except))
if (user_allowed_by_security_group_context(client, iConf.central_spamfilter_except, &context))
user_is_exempt_central = 1;
for (tkl = tklines[tkl_hash('F')]; tkl; tkl = tkl->next)
@@ -5420,22 +5426,16 @@ int _match_spamfilter(Client *client, const char *str_in, int target, const char
/* Run any pre 'rule' if there is any (false means 'no hit') */
if (tkl->ptr.spamfilter->rule)
{
crule_context context;
memset(&context, 0, sizeof(context));
context.client = client;
context.text = str_in;
context.destination = destination;
if (!crule_eval(&context, tkl->ptr.spamfilter->rule))
continue;
}
/* Check any 'except' rule if there is any (true means 'no hit') */
if (tkl->ptr.spamfilter->except && user_allowed_by_security_group(client, tkl->ptr.spamfilter->except))
if (tkl->ptr.spamfilter->except && user_allowed_by_security_group_context(client, tkl->ptr.spamfilter->except, &context))
continue;
if (tkl->ptr.spamfilter->match && (tkl->ptr.spamfilter->match->type != MATCH_NONE))
{
// TODO: wait, why are we running slow spamfilter detection for simple (non-regex) too ?
#ifdef SPAMFILTER_DETECTSLOW
if (tkl->ptr.spamfilter->match->type == MATCH_PCRE_REGEX)
{