ircd: implement support for remote module load/unload/etc commands

This commit is contained in:
William Pitcock 2016-01-12 00:37:54 -06:00
parent cc7ae51cdc
commit 15feac531c
4 changed files with 188 additions and 63 deletions

View file

@ -673,6 +673,7 @@ shared {
* undline - allow removing dlines
* grant - allow granting operator status
* die - allow remote DIE/RESTART
* module - allow remote module commands
* none - disallow everything
*/

View file

@ -82,22 +82,23 @@ struct remote_conf
};
/* flags used in shared/cluster */
#define SHARED_TKLINE 0x0001
#define SHARED_PKLINE 0x0002
#define SHARED_UNKLINE 0x0004
#define SHARED_LOCOPS 0x0008
#define SHARED_TXLINE 0x0010
#define SHARED_PXLINE 0x0020
#define SHARED_UNXLINE 0x0040
#define SHARED_TRESV 0x0080
#define SHARED_PRESV 0x0100
#define SHARED_UNRESV 0x0200
#define SHARED_REHASH 0x0400
#define SHARED_TDLINE 0x0800
#define SHARED_PDLINE 0x1000
#define SHARED_UNDLINE 0x2000
#define SHARED_GRANT 0x4000
#define SHARED_DIE 0x8000
#define SHARED_TKLINE 0x00001
#define SHARED_PKLINE 0x00002
#define SHARED_UNKLINE 0x00004
#define SHARED_LOCOPS 0x00008
#define SHARED_TXLINE 0x00010
#define SHARED_PXLINE 0x00020
#define SHARED_UNXLINE 0x00040
#define SHARED_TRESV 0x00080
#define SHARED_PRESV 0x00100
#define SHARED_UNRESV 0x00200
#define SHARED_REHASH 0x00400
#define SHARED_TDLINE 0x00800
#define SHARED_PDLINE 0x01000
#define SHARED_UNDLINE 0x02000
#define SHARED_GRANT 0x04000
#define SHARED_DIE 0x08000
#define SHARED_MODULE 0x10000
#define SHARED_ALL (SHARED_TKLINE | SHARED_PKLINE | SHARED_UNKLINE |\
SHARED_PXLINE | SHARED_TXLINE | SHARED_UNXLINE |\

View file

