1
0
mirror of https://github.com/unrealircd/unrealircd.git synced 2026-06-28 03:46:37 +02:00

Add TKL exception type handling (phase 2 of X)

This commit is contained in:
Bram Matthys
2019-09-01 10:52:35 +02:00
parent cdcac52d81
commit 76b1655f9b
5 changed files with 348 additions and 65 deletions
+3
View File
@@ -648,6 +648,8 @@ extern MODVAR int (*tkl_chartotype)(char c);
extern MODVAR char *(*tkl_type_string)(aTKline *tk);
extern MODVAR aTKline *(*tkl_add_serverban)(int type, char *usermask, char *hostmask, char *reason, char *setby,
time_t expire_at, time_t set_at, int soft, int flags);
extern MODVAR aTKline *(*tkl_add_banexception)(int type, char *usermask, char *hostmask, char *reason, char *set_by,
time_t expire_at, time_t set_at, int soft, char *bantypes, int flags);
extern MODVAR aTKline *(*tkl_add_nameban)(int type, char *name, int hold, char *reason, char *setby,
time_t expire_at, time_t set_at, int flags);
extern MODVAR aTKline *(*tkl_add_spamfilter)(int type, unsigned short target, unsigned short action, aMatch *match, char *setby,
@@ -655,6 +657,7 @@ extern MODVAR aTKline *(*tkl_add_spamfilter)(int type, unsigned short target, un
time_t spamf_tkl_duration, char *spamf_tkl_reason,
int flags);
extern MODVAR aTKline *(*find_tkl_serverban)(int type, char *usermask, char *hostmask, int softban);
extern MODVAR aTKline *(*find_tkl_banexception)(int type, char *usermask, char *hostmask, int softban);
extern MODVAR aTKline *(*find_tkl_nameban)(int type, char *name, int hold);
extern MODVAR aTKline *(*find_tkl_spamfilter)(int type, char *match_string, unsigned short action, unsigned short target);
extern MODVAR void (*sendnotice_tkl_del)(char *removed_by, aTKline *tkl);
+2
View File
@@ -1235,12 +1235,14 @@ enum EfunctionType {
EFUNC_BROADCAST_MD_GLOBALVAR_CMD,
EFUNC_TKL_IP_HASH,
EFUNC_TKL_IP_HASH_TYPE,
EFUNC_TKL_ADD_BANEXCEPTION,
EFUNC_TKL_ADD_NAMEBAN,
EFUNC_TKL_ADD_SPAMFILTER,
EFUNC_SENDNOTICE_TKL_ADD,
EFUNC_SENDNOTICE_TKL_DEL,
EFUNC_FREE_TKL,
EFUNC_FIND_TKL_SERVERBAN,
EFUNC_FIND_TKL_BANEXCEPTION,
EFUNC_FIND_TKL_NAMEBAN,
EFUNC_FIND_TKL_SPAMFILTER,
};
+25 -11
View File
@@ -68,6 +68,7 @@ typedef struct ConfItem aConfItem;
typedef struct t_kline aTKline;
typedef struct _spamfilter Spamfilter;
typedef struct _serverban ServerBan;
typedef struct _banexception BanException;
typedef struct _nameban NameBan;
typedef struct _spamexcept SpamExcept;
typedef struct _conditionalconfig ConditionalConfig;
@@ -703,7 +704,7 @@ struct Server {
/* tkl:
* TKL_KILL|TKL_GLOBAL = Global K-Line (GLINELine)
* TKL_KILL|TKL_GLOBAL = Global K-Line (GLINE)
* TKL_ZAP|TKL_GLOBAL = Global Z-Line (ZLINE)
* TKL_KILL = Local K-Line
* TKL_ZAP = Local Z-Line
@@ -714,7 +715,7 @@ struct Server {
#define TKL_SHUN 0x0008
#define TKL_SPAMF 0x0020
#define TKL_NAME 0x0040
#define TKL_EXCEPT 0x0080
#define TKL_EXCEPTION 0x0080
#define TKLIsServerBan(tkl) ((tkl)->type & (TKL_KILL|TKL_ZAP|TKL_SHUN))
#define TKLIsServerBanType(tpe) ((tpe) & (TKL_KILL|TKL_ZAP|TKL_SHUN))
@@ -722,6 +723,8 @@ struct Server {
#define TKLIsSpamfilterType(tpe) ((tpe) & TKL_SPAMF)
#define TKLIsNameBan(tkl) ((tkl)->type & TKL_NAME)
#define TKLIsNameBanType(tpe) ((tpe) & TKL_NAME)
#define TKLIsBanException(tkl) ((tkl)->type & TKL_EXCEPTION)
#define TKLIsBanExceptionType(tpe) ((tpe) & TKL_EXCEPTION)
#define SPAMF_CHANMSG 0x0001 /* c */
#define SPAMF_USERMSG 0x0002 /* p */
@@ -737,15 +740,6 @@ struct Server {
/* Other flags only for function calls: */
#define SPAMFLAG_NOWARN 0x0001
/** Spamfilter sub-struct of TKL entry (Spamfilter) */
struct _spamfilter {
unsigned short target;
unsigned short action; /**< Ban action, see BAN_ACT* */
aMatch *match; /**< Spamfilter matcher */
char *tkl_reason; /**< Reason to use for bans placed by this spamfilter, escaped by unreal_encodespace(). */
time_t tkl_duration; /**< Duration of bans placed by this spamfilter */
};
/** Server ban sub-struct of TKL entry (KLINE/GLINE/ZLINE/GZLINE/SHUN) */
struct _serverban {
char *usermask; /**< User mask */
@@ -761,6 +755,25 @@ struct _nameban {
char *reason; /**< Reason */
};
/** Spamfilter sub-struct of TKL entry (Spamfilter) */
struct _spamfilter {
unsigned short target;
unsigned short action; /**< Ban action, see BAN_ACT* */
aMatch *match; /**< Spamfilter matcher */
char *tkl_reason; /**< Reason to use for bans placed by this spamfilter, escaped by unreal_encodespace(). */
time_t tkl_duration; /**< Duration of bans placed by this spamfilter */
};
/** Ban exception sub-struct of TKL entry (ELINE) */
struct _banexception {
char *usermask; /**< User mask */
char *hostmask; /**< Host mask */
unsigned short subtype; /**< See TKL_SUBTYPE_* */
char *bantypes; /**< Exception types */
char *reason; /**< Reason */
};
#define TKL_SUBTYPE_NONE 0x0000
#define TKL_SUBTYPE_SOFT 0x0001 /* (require SASL) */
@@ -778,6 +791,7 @@ struct t_kline {
Spamfilter *spamfilter;
ServerBan *serverban;
NameBan *nameban;
BanException *banexception;
} ptr;
};
+10
View File
@@ -54,6 +54,8 @@ aTKline *(*tkl_add_spamfilter)(int type, unsigned short target, unsigned short a
time_t expire_at, time_t set_at,
time_t spamf_tkl_duration, char *spamf_tkl_reason,
int flags);
aTKline *(*tkl_add_banexception)(int type, char *usermask, char *hostmask, char *reason, char *set_by,
time_t expire_at, time_t set_at, int soft, char *bantypes, int flags);
aTKline *(*tkl_del_line)(aTKline *tkl);
void (*tkl_check_local_remove_shun)(aTKline *tmp);
int (*find_tkline_match)(aClient *cptr, int skip_soft);
@@ -111,6 +113,7 @@ void (*sendnotice_tkl_del)(char *removed_by, aTKline *tkl);
void (*sendnotice_tkl_add)(aTKline *tkl);
void (*free_tkl)(aTKline *tkl);
aTKline *(*find_tkl_serverban)(int type, char *usermask, char *hostmask, int softban);
aTKline *(*find_tkl_banexception)(int type, char *usermask, char *hostmask, int softban);
aTKline *(*find_tkl_nameban)(int type, char *name, int hold);
aTKline *(*find_tkl_spamfilter)(int type, char *match_string, unsigned short action, unsigned short target);
@@ -246,6 +249,11 @@ void efunctions_switchover(void)
{
if (e->willberemoved)
continue;
if (!efunction_table[i].funcptr)
{
ircd_log(LOG_ERROR, "[BUG] efunctions_switchover(): someone forgot to initialize the function table for efunc %d", i);
abort();
}
*efunction_table[i].funcptr = e->func.voidfunc; /* This is the new one. */
if (!(e->owner->options & MOD_OPT_PERM))
e->willberemoved = 1;
@@ -281,6 +289,7 @@ void efunctions_init(void)
efunc_init_function(EFUNC_TKL_HASH, tkl_hash, NULL);
efunc_init_function(EFUNC_TKL_TYPETOCHAR, tkl_typetochar, NULL);
efunc_init_function(EFUNC_TKL_ADD_SERVERBAN, tkl_add_serverban, NULL);
efunc_init_function(EFUNC_TKL_ADD_BANEXCEPTION, tkl_add_banexception, NULL);
efunc_init_function(EFUNC_TKL_DEL_LINE, tkl_del_line, NULL);
efunc_init_function(EFUNC_TKL_CHECK_LOCAL_REMOVE_SHUN, tkl_check_local_remove_shun, NULL);
efunc_init_function(EFUNC_FIND_TKLINE_MATCH, find_tkline_match, NULL);
@@ -340,6 +349,7 @@ void efunctions_init(void)
efunc_init_function(EFUNC_SENDNOTICE_TKL_DEL, sendnotice_tkl_del, NULL);
efunc_init_function(EFUNC_FREE_TKL, free_tkl, NULL);
efunc_init_function(EFUNC_FIND_TKL_SERVERBAN, find_tkl_serverban, NULL);
efunc_init_function(EFUNC_FIND_TKL_BANEXCEPTION, find_tkl_banexception, NULL);
efunc_init_function(EFUNC_FIND_TKL_NAMEBAN, find_tkl_nameban, NULL);
efunc_init_function(EFUNC_FIND_TKL_SPAMFILTER, find_tkl_spamfilter, NULL);
}
+308 -54
View File
@@ -42,6 +42,8 @@ int _tkl_chartotype(char c);
char *_tkl_type_string(aTKline *tk);
aTKline *_tkl_add_serverban(int type, char *usermask, char *hostmask, char *reason, char *set_by,
time_t expire_at, time_t set_at, int soft, int flags);
aTKline *_tkl_add_banexception(int type, char *usermask, char *hostmask, char *reason, char *set_by,
time_t expire_at, time_t set_at, int soft, char *bantypes, int flags);
aTKline *_tkl_add_nameban(int type, char *name, int hold, char *reason, char *set_by,
time_t expire_at, time_t set_at, int flags);
aTKline *_tkl_add_spamfilter(int type, unsigned short target, unsigned short action, aMatch *match, char *set_by,
@@ -71,6 +73,7 @@ int _match_user(char *rmask, aClient *acptr, int options);
int _tkl_ip_hash(char *ip);
int _tkl_ip_hash_type(int type);
aTKline *_find_tkl_serverban(int type, char *usermask, char *hostmask, int softban);
aTKline *_find_tkl_banexception(int type, char *usermask, char *hostmask, int softban);
aTKline *_find_tkl_nameban(int type, char *name, int hold);
aTKline *_find_tkl_spamfilter(int type, char *match_string, unsigned short action, unsigned short target);
@@ -96,6 +99,7 @@ MOD_TEST(tkl)
EfunctionAdd(modinfo->handle, EFUNC_TKL_CHARTOTYPE, TO_INTFUNC(_tkl_chartotype));
EfunctionAddPChar(modinfo->handle, EFUNC_TKL_TYPE_STRING, _tkl_type_string);
EfunctionAddPVoid(modinfo->handle, EFUNC_TKL_ADD_SERVERBAN, TO_PVOIDFUNC(_tkl_add_serverban));
EfunctionAddPVoid(modinfo->handle, EFUNC_TKL_ADD_BANEXCEPTION, TO_PVOIDFUNC(_tkl_add_banexception));
EfunctionAddPVoid(modinfo->handle, EFUNC_TKL_ADD_NAMEBAN, TO_PVOIDFUNC(_tkl_add_nameban));
EfunctionAddPVoid(modinfo->handle, EFUNC_TKL_ADD_SPAMFILTER, TO_PVOIDFUNC(_tkl_add_spamfilter));
EfunctionAddVoid(modinfo->handle, EFUNC_TKL_DEL_LINE, _tkl_del_line);
@@ -107,6 +111,7 @@ MOD_TEST(tkl)
EfunctionAddPVoid(modinfo->handle, EFUNC_FIND_QLINE, TO_PVOIDFUNC(_find_qline));
EfunctionAddPVoid(modinfo->handle, EFUNC_FIND_TKLINE_MATCH_ZAP, TO_PVOIDFUNC(_find_tkline_match_zap));
EfunctionAddPVoid(modinfo->handle, EFUNC_FIND_TKL_SERVERBAN, TO_PVOIDFUNC(_find_tkl_serverban));
EfunctionAddPVoid(modinfo->handle, EFUNC_FIND_TKL_BANEXCEPTION, TO_PVOIDFUNC(_find_tkl_banexception));
EfunctionAddPVoid(modinfo->handle, EFUNC_FIND_TKL_NAMEBAN, TO_PVOIDFUNC(_find_tkl_nameban));
EfunctionAddPVoid(modinfo->handle, EFUNC_FIND_TKL_SPAMFILTER, TO_PVOIDFUNC(_find_tkl_spamfilter));
EfunctionAddVoid(modinfo->handle, EFUNC_TKL_STATS, _tkl_stats);
@@ -1388,7 +1393,7 @@ char _tkl_typetochar(int type)
return 'F';
if (type & TKL_NAME)
return 'Q';
if (type & TKL_EXCEPT)
if (type & TKL_EXCEPTION)
return 'E';
} else {
if (type & TKL_KILL)
@@ -1399,7 +1404,7 @@ char _tkl_typetochar(int type)
return 'f';
if (type & TKL_NAME)
return 'q';
if (type & TKL_EXCEPT)
if (type & TKL_EXCEPTION)
return 'e';
}
sendto_realops("[BUG]: tkl_typetochar(): unknown type 0x%x !!!", type);
@@ -1424,6 +1429,8 @@ int _tkl_chartotype(char c)
return TKL_SPAMF|TKL_GLOBAL;
case 'Q':
return TKL_NAME|TKL_GLOBAL;
case 'E':
return TKL_EXCEPTION|TKL_GLOBAL;
case 'k':
return TKL_KILL;
case 'z':
@@ -1432,10 +1439,8 @@ int _tkl_chartotype(char c)
return TKL_SPAMF;
case 'q':
return TKL_NAME;
case 'E':
return TKL_EXCEPT|TKL_GLOBAL;
case 'e':
return TKL_EXCEPT;
return TKL_EXCEPTION;
default:
return 0;
}
@@ -1484,7 +1489,8 @@ int tkl_ip_hash_tkl(aTKline *tkl)
{
if (TKLIsServerBan(tkl))
return tkl_ip_hash(tkl->ptr.serverban->hostmask);
// TODO: expand for except
if (TKLIsBanException(tkl))
return tkl_ip_hash(tkl->ptr.banexception->hostmask);
return -1;
}
@@ -1641,6 +1647,67 @@ aTKline *_tkl_add_serverban(int type, char *usermask, char *hostmask, char *reas
return tkl;
}
/** Add a ban exception TKL entry.
* @param type TKL_EXCEPTION or TKLEXCEPT|TKL_GLOBAL.
* @param usermask The user mask
* @param hostmask The host mask
* @param reason The reason for the ban
* @param set_by Who (or what) set the ban
* @param expire_at When will the ban expire (0 for permanent)
* @param set_at When was the ban set
* @param soft Whether it's a soft-ban
* @param bantypes The ban types to exempt from
* @param flags Any TKL_FLAG_* (TKL_FLAG_CONFIG, etc..)
* @returns The TKL entry, or NULL in case of a problem,
* such as a regex failing to compile, memory problem, ..
* @notes
* Be sure not to call this function for spamfilters,
* qlines or exempts, which have their own function!
*/
aTKline *_tkl_add_banexception(int type, char *usermask, char *hostmask, char *reason, char *set_by,
time_t expire_at, time_t set_at, int soft, char *bantypes, int flags)
{
aTKline *tkl;
int index, index2;
if (!TKLIsBanExceptionType(type))
abort();
tkl = MyMallocEx(sizeof(aTKline));
/* First the common fields */
tkl->type = type;
tkl->flags = flags;
tkl->set_at = set_at;
tkl->set_by = strdup(set_by);
tkl->expire_at = expire_at;
/* Now the ban except fields */
tkl->ptr.banexception = MyMallocEx(sizeof(BanException));
tkl->ptr.banexception->usermask = strdup(usermask);
tkl->ptr.banexception->hostmask = strdup(hostmask);
if (soft)
tkl->ptr.banexception->subtype = TKL_SUBTYPE_SOFT;
tkl->ptr.banexception->bantypes = strdup(bantypes);
tkl->ptr.banexception->reason = strdup(reason);
/* For ip hash table TKL's... */
index = tkl_ip_hash_type(tkl_typetochar(type));
if (index >= 0)
{
index2 = tkl_ip_hash_tkl(tkl);
if (index2 >= 0)
{
AddListItem(tkl, tklines_ip_hash[index][index2]);
return tkl;
}
}
/* If we get here it's just for our normal list.. */
index = tkl_hash(tkl_typetochar(type));
AddListItem(tkl, tklines[index]);
return tkl;
}
/** Add a name ban TKL entry (Q-Line), used for banning nicks and channels.
* @param type The TKL type, one of TKL_*,
* optionally OR'ed with TKL_GLOBAL.
@@ -1905,12 +1972,73 @@ EVENT(tkl_check_expire)
}
}
/** Helper function for find_tkl_exception() */
int find_tkl_exception_matcher(aClient *cptr, aTKline *tkl)
{
char uhost[NICKLEN+HOSTLEN+1];
Hook *hook;
if (!TKLIsBanException(tkl))
return 0;
snprintf(uhost, sizeof(uhost), "%s@%s", tkl->ptr.banexception->usermask, tkl->ptr.banexception->hostmask);
// FIXME: check exception ban types!! (right now it always matches)
if (match_user(uhost, cptr, MATCH_CHECK_REAL))
{
if (!(tkl->ptr.banexception->subtype & TKL_SUBTYPE_SOFT))
return 1; /* hard ban exempt */
if ((tkl->ptr.banexception->subtype & TKL_SUBTYPE_SOFT) && IsLoggedIn(cptr))
return 1; /* soft ban exempt - only matches if user is logged in */
}
return 0; /* not found */
}
int find_tkl_exception(aTKline *ban_tkl, aClient *cptr)
{
aTKline *tkl, *ret;
int index, index2;
Hook *hook;
if (IsServer(cptr) || IsMe(cptr))
return 1;
/* First, the TKL ip hash table entries.. */
index = tkl_ip_hash_type('e');
index2 = tkl_ip_hash(GetIP(cptr));
if (index2 >= 0)
{
for (tkl = tklines_ip_hash[index][index2]; tkl; tkl = tkl->next)
{
if (find_tkl_exception_matcher(cptr, tkl))
return 1; /* exempt */
}
}
/* If not banned (yet), then check regular entries.. */
for (tkl = tklines[tkl_hash('e')]; tkl; tkl = tkl->next)
{
if (find_tkl_exception_matcher(cptr, tkl))
return 1; /* exempt */
}
// FIXME: REMOVE CONF_EXCEPT_TKL plz and CONF_EXCEPT_BAN
for (hook = Hooks[HOOKTYPE_TKL_EXCEPT]; hook; hook = hook->next)
{
if (hook->func.intfunc(cptr, tkl) > 0)
return 1; /* exempt by hook */
}
return 0; /* Not exempt */
}
/** Helper function for find_tkline_match() */
int find_tkline_match_matcher(aClient *cptr, int skip_soft, aTKline *tkl)
{
char uhost[NICKLEN+HOSTLEN+1];
ConfigItem_except *excepts;
int match_type = 0;
Hook *hook;
if (!TKLIsServerBan(tkl) || (tkl->type & TKL_SHUN))
@@ -1928,25 +2056,8 @@ int find_tkline_match_matcher(aClient *cptr, int skip_soft, aTKline *tkl)
((tkl->ptr.serverban->subtype & TKL_SUBTYPE_SOFT) && !IsLoggedIn(cptr)))
{
/* Found match. Now check for exception... */
if (((tkl->type & TKL_KILL) || (tkl->type & TKL_ZAP)) && !(tkl->type & TKL_GLOBAL))
match_type = CONF_EXCEPT_BAN;
else
match_type = CONF_EXCEPT_TKL;
for (excepts = conf_except; excepts; excepts = excepts->next)
{
if (excepts->flag.type != match_type || (match_type == CONF_EXCEPT_TKL &&
excepts->type != tkl->type))
continue;
if (match_user(excepts->mask, cptr, MATCH_CHECK_REAL))
return 0; /* exempt by except block */
}
for (hook = Hooks[HOOKTYPE_TKL_EXCEPT]; hook; hook = hook->next)
{
if (hook->func.intfunc(cptr, tkl) > 0)
return 0; /* exempt by hook */
}
if (find_tkl_exception(tkl, cptr))
return 0; /* exempted */
return 1; /* banned */
}
}
@@ -2574,19 +2685,6 @@ void tkl_synch_send_entry(int add, aClient *sender, aClient *to, aTKline *tkl)
typ = tkl_typetochar(tkl->type);
if (TKLIsSpamfilter(tkl))
{
sendto_one(to, NULL, ":%s TKL %c %c %s %s %s %lld %lld %lld %s %s :%s", sender->name,
add ? '+' : '-',
typ,
spamfilter_target_inttostring(tkl->ptr.spamfilter->target),
banact_valtostring(tkl->ptr.spamfilter->action),
tkl->set_by,
(long long)tkl->expire_at, (long long)tkl->set_at,
(long long)tkl->ptr.spamfilter->tkl_duration, tkl->ptr.spamfilter->tkl_reason,
unreal_match_method_valtostr(tkl->ptr.spamfilter->match->type),
tkl->ptr.spamfilter->match->str);
} else
if (TKLIsServerBan(tkl))
{
sendto_one(to, NULL, ":%s TKL %c %c %s%s %s %s %lld %lld :%s", sender->name,
@@ -2608,6 +2706,36 @@ void tkl_synch_send_entry(int add, aClient *sender, aClient *to, aTKline *tkl)
tkl->set_by,
(long long)tkl->expire_at, (long long)tkl->set_at,
tkl->ptr.nameban->reason);
} else
if (TKLIsSpamfilter(tkl))
{
sendto_one(to, NULL, ":%s TKL %c %c %s %s %s %lld %lld %lld %s %s :%s", sender->name,
add ? '+' : '-',
typ,
spamfilter_target_inttostring(tkl->ptr.spamfilter->target),
banact_valtostring(tkl->ptr.spamfilter->action),
tkl->set_by,
(long long)tkl->expire_at, (long long)tkl->set_at,
(long long)tkl->ptr.spamfilter->tkl_duration, tkl->ptr.spamfilter->tkl_reason,
unreal_match_method_valtostr(tkl->ptr.spamfilter->match->type),
tkl->ptr.spamfilter->match->str);
} else
if (TKLIsBanException(tkl))
{
sendto_one(to, NULL, ":%s TKL %c %c %s%s %s %s %lld %lld %s :%s", sender->name,
add ? '+' : '-',
typ,
(tkl->ptr.banexception->subtype & TKL_SUBTYPE_SOFT) ? "%" : "",
*tkl->ptr.banexception->usermask ? tkl->ptr.banexception->usermask : "*",
tkl->ptr.banexception->hostmask, tkl->set_by,
(long long)tkl->expire_at, (long long)tkl->set_at,
tkl->ptr.banexception->bantypes,
tkl->ptr.banexception->reason);
} else
{
sendto_ops_and_log("[BUG] tkl_synch_send_entry() called, but unknown type %d/'%c'",
tkl->type, typ);
abort();
}
}
@@ -2698,10 +2826,10 @@ char *_tkl_type_string(aTKline *tkl)
case TKL_SPAMF | TKL_GLOBAL:
strlcat(txt, "Spamfilter", sizeof(txt));
break;
case TKL_EXCEPT:
case TKL_EXCEPTION:
strlcat(txt, "Local Exception", sizeof(txt));
break;
case TKL_EXCEPT | TKL_GLOBAL:
case TKL_EXCEPTION | TKL_GLOBAL:
strlcat(txt, "Exception", sizeof(txt));
break;
default:
@@ -2737,6 +2865,32 @@ aTKline *_find_tkl_serverban(int type, char *usermask, char *hostmask, int softb
return NULL; /* Not found */
}
/** Find a ban exception TKL - only used to prevent duplicates and for deletion */
aTKline *_find_tkl_banexception(int type, char *usermask, char *hostmask, int softban)
{
char tpe = tkl_typetochar(type);
aTKline *head, *tkl;
if (!TKLIsBanExceptionType(type))
abort();
head = tkl_find_head(tpe, hostmask, tklines[tkl_hash(tpe)]);
for (tkl = head; tkl; tkl = tkl->next)
{
if (tkl->type == type)
{
if (!stricmp(tkl->ptr.banexception->hostmask, hostmask) &&
!stricmp(tkl->ptr.banexception->usermask, usermask))
{
/* And an extra check for soft/hard ban mismatches.. */
if ((tkl->ptr.banexception->subtype & TKL_SUBTYPE_SOFT) == softban)
return tkl;
}
}
}
return NULL; /* Not found */
}
/** Find a name ban TKL (qline) - only used to prevent duplicates and for deletion */
aTKline *_find_tkl_nameban(int type, char *name, int hold)
{
@@ -2835,6 +2989,23 @@ void _sendnotice_tkl_add(aTKline *tkl)
set_at,
tkl->set_by);
} else
if (TKLIsBanException(tkl))
{
if (tkl->expire_at != 0)
{
ircsnprintf(buf, sizeof(buf), "Exception added for %s%s@%s for types '%s' on %s GMT (from %s to expire at %s GMT: %s)",
(tkl->ptr.banexception->subtype & TKL_SUBTYPE_SOFT) ? "%" : "",
tkl->ptr.banexception->usermask, tkl->ptr.banexception->hostmask,
tkl->ptr.banexception->bantypes,
set_at, tkl->set_by, expire_at, tkl->ptr.banexception->reason);
} else {
ircsnprintf(buf, sizeof(buf), "Permanent exception added for %s%s@%s for types '%s' on %s GMT (from %s: %s)",
(tkl->ptr.banexception->subtype & TKL_SUBTYPE_SOFT) ? "%" : "",
tkl->ptr.banexception->usermask, tkl->ptr.banexception->hostmask,
tkl->ptr.banexception->bantypes,
set_at, tkl->set_by, tkl->ptr.banexception->reason);
}
} else
{
ircsnprintf(buf, sizeof(buf), "[BUG] %s added but type unhandled in sendnotice_tkl_add()!!!", tkl_type_str);
}
@@ -2879,6 +3050,14 @@ void _sendnotice_tkl_del(char *removed_by, aTKline *tkl)
"%s removed Spamfilter '%s' (set at %s)",
removed_by, tkl->ptr.spamfilter->match->str, set_at);
} else
if (TKLIsBanException(tkl))
{
ircsnprintf(buf, sizeof(buf),
"%s removed exception on %s@%s (set at %s - reason: %s)",
removed_by,
tkl->ptr.banexception->usermask, tkl->ptr.banexception->hostmask,
set_at, tkl->ptr.banexception->reason);
} else
{
ircsnprintf(buf, sizeof(buf), "[BUG] %s added but type unhandled in sendnotice_tkl_del()!!!!!", tkl_type_str);
}
@@ -2975,6 +3154,54 @@ CMD_FUNC(m_tkl_add)
set_by, expire_at, set_at, softban, 0);
}
} else
if (TKLIsBanExceptionType(type))
{
/* Validate ban exception TKL fields */
int softban = 0;
char *usermask = parv[3];
char *hostmask = parv[4];
char *bantypes = parv[8];
char *reason;
if (parc < 10)
return 0;
reason = parv[9];
/* Some simple validation on usermask and hostmask:
* may not contain an @. Yeah, some services or self-written
* linked servers are known to have sent this in the past.
*/
if (strchr(usermask, '@') || strchr(hostmask, '@'))
{
sendto_realops("Ignoring TKL exception entry %s@%s from %s. "
"Invalid usermask '%s' or hostmask '%s'.",
usermask, hostmask, sptr->name, usermask, hostmask);
return 0;
}
/* In case of a soft ban, strip the percent sign early,
* so parv[3] (username) is really the username without any prefix.
* Set the 'softban' flag if this is the case.
*/
if (*usermask == '%')
{
usermask++;
softban = 1;
}
/* At this moment we do not validate 'bantypes' since a missing
* or wrong type does not cause harm anyway.
*/
tkl = find_tkl_banexception(type, usermask, hostmask, softban);
if (tkl)
{
tkl_entry_exists = 1;
} else {
tkl = tkl_add_banexception(type, usermask, hostmask, reason,
set_by, expire_at, set_at, softban, bantypes, 0);
}
} else
if (TKLIsNameBanType(type))
{
/* Validate name ban TKL fields */
@@ -3159,6 +3386,21 @@ CMD_FUNC(m_tkl_del)
tkl = find_tkl_serverban(type, usermask, hostmask, softban);
}
else if (TKLIsBanExceptionType(type))
{
char *usermask = parv[3];
char *hostmask = parv[4];
int softban = 0;
/* other parameters are ignored */
if (*usermask == '%')
{
usermask++;
softban = 1;
}
tkl = find_tkl_banexception(type, usermask, hostmask, softban);
}
else if (TKLIsNameBanType(type))
{
int hold = 0;
@@ -3226,7 +3468,18 @@ CMD_FUNC(m_tkl_del)
if (type & TKL_GLOBAL)
tkl_broadcast_entry(0, sptr, cptr, tkl);
if (TKLIsBanException(tkl))
{
/* Since an exception has been removed we have to re-check if
* any connected user is now matched by a ban.
* Set flag here, actual checking takes place in main loop.
*/
loop.do_bancheck = 1;
}
tkl_del_line(tkl);
return 0;
}
@@ -3241,19 +3494,20 @@ CMD_FUNC(m_tkl_del)
* This routine is used both internally by the ircd (to
* for example add local klines, zlines, etc) and over the
* network (glines, gzlines, spamfilter, etc).
* add: remove: spamfilter spamfilter sqline:
* remove in U4: with TKLEXT2:
* parv[ 1]: + - - +/- +/-
* parv[ 2]: type type type type type
* parv[ 3]: user user target target hold
* parv[ 4]: host host action action host
* parv[ 5]: set_by removedby (un)set_by set_by set_by
* parv[ 6]: expire_at expire_at (0) expire_at (0) expire_at
* parv[ 7]: set_at set_at set_at set_at
* parv[ 8]: reason regex tkl duration reason
* parv[ 9]: tkl reason [A]
* parv[10]: match-type [B]
* parv[11]: match-string [C]
*
* serverban serverban spamfilter spamfilter sqline: ban exception:
* add: remove: remove in U4: with TKLEXT2:
* parv[ 1]: + - - +/- +/- +/-
* parv[ 2]: type type type type type type
* parv[ 3]: user user target target hold user
* parv[ 4]: host host action action host host
* parv[ 5]: set_by removedby (un)set_by set_by/unset_by set_by set_by
* parv[ 6]: expire_at expire_at (0) expire_at (0) expire_at expire_at
* parv[ 7]: set_at set_at set_at set_at set_at
* parv[ 8]: reason regex tkl duration reason except_type
* parv[ 9]: tkl reason [A] reason
* parv[10]: match-type [B]
* parv[11]: match-string [C]
*
* [A] tkl reason field must be escaped by caller [eg: use unreal_encodespace()
* if m_tkl is called internally].