anope

- supernets anope source code & configuration
git clone git://git.acid.vegas/anope.git
Log | Files | Refs | Archive | README

os_oper.cpp (8155B)

      1 /* OperServ core functions
      2  *
      3  * (C) 2003-2022 Anope Team
      4  * Contact us at team@anope.org
      5  *
      6  * Please read COPYING and README for further details.
      7  *
      8  * Based on the original code of Epona by Lara.
      9  * Based on the original code of Services by Andy Church.
     10  */
     11 
     12 #include "module.h"
     13 
     14 struct MyOper : Oper, Serializable
     15 {
     16 	MyOper(const Anope::string &n, OperType *o) : Oper(n, o), Serializable("Oper") { }
     17 
     18 	void Serialize(Serialize::Data &data) const anope_override
     19 	{
     20 		data["name"] << this->name;
     21 		data["type"] << this->ot->GetName();
     22 	}
     23 
     24 	static Serializable* Unserialize(Serializable *obj, Serialize::Data &data)
     25 	{
     26 		Anope::string stype, sname;
     27 
     28 		data["type"] >> stype;
     29 		data["name"] >> sname;
     30 
     31 		OperType *ot = OperType::Find(stype);
     32 		if (ot == NULL)
     33 			return NULL;
     34 		NickCore *nc = NickCore::Find(sname);
     35 		if (nc == NULL)
     36 			return NULL;
     37 
     38 		MyOper *myo;
     39 		if (obj)
     40 			myo = anope_dynamic_static_cast<MyOper *>(obj);
     41 		else
     42 			myo = new MyOper(nc->display, ot);
     43 		nc->o = myo;
     44 		Log(LOG_NORMAL, "operserv/oper") << "Tied oper " << nc->display << " to type " << ot->GetName();
     45 		return myo;
     46 	}
     47 };
     48 
     49 class CommandOSOper : public Command
     50 {
     51 	bool HasPrivs(CommandSource &source, OperType *ot) const
     52 	{
     53 		std::list<Anope::string> commands = ot->GetCommands(), privs = ot->GetPrivs();
     54 
     55 		for (std::list<Anope::string>::iterator it = commands.begin(); it != commands.end(); ++it)
     56 			if (!source.HasCommand(*it))
     57 				return false;
     58 
     59 		for (std::list<Anope::string>::iterator it = privs.begin(); it != privs.end(); ++it)
     60 			if (!source.HasPriv(*it))
     61 				return false;
     62 
     63 		return true;
     64 	}
     65 
     66  public:
     67 	CommandOSOper(Module *creator) : Command(creator, "operserv/oper", 1, 3)
     68 	{
     69 		this->SetDesc(_("View and change Services Operators"));
     70 		this->SetSyntax(_("ADD \037oper\037 \037type\037"));
     71 		this->SetSyntax(_("DEL \037oper\037"));
     72 		this->SetSyntax(_("INFO [\037type\037]"));
     73 		this->SetSyntax("LIST");
     74 	}
     75 
     76 	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
     77 	{
     78 		const Anope::string &subcommand = params[0];
     79 
     80 		if (subcommand.equals_ci("ADD") && params.size() > 2)
     81 		{
     82 			const Anope::string &oper = params[1];
     83 			const Anope::string &otype = params[2];
     84 
     85 			if (!source.HasPriv("operserv/oper/modify"))
     86 			{
     87 				source.Reply(ACCESS_DENIED);
     88 				return;
     89 			}
     90 
     91 			const NickAlias *na = NickAlias::Find(oper);
     92 			if (na == NULL)
     93 				source.Reply(NICK_X_NOT_REGISTERED, oper.c_str());
     94 			else if (na->nc->o)
     95 				source.Reply(_("Nick \002%s\002 is already an operator."), na->nick.c_str());
     96 			else
     97 			{
     98 				OperType *ot = OperType::Find(otype);
     99 				if (ot == NULL)
    100 				{
    101 					source.Reply(_("Oper type \002%s\002 has not been configured."), otype.c_str());
    102 					return;
    103 				}
    104 
    105 				if (!HasPrivs(source, ot))
    106 				{
    107 					source.Reply(ACCESS_DENIED);
    108 					return;
    109 				}
    110 
    111 				na->nc->o = new MyOper(na->nc->display, ot);
    112 
    113 				if (Anope::ReadOnly)
    114 					source.Reply(READ_ONLY_MODE);
    115 
    116 				Log(LOG_ADMIN, source, this) << "ADD " << na->nick << " as type " << ot->GetName();
    117 				source.Reply("%s (%s) added to the \002%s\002 list.", na->nick.c_str(), na->nc->display.c_str(), ot->GetName().c_str());
    118 			}
    119 		}
    120 		else if (subcommand.equals_ci("DEL") && params.size() > 1)
    121 		{
    122 			const Anope::string &oper = params[1];
    123 
    124 			if (!source.HasPriv("operserv/oper/modify"))
    125 			{
    126 				source.Reply(ACCESS_DENIED);
    127 				return;
    128 			}
    129 
    130 			const NickAlias *na = NickAlias::Find(oper);
    131 			if (na == NULL)
    132 				source.Reply(NICK_X_NOT_REGISTERED, oper.c_str());
    133 			else if (!na->nc || !na->nc->o)
    134 				source.Reply(_("Nick \002%s\002 is not a Services Operator."), oper.c_str());
    135 			else if (!HasPrivs(source, na->nc->o->ot))
    136 				source.Reply(ACCESS_DENIED);
    137 			else if (std::find(Config->Opers.begin(), Config->Opers.end(), na->nc->o) != Config->Opers.end())
    138 				source.Reply(_("Oper \002%s\002 is configured in the configuration file(s) and can not be removed by this command."), na->nc->display.c_str());
    139 			else
    140 			{
    141 				delete na->nc->o;
    142 				na->nc->o = NULL;
    143 
    144 				if (Anope::ReadOnly)
    145 					source.Reply(READ_ONLY_MODE);
    146 
    147 				Log(LOG_ADMIN, source, this) << "DEL " << na->nick;
    148 				source.Reply(_("Oper privileges removed from %s (%s)."), na->nick.c_str(), na->nc->display.c_str());
    149 			}
    150 		}
    151 		else if (subcommand.equals_ci("LIST"))
    152 		{
    153 			source.Reply(_("Name     Type"));
    154 			for (nickcore_map::const_iterator it = NickCoreList->begin(), it_end = NickCoreList->end(); it != it_end; ++it)
    155 			{
    156 				const NickCore *nc = it->second;
    157 
    158 				if (!nc->o)
    159 					continue;
    160 
    161 				source.Reply(_("%-8s %s"), nc->o->name.c_str(), nc->o->ot->GetName().c_str());
    162 				if (std::find(Config->Opers.begin(), Config->Opers.end(), nc->o) != Config->Opers.end())
    163 					source.Reply(_("   This oper is configured in the configuration file."));
    164 				for (std::list<User *>::const_iterator uit = nc->users.begin(); uit != nc->users.end(); ++uit)
    165 				{
    166 					User *u = *uit;
    167 					source.Reply(_("   %s is online using this oper block."), u->nick.c_str());
    168 				}
    169 			}
    170 		}
    171 		else if (subcommand.equals_ci("INFO"))
    172 		{
    173 			if (params.size() < 2)
    174 			{
    175 				source.Reply(_("Available opertypes:"));
    176 				for (unsigned i = 0; i < Config->MyOperTypes.size(); ++i)
    177 				{
    178 					OperType *ot = Config->MyOperTypes[i];
    179 					source.Reply("%s", ot->GetName().c_str());
    180 				}
    181 				return;
    182 			}
    183 
    184 			Anope::string fulltype = params[1];
    185 			if (params.size() > 2)
    186 				fulltype += " " + params[2];
    187 			OperType *ot = OperType::Find(fulltype);
    188 			if (ot == NULL)
    189 				source.Reply(_("Oper type \002%s\002 has not been configured."), fulltype.c_str());
    190 			else
    191 			{
    192 				if (ot->GetCommands().empty())
    193 					source.Reply(_("Opertype \002%s\002 has no allowed commands."), ot->GetName().c_str());
    194 				else
    195 				{
    196 					source.Reply(_("Available commands for \002%s\002:"), ot->GetName().c_str());
    197 					Anope::string buf;
    198 					std::list<Anope::string> cmds = ot->GetCommands();
    199 					for (std::list<Anope::string>::const_iterator it = cmds.begin(), it_end = cmds.end(); it != it_end; ++it)
    200 					{
    201 						buf += *it + " ";
    202 						if (buf.length() > 400)
    203 						{
    204 							source.Reply("%s", buf.c_str());
    205 							buf.clear();
    206 						}
    207 					}
    208 					if (!buf.empty())
    209 					{
    210 						source.Reply("%s", buf.c_str());
    211 						buf.clear();
    212 					}
    213 				}
    214 				if (ot->GetPrivs().empty())
    215 					source.Reply(_("Opertype \002%s\002 has no allowed privileges."), ot->GetName().c_str());
    216 				else
    217 				{
    218 					source.Reply(_("Available privileges for \002%s\002:"), ot->GetName().c_str());
    219 					Anope::string buf;
    220 					std::list<Anope::string> privs = ot->GetPrivs();
    221 					for (std::list<Anope::string>::const_iterator it = privs.begin(), it_end = privs.end(); it != it_end; ++it)
    222 					{
    223 						buf += *it + " ";
    224 						if (buf.length() > 400)
    225 						{
    226 							source.Reply("%s", buf.c_str());
    227 							buf.clear();
    228 						}
    229 					}
    230 					if (!buf.empty())
    231 					{
    232 						source.Reply("%s", buf.c_str());
    233 						buf.clear();
    234 					}
    235 				}
    236 				if (!ot->modes.empty())
    237 					source.Reply(_("Opertype \002%s\002 receives modes \002%s\002 once identified."), ot->GetName().c_str(), ot->modes.c_str());
    238 			}
    239 		}
    240 		else
    241 			this->OnSyntaxError(source, subcommand);
    242 
    243 		return;
    244 	}
    245 
    246 	bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
    247 	{
    248 		this->SendSyntax(source);
    249 		source.Reply(" ");
    250 		source.Reply(_("Allows you to change and view Services Operators.\n"
    251 				"Note that operators removed by this command but are still set in\n"
    252 				"the configuration file are not permanently affected by this."));
    253 		return true;
    254 	}
    255 };
    256 
    257 class OSOper : public Module
    258 {
    259 	Serialize::Type myoper_type;
    260 	CommandOSOper commandosoper;
    261 
    262  public:
    263 	OSOper(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
    264 		myoper_type("Oper", MyOper::Unserialize), commandosoper(this)
    265 	{
    266 	}
    267 
    268 	~OSOper()
    269 	{
    270 		for (nickcore_map::const_iterator it = NickCoreList->begin(), it_end = NickCoreList->end(); it != it_end; ++it)
    271 		{
    272 			NickCore *nc = it->second;
    273 
    274 			if (nc->o && dynamic_cast<MyOper *>(nc->o))
    275 			{
    276 				delete nc->o;
    277 				nc->o = NULL;
    278 			}
    279 		}
    280 	}
    281 
    282 	void OnDelCore(NickCore *nc) anope_override
    283 	{
    284 		if (nc->o && dynamic_cast<MyOper *>(nc->o))
    285 		{
    286 			delete nc->o;
    287 			nc->o = NULL;
    288 		}
    289 	}
    290 };
    291 
    292 MODULE_INIT(OSOper)