From aa3e66bb5b802b54324d79d5d246dc9155c36f86 Mon Sep 17 00:00:00 2001 From: Bram Matthys Date: Wed, 5 Sep 2018 16:24:08 +0200 Subject: [PATCH] We now use standard formatted messages for all K-Lines, G-Lines and any other bans that will cause the user to be disconnected. For technical details see the banned_client() function. It's likely I made some mistakes somewhere => testing required!! --- doc/RELEASE-NOTES | 3 + include/h.h | 4 +- include/struct.h | 10 +-- src/modules.c | 11 ++-- src/modules/m_chgname.c | 24 +++++--- src/modules/m_message.c | 2 +- src/modules/m_nick.c | 37 +++-------- src/modules/m_pass.c | 19 ++---- src/modules/m_server.c | 4 +- src/modules/m_setname.c | 53 ++++++++-------- src/modules/m_svsfline.c | 4 +- src/modules/m_svsnline.c | 4 +- src/modules/m_tkl.c | 130 ++++++++++----------------------------- src/modules/m_tsctl.c | 4 +- src/operclass.c | 2 +- src/s_bsd.c | 16 ++--- src/s_misc.c | 74 ++++++++++++++++++++++ src/s_serv.c | 7 +-- src/send.c | 27 ++++++++ 19 files changed, 225 insertions(+), 210 deletions(-) diff --git a/doc/RELEASE-NOTES b/doc/RELEASE-NOTES index 2ea1c326d..775f37679 100644 --- a/doc/RELEASE-NOTES +++ b/doc/RELEASE-NOTES @@ -83,6 +83,9 @@ Other changes: * Windows users may be prompted to install the Visual C++ redistributable package for Visual Studio 2017. This is because we now build on VS 2017 instead of VS 2012. +* We now use standard formatted messages for all K-Lines, G-Lines and + any other bans that will cause the user to be disconnected. + For technical details see the banned_client() function. Module coders: * Windows: Be aware that we now build with Visual Studio 2017. This means diff --git a/include/h.h b/include/h.h index c2709a296..e59c8745c 100644 --- a/include/h.h +++ b/include/h.h @@ -629,8 +629,7 @@ extern MODVAR int (*find_tkline_match)(aClient *cptr, int skip_soft); extern MODVAR int (*find_shun)(aClient *cptr); extern MODVAR int (*find_spamfilter_user)(aClient *sptr, int flags); extern MODVAR aTKline *(*find_qline)(aClient *cptr, char *nick, int *ishold); -extern MODVAR int (*find_tkline_match_zap)(aClient *cptr); -extern MODVAR int (*find_tkline_match_zap_ex)(aClient *cptr, aTKline **rettk); +extern MODVAR aTKline *(*find_tkline_match_zap)(aClient *cptr); extern MODVAR void (*tkl_stats)(aClient *cptr, int type, char *para); extern MODVAR void (*tkl_synch)(aClient *sptr); extern MODVAR int (*m_tkl)(aClient *cptr, aClient *sptr, int parc, char *parv[]); @@ -797,3 +796,4 @@ extern MODVAR int current_serial; extern char *spki_fingerprint(aClient *acptr); extern int is_module_loaded(char *name); extern void close_std_descriptors(void); +extern int banned_client(aClient *acptr, char *bantype, char *reason, int global, int noexit); diff --git a/include/struct.h b/include/struct.h index f1d6e46a6..fbb16f361 100644 --- a/include/struct.h +++ b/include/struct.h @@ -714,10 +714,10 @@ struct Server { /* tkl: - * TKL_KILL|TKL_GLOBAL = Global K:Line (G:Line) - * TKL_ZAP|TKL_GLOBAL = Global Z:Line (ZLINE) - * TKL_KILL = Timed local K:Line - * TKL_ZAP = Local Z:Line + * TKL_KILL|TKL_GLOBAL = Global K-Line (GLINELine) + * TKL_ZAP|TKL_GLOBAL = Global Z-Line (ZLINE) + * TKL_KILL = Local K-Line + * TKL_ZAP = Local Z-Line */ #define TKL_KILL 0x0001 #define TKL_ZAP 0x0002 @@ -1788,6 +1788,8 @@ typedef enum { PLAINTEXT_POLICY_DENY=3 } PlaintextPolicy; +#define NO_EXIT_CLIENT 99 + #endif /* __struct_include__ */ #include "dynconf.h" diff --git a/src/modules.c b/src/modules.c index 1ae4dfd05..a172a25d5 100644 --- a/src/modules.c +++ b/src/modules.c @@ -100,14 +100,13 @@ int (*find_tkline_match)(aClient *cptr, int skip_soft); int (*find_shun)(aClient *cptr); int(*find_spamfilter_user)(aClient *sptr, int flags); aTKline *(*find_qline)(aClient *cptr, char *nick, int *ishold); -int (*find_tkline_match_zap)(aClient *cptr); +aTKline *(*find_tkline_match_zap)(aClient *cptr); void (*tkl_stats)(aClient *cptr, int type, char *para); void (*tkl_synch)(aClient *sptr); int (*m_tkl)(aClient *cptr, aClient *sptr, int parc, char *parv[]); int (*place_host_ban)(aClient *sptr, int action, char *reason, long duration); int (*dospamfilter)(aClient *sptr, char *str_in, int type, char *target, int flags, aTKline **rettk); int (*dospamfilter_viruschan)(aClient *sptr, aTKline *tk, int type); -int (*find_tkline_match_zap_ex)(aClient *cptr, aTKline **rettk); void (*send_list)(aClient *cptr); unsigned char *(*StripColors)(unsigned char *text); const char *(*StripControlCodes)(unsigned char *text); @@ -166,11 +165,11 @@ static const EfunctionsList efunction_table[MAXEFUNCTIONS] = { /* 23 */ {"place_host_ban", (void *)&place_host_ban}, /* 24 */ {"dospamfilter", (void *)&dospamfilter}, /* 25 */ {"dospamfilter_viruschan", (void *)&dospamfilter_viruschan}, -/* 26 */ {"find_tkline_match_zap_ex", (void *)&find_tkline_match_zap_ex}, +/* 26 */ {NULL, NULL}, /* 27 */ {"send_list", (void *)&send_list}, -/* 28 */ {NULL,NULL}, -/* 29 */ {NULL,NULL}, -/* 30 */ {NULL,NULL}, +/* 28 */ {NULL, NULL}, +/* 29 */ {NULL, NULL}, +/* 30 */ {NULL, NULL}, /* 31 */ {"StripColors", (void *)&StripColors}, /* 32 */ {"StripControlCodes", (void *)&StripControlCodes}, /* 33 */ {"spamfilter_build_user_string", (void *)&spamfilter_build_user_string}, diff --git a/src/modules/m_chgname.c b/src/modules/m_chgname.c index d6e6550ef..e41c8ac29 100644 --- a/src/modules/m_chgname.c +++ b/src/modules/m_chgname.c @@ -68,6 +68,7 @@ MOD_UNLOAD(m_chgname) CMD_FUNC(m_chgname) { aClient *acptr; + ConfigItem_ban *bconf; if (!ValidatePermissionsForPath("client:name",sptr,NULL,NULL,NULL)) { @@ -98,16 +99,7 @@ CMD_FUNC(m_chgname) if ((acptr = find_person(parv[1], NULL))) { - /* set the realname first to make n:line checking work */ - ircsnprintf(acptr->info, sizeof(acptr->info), "%s", parv[2]); - /* only check for n:lines if the person who's name is being changed is not an oper */ - if (!ValidatePermissionsForPath("immune:realnameban",acptr,NULL,NULL,NULL) && Find_ban(NULL, acptr->info, CONF_BAN_REALNAME)) { - int xx; - xx = - exit_client(cptr, sptr, &me, - "Your GECOS (real name) is banned from this server"); - return xx; - } + /* Let's log this first */ if (!IsULine(sptr)) { sendto_snomask(SNO_EYES, @@ -121,6 +113,18 @@ CMD_FUNC(m_chgname) GetHost(acptr), parv[2]); } + /* set the realname to make ban checking work */ + ircsnprintf(acptr->info, sizeof(acptr->info), "%s", parv[2]); + + /* only check for realname bans if the person who's name is being changed is NOT an oper */ + if (!ValidatePermissionsForPath("immune:realnameban",acptr,NULL,NULL,NULL) && + ((bconf = Find_ban(NULL, acptr->info, CONF_BAN_REALNAME)))) + { + int xx = banned_client(acptr, "realname", bconf->reason?bconf->reason:"", 0, 0); + if (sptr == acptr) + return xx; /* we just killed ourselves */ + return 0; + } sendto_server(cptr, 0, 0, ":%s CHGNAME %s :%s", sptr->name, acptr->name, parv[2]); diff --git a/src/modules/m_message.c b/src/modules/m_message.c index 930bd2a4f..e015beaaf 100644 --- a/src/modules/m_message.c +++ b/src/modules/m_message.c @@ -552,7 +552,7 @@ size_t n = strlen(f); * 0: block * <0: immediately return with this value (could be FLUSH_BUFFER) * HISTORY: - * F:Line stuff by _Jozeph_ added by Stskeeps with comments. + * Dcc ban stuff by _Jozeph_ added by Stskeeps with comments. * moved and various improvements by Syzop. */ static int check_dcc(aClient *sptr, char *target, aClient *targetcli, char *text) diff --git a/src/modules/m_nick.c b/src/modules/m_nick.c index 2ed5eac73..1082406a8 100644 --- a/src/modules/m_nick.c +++ b/src/modules/m_nick.c @@ -353,9 +353,9 @@ CMD_FUNC(m_uid) if (IsServer(sptr) && !ishold) /* server introducing new client */ { acptrs = find_server(sptr->user == NULL ? parv[6] : sptr->user->server, NULL); - /* (NEW: no unregistered q:line msgs anymore during linking) */ + /* (NEW: no unregistered Q-Line msgs anymore during linking) */ if (!acptrs || (acptrs->serv && acptrs->serv->flags.synced)) - sendto_snomask(SNO_QLINE, "Q:lined nick %s from %s on %s", nick, + sendto_snomask(SNO_QLINE, "Q-Lined nick %s from %s on %s", nick, (*sptr->name != 0 && !IsServer(sptr) ? sptr->name : ""), acptrs ? acptrs->name : "unknown server"); @@ -363,7 +363,7 @@ CMD_FUNC(m_uid) if (IsServer(cptr) && IsPerson(sptr) && !ishold) /* remote user changing nick */ { - sendto_snomask(SNO_QLINE, "Q:lined nick %s from %s on %s", nick, + sendto_snomask(SNO_QLINE, "Q-Lined nick %s from %s on %s", nick, sptr->name, sptr->srvptr ? sptr->srvptr->name : ""); } } @@ -695,9 +695,9 @@ CMD_FUNC(m_nick) if (IsServer(sptr) && !ishold) /* server introducing new client */ { acptrs = find_server(sptr->user == NULL ? parv[6] : sptr->user->server, NULL); - /* (NEW: no unregistered q:line msgs anymore during linking) */ + /* (NEW: no unregistered Q-Line msgs anymore during linking) */ if (!acptrs || (acptrs->serv && acptrs->serv->flags.synced)) - sendto_snomask(SNO_QLINE, "Q:lined nick %s from %s on %s", nick, + sendto_snomask(SNO_QLINE, "Q-Lined nick %s from %s on %s", nick, (*sptr->name != 0 && !IsServer(sptr) ? sptr->name : ""), acptrs ? acptrs->name : "unknown server"); @@ -705,7 +705,7 @@ CMD_FUNC(m_nick) if (IsServer(cptr) && IsPerson(sptr) && !ishold) /* remote user changing nick */ { - sendto_snomask(SNO_QLINE, "Q:lined nick %s from %s on %s", nick, + sendto_snomask(SNO_QLINE, "Q-Lined nick %s from %s on %s", nick, sptr->name, sptr->srvptr ? sptr->srvptr->name : ""); } @@ -1331,38 +1331,19 @@ int _register_user(aClient *cptr, aClient *sptr, char *nick, char *username, cha if ((bconf = Find_ban(sptr, NULL, CONF_BAN_USER))) { ircstp->is_ref++; - sendto_one(cptr, - ":%s %d %s :*** You are not welcome on this server (%s)" - " Email %s for more information.", - me.name, ERR_YOUREBANNEDCREEP, - cptr->name, bconf->reason ? bconf->reason : "", - KLINE_ADDRESS); - return exit_client(cptr, cptr, cptr, "You are banned"); + return banned_client(sptr, "K-Lined", bconf->reason?bconf->reason:"", 0, 0); } /* Check ban realname { } blocks */ if ((bconf = Find_ban(NULL, sptr->info, CONF_BAN_REALNAME))) { ircstp->is_ref++; - sendto_one(cptr, - ":%s %d %s :*** Your GECOS (real name) is not allowed on this server (%s)" - " Please change it and reconnect", - me.name, ERR_YOUREBANNEDCREEP, - cptr->name, bconf->reason ? bconf->reason : ""); - - return exit_client(cptr, sptr, &me, - "Your GECOS (real name) is banned from this server"); + return banned_client(sptr, "realname", bconf->reason?bconf->reason:"", 0, 0); } /* Check require sasl { } blocks */ if (!IsLoggedIn(sptr) && (bconf = Find_ban(sptr, NULL, CONF_BAN_UNAUTHENTICATED))) { ircstp->is_ref++; - sendto_one(cptr, - ":%s %d %s :*** You are not welcome on this server (%s)" - " Email %s for more information.", - me.name, ERR_YOUREBANNEDCREEP, - cptr->name, bconf->reason ? bconf->reason : "", - KLINE_ADDRESS); - return exit_client(cptr, cptr, cptr, "You are banned"); + return banned_client(sptr, "Require-SASL", bconf->reason?bconf->reason:"", 0, 0); } tkl_check_expire(NULL); /* Check G/Z lines before shuns -- kill before quite -- codemastr */ diff --git a/src/modules/m_pass.c b/src/modules/m_pass.c index 1be308c42..d76dd5913 100644 --- a/src/modules/m_pass.c +++ b/src/modules/m_pass.c @@ -69,24 +69,17 @@ MOD_UNLOAD(m_pass) /** Handles zlines/gzlines/throttling/unknown connections */ DLLFUNC int _check_banned(aClient *cptr) { -int i, j; -aTKline *tk; -aClient *acptr, *acptr2; -ConfigItem_ban *bconf; - - j = 1; + aTKline *tk; + aClient *acptr; + ConfigItem_ban *bconf; if ((bconf = Find_ban(cptr, NULL, CONF_BAN_IP))) { - ircsnprintf(zlinebuf, BUFSIZE, - "You are not welcome on this server: %s. Email %s for more information.", - bconf->reason ? bconf->reason : "no reason", KLINE_ADDRESS); - return exit_client(cptr, cptr, &me, zlinebuf); + return banned_client(cptr, "K-Lined", bconf->reason ? bconf->reason : "", 0, 0); } - else if (find_tkline_match_zap_ex(cptr, &tk) != -1) + else if ((tk = find_tkline_match_zap(cptr))) { - ircsnprintf(zlinebuf, BUFSIZE, "Z:Lined (%s)", tk->reason); - return exit_client(cptr, cptr, &me, zlinebuf); + return banned_client(cptr, "Z-Lined", tk->reason, (tk->type & TKL_GLOBAL)?1:0, 0); } else { diff --git a/src/modules/m_server.c b/src/modules/m_server.c index 01e5e0159..0e6f4efdf 100644 --- a/src/modules/m_server.c +++ b/src/modules/m_server.c @@ -688,8 +688,8 @@ CMD_FUNC(m_server_remote) acptr->serv->up = find_or_add(acptr->srvptr->name); SetServer(acptr); ircd_log(LOG_SERVER, "SERVER %s (from %s)", acptr->name, acptr->srvptr->name); - /* Taken from bahamut makes it so all servers behind a U:lined - * server are also U:lined, very helpful if HIDE_ULINES is on + /* Taken from bahamut makes it so all servers behind a U-Lined + * server are also U-Lined, very helpful if HIDE_ULINES is on */ if (IsULine(sptr) || (Find_uline(acptr->name))) diff --git a/src/modules/m_setname.c b/src/modules/m_setname.c index a24069ba2..a9961b836 100644 --- a/src/modules/m_setname.c +++ b/src/modules/m_setname.c @@ -61,14 +61,15 @@ MOD_UNLOAD(m_setname) */ CMD_FUNC(m_setname) { - int xx; - char tmpinfo[REALLEN + 1]; - char spamfilter_user[NICKLEN + USERLEN + HOSTLEN + REALLEN + 64]; + int xx; + char tmpinfo[REALLEN + 1]; + char spamfilter_user[NICKLEN + USERLEN + HOSTLEN + REALLEN + 64]; + ConfigItem_ban *bconf; - if ((parc < 2) || BadPtr(parv[1])) - { - sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, sptr->name, "SETNAME"); - return 0; + if ((parc < 2) || BadPtr(parv[1])) + { + sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, sptr->name, "SETNAME"); + return 0; } if (strlen(parv[1]) > REALLEN) @@ -81,29 +82,33 @@ CMD_FUNC(m_setname) return 0; } - /* set temp info for spamfilter check*/ - strcpy(tmpinfo, sptr->info); - /* set the new name before we check, but don't send to servers unless it is ok */ - strcpy(sptr->info, parv[1]); - spamfilter_build_user_string(spamfilter_user, sptr->name, sptr); - xx = dospamfilter(sptr, spamfilter_user, SPAMF_USER, NULL, 0, NULL); - if (xx < 0) - { - if (xx != FLUSH_BUFFER) - strcpy(sptr->info, tmpinfo); /* restore (if client wasn't killed already, that is) */ - return xx; - } + /* set temp info for spamfilter check*/ + strcpy(tmpinfo, sptr->info); + /* set the new name before we check, but don't send to servers unless it is ok */ + strcpy(sptr->info, parv[1]); + spamfilter_build_user_string(spamfilter_user, sptr->name, sptr); + xx = dospamfilter(sptr, spamfilter_user, SPAMF_USER, NULL, 0, NULL); + if (xx < 0) + { + if (xx != FLUSH_BUFFER) + strcpy(sptr->info, tmpinfo); /* restore (if client wasn't killed already, that is) */ + return xx; + } - /* Check for n:lines here too */ - if (!ValidatePermissionsForPath("immune:namecheck",sptr,NULL,NULL,NULL) && Find_ban(NULL, sptr->info, CONF_BAN_REALNAME)) - return exit_client(cptr, sptr, &me, - "Your GECOS (real name) is banned from this server"); + /* Check for realname bans here too */ + if (!ValidatePermissionsForPath("immune:realnameban",sptr,NULL,NULL,NULL) && + ((bconf = Find_ban(NULL, sptr->info, CONF_BAN_REALNAME)))) + { + return banned_client(sptr, "realname", bconf->reason?bconf->reason:"", 0, 0); + } sendto_server(cptr, 0, 0, ":%s SETNAME :%s", sptr->name, parv[1]); if (MyConnect(sptr)) + { sendnotice(sptr, "Your \"real name\" is now set to be %s - you have to set it manually to undo it", - parv[1]); + parv[1]); + } return 0; } diff --git a/src/modules/m_svsfline.c b/src/modules/m_svsfline.c index 700390f3a..40420792b 100644 --- a/src/modules/m_svsfline.c +++ b/src/modules/m_svsfline.c @@ -59,8 +59,8 @@ CMD_FUNC(m_svsfline) switch (*parv[1]) { - /* Allow non-U:lines to send ONLY SVSFLINE +, but don't send it out - * unless it is from a U:line -- codemastr */ + /* Allow non-U-Lines to send ONLY SVSFLINE +, but don't send it out + * unless it is from a U-Line -- codemastr */ case '+': { if (parc < 4) diff --git a/src/modules/m_svsnline.c b/src/modules/m_svsnline.c index 3d403ab01..87746cbbc 100644 --- a/src/modules/m_svsnline.c +++ b/src/modules/m_svsnline.c @@ -92,8 +92,8 @@ CMD_FUNC(m_svsnline) switch (*parv[1]) { - /* Allow non-U:lines to send ONLY SVSNLINE +, but don't send it out - * unless it is from a U:line -- codemastr */ + /* Allow non-U-Lines to send ONLY SVSNLINE +, but don't send it out + * unless it is from a U-Line -- codemastr */ case '+': { if (parc < 4) diff --git a/src/modules/m_tkl.c b/src/modules/m_tkl.c index 9914a2785..8954bbe55 100644 --- a/src/modules/m_tkl.c +++ b/src/modules/m_tkl.c @@ -62,8 +62,7 @@ int _find_tkline_match(aClient *cptr, int skip_soft); int _find_shun(aClient *cptr); int _find_spamfilter_user(aClient *sptr, int flags); aTKline *_find_qline(aClient *cptr, char *nick, int *ishold); -int _find_tkline_match_zap(aClient *cptr); -int _find_tkline_match_zap_ex(aClient *cptr, aTKline **rettk); +aTKline *_find_tkline_match_zap(aClient *cptr); void _tkl_stats(aClient *cptr, int type, char *para); void _tkl_synch(aClient *sptr); int _m_tkl(aClient *cptr, aClient *sptr, int parc, char *parv[]); @@ -113,8 +112,7 @@ MOD_TEST(m_tkl) EfunctionAdd(modinfo->handle, EFUNC_FIND_SHUN, _find_shun); EfunctionAdd(modinfo->handle, EFUNC_FIND_SPAMFILTER_USER, _find_spamfilter_user); EfunctionAddPVoid(modinfo->handle, EFUNC_FIND_QLINE, TO_PVOIDFUNC(_find_qline)); - EfunctionAdd(modinfo->handle, EFUNC_FIND_TKLINE_MATCH_ZAP, _find_tkline_match_zap); - EfunctionAdd(modinfo->handle, EFUNC_FIND_TKLINE_MATCH_ZAP_EX, _find_tkline_match_zap_ex); + EfunctionAddPVoid(modinfo->handle, EFUNC_FIND_TKLINE_MATCH_ZAP, TO_PVOIDFUNC(_find_tkline_match_zap)); EfunctionAddVoid(modinfo->handle, EFUNC_TKL_STATS, _tkl_stats); EfunctionAddVoid(modinfo->handle, EFUNC_TKL_SYNCH, _tkl_synch); EfunctionAdd(modinfo->handle, EFUNC_M_TKL, _m_tkl); @@ -1129,24 +1127,24 @@ aTKline *_tkl_expire(aTKline * tmp) if (tmp->type & TKL_GLOBAL) { if (tmp->type & TKL_KILL) - strlcpy(whattype, "G:Line", sizeof(whattype)); + strlcpy(whattype, "G-Line", sizeof(whattype)); else if (tmp->type & TKL_ZAP) - strlcpy(whattype, "Global Z:Line", sizeof(whattype)); + strlcpy(whattype, "Global Z-Line", sizeof(whattype)); else if (tmp->type & TKL_SHUN) strlcpy(whattype, "Shun", sizeof(whattype)); else if (tmp->type & TKL_NICK) - strlcpy(whattype, "Global Q:line", sizeof(whattype)); + strlcpy(whattype, "Global Q-Line", sizeof(whattype)); } else { if (tmp->type & TKL_KILL) - strlcpy(whattype, "K:Line", sizeof(whattype)); + strlcpy(whattype, "K-Line", sizeof(whattype)); else if (tmp->type & TKL_ZAP) - strlcpy(whattype, "Z:Line", sizeof(whattype)); + strlcpy(whattype, "Z-Line", sizeof(whattype)); else if (tmp->type & TKL_SHUN) strlcpy(whattype, "Local Shun", sizeof(whattype)); else if (tmp->type & TKL_NICK) - strlcpy(whattype, "Q:line", sizeof(whattype)); + strlcpy(whattype, "Q-Line", sizeof(whattype)); } if (!(tmp->type & TKL_NICK)) { @@ -1159,7 +1157,7 @@ aTKline *_tkl_expire(aTKline * tmp) whattype, tmp->usermask, tmp->hostmask, tmp->setby, tmp->reason, TStime() - tmp->set_at); } - else if (!(*tmp->usermask == 'H')) /* Q:line but not a hold */ + else if (!(*tmp->usermask == 'H')) /* Q-Line but not a hold */ { sendto_snomask(SNO_TKL, "*** Expiring %s (%s) made by %s (Reason: %s) set %li seconds ago", @@ -1202,7 +1200,6 @@ EVENT(_tkl_check_expire) int _find_tkline_match(aClient *cptr, int skip_soft) { aTKline *lp; - char msge[1024]; int banned = 0; ConfigItem_except *excepts; int match_type = 0; @@ -1274,58 +1271,16 @@ int _find_tkline_match(aClient *cptr, int skip_soft) if (lp->type & TKL_KILL) { + ircstp->is_ref++; if (lp->type & TKL_GLOBAL) - { - ircstp->is_ref++; - if (GLINE_ADDRESS) - sendto_one(cptr, ":%s NOTICE %s :*** You are %s from %s (%s). Email %s for more information.", - me.name, cptr->name, - (lp->expire_at ? "banned" : "permanently banned"), - ircnetwork, lp->reason, GLINE_ADDRESS); - else - sendto_one(cptr, ":%s NOTICE %s :*** You are %s from %s (%s)", - me.name, cptr->name, - (lp->expire_at ? "banned" : "permanently banned"), - ircnetwork, lp->reason); - - if (HIDE_BAN_REASON && IsRegistered(cptr)) - ircsnprintf(msge, sizeof(msge), "User has been %s from %s", - (lp->expire_at ? "banned" : "permanently banned"), - ircnetwork); - else - ircsnprintf(msge, sizeof(msge), "User has been %s from %s (%s)", - (lp->expire_at ? "banned" : "permanently banned"), - ircnetwork, lp->reason); - - return exit_client(cptr, cptr, &me, msge); - } + return banned_client(cptr, "G-Lined", lp->reason, 1, 0); else - { - ircstp->is_ref++; - sendto_one(cptr, ":%s NOTICE %s :*** You are %s from %s (%s). Email %s for more information.", - me.name, cptr->name, - (lp->expire_at ? "banned" : "permanently banned"), - me.name, lp->reason, KLINE_ADDRESS); - - if (HIDE_BAN_REASON && IsRegistered(cptr)) - ircsnprintf(msge, sizeof(msge), "User is %s", - (lp->expire_at ? "banned" : "permanently banned")); - else - ircsnprintf(msge, sizeof(msge), "User is %s (%s)", - (lp->expire_at ? "banned" : "permanently banned"), - lp->reason); - - return exit_client(cptr, cptr, &me, msge); - } + return banned_client(cptr, "K-Lined", lp->reason, 0, 0); } if (lp->type & TKL_ZAP) { ircstp->is_ref++; - if (HIDE_BAN_REASON && IsRegistered(cptr)) - strlcpy(msge, "Z:lined", sizeof(msge)); - else - ircsnprintf(msge, sizeof(msge), "Z:lined (%s)",lp->reason); - return exit_client(cptr, cptr, &me, msge); + return banned_client(cptr, "Z-Lined", lp->reason, (lp->type & TKL_GLOBAL)?1:0, 0); } return 3; @@ -1540,25 +1495,20 @@ aTKline *_find_qline(aClient *cptr, char *nick, int *ishold) } -/** Check if specified user matches a (G)ZLINE. If so, kill the user. - * This is the extended version which returns the tkline that matched. - * @retval 1 if matched (user is killed, don't touch 'cptr' anymore), - * or -1 if not matched. +/** Find matching (G)ZLINE, if any. + * Note: function prototype changed as per UnrealIRCd 4.0.19. + * @retval The (G)Z-Line that matched, or NULL if no such ban was found. */ -int _find_tkline_match_zap_ex(aClient *cptr, aTKline **rettk) +aTKline *_find_tkline_match_zap(aClient *cptr) { aTKline *lp; char *cip; TS nowtime; - char msge[1024]; ConfigItem_except *excepts; Hook *hook; - if (rettk) - *rettk = NULL; - if (IsServer(cptr) || IsMe(cptr)) - return -1; + return NULL; nowtime = TStime(); cip = GetIP(cptr); @@ -1577,33 +1527,17 @@ int _find_tkline_match_zap_ex(aClient *cptr, aTKline **rettk) if (excepts->flag.type != CONF_EXCEPT_BAN) continue; if (match_user(excepts->mask, cptr, MATCH_CHECK_IP)) - return -1; /* exempt */ + return NULL; /* exempt */ } for (hook = Hooks[HOOKTYPE_TKL_EXCEPT]; hook; hook = hook->next) if (hook->func.intfunc(cptr, lp) > 0) - return -1; /* exempt */ + return NULL; /* exempt */ - ircstp->is_ref++; - ircsnprintf(msge, sizeof(msge), - "ERROR :Closing Link: [%s] Z:Lined (%s)\r\n", - cptr->ip, lp->reason); - strlcpy(zlinebuf, msge, sizeof zlinebuf); - if (rettk) - *rettk = lp; - return (1); + return lp; } } - return -1; -} -/** Check if user matches a (G)ZLINE. If so, kill the user. - * This is the simplified version. - * @retval 1 if matched (user is killed, don't touch 'cptr' anymore), - * or -1 if not matched. - */ -int _find_tkline_match_zap(aClient *cptr) -{ - return _find_tkline_match_zap_ex(cptr, NULL); + return NULL; } #define BY_MASK 0x1 @@ -1885,28 +1819,28 @@ char *tkl_type_string(aTKline *tk) switch (tk->type) { case TKL_KILL: - strlcat(txt, "K:Line", sizeof(txt)); + strlcat(txt, "K-Line", sizeof(txt)); break; case TKL_ZAP: - strlcat(txt, "Z:Line", sizeof(txt)); + strlcat(txt, "Z-Line", sizeof(txt)); break; case TKL_KILL | TKL_GLOBAL: - strlcat(txt, "G:Line", sizeof(txt)); + strlcat(txt, "G-Line", sizeof(txt)); break; case TKL_ZAP | TKL_GLOBAL: - strlcat(txt, "Global Z:line", sizeof(txt)); + strlcat(txt, "Global Z-Line", sizeof(txt)); break; case TKL_SHUN | TKL_GLOBAL: strlcat(txt, "Shun", sizeof(txt)); break; case TKL_NICK | TKL_GLOBAL: - strlcat(txt, "Global Q:line", sizeof(txt)); + strlcat(txt, "Global Q-Line", sizeof(txt)); break; case TKL_NICK: - strlcat(txt, "Q:line", sizeof(txt)); + strlcat(txt, "Q-Line", sizeof(txt)); break; default: - strlcat(txt, "Unknown *:Line", sizeof(txt)); + strlcat(txt, "Unknown *-Line", sizeof(txt)); } return txt; @@ -2067,7 +2001,7 @@ int _m_tkl(aClient *cptr, aClient *sptr, int parc, char *parv[]) } } } - /* *:Line already exists! */ + /* *Line already exists! */ if (found == 1) { /* SYZTAG: TODO: check for tklreason/tklduration differences */ @@ -2202,7 +2136,7 @@ int _m_tkl(aClient *cptr, aClient *sptr, int parc, char *parv[]) spamfilter_check_users(tk); } else { char buf[512]; - char *tkl_type_str = tkl_type_string(tk); /* eg: "K:Line" */ + char *tkl_type_str = tkl_type_string(tk); /* eg: "K-Line" */ if (expiry_1 != 0) { @@ -2382,7 +2316,7 @@ int _m_tkl(aClient *cptr, aClient *sptr, int parc, char *parv[]) /* So... do we have a match? Then we start the removal process: */ if (match) { - char *tkl_type_str = tkl_type_string(tk); /* eg: "K:Line" */ + char *tkl_type_str = tkl_type_string(tk); /* eg: "K-Line" */ strlcpy(gmt, asctime(gmtime((TS *)&tk->set_at)), sizeof(gmt)); iCstrip(gmt); diff --git a/src/modules/m_tsctl.c b/src/modules/m_tsctl.c index 4d924733a..8a34c1984 100644 --- a/src/modules/m_tsctl.c +++ b/src/modules/m_tsctl.c @@ -173,11 +173,11 @@ CMD_FUNC(m_tsctl) timediff = atol(parv[2]); timediff = timediff - time(NULL); - ircd_log(LOG_ERROR, "TSCTL: U:line %s set time to be %li (timediff: %li, was %li)", + ircd_log(LOG_ERROR, "TSCTL: U-Line %s set time to be %li (timediff: %li, was %li)", sptr->name, atol(parv[2]), timediff, TSoffset); TSoffset = timediff; sendto_ops - ("TS Control - U:line set time to be %li (timediff: %li)", + ("TS Control - U-Line set time to be %li (timediff: %li)", atol(parv[2]), timediff); sendto_server(cptr, 0, 0, ":%s TSCTL svstime %li", sptr->name, atol(parv[2])); diff --git a/src/operclass.c b/src/operclass.c index bbc7a3ce1..2674cde04 100644 --- a/src/operclass.c +++ b/src/operclass.c @@ -302,7 +302,7 @@ OperPermission ValidatePermissionsForPath(char* path, aClient *sptr, aClient *vi if (!sptr) return OPER_DENY; - /* Trust Servers, U:Lines and remote opers */ + /* Trust Servers, U-Lines and remote opers */ if (IsServer(sptr) || IsULine(sptr) || (IsOper(sptr) && !MyClient(sptr))) return OPER_ALLOW; diff --git a/src/s_bsd.c b/src/s_bsd.c index d0e18cc5c..a032ca809 100644 --- a/src/s_bsd.c +++ b/src/s_bsd.c @@ -992,6 +992,7 @@ aClient *add_connection(ConfigItem_listen *listener, int fd) { aClient *acptr, *acptr2; ConfigItem_ban *bconf; + aTKline *tk; int i, j; char *ip; int port = 0; @@ -1026,6 +1027,7 @@ add_con_refuse: set_sockhost(acptr, ip); acptr->ip = strdup(ip); acptr->local->port = port; + acptr->fd = fd; /* Tag loopback connections as FLAGS_LOCAL */ if (is_loopback_ip(acptr->ip)) @@ -1060,19 +1062,14 @@ add_con_refuse: { if (bconf) { - ircsnprintf(zlinebuf, sizeof(zlinebuf), - "ERROR :Closing Link: [%s] (You are not welcome on " - "this server: %s. Email %s for more information.)\r\n", - acptr->ip, - bconf->reason ? bconf->reason : "no reason", - KLINE_ADDRESS); - (void)send(fd, zlinebuf, strlen(zlinebuf), 0); + banned_client(acptr, "K-Lined", bconf->reason ? bconf->reason : "no reason", 0, NO_EXIT_CLIENT); goto add_con_refuse; } } - else if (find_tkline_match_zap(acptr) != -1) + else if ((tk = find_tkline_match_zap(acptr))) { - (void)send(fd, zlinebuf, strlen(zlinebuf), 0); + ircstp->is_ref++; + banned_client(acptr, "Z-Lined", tk->reason, (tk->type & TKL_GLOBAL)?1:0, NO_EXIT_CLIENT); goto add_con_refuse; } else @@ -1092,7 +1089,6 @@ add_con_refuse: add_throttling_bucket(acptr); } - acptr->fd = fd; acptr->local->listener = listener; if (acptr->local->listener != NULL) acptr->local->listener->clients++; diff --git a/src/s_misc.c b/src/s_misc.c index c3e262580..e969e4a46 100644 --- a/src/s_misc.c +++ b/src/s_misc.c @@ -1206,3 +1206,77 @@ int IsWebsocket(aClient *acptr) return 0; /* websocket module not loaded */ return (MyConnect(acptr) && moddata_client(acptr, md).ptr) ? 1 : 0; } + +extern void send_raw_direct(aClient *user, char *pattern, ...); + +/** Generic function to inform the user he/she has been banned. + * @param acptr The affected client. + * @param bantype The ban type, such as: "K-Lined", "G-Lined" or "realname". + * @param reason The specified reason. + * @param global Whether the ban is global (1) or for this server only (0) + * @param noexit Set this to NO_EXIT_CLIENT to make us not call exit_client(). + * This is really only needed from the accept code, do not + * use it anywhere else. No really, never. + * + * @notes This function will call exit_client() appropriately. + * @retval Usually FLUSH_BUFFER. In any case: do not touch 'acptr' after + * calling this function! + */ +int banned_client(aClient *acptr, char *bantype, char *reason, int global, int noexit) +{ + char buf[512], contactbuf[512]; + + if (!MyConnect(acptr)) + abort(); /* hmm... or be more flexible? */ + + if (1) + { + snprintf(contactbuf, sizeof(contactbuf), "Email %s for more information.", + (global && GLINE_ADDRESS) ? GLINE_ADDRESS : KLINE_ADDRESS); + } + + snprintf(buf, sizeof(buf), "You are not welcome on this %s. %s: %s. %s", + global ? "network" : "server", + bantype, + reason, + contactbuf); + + /* This is a bit extensive but we will send both a YOUAREBANNEDCREEP + * and a notice to the user. + * The YOUAREBANNEDCREEP will be helpful for the client since it makes + * clear the user should not quickly reconnect, as (s)he is banned. + * The notice still needs to be there because it stands out well + * at most IRC clients. + */ + if (noexit != NO_EXIT_CLIENT) + { + sendto_one(acptr,":%s %d %s :%s", + me.name, ERR_YOUREBANNEDCREEP, + (*acptr->name ? acptr->name : "*"), + buf); + sendnotice(acptr, "%s", buf); + } else { + send_raw_direct(acptr, ":%s %d %s :%s", + me.name, ERR_YOUREBANNEDCREEP, + (*acptr->name ? acptr->name : "*"), + buf); + send_raw_direct(acptr, ":%s NOTICE %s :%s", + me.name, (*acptr->name ? acptr->name : "*"), buf); + } + + /* The final message in the ERROR is shorter. */ + if (HIDE_BAN_REASON && IsRegistered(acptr)) + snprintf(buf, sizeof(buf), "Banned (%s)", bantype); + else + snprintf(buf, sizeof(buf), "Banned (%s): %s", bantype, reason); + + if (noexit != NO_EXIT_CLIENT) + { + return exit_client(acptr, acptr, acptr, buf); + } else { + /* Special handling for direct Z-line code */ + send_raw_direct(acptr, "ERROR :Closing Link: [%s] (%s)", + acptr->ip, buf); + return 0; + } +} diff --git a/src/s_serv.c b/src/s_serv.c index a1c9fe968..81793db2c 100644 --- a/src/s_serv.c +++ b/src/s_serv.c @@ -814,11 +814,8 @@ CMD_FUNC(m_rehash) /* ** m_restart ** -** parv[1] - password *OR* reason if no X:line -** parv[2] - reason for restart (optional & only if X:line exists) -** -** The password is only valid if there is a matching X line in the -** config file. If it is not, then it becomes the +** parv[1] - password *OR* reason if no drpass { } block exists +** parv[2] - reason for restart (optional & only if drpass block exists) */ CMD_FUNC(m_restart) { diff --git a/src/send.c b/src/send.c index 51a54969a..1889145dc 100644 --- a/src/send.c +++ b/src/send.c @@ -1446,3 +1446,30 @@ va_list vl; vsendto_one(to, realpattern, vl); va_end(vl); } + +/** Send raw data directly to socket, bypassing everything. + * Looks like an interesting function to call? NO! STOP! + * Don't use this function. It may only be used by the initial + * Z-Line check via the codepath to banned_client(). + * YOU SHOULD NEVER USE THIS FUNCTION. + * If you want to send raw data (without formatting) to a client + * then have a look at sendbufto_one() instead. + * + * Side-effects: + * Too many to list here. Only in the early accept code the + * "if's" and side-effects are under control. + * + * By the way, did I already mention that you SHOULD NOT USE THIS + * FUNCTION? ;) + */ +void send_raw_direct(aClient *user, char *pattern, ...) +{ + va_list vl; + int sendlen; + + *sendbuf = '\0'; + va_start(vl, pattern); + sendlen = vmakebuf_local_withprefix(sendbuf, sizeof sendbuf, user, pattern, vl); + va_end(vl); + send(user->fd, sendbuf, sendlen, 0); +}