@ -25,8 +25,6 @@
*/
#include "stdinc.h"
#include "modules.h"
#include "logger.h"
#include "ircd.h"
@ -38,7 +36,7 @@
#include "parse.h"
#include "ircd_defs.h"
#include "match.h"
#include "s_serv.h"
#include <ltdl.h>
@ -73,29 +71,41 @@ static int mo_modreload(struct Client *, struct Client *, int, const char **);
static int mo_modunload(struct Client *, struct Client *, int, const char **);
static int mo_modrestart(struct Client *, struct Client *, int, const char **);
static int me_modload(struct Client *, struct Client *, int, const char **);
static int me_modlist(struct Client *, struct Client *, int, const char **);
static int me_modreload(struct Client *, struct Client *, int, const char **);
static int me_modunload(struct Client *, struct Client *, int, const char **);
static int me_modrestart(struct Client *, struct Client *, int, const char **);
static int do_modload(struct Client *, const char *);
static int do_modunload(struct Client *, const char *);
static int do_modreload(struct Client *, const char *);
static int do_modlist(struct Client *, const char *);
static int do_modrestart(struct Client *);
struct Message modload_msgtab = {
"MODLOAD", 0, 0, 0, MFLG_SLOW,
{mg_unreg, mg_not_oper, mg_ignore, mg_ignore, mg_ignore, {mo_modload, 2}}
{mg_unreg, mg_not_oper, mg_ignore, mg_ignore, {me_modload, 2}, {mo_modload, 2}}
};
struct Message modunload_msgtab = {
"MODUNLOAD", 0, 0, 0, MFLG_SLOW,
{mg_unreg, mg_not_oper, mg_ignore, mg_ignore, mg_ignore, {mo_modunload, 2}}
{mg_unreg, mg_not_oper, mg_ignore, mg_ignore, {me_modunload, 2}, {mo_modunload, 2}}
};
struct Message modreload_msgtab = {
"MODRELOAD", 0, 0, 0, MFLG_SLOW,
{mg_unreg, mg_not_oper, mg_ignore, mg_ignore, mg_ignore, {mo_modreload, 2}}
{mg_unreg, mg_not_oper, mg_ignore, mg_ignore, {me_modreload, 2}, {mo_modreload, 2}}
};
struct Message modlist_msgtab = {
"MODLIST", 0, 0, 0, MFLG_SLOW,
{mg_unreg, mg_not_oper, mg_ignore, mg_ignore, mg_ignore, {mo_modlist, 0}}
{mg_unreg, mg_not_oper, mg_ignore, mg_ignore, {me_modlist, 0}, {mo_modlist, 0}}
};
struct Message modrestart_msgtab = {
"MODRESTART", 0, 0, 0, MFLG_SLOW,
{mg_unreg, mg_not_oper, mg_ignore, mg_ignore, mg_ignore, {mo_modrestart, 0}}
{mg_unreg, mg_not_oper, mg_ignore, mg_ignore, {me_modrestart, 0}, {mo_modrestart, 0}}
};
void
@ -318,8 +328,6 @@ load_one_module(const char *path, int coremodule)
static int
mo_modload(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
{
char *m_bn;
if(!IsOperAdmin(source_p))
{
sendto_one(source_p, form_str(ERR_NOPRIVS),
@ -327,7 +335,34 @@ mo_modload(struct Client *client_p, struct Client *source_p, int parc, const cha
return 0;
}
m_bn = rb_basename(parv[1]);
if(parc > 2)
{
sendto_match_servs(source_p, parv[2], CAP_ENCAP, NOCAPS,
"ENCAP %s MODLOAD %s", parv[2], parv[1]);
if (match(parv[2], me.name) == 0)
return 0;
}
return do_modload(source_p, parv[1]);
}
static int
me_modload(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
{
if(!find_shared_conf(source_p->username, source_p->host, source_p->servptr->name, SHARED_MODULE))
{
sendto_one_notice(source_p, ":*** You do not have an appropriate shared block "
"to load modules on this server.");
return 0;
}
return do_modload(source_p, parv[1]);
}
static int
do_modload(struct Client *source_p, const char *module)
{
char *m_bn = rb_basename(module);
if(findmodule_byname(m_bn) != -1)
{
@ -336,7 +371,7 @@ mo_modload(struct Client *client_p, struct Client *source_p, int parc, const cha
return 0;
}
load_one_module(parv[1], 0);
load_one_module(module, 0);
rb_free(m_bn);
@ -348,9 +383,6 @@ mo_modload(struct Client *client_p, struct Client *source_p, int parc, const cha
static int
mo_modunload(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
{
char *m_bn;
int modindex;
if(!IsOperAdmin(source_p))
{
sendto_one(source_p, form_str(ERR_NOPRIVS),
@ -358,7 +390,35 @@ mo_modunload(struct Client *client_p, struct Client *source_p, int parc, const c
return 0;
}
m_bn = rb_basename(parv[1]);
if(parc > 2)
{
sendto_match_servs(source_p, parv[2], CAP_ENCAP, NOCAPS,
"ENCAP %s MODUNLOAD %s", parv[2], parv[1]);
if (match(parv[2], me.name) == 0)
return 0;
}
return do_modunload(source_p, parv[1]);
}
static int
me_modunload(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
{
if(!find_shared_conf(source_p->username, source_p->host, source_p->servptr->name, SHARED_MODULE))
{
sendto_one_notice(source_p, ":*** You do not have an appropriate shared block "
"to load modules on this server.");
return 0;
}
return do_modunload(source_p, parv[1]);
}
static int
do_modunload(struct Client *source_p, const char *module)
{
int modindex;
char *m_bn = rb_basename(module);
if((modindex = findmodule_byname(m_bn)) == -1)
{
@ -387,10 +447,6 @@ mo_modunload(struct Client *client_p, struct Client *source_p, int parc, const c
static int
mo_modreload(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
{
char *m_bn;
int modindex;
int check_core;
if(!IsOperAdmin(source_p))
{
sendto_one(source_p, form_str(ERR_NOPRIVS),
@ -398,7 +454,36 @@ mo_modreload(struct Client *client_p, struct Client *source_p, int parc, const c
return 0;
}
m_bn = rb_basename(parv[1]);
if(parc > 2)
{
sendto_match_servs(source_p, parv[2], CAP_ENCAP, NOCAPS,
"ENCAP %s MODRELOAD %s", parv[2], parv[1]);
if (match(parv[2], me.name) == 0)
return 0;
}
return do_modreload(source_p, parv[1]);
}
static int
me_modreload(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
{
if(!find_shared_conf(source_p->username, source_p->host, source_p->servptr->name, SHARED_MODULE))
{
sendto_one_notice(source_p, ":*** You do not have an appropriate shared block "
"to load modules on this server.");
return 0;
}
return do_modreload(source_p, parv[1]);
}
static int
do_modreload(struct Client *source_p, const char *module)
{
int modindex;
int check_core;
char *m_bn = rb_basename(module);
if((modindex = findmodule_byname(m_bn)) == -1)
{
@ -418,7 +503,7 @@ mo_modreload(struct Client *client_p, struct Client *source_p, int parc, const c
if((load_one_module(m_bn, check_core) == -1) && check_core)
{
sendto_realops_snomask(SNO_GENERAL, L_ALL,
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
"Error reloading core module: %s: terminating ircd", m_bn);
ilog(L_MAIN, "Error loading core module %s: terminating ircd", m_bn);
exit(0);
@ -432,8 +517,6 @@ mo_modreload(struct Client *client_p, struct Client *source_p, int parc, const c
static int
mo_modlist(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
{
int i;
if(!IsOperAdmin(source_p))
{
sendto_one(source_p, form_str(ERR_NOPRIVS),
@ -441,11 +524,40 @@ mo_modlist(struct Client *client_p, struct Client *source_p, int parc, const cha
return 0;
}
if(parc > 2)
{
sendto_match_servs(source_p, parv[2], CAP_ENCAP, NOCAPS,
"ENCAP %s MODLIST %s", parv[2], parv[1]);
if (match(parv[2], me.name) == 0)
return 0;
}
return do_modlist(source_p, parc > 1 ? parv[1] : 0);
}
static int
me_modlist(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
{
if(!find_shared_conf(source_p->username, source_p->host, source_p->servptr->name, SHARED_MODULE))
{
sendto_one_notice(source_p, ":*** You do not have an appropriate shared block "
"to load modules on this server.");
return 0;
}
return do_modlist(source_p, parv[1]);
}
static int
do_modlist(struct Client *source_p, const char *pattern)
{
int i;
for (i = 0; i < num_mods; i++)
{
if(parc > 1)
if(pattern)
{
if(match(parv[1], modlist[i]->name))
if(match(pattern, modlist[i]->name))
{
sendto_one(source_p, form_str(RPL_MODLIST),
me.name, source_p->name,
@ -458,8 +570,7 @@ mo_modlist(struct Client *client_p, struct Client *source_p, int parc, const cha
{
sendto_one(source_p, form_str(RPL_MODLIST),
me.name, source_p->name, modlist[i]->name,
(unsigned long)(uintptr_t)modlist[i]->address,
modlist[i]->version,
(unsigned long)(uintptr_t)modlist[i]->address, modlist[i]->version,
modlist[i]->core ? "(core)" : "");
}
}
@ -472,8 +583,6 @@ mo_modlist(struct Client *client_p, struct Client *source_p, int parc, const cha
static int
mo_modrestart(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
{
int modnum;
if(!IsOperAdmin(source_p))
{
sendto_one(source_p, form_str(ERR_NOPRIVS),
@ -481,6 +590,35 @@ mo_modrestart(struct Client *client_p, struct Client *source_p, int parc, const
return 0;
}
if(parc > 1)
{
sendto_match_servs(source_p, parv[1], CAP_ENCAP, NOCAPS,
"ENCAP %s MODRESTART", parv[1]);
if (match(parv[1], me.name) == 0)
return 0;
}
return do_modrestart(source_p);
}
static int
me_modrestart(struct Client *client_p, struct Client *source_p, int parc, const char **parv)
{
if(!find_shared_conf(source_p->username, source_p->host, source_p->servptr->name, SHARED_MODULE))
{
sendto_one_notice(source_p, ":*** You do not have an appropriate shared block "
"to load modules on this server.");
return 0;
}
return do_modrestart(source_p);
}
static int
do_modrestart(struct Client *source_p)
{
int modnum;
sendto_one_notice(source_p, ":Reloading all modules");
modnum = num_mods;
@ -491,7 +629,7 @@ mo_modrestart(struct Client *client_p, struct Client *source_p, int parc, const
load_core_modules(0);
rehash(0);
sendto_realops_snomask(SNO_GENERAL, L_ALL,
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
"Module Restart: %d modules unloaded, %d modules loaded",
modnum, num_mods);
ilog(L_MAIN, "Module Restart: %d modules unloaded, %d modules loaded", modnum, num_mods);
@ -499,22 +637,6 @@ mo_modrestart(struct Client *client_p, struct Client *source_p, int parc, const
}
#ifndef RTLD_NOW
#define RTLD_NOW RTLD_LAZY /* openbsd deficiency */
#endif
#ifndef RTLD_LOCAL
#define RTLD_LOCAL 0
#endif
#ifdef CHARYBDIS_PROFILE
# ifndef RTLD_PROFILE
# warning libdl may not support profiling, sucks. :(
# define RTLD_PROFILE 0
# endif
#endif
static void increase_modlist(void);
#define MODS_INCREMENT 10

View file

@ -391,6 +391,7 @@ static struct mode_table shared_table[] =
{ "rehash", SHARED_REHASH },
{ "grant", SHARED_GRANT },
{ "die", SHARED_DIE },
{ "module", SHARED_MODULE },
{ "all", SHARED_ALL },
{ "none", 0 },
{NULL, 0}