From e5fe33f011ac4e1c6eb86c1a45b466d06adb79d5 Mon Sep 17 00:00:00 2001 From: jesopo Date: Fri, 15 Apr 2022 13:55:22 +0000 Subject: [PATCH 1/4] run spamfilters against NICK --- extensions/filter.c | 25 +++++++++++++++++++++++++ modules/core/m_nick.c | 6 ++++++ 2 files changed, 31 insertions(+) diff --git a/extensions/filter.c b/extensions/filter.c index bebcbdfca..fecba7542 100644 --- a/extensions/filter.c +++ b/extensions/filter.c @@ -56,6 +56,7 @@ static const char filter_desc[] = "Filter messages using a precompiled Hyperscan static void filter_msg_user(void *data); static void filter_msg_channel(void *data); static void filter_client_quit(void *data); +static void filter_client_nick(void *data); static void on_client_exit(void *data); static void mo_setfilter(struct MsgBuf *, struct Client *, struct Client *, int, const char **); @@ -93,6 +94,7 @@ mapi_hfn_list_av1 filter_hfnlist[] = { { "privmsg_user", filter_msg_user }, { "privmsg_channel", filter_msg_channel }, { "client_quit", filter_client_quit }, + { "local_nick_change", filter_client_nick }, { "client_exit", on_client_exit }, { NULL, NULL } }; @@ -483,6 +485,29 @@ filter_client_quit(void *data_) /* No point in doing anything with ACT_KILL */ } +void +filter_client_nick(void *data_) +{ + hook_cdata *data = data_; + struct Client *s = data->client; + if (IsOper(s)) { + return; + } + + unsigned r = match_message("0", s, "NICK", NULL, data->arg2); + if (r & ACT_DROP) { + data->arg2 = NULL; + } + if (r & ACT_ALARM) { + sendto_realops_snomask(SNO_GENERAL, L_ALL | L_NETWIDE, + "FILTER: %s!%s@%s [%s]", + s->name, s->username, s->host, s->sockhost); + } + if (r & ACT_KILL) { + exit_client(NULL, s, s, FILTER_EXIT_MSG); + } +} + void on_client_exit(void *data_) { diff --git a/modules/core/m_nick.c b/modules/core/m_nick.c index dcdd48371..df221831d 100644 --- a/modules/core/m_nick.c +++ b/modules/core/m_nick.c @@ -671,6 +671,12 @@ change_local_nick(struct Client *client_p, struct Client *source_p, hook_info.arg2 = nick; call_hook(h_local_nick_change, &hook_info); + if (!hook_info.arg2) { + sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME), + me.name, EmptyString(source_p->name) ? "*" : source_p->name, nick); + return; + } + sendto_realops_snomask(SNO_NCHANGE, L_ALL, "Nick change: From %s to %s [%s@%s]", source_p->name, nick, source_p->username, source_p->host); From abc23d5c27dec37bdc87fbeefbe88cad51769431 Mon Sep 17 00:00:00 2001 From: jesopo Date: Fri, 2 Feb 2024 01:03:56 +0000 Subject: [PATCH 2/4] also run filters against pre-reg NICK --- extensions/filter.c | 49 ++++++++++++++++++++++++++++++++++--------- include/hook.h | 8 +++++++ modules/core/m_nick.c | 33 ++++++++++++++++++++++++----- 3 files changed, 75 insertions(+), 15 deletions(-) diff --git a/extensions/filter.c b/extensions/filter.c index fecba7542..9867daa39 100644 --- a/extensions/filter.c +++ b/extensions/filter.c @@ -41,6 +41,8 @@ #include "operhash.h" #include "inline/stringops.h" #include "msgbuf.h" +#include "hostmask.h" +#include "s_conf.h" #include #include @@ -56,7 +58,8 @@ static const char filter_desc[] = "Filter messages using a precompiled Hyperscan static void filter_msg_user(void *data); static void filter_msg_channel(void *data); static void filter_client_quit(void *data); -static void filter_client_nick(void *data); +static void filter_client_nick_set(void *data); +static void filter_client_nick_change(void *data); static void on_client_exit(void *data); static void mo_setfilter(struct MsgBuf *, struct Client *, struct Client *, int, const char **); @@ -94,7 +97,8 @@ mapi_hfn_list_av1 filter_hfnlist[] = { { "privmsg_user", filter_msg_user }, { "privmsg_channel", filter_msg_channel }, { "client_quit", filter_client_quit }, - { "local_nick_change", filter_client_nick }, + { "local_nick_set_approve", filter_client_nick_set }, + { "local_nick_change_approve", filter_client_nick_change }, { "client_exit", on_client_exit }, { NULL, NULL } }; @@ -353,21 +357,21 @@ unsigned match_message(const char *prefix, snprintf(check_buffer, sizeof check_buffer, "%s:%s!%s@%s#%c %s%s%s :%s", prefix, #if FILTER_NICK - source->name, + source ? source->name : "*", #else "*", #endif #if FILTER_USER - source->username, + source ? source->username : "*", #else "*", #endif #if FILTER_HOST - source->host, + source ? source->host : "*", #else "*", #endif - source->user && source->user->suser[0] != '\0' ? '1' : '0', + source && source->user && source->user->suser[0] != '\0' ? '1' : '0', command, target ? " " : "", target ? target : "", @@ -486,17 +490,17 @@ filter_client_quit(void *data_) } void -filter_client_nick(void *data_) +filter_client_nick_change(void *data_) { - hook_cdata *data = data_; + hook_data_nick_approval *data = data_; struct Client *s = data->client; if (IsOper(s)) { return; } - unsigned r = match_message("0", s, "NICK", NULL, data->arg2); + unsigned r = match_message("0", s, "NICK", NULL, data->nick); if (r & ACT_DROP) { - data->arg2 = NULL; + data->approved = 0; } if (r & ACT_ALARM) { sendto_realops_snomask(SNO_GENERAL, L_ALL | L_NETWIDE, @@ -508,6 +512,31 @@ filter_client_nick(void *data_) } } +void +filter_client_nick_set(void *data_) +{ + hook_data_nick_approval *data = data_; + struct Client *s = data->client; + struct sockaddr *addr = (void *)&s->localClient->ip; + + if(find_conf_by_address( + NULL, NULL, NULL, addr, CONF_EXEMPTDLINE | 1, GET_SS_FAMILY(addr), NULL, NULL)) + return; + + unsigned r = match_message("0", NULL, "NICK", NULL, data->nick); + if (r & ACT_DROP) { + data->approved = 0; + } + if (r & ACT_ALARM) { + sendto_realops_snomask(SNO_GENERAL, L_ALL | L_NETWIDE, + "FILTER:REGISTER: %s@%s", + s->id, s->sockhost); + } + if (r & ACT_KILL) { + exit_client(NULL, s, s, FILTER_EXIT_MSG); + } +} + void on_client_exit(void *data_) { diff --git a/include/hook.h b/include/hook.h index fc56b2888..9e6cc6dff 100644 --- a/include/hook.h +++ b/include/hook.h @@ -164,6 +164,14 @@ typedef struct int del; } hook_data_cap_change; +typedef struct +{ + struct Client *client; + const void *nick; + int approved; +} hook_data_nick_approval; + + enum message_type { MESSAGE_TYPE_NOTICE, MESSAGE_TYPE_PRIVMSG, diff --git a/modules/core/m_nick.c b/modules/core/m_nick.c index df221831d..5515fad3b 100644 --- a/modules/core/m_nick.c +++ b/modules/core/m_nick.c @@ -79,7 +79,9 @@ static void perform_nick_collides(struct Client *, struct Client *, static void perform_nickchange_collides(struct Client *, struct Client *, struct Client *, int, const char **, time_t, const char *); +static int h_local_nick_set_approve; static int h_local_nick_change; +static int h_local_nick_change_approve; static int h_remote_nick_change; struct Message nick_msgtab = { @@ -103,7 +105,9 @@ mapi_clist_av1 nick_clist[] = { &nick_msgtab, &uid_msgtab, &euid_msgtab, &save_msgtab, NULL }; mapi_hlist_av1 nick_hlist[] = { + { "local_nick_set_approve", &h_local_nick_set_approve }, { "local_nick_change", &h_local_nick_change }, + { "local_nick_change_approve", &h_local_nick_change_approve }, { "remote_nick_change", &h_remote_nick_change }, { NULL, NULL } }; @@ -121,6 +125,7 @@ mr_nick(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_ { struct Client *target_p; char nick[NICKLEN]; + hook_data_nick_approval hook_approve; if (strlen(client_p->id) == 3 || (source_p->preClient && !EmptyString(source_p->preClient->id))) { @@ -161,6 +166,18 @@ mr_nick(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_ return; } + hook_approve.client = source_p; + hook_approve.nick = nick; + hook_approve.approved = 1; + call_hook(h_local_nick_set_approve, &hook_approve); + + if (!hook_approve.approved) { + /* send the same error they'd get if this nick was RESV */ + sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME), + me.name, EmptyString(source_p->name) ? "*" : source_p->name, nick); + return; + } + if((target_p = find_named_client(nick)) == NULL) set_initial_nick(client_p, source_p, nick); else if(source_p == target_p) @@ -622,6 +639,7 @@ change_local_nick(struct Client *client_p, struct Client *source_p, struct Channel *chptr; char note[NICKLEN + 10]; int samenick; + hook_data_nick_approval hook_approve; hook_cdata hook_info; if (dosend) @@ -666,17 +684,22 @@ change_local_nick(struct Client *client_p, struct Client *source_p, invalidate_bancache_user(source_p); } - hook_info.client = source_p; - hook_info.arg1 = source_p->name; - hook_info.arg2 = nick; - call_hook(h_local_nick_change, &hook_info); + hook_approve.client = source_p; + hook_approve.nick = nick; + hook_approve.approved = 1; + call_hook(h_local_nick_change_approve, &hook_approve); - if (!hook_info.arg2) { + if (!hook_approve.approved) { sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME), me.name, EmptyString(source_p->name) ? "*" : source_p->name, nick); return; } + hook_info.client = source_p; + hook_info.arg1 = source_p->name; + hook_info.arg2 = nick; + call_hook(h_local_nick_change, &hook_info); + sendto_realops_snomask(SNO_NCHANGE, L_ALL, "Nick change: From %s to %s [%s@%s]", source_p->name, nick, source_p->username, source_p->host); From a02a6fa344f7c50fa7a55f3ace22b629e9571cf7 Mon Sep 17 00:00:00 2001 From: jesopo Date: Fri, 2 Feb 2024 01:25:11 +0000 Subject: [PATCH 3/4] comment here too why not --- modules/core/m_nick.c | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/core/m_nick.c b/modules/core/m_nick.c index 5515fad3b..80724257c 100644 --- a/modules/core/m_nick.c +++ b/modules/core/m_nick.c @@ -690,6 +690,7 @@ change_local_nick(struct Client *client_p, struct Client *source_p, call_hook(h_local_nick_change_approve, &hook_approve); if (!hook_approve.approved) { + /* send the same error they'd get if this nick was RESV */ sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME), me.name, EmptyString(source_p->name) ? "*" : source_p->name, nick); return; From 7d5e73d800be98c7e9b48633b34a8656f32a6e96 Mon Sep 17 00:00:00 2001 From: jesopo Date: Fri, 2 Feb 2024 13:11:13 +0000 Subject: [PATCH 4/4] s->id probably won't be set by this point --- extensions/filter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/filter.c b/extensions/filter.c index 9867daa39..54548308c 100644 --- a/extensions/filter.c +++ b/extensions/filter.c @@ -529,8 +529,8 @@ filter_client_nick_set(void *data_) } if (r & ACT_ALARM) { sendto_realops_snomask(SNO_GENERAL, L_ALL | L_NETWIDE, - "FILTER:REGISTER: %s@%s", - s->id, s->sockhost); + "FILTER:REGISTER: %s [%s]", + s->host, s->sockhost); } if (r & ACT_KILL) { exit_client(NULL, s, s, FILTER_EXIT_MSG);