From dd830261dbd34418412bacfe2783f98bfbf1eeff Mon Sep 17 00:00:00 2001 From: Bram Matthys Date: Wed, 8 Feb 2023 08:57:43 +0100 Subject: [PATCH] Reject a link for anope or atheme if there is no ulines { } for it. This is checked for both local and remote services linking in. Naturally, the list can be expanded to include more services that really need ulines { }, and not statistical services or some other purpose non-unrealircd servers, which is the reason why cannot blindly assume all non-unrealircd servers require ulines. This should hopefully help users a lot with "mysterious" issues with services that we see too often in the support channel. Suggested in https://bugs.unrealircd.org/view.php?id=5742 Note that this does require services to communicate their software version via EAUTH. Anope does this for years already, but atheme only does so since 10 days ago (git only, presumably not released yet) after Valware filed a PR. --- include/h.h | 1 + include/modules.h | 1 + src/api-efunctions.c | 2 ++ src/modules/protoctl.c | 5 +++++ src/modules/server.c | 24 ++++++++++++++++++++++++ src/modules/sinfo.c | 8 ++++++++ 6 files changed, 41 insertions(+) diff --git a/include/h.h b/include/h.h index 525147704..d01876d4a 100644 --- a/include/h.h +++ b/include/h.h @@ -820,6 +820,7 @@ extern MODVAR int (*do_remote_nick_name)(char *nick); extern MODVAR const char *(*charsys_get_current_languages)(void); extern MODVAR void (*broadcast_sinfo)(Client *acptr, Client *to, Client *except); extern MODVAR void (*connect_server)(ConfigItem_link *aconf, Client *by, struct hostent *hp); +extern MODVAR int (*is_services_but_not_ulined)(Client *client); extern MODVAR void (*parse_message_tags)(Client *cptr, char **str, MessageTag **mtag_list); extern MODVAR const char *(*mtags_to_string)(MessageTag *m, Client *acptr); extern MODVAR int (*can_send_to_channel)(Client *cptr, Channel *channel, const char **msgtext, const char **errmsg, int notice); diff --git a/include/modules.h b/include/modules.h index 8f3924b6a..10fd11fda 100644 --- a/include/modules.h +++ b/include/modules.h @@ -2507,6 +2507,7 @@ enum EfunctionType { EFUNC_CHARSYS_GET_CURRENT_LANGUAGES, EFUNC_BROADCAST_SINFO, EFUNC_CONNECT_SERVER, + EFUNC_IS_SERVICES_BUT_NOT_ULINED, EFUNC_PARSE_MESSAGE_TAGS, EFUNC_MTAGS_TO_STRING, EFUNC_TKL_CHARTOTYPE, diff --git a/src/api-efunctions.c b/src/api-efunctions.c index 601eb62b9..aa7962847 100644 --- a/src/api-efunctions.c +++ b/src/api-efunctions.c @@ -106,6 +106,7 @@ int (*do_remote_nick_name)(char *nick); const char *(*charsys_get_current_languages)(void); void (*broadcast_sinfo)(Client *client, Client *to, Client *except); void (*connect_server)(ConfigItem_link *aconf, Client *by, struct hostent *hp); +int (*is_services_but_not_ulined)(Client *client); void (*parse_message_tags)(Client *client, char **str, MessageTag **mtag_list); const char *(*mtags_to_string)(MessageTag *m, Client *client); int (*can_send_to_channel)(Client *client, Channel *channel, const char **msgtext, const char **errmsg, int notice); @@ -389,6 +390,7 @@ void efunctions_init(void) efunc_init_function(EFUNC_CHARSYS_GET_CURRENT_LANGUAGES, charsys_get_current_languages, NULL); efunc_init_function(EFUNC_BROADCAST_SINFO, broadcast_sinfo, NULL); efunc_init_function(EFUNC_CONNECT_SERVER, connect_server, NULL); + efunc_init_function(EFUNC_IS_SERVICES_BUT_NOT_ULINED, is_services_but_not_ulined, NULL); efunc_init_function(EFUNC_PARSE_MESSAGE_TAGS, parse_message_tags, &parse_message_tags_default_handler); efunc_init_function(EFUNC_MTAGS_TO_STRING, mtags_to_string, &mtags_to_string_default_handler); efunc_init_function(EFUNC_TKL_CHARTOTYPE, tkl_chartotype, NULL); diff --git a/src/modules/protoctl.c b/src/modules/protoctl.c index c45af25e0..b4d48c4b8 100644 --- a/src/modules/protoctl.c +++ b/src/modules/protoctl.c @@ -277,6 +277,11 @@ CMD_FUNC(cmd_protoctl) client->server->features.protocol = atoi(protocol); if (software) safe_strdup(client->server->features.software, software); + if (is_services_but_not_ulined(client)) + { + exit_client_fmt(client, NULL, "Services detected but no ulines { } for server name %s", client->name); + return; + } if (!IsHandshake(client) && aconf) /* Send PASS early... */ sendto_one(client, NULL, "PASS :%s", (aconf->auth->type == AUTHTYPE_PLAINTEXT) ? aconf->auth->data : "*"); } diff --git a/src/modules/server.c b/src/modules/server.c index 995311015..a40a589b3 100644 --- a/src/modules/server.c +++ b/src/modules/server.c @@ -57,6 +57,7 @@ void server_generic_free(ModData *m); int server_post_connect(Client *client); void _connect_server(ConfigItem_link *aconf, Client *by, struct hostent *hp); static int connect_server_helper(ConfigItem_link *, Client *); +int _is_services_but_not_ulined(Client *client); /* Global variables */ static cfgstruct cfg; @@ -81,6 +82,7 @@ MOD_TEST() EfunctionAdd(modinfo->handle, EFUNC_CHECK_DENY_VERSION, _check_deny_version); EfunctionAddVoid(modinfo->handle, EFUNC_BROADCAST_SINFO, _broadcast_sinfo); EfunctionAddVoid(modinfo->handle, EFUNC_CONNECT_SERVER, _connect_server); + EfunctionAdd(modinfo->handle, EFUNC_IS_SERVICES_BUT_NOT_ULINED, _is_services_but_not_ulined); HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, server_config_test); return MOD_SUCCESS; } @@ -1979,3 +1981,25 @@ static int connect_server_helper(ConfigItem_link *aconf, Client *client) return 1; } +int _is_services_but_not_ulined(Client *client) +{ + if (!client->server || !client->server->features.software || !*client->name) + return 0; /* cannot detect software version or name not available yet */ + + if (our_strcasestr(client->server->features.software, "anope") || + our_strcasestr(client->server->features.software, "atheme")) + { + if (!find_uline(client->name)) + { + unreal_log(ULOG_ERROR, "link", "LINK_NO_ULINES", client, + "Server $client is a services server ($software). " + "However, server $me does not have $client in the ulines { } block, " + "which is required for services servers. " + "See https://www.unrealircd.org/docs/Ulines_block", + log_data_client("me", &me), + log_data_string("software", client->server->features.software)); + return 1; /* Is services AND no ulines { } entry */ + } + } + return 0; +} diff --git a/src/modules/sinfo.c b/src/modules/sinfo.c index 451db5854..15235a2f5 100644 --- a/src/modules/sinfo.c +++ b/src/modules/sinfo.c @@ -104,6 +104,14 @@ CMD_FUNC(sinfo_server) else safe_strdup(client->server->features.software, parv[parc-1]); + if (is_services_but_not_ulined(client)) + { + char buf[512]; + snprintf(buf, sizeof(buf), "Services detected but no ulines { } for server name %s", client->name); + exit_client_ex(client, &me, NULL, buf); + return; + } + /* Broadcast to 'the other side' of the net */ concat_params(buf, sizeof(buf), parc, parv); sendto_server(client, 0, 0, NULL, ":%s SINFO %s", client->id, buf);