mirror of
https://github.com/unrealircd/unrealircd.git
synced 2026-06-29 20:06:37 +02:00
4e5598b6cf
This is an easier way to call the next command override handler from command override functions. It passes the standard parameters so you don't have to worry about which parameters a CMD_OVERRIDE_FUNC() contains. This so it is easier to change command parameters in future UnrealIRCd versions, should it be needed, then it may be possible without any source code changes on the module developer side. - CallCommandOverride(ovr, client, recv_mtags, parc, parv); + CALL_NEXT_COMMAND_OVERRIDE();
468 lines
10 KiB
C
468 lines
10 KiB
C
/*
|
|
* hideserver.c - Hide certain or all servers from /MAP & /LINKS
|
|
*
|
|
* Note that this module simple hides servers. It does not truly
|
|
* increase security. Use as you wish.
|
|
*
|
|
* (C) Copyright 2003-2004 AngryWolf <angrywolf@flashmail.com>
|
|
* (C) Copyright 2016 Bram Matthys <syzop@vulnscan.org>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 1, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
#include "unrealircd.h"
|
|
|
|
CMD_OVERRIDE_FUNC(override_map);
|
|
CMD_OVERRIDE_FUNC(override_links);
|
|
static int cb_test(ConfigFile *, ConfigEntry *, int, int *);
|
|
static int cb_conf(ConfigFile *, ConfigEntry *, int);
|
|
|
|
ConfigItem_ulines *HiddenServers;
|
|
|
|
static struct
|
|
{
|
|
unsigned disable_map : 1;
|
|
unsigned disable_links : 1;
|
|
char *map_deny_message;
|
|
char *links_deny_message;
|
|
} Settings;
|
|
|
|
static ModuleInfo *MyModInfo;
|
|
#define MyMod MyModInfo->handle
|
|
#define SAVE_MODINFO MyModInfo = modinfo;
|
|
|
|
static int lmax = 0;
|
|
static int umax = 0;
|
|
|
|
static int dcount(int n)
|
|
{
|
|
int cnt = 0;
|
|
|
|
while (n != 0)
|
|
{
|
|
n = n/10;
|
|
cnt++;
|
|
}
|
|
|
|
return cnt;
|
|
}
|
|
|
|
ModuleHeader MOD_HEADER
|
|
= {
|
|
"hideserver",
|
|
"5.0",
|
|
"Hide servers from /MAP & /LINKS",
|
|
"UnrealIRCd Team",
|
|
"unrealircd-6",
|
|
};
|
|
|
|
static void InitConf()
|
|
{
|
|
memset(&Settings, 0, sizeof Settings);
|
|
}
|
|
|
|
static void FreeConf()
|
|
{
|
|
ConfigItem_ulines *h, *next;
|
|
|
|
safe_free(Settings.map_deny_message);
|
|
safe_free(Settings.links_deny_message);
|
|
|
|
for (h = HiddenServers; h; h = next)
|
|
{
|
|
next = h->next;
|
|
DelListItem(h, HiddenServers);
|
|
safe_free(h->servername);
|
|
safe_free(h);
|
|
}
|
|
}
|
|
|
|
MOD_TEST()
|
|
{
|
|
SAVE_MODINFO
|
|
HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, cb_test);
|
|
|
|
return MOD_SUCCESS;
|
|
}
|
|
|
|
MOD_INIT()
|
|
{
|
|
MARK_AS_OFFICIAL_MODULE(modinfo);
|
|
SAVE_MODINFO
|
|
HiddenServers = NULL;
|
|
InitConf();
|
|
|
|
HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, cb_conf);
|
|
|
|
return MOD_SUCCESS;
|
|
}
|
|
|
|
MOD_LOAD()
|
|
{
|
|
if (!CommandOverrideAdd(MyMod, "MAP", 0, override_map))
|
|
return MOD_FAILED;
|
|
|
|
if (!CommandOverrideAdd(MyMod, "LINKS", 0, override_links))
|
|
return MOD_FAILED;
|
|
|
|
return MOD_SUCCESS;
|
|
}
|
|
|
|
MOD_UNLOAD()
|
|
{
|
|
FreeConf();
|
|
|
|
return MOD_SUCCESS;
|
|
}
|
|
|
|
static int cb_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
|
|
{
|
|
ConfigEntry *cep;
|
|
int errors = 0;
|
|
|
|
if (type == CONFIG_MAIN)
|
|
{
|
|
if (!strcmp(ce->name, "hideserver"))
|
|
{
|
|
for (cep = ce->items; cep; cep = cep->next)
|
|
{
|
|
if (!strcmp(cep->name, "hide"))
|
|
{
|
|
/* No checking needed */
|
|
}
|
|
else if (!cep->value)
|
|
{
|
|
config_error("%s:%i: %s::%s without value",
|
|
cep->file->filename,
|
|
cep->line_number,
|
|
ce->name, cep->name);
|
|
errors++;
|
|
continue;
|
|
}
|
|
else if (!strcmp(cep->name, "disable-map"))
|
|
;
|
|
else if (!strcmp(cep->name, "disable-links"))
|
|
;
|
|
else if (!strcmp(cep->name, "map-deny-message"))
|
|
;
|
|
else if (!strcmp(cep->name, "links-deny-message"))
|
|
;
|
|
else
|
|
{
|
|
config_error("%s:%i: unknown directive hideserver::%s",
|
|
cep->file->filename, cep->line_number, cep->name);
|
|
errors++;
|
|
}
|
|
}
|
|
*errs = errors;
|
|
return errors ? -1 : 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int cb_conf(ConfigFile *cf, ConfigEntry *ce, int type)
|
|
{
|
|
ConfigEntry *cep, *cepp;
|
|
ConfigItem_ulines *ca;
|
|
|
|
if (type == CONFIG_MAIN)
|
|
{
|
|
if (!strcmp(ce->name, "hideserver"))
|
|
{
|
|
for (cep = ce->items; cep; cep = cep->next)
|
|
{
|
|
if (!strcmp(cep->name, "disable-map"))
|
|
Settings.disable_map = config_checkval(cep->value, CFG_YESNO);
|
|
else if (!strcmp(cep->name, "disable-links"))
|
|
Settings.disable_links = config_checkval(cep->value, CFG_YESNO);
|
|
else if (!strcmp(cep->name, "map-deny-message"))
|
|
{
|
|
safe_strdup(Settings.map_deny_message, cep->value);
|
|
}
|
|
else if (!strcmp(cep->name, "links-deny-message"))
|
|
{
|
|
safe_strdup(Settings.links_deny_message, cep->value);
|
|
}
|
|
else if (!strcmp(cep->name, "hide"))
|
|
{
|
|
for (cepp = cep->items; cepp; cepp = cepp->next)
|
|
{
|
|
if (!strcasecmp(cepp->name, me.name))
|
|
continue;
|
|
|
|
ca = safe_alloc(sizeof(ConfigItem_ulines));
|
|
safe_strdup(ca->servername, cepp->name);
|
|
AddListItem(ca, HiddenServers);
|
|
}
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
ConfigItem_ulines *FindHiddenServer(char *servername)
|
|
{
|
|
ConfigItem_ulines *h;
|
|
|
|
for (h = HiddenServers; h; h = h->next)
|
|
if (!strcasecmp(servername, h->servername))
|
|
break;
|
|
|
|
return h;
|
|
}
|
|
|
|
/*
|
|
* New /MAP format -Potvin
|
|
* dump_map function.
|
|
*/
|
|
static void dump_map(Client *client, Client *server, char *mask, int prompt_length, int length)
|
|
{
|
|
static char prompt[64];
|
|
char *p = &prompt[prompt_length];
|
|
int cnt = 0;
|
|
Client *acptr;
|
|
|
|
*p = '\0';
|
|
|
|
if (prompt_length > 60)
|
|
sendnumeric(client, RPL_MAPMORE, prompt, length, server->name);
|
|
else
|
|
{
|
|
char tbuf[256];
|
|
char sid[10];
|
|
int len = length - strlen(server->name) + 1;
|
|
|
|
if (len < 0)
|
|
len = 0;
|
|
if (len > 255)
|
|
len = 255;
|
|
|
|
tbuf[len--] = '\0';
|
|
while (len >= 0)
|
|
tbuf[len--] = '-';
|
|
if (IsOper(client))
|
|
snprintf(sid, sizeof(sid), " [%s]", server->id);
|
|
sendnumeric(client, RPL_MAP, prompt, server->name, tbuf, umax,
|
|
server->server->users, (double)(lmax < 10) ? 4 : (lmax == 100) ? 6 : 5,
|
|
(server->server->users * 100.0 / irccounts.clients),
|
|
IsOper(client) ? sid : "");
|
|
cnt = 0;
|
|
}
|
|
|
|
if (prompt_length > 0)
|
|
{
|
|
p[-1] = ' ';
|
|
if (p[-2] == '`')
|
|
p[-2] = ' ';
|
|
}
|
|
if (prompt_length > 60)
|
|
return;
|
|
|
|
strcpy(p, "|-");
|
|
|
|
list_for_each_entry(acptr, &global_server_list, client_node)
|
|
{
|
|
if (acptr->uplink != server ||
|
|
(IsULine(acptr) && HIDE_ULINES && !ValidatePermissionsForPath("server:info:map:ulines",client,NULL,NULL,NULL)))
|
|
continue;
|
|
if (FindHiddenServer(acptr->name))
|
|
break;
|
|
SetMap(acptr);
|
|
cnt++;
|
|
}
|
|
|
|
list_for_each_entry(acptr, &global_server_list, client_node)
|
|
{
|
|
if (IsULine(acptr) && HIDE_ULINES && !ValidatePermissionsForPath("server:info:map:ulines",client,NULL,NULL,NULL))
|
|
continue;
|
|
if (FindHiddenServer(acptr->name))
|
|
break;
|
|
if (acptr->uplink != server)
|
|
continue;
|
|
if (!IsMap(acptr))
|
|
continue;
|
|
if (--cnt == 0)
|
|
*p = '`';
|
|
dump_map(client, acptr, mask, prompt_length + 2, length - 2);
|
|
}
|
|
|
|
if (prompt_length > 0)
|
|
p[-1] = '-';
|
|
}
|
|
|
|
void dump_flat_map(Client *client, Client *server, int length)
|
|
{
|
|
char buf[4];
|
|
char tbuf[256];
|
|
Client *acptr;
|
|
int cnt = 0, len = 0, hide_ulines;
|
|
|
|
hide_ulines = (HIDE_ULINES && !ValidatePermissionsForPath("server:info:map:ulines",client,NULL,NULL,NULL)) ? 1 : 0;
|
|
|
|
len = length - strlen(server->name) + 3;
|
|
if (len < 0)
|
|
len = 0;
|
|
if (len > 255)
|
|
len = 255;
|
|
|
|
tbuf[len--] = '\0';
|
|
while (len >= 0)
|
|
tbuf[len--] = '-';
|
|
|
|
sendnumeric(client, RPL_MAP, "", server->name, tbuf, umax, server->server->users,
|
|
(lmax < 10) ? 4 : (lmax == 100) ? 6 : 5,
|
|
(server->server->users * 100.0 / irccounts.clients), "");
|
|
|
|
list_for_each_entry(acptr, &global_server_list, client_node)
|
|
{
|
|
if ((IsULine(acptr) && hide_ulines) || (acptr == server))
|
|
continue;
|
|
if (FindHiddenServer(acptr->name))
|
|
break;
|
|
cnt++;
|
|
}
|
|
|
|
strcpy(buf, "|-");
|
|
list_for_each_entry(acptr, &global_server_list, client_node)
|
|
{
|
|
if ((IsULine(acptr) && hide_ulines) || (acptr == server))
|
|
continue;
|
|
if (FindHiddenServer(acptr->name))
|
|
break;
|
|
if (--cnt == 0)
|
|
*buf = '`';
|
|
|
|
len = length - strlen(acptr->name) + 1;
|
|
if (len < 0)
|
|
len = 0;
|
|
if (len > 255)
|
|
len = 255;
|
|
|
|
tbuf[len--] = '\0';
|
|
while (len >= 0)
|
|
tbuf[len--] = '-';
|
|
|
|
sendnumeric(client, RPL_MAP, buf, acptr->name, tbuf, umax, acptr->server->users,
|
|
(lmax < 10) ? 4 : (lmax == 100) ? 6 : 5,
|
|
(acptr->server->users * 100.0 / irccounts.clients), "");
|
|
}
|
|
}
|
|
|
|
/*
|
|
** New /MAP format. -Potvin
|
|
** cmd_map (NEW)
|
|
**
|
|
** parv[1] = server mask
|
|
**/
|
|
CMD_OVERRIDE_FUNC(override_map)
|
|
{
|
|
Client *acptr;
|
|
int longest = strlen(me.name);
|
|
float avg_users = 0.0;
|
|
|
|
umax = 0;
|
|
lmax = 0;
|
|
|
|
if (parc < 2)
|
|
parv[1] = "*";
|
|
|
|
if (IsOper(client))
|
|
{
|
|
CALL_NEXT_COMMAND_OVERRIDE();
|
|
return;
|
|
}
|
|
|
|
if (Settings.disable_map)
|
|
{
|
|
if (Settings.map_deny_message)
|
|
sendnotice(client, "%s", Settings.map_deny_message);
|
|
else
|
|
sendnumeric(client, RPL_MAPEND);
|
|
return;
|
|
}
|
|
|
|
list_for_each_entry(acptr, &global_server_list, client_node)
|
|
{
|
|
int perc = 0;
|
|
if (FindHiddenServer(acptr->name))
|
|
break;
|
|
perc = (acptr->server->users * 100 / irccounts.clients);
|
|
if ((strlen(acptr->name) + acptr->hopcount * 2) > longest)
|
|
longest = strlen(acptr->name) + acptr->hopcount * 2;
|
|
if (lmax < perc)
|
|
lmax = perc;
|
|
if (umax < dcount(acptr->server->users))
|
|
umax = dcount(acptr->server->users);
|
|
}
|
|
|
|
if (longest > 60)
|
|
longest = 60;
|
|
longest += 2;
|
|
|
|
if (FLAT_MAP && !ValidatePermissionsForPath("server:info:map:real-map",client,NULL,NULL,NULL))
|
|
dump_flat_map(client, &me, longest);
|
|
else
|
|
dump_map(client, &me, "*", 0, longest);
|
|
|
|
avg_users = irccounts.clients * 1.0 / irccounts.servers;
|
|
sendnumeric(client, RPL_MAPUSERS, irccounts.servers, (irccounts.servers > 1 ? "s" : ""), irccounts.clients,
|
|
(irccounts.clients > 1 ? "s" : ""), avg_users);
|
|
sendnumeric(client, RPL_MAPEND);
|
|
}
|
|
|
|
CMD_OVERRIDE_FUNC(override_links)
|
|
{
|
|
Client *acptr;
|
|
int flat = (FLAT_MAP && !IsOper(client)) ? 1 : 0;
|
|
|
|
if (IsOper(client))
|
|
{
|
|
CALL_NEXT_COMMAND_OVERRIDE();
|
|
return;
|
|
}
|
|
|
|
if (Settings.disable_links)
|
|
{
|
|
if (Settings.links_deny_message)
|
|
sendnotice(client, "%s", Settings.links_deny_message);
|
|
else
|
|
sendnumeric(client, RPL_ENDOFLINKS, "*");
|
|
return;
|
|
}
|
|
|
|
list_for_each_entry(acptr, &global_server_list, client_node)
|
|
{
|
|
/* Some checks */
|
|
if (HIDE_ULINES && IsULine(acptr) && !ValidatePermissionsForPath("server:info:map:ulines",client,NULL,NULL,NULL))
|
|
continue;
|
|
if (FindHiddenServer(acptr->name))
|
|
continue;
|
|
if (flat)
|
|
sendnumeric(client, RPL_LINKS, acptr->name, me.name,
|
|
1, (acptr->info[0] ? acptr->info : "(Unknown Location)"));
|
|
else
|
|
sendnumeric(client, RPL_LINKS, acptr->name, acptr->uplink ? acptr->uplink->name : me.name,
|
|
acptr->hopcount, (acptr->info[0] ? acptr->info : "(Unknown Location)"));
|
|
}
|
|
|
|
sendnumeric(client, RPL_ENDOFLINKS, "*");
|
|
}
|