mirror of
https://github.com/unrealircd/unrealircd.git
synced 2026-06-29 11:16:37 +02:00
Update central spamreport, https://www.unrealircd.org/docs/Central_spamreport
set::central-blocklist::spamreport and ::spamreport-enabled are now GONE.
We now require a normal spamreport block, just like for other spamreport
functionality. So, if you want to enable this feature, use:
spamreport unrealircd { type central-spamreport; }
See https://www.unrealircd.org/docs/Central_spamreport for all info.
You can use CBL with central spamreport or central spamreport without CBL.
All explained at that URL.
This commit is contained in:
@@ -927,6 +927,8 @@ extern void (*crule_free)(CRuleNode **);
|
||||
extern const char *(*crule_errstring)(int errcode);
|
||||
extern void (*ban_act_set_reputation)(Client *client, BanAction *action);
|
||||
extern const char *(*get_central_api_key)(void);
|
||||
extern int (*central_spamreport)(Client *target);
|
||||
extern int (*central_spamreport_enabled)(void);
|
||||
/* /Efuncs */
|
||||
|
||||
/* TLS functions */
|
||||
@@ -982,6 +984,8 @@ extern void cancel_ident_lookup_default_handler(Client *client);
|
||||
extern int spamreport_default_handler(Client *client, const char *ip, NameValuePrioList *details, const char *spamreport_block);
|
||||
extern void ban_act_set_reputation_default_handler(Client *client, BanAction *action);
|
||||
extern const char *get_central_api_key_default_handler(void);
|
||||
extern int central_spamreport_default_handler(Client *target);
|
||||
extern int central_spamreport_enabled_default_handler(void);
|
||||
/* End of default handlers for efunctions */
|
||||
|
||||
extern MODVAR MOTDFile opermotd, svsmotd, motd, botmotd, smotd, rules;
|
||||
|
||||
@@ -2685,6 +2685,8 @@ enum EfunctionType {
|
||||
EFUNC_CRULE_ERRSTRING,
|
||||
EFUNC_BAN_ACT_SET_REPUTATION,
|
||||
EFUNC_GET_CENTRAL_API_KEY,
|
||||
EFUNC_CENTRAL_SPAMREPORT,
|
||||
EFUNC_CENTRAL_SPAMREPORT_ENABLED,
|
||||
};
|
||||
|
||||
/* Module flags */
|
||||
|
||||
@@ -172,6 +172,8 @@ void (*crule_free)(CRuleNode **);
|
||||
const char *(*crule_errstring)(int errcode);
|
||||
void (*ban_act_set_reputation)(Client *client, BanAction *action);
|
||||
const char *(*get_central_api_key)(void);
|
||||
int (*central_spamreport)(Client *target);
|
||||
int (*central_spamreport_enabled)(void);
|
||||
|
||||
Efunction *EfunctionAddMain(Module *module, EfunctionType eftype, int (*func)(), void (*vfunc)(), void *(*pvfunc)(), char *(*stringfunc)(), const char *(*conststringfunc)())
|
||||
{
|
||||
@@ -489,4 +491,6 @@ void efunctions_init(void)
|
||||
efunc_init_function(EFUNC_CRULE_ERRSTRING, crule_errstring, NULL, EFUNC_FLAG_EARLY);
|
||||
efunc_init_function(EFUNC_BAN_ACT_SET_REPUTATION, ban_act_set_reputation, ban_act_set_reputation_default_handler, 0);
|
||||
efunc_init_function(EFUNC_GET_CENTRAL_API_KEY, get_central_api_key, get_central_api_key_default_handler, 0);
|
||||
efunc_init_function(EFUNC_CENTRAL_SPAMREPORT, central_spamreport, central_spamreport_default_handler, 0);
|
||||
efunc_init_function(EFUNC_CENTRAL_SPAMREPORT_ENABLED, central_spamreport_enabled, central_spamreport_enabled_default_handler, 0);
|
||||
}
|
||||
|
||||
+10
@@ -1897,6 +1897,16 @@ const char *get_central_api_key_default_handler(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int central_spamreport_default_handler(Client *target)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int central_spamreport_enabled_default_handler(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** my_timegm: mktime()-like function which will use GMT/UTC.
|
||||
* Strangely enough there is no standard function for this.
|
||||
* On some *NIX OS's timegm() may be available, sometimes only
|
||||
|
||||
@@ -58,7 +58,6 @@ struct cfgstruct {
|
||||
char *api_key;
|
||||
int max_downloads;
|
||||
int blocklist_enabled;
|
||||
int spamreport_enabled;
|
||||
SecurityGroup *except;
|
||||
ScoreAction *actions;
|
||||
};
|
||||
@@ -73,6 +72,7 @@ static struct reqstruct req;
|
||||
CBLTransfer *cbltransfers = NULL;
|
||||
|
||||
/* Forward declarations */
|
||||
int _central_spamreport(Client *client);
|
||||
int cbl_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs);
|
||||
int cbl_config_posttest(int *errs);
|
||||
int cbl_config_run(ConfigFile *cf, ConfigEntry *ce, int type);
|
||||
@@ -106,7 +106,6 @@ void set_tag(Client *client, const char *tag, int value);
|
||||
|
||||
CMD_OVERRIDE_FUNC(cbl_override);
|
||||
CMD_OVERRIDE_FUNC(cbl_override_spamreport_gather);
|
||||
CMD_OVERRIDE_FUNC(cbl_override_spamreport_cmd);
|
||||
|
||||
static void set_default_score_action(ScoreAction *action)
|
||||
{
|
||||
@@ -183,6 +182,7 @@ MOD_TEST()
|
||||
MARK_AS_OFFICIAL_MODULE(modinfo);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, cbl_config_test);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_CONFIGPOSTTEST, 0, cbl_config_posttest);
|
||||
EfunctionAdd(modinfo->handle, EFUNC_CENTRAL_SPAMREPORT, _central_spamreport);
|
||||
return MOD_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ MOD_LOAD()
|
||||
do_command_overrides(modinfo);
|
||||
|
||||
/* Enable gathering of "last 10 lines" for SPAMREPORT, only if SPAMREPORT is enabled: */
|
||||
if (cfg.spamreport_enabled)
|
||||
if (central_spamreport_enabled())
|
||||
{
|
||||
CommandOverrideAdd(modinfo->handle, "NICK", -2, cbl_override_spamreport_gather);
|
||||
CommandOverrideAdd(modinfo->handle, "PRIVMSG", -2, cbl_override_spamreport_gather);
|
||||
@@ -255,8 +255,6 @@ MOD_LOAD()
|
||||
CommandOverrideAdd(modinfo->handle, "KNOCK", -2, cbl_override_spamreport_gather);
|
||||
}
|
||||
|
||||
CommandOverrideAdd(modinfo->handle, "SPAMREPORT", -2, cbl_override_spamreport_cmd);
|
||||
|
||||
EventAdd(modinfo->handle, "centralblocklist_timeout_evt", centralblocklist_timeout_evt, NULL, 1000, 0);
|
||||
EventAdd(modinfo->handle, "centralblocklist_bundle_requests", centralblocklist_bundle_requests, NULL, 1000, 0);
|
||||
return MOD_SUCCESS;
|
||||
@@ -340,6 +338,12 @@ int cbl_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
|
||||
} else
|
||||
if (!strcmp(cep->name, "spamreport") || !strcmp(cep->name, "spamreport-enabled"))
|
||||
{
|
||||
config_error("%s:%i: set::central-blocklist::%s: This setting is deprecated. "
|
||||
"Please remove this setting, and, if you wish to use spamreport, add a "
|
||||
"spamreport unrealircd { type central-spamreport; } block in your main config. "
|
||||
"See https://www.unrealircd.org/docs/Central_spamreport",
|
||||
cep->file->filename, cep->line_number, cep->name);
|
||||
errors++;
|
||||
} else
|
||||
if (!strcmp(cep->name, "blocklist") || !strcmp(cep->name, "blocklist-enabled"))
|
||||
{
|
||||
@@ -436,10 +440,6 @@ int cbl_config_run(ConfigFile *cf, ConfigEntry *ce, int type)
|
||||
{
|
||||
safe_strdup(cfg.url, cep->value);
|
||||
} else
|
||||
if (!strcmp(cep->name, "spamreport") || !strcmp(cep->name, "spamreport-enabled"))
|
||||
{
|
||||
cfg.spamreport_enabled = config_checkval(cep->value, CFG_YESNO);
|
||||
} else
|
||||
if (!strcmp(cep->name, "blocklist-enabled"))
|
||||
{
|
||||
cfg.blocklist_enabled = config_checkval(cep->value, CFG_YESNO);
|
||||
@@ -770,7 +770,7 @@ int cbl_is_handshake_finished(Client *client)
|
||||
void cbl_allow(Client *client)
|
||||
{
|
||||
if (CBL(client))
|
||||
CBL(client)->allowed_in = 2;
|
||||
CBL(client)->allowed_in = 1;
|
||||
|
||||
if (is_handshake_finished(client))
|
||||
register_user(client);
|
||||
@@ -952,16 +952,13 @@ void cbl_download_complete(OutgoingWebRequest *request, OutgoingWebResponse *res
|
||||
void cbl_mdata_free(ModData *m)
|
||||
{
|
||||
CBLUser *cbl = (CBLUser *)m->ptr;
|
||||
int i;
|
||||
|
||||
if (cbl)
|
||||
{
|
||||
json_decref(cbl->handshake);
|
||||
if (cbl->allowed_in == 2)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < SPAMREPORT_NUM_REMEMBERED_CMDS; i++)
|
||||
safe_free(cbl->last_cmds[i]);
|
||||
}
|
||||
for (i = 0; i < SPAMREPORT_NUM_REMEMBERED_CMDS; i++)
|
||||
safe_free(cbl->last_cmds[i]);
|
||||
safe_free(cbl);
|
||||
m->ptr = NULL;
|
||||
}
|
||||
@@ -1056,7 +1053,7 @@ EVENT(centralblocklist_bundle_requests)
|
||||
/** Remember last # commands for SPAMREPORT */
|
||||
CMD_OVERRIDE_FUNC(cbl_override_spamreport_gather)
|
||||
{
|
||||
if (MyUser(client) && CBL(client) && (CBL(client)->allowed_in == 2))
|
||||
if (MyUser(client) && CBL(client))
|
||||
{
|
||||
char record_cmd = 1;
|
||||
|
||||
@@ -1078,7 +1075,7 @@ CMD_OVERRIDE_FUNC(cbl_override_spamreport_gather)
|
||||
CALL_NEXT_COMMAND_OVERRIDE();
|
||||
}
|
||||
|
||||
void cbl_spamreport(Client *from, Client *client)
|
||||
int _central_spamreport(Client *client)
|
||||
{
|
||||
json_t *j, *requests, *data, *cmds, *item;
|
||||
OutgoingWebRequest *w;
|
||||
@@ -1090,7 +1087,7 @@ void cbl_spamreport(Client *from, Client *client)
|
||||
int cnt = 0;
|
||||
|
||||
if (!MyUser(client) || !CBL(client))
|
||||
return; /* Only possible if hot-loading */
|
||||
return 0; /* Only possible if hot-loading */
|
||||
|
||||
num = downloads_in_progress();
|
||||
if (num > cfg.max_downloads)
|
||||
@@ -1098,7 +1095,7 @@ void cbl_spamreport(Client *from, Client *client)
|
||||
unreal_log(ULOG_WARNING, "central-blocklist", "CENTRAL_BLOCKLIST_TOO_MANY_CONCURRENT_REQUESTS", NULL,
|
||||
"Already $num_requests HTTP(S) requests in progress.",
|
||||
log_data_integer("num_requests", num));
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
j = json_object();
|
||||
@@ -1139,7 +1136,7 @@ void cbl_spamreport(Client *from, Client *client)
|
||||
unreal_log(ULOG_WARNING, "central-blocklist", "CENTRAL_BLOCKLIST_BUG_SERIALIZE", client,
|
||||
"Unable to serialize JSON request. Weird.");
|
||||
json_decref(j);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
json_decref(j);
|
||||
@@ -1154,62 +1151,5 @@ void cbl_spamreport(Client *from, Client *client)
|
||||
w->max_redirects = 1;
|
||||
w->callback = download_complete_dontcare;
|
||||
url_start_async(w);
|
||||
}
|
||||
|
||||
CMD_OVERRIDE_FUNC(cbl_override_spamreport_cmd)
|
||||
{
|
||||
if (ValidatePermissionsForPath("server-ban:spamreport",client,NULL,NULL,NULL) &&
|
||||
(parc > 1) &&
|
||||
!((parc > 2) && strcasecmp(parv[2], "unrealircd"))
|
||||
)
|
||||
{
|
||||
Client *target = find_user(parv[1], NULL);
|
||||
if (target)
|
||||
{
|
||||
if (!MyUser(target))
|
||||
{
|
||||
/* Forward it to other server */
|
||||
if (parc > 2)
|
||||
{
|
||||
sendto_one(target, NULL, ":%s SPAMREPORT %s %s",
|
||||
client->id, parv[1], parv[2]);
|
||||
} else {
|
||||
sendto_one(target, NULL, ":%s SPAMREPORT %s",
|
||||
client->id, parv[1]);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
/* My client. */
|
||||
int n;
|
||||
|
||||
if (!cfg.spamreport_enabled)
|
||||
{
|
||||
if ((parc > 2) && !strcasecmp(parv[2], "unrealircd"))
|
||||
{
|
||||
sendnotice(client, "Spamreporting to UnrealIRCd is not enabled on this server. "
|
||||
"To enable, add: set { central-blocklist { spamreport yes; } }");
|
||||
return;
|
||||
}
|
||||
CALL_NEXT_COMMAND_OVERRIDE();
|
||||
}
|
||||
|
||||
/* Report to UnrealIRCd first... */
|
||||
sendnotice(client, "Sending spam report to UnrealIRCd...");
|
||||
cbl_spamreport(client, target);
|
||||
if ((parc > 2) && !strcasecmp(parv[2], "unrealircd"))
|
||||
{
|
||||
sendnotice(client, "Sending spam report to %d target(s)", 1);
|
||||
return; /* We are done */
|
||||
}
|
||||
|
||||
/* There may be more spamreport blocks: */
|
||||
n = spamreport(target, target->ip, NULL, NULL);
|
||||
if (n < 0)
|
||||
n = 0;
|
||||
sendnotice(client, "Sending spam report to %d target(s)", n + 1); /* +1 for unrealircd :D */
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
CALL_NEXT_COMMAND_OVERRIDE();
|
||||
return 1;
|
||||
}
|
||||
|
||||
+52
-25
@@ -20,14 +20,15 @@ ModuleHeader MOD_HEADER
|
||||
typedef enum SpamreportType {
|
||||
SPAMREPORT_TYPE_SIMPLE = 1,
|
||||
SPAMREPORT_TYPE_DRONEBL = 2,
|
||||
} SpamReportType;
|
||||
SPAMREPORT_TYPE_CENTRAL_SPAMREPORT = 3,
|
||||
} SpamreportType;
|
||||
|
||||
typedef struct Spamreport Spamreport;
|
||||
struct Spamreport {
|
||||
Spamreport *prev, *next;
|
||||
char *name; /**< Name of the block, spamreport <this> { } */
|
||||
char *url; /**< URL to use */
|
||||
SpamReportType type;
|
||||
SpamreportType type;
|
||||
HttpMethod http_method;
|
||||
NameValuePrioList *parameters;
|
||||
SecurityGroup *except;
|
||||
@@ -51,7 +52,9 @@ int tkl_config_run_spamreport(ConfigFile *, ConfigEntry *, int);
|
||||
Spamreport *find_spamreport_block(const char *name);
|
||||
void free_spamreport_blocks(void);
|
||||
int _spamreport(Client *client, const char *ip, NameValuePrioList *details, const char *spamreport_block);
|
||||
int _central_spamreport_enabled(void);
|
||||
void spamreportcounters_free_all(ModData *m);
|
||||
SpamreportType parse_spamreport_type(const char *s);
|
||||
|
||||
/* Variables */
|
||||
Spamreport *spamreports = NULL;
|
||||
@@ -61,6 +64,7 @@ MOD_TEST()
|
||||
{
|
||||
MARK_AS_OFFICIAL_MODULE(modinfo);
|
||||
EfunctionAdd(modinfo->handle, EFUNC_SPAMREPORT, _spamreport);
|
||||
EfunctionAdd(modinfo->handle, EFUNC_CENTRAL_SPAMREPORT_ENABLED, _central_spamreport_enabled);
|
||||
HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, tkl_config_test_spamreport);
|
||||
return MOD_SUCCESS;
|
||||
}
|
||||
@@ -92,7 +96,7 @@ int tkl_config_test_spamreport(ConfigFile *cf, ConfigEntry *ce, int type, int *e
|
||||
ConfigEntry *cep, *cepp;
|
||||
int errors = 0;
|
||||
char has_url=0, has_type=0, has_type_dronebl=0, has_http_method=0;
|
||||
char has_dronebl_type=0, has_dronebl_rpckey=0;
|
||||
char has_dronebl_type, has_dronebl_rpckey=0;
|
||||
|
||||
/* We are only interested in spamreport { } blocks */
|
||||
if ((type != CONFIG_MAIN) || strcmp(ce->name, "spamreport"))
|
||||
@@ -103,12 +107,6 @@ int tkl_config_test_spamreport(ConfigFile *cf, ConfigEntry *ce, int type, int *e
|
||||
config_error("%s:%i: spamreport block has no name, should be like: spamfilter <name> { }",
|
||||
ce->file->filename, ce->line_number);
|
||||
errors++;
|
||||
} else
|
||||
if (!strcasecmp(ce->value, "unrealircd"))
|
||||
{
|
||||
config_error("%s:%i: spamreport block cannot be named 'unrealircd', is a reserved name.",
|
||||
ce->file->filename, ce->line_number);
|
||||
errors++;
|
||||
}
|
||||
|
||||
for (cep = ce->items; cep; cep = cep->next)
|
||||
@@ -160,15 +158,11 @@ int tkl_config_test_spamreport(ConfigFile *cf, ConfigEntry *ce, int type, int *e
|
||||
cep->line_number, "spamreport::type");
|
||||
continue;
|
||||
}
|
||||
has_type = 1;
|
||||
if (!strcmp(cep->value, "simple"))
|
||||
;
|
||||
else if (!strcmp(cep->value, "dronebl"))
|
||||
has_type_dronebl = 1;
|
||||
else
|
||||
has_type = parse_spamreport_type(cep->value);
|
||||
if (!has_type)
|
||||
{
|
||||
config_error("%s:%i: spamreport::type: only 'simple' is supported at the moment",
|
||||
cep->file->filename, cep->line_number);
|
||||
config_error("%s:%i: spamreport::type: unknown type '%s', supported types are: simple, dronebl, central-spamreport.",
|
||||
cep->file->filename, cep->line_number, cep->value);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
@@ -213,7 +207,11 @@ int tkl_config_test_spamreport(ConfigFile *cf, ConfigEntry *ce, int type, int *e
|
||||
errors++;
|
||||
}
|
||||
|
||||
if (has_type_dronebl)
|
||||
if (has_type == SPAMREPORT_TYPE_CENTRAL_SPAMREPORT)
|
||||
{
|
||||
/* Nothing required */
|
||||
} else
|
||||
if (has_type == SPAMREPORT_TYPE_DRONEBL)
|
||||
{
|
||||
if (!has_dronebl_rpckey || !has_dronebl_type)
|
||||
{
|
||||
@@ -269,12 +267,14 @@ int tkl_config_run_spamreport(ConfigFile *cf, ConfigEntry *ce, int type)
|
||||
}
|
||||
else if (!strcmp(cep->name, "type"))
|
||||
{
|
||||
if (!strcmp(cep->value, "simple"))
|
||||
s->type = SPAMREPORT_TYPE_SIMPLE;
|
||||
else if (!strcmp(cep->value, "dronebl"))
|
||||
s->type = SPAMREPORT_TYPE_DRONEBL;
|
||||
else
|
||||
abort();
|
||||
s->type = parse_spamreport_type(cep->value);
|
||||
|
||||
if ((s->type == SPAMREPORT_TYPE_CENTRAL_SPAMREPORT) &&
|
||||
!is_module_loaded("central-blocklist"))
|
||||
{
|
||||
config_warn("%s:%d: blacklist block with type 'central-spamreport' but the 'central-blocklist' module is not loaded.",
|
||||
ce->file->filename, ce->line_number);
|
||||
}
|
||||
}
|
||||
else if (!strcmp(cep->name, "http-method"))
|
||||
{
|
||||
@@ -344,6 +344,17 @@ Spamreport *find_spamreport_block(const char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SpamreportType parse_spamreport_type(const char *s)
|
||||
{
|
||||
if (!strcmp(s, "simple"))
|
||||
return SPAMREPORT_TYPE_SIMPLE;
|
||||
else if (!strcmp(s, "dronebl"))
|
||||
return SPAMREPORT_TYPE_DRONEBL;
|
||||
else if (!strcmp(s, "central-spamreport"))
|
||||
return SPAMREPORT_TYPE_CENTRAL_SPAMREPORT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns 1 if ratelimited (don't do the request), otherwise 0 */
|
||||
int spamfilter_block_rate_limited(Spamreport *spamreport)
|
||||
{
|
||||
@@ -390,6 +401,16 @@ int spamfilter_block_rate_limited(Spamreport *spamreport)
|
||||
return 0; /* All OK */
|
||||
}
|
||||
|
||||
/** Return 1 if there is a spamreport { type central-spamreport; } block */
|
||||
int _central_spamreport_enabled(void)
|
||||
{
|
||||
Spamreport *s;
|
||||
for (s = spamreports; s; s = s->next)
|
||||
if (s->type == SPAMREPORT_TYPE_CENTRAL_SPAMREPORT)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _spamreport(Client *client, const char *ip, NameValuePrioList *details, const char *spamreport_block)
|
||||
{
|
||||
Spamreport *s;
|
||||
@@ -421,7 +442,7 @@ int _spamreport(Client *client, const char *ip, NameValuePrioList *details, cons
|
||||
|
||||
s = find_spamreport_block(spamreport_block);
|
||||
if (!s)
|
||||
return -1; /* NOTFOUND */
|
||||
return 0; /* NOTFOUND */
|
||||
|
||||
if (s->except && client && user_allowed_by_security_group(client, s->except))
|
||||
return 0;
|
||||
@@ -465,7 +486,13 @@ int _spamreport(Client *client, const char *ip, NameValuePrioList *details, cons
|
||||
safe_free_nvplist(list); // frees all the duplicated lists
|
||||
add_nvplist(&headers, 0, "Content-Type", "text/xml");
|
||||
} else
|
||||
if (s->type == SPAMREPORT_TYPE_CENTRAL_SPAMREPORT)
|
||||
{
|
||||
return central_spamreport(client);
|
||||
} else
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
#ifdef DEBUGMODE
|
||||
unreal_log(ULOG_DEBUG, "spamreport", "SPAMREPORT_SEND_REQUEST", NULL,
|
||||
|
||||
Reference in New Issue
Block a user