anope

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

access.cpp (11415B)

      1 /*
      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 "service.h"
     13 #include "access.h"
     14 #include "regchannel.h"
     15 #include "users.h"
     16 #include "account.h"
     17 #include "protocol.h"
     18 
     19 static struct
     20 {
     21 	Anope::string name;
     22 	Anope::string desc;
     23 } descriptions[] = {
     24 	{"ACCESS_CHANGE", _("Allowed to modify the access list")},
     25 	{"ACCESS_LIST", _("Allowed to view the access list")},
     26 	{"AKICK", _("Allowed to use the AKICK command")},
     27 	{"ASSIGN", _("Allowed to assign/unassign a bot")},
     28 	{"AUTOHALFOP", _("Automatic halfop upon join")},
     29 	{"AUTOOP", _("Automatic channel operator status upon join")},
     30 	{"AUTOOWNER", _("Automatic owner upon join")},
     31 	{"AUTOPROTECT", _("Automatic protect upon join")},
     32 	{"AUTOVOICE", _("Automatic voice on join")},
     33 	{"BADWORDS", _("Allowed to modify channel badwords list")},
     34 	{"BAN", _("Allowed to ban users")},
     35 	{"FANTASIA", _("Allowed to use fantasy commands")},
     36 	{"FOUNDER", _("Allowed to issue commands restricted to channel founders")},
     37 	{"GETKEY", _("Allowed to use GETKEY command")},
     38 	{"GREET", _("Greet message displayed on join")},
     39 	{"HALFOP", _("Allowed to (de)halfop users")},
     40 	{"HALFOPME", _("Allowed to (de)halfop him/herself")},
     41 	{"INFO", _("Allowed to get full INFO output")},
     42 	{"INVITE", _("Allowed to use the INVITE command")},
     43 	{"KICK", _("Allowed to use the KICK command")},
     44 	{"MEMO", _("Allowed to read channel memos")},
     45 	{"MODE", _("Allowed to use the MODE command")},
     46 	{"NOKICK", _("Prevents users being kicked by Services")},
     47 	{"OP", _("Allowed to (de)op users")},
     48 	{"OPME", _("Allowed to (de)op him/herself")},
     49 	{"OWNER", _("Allowed to (de)owner users")},
     50 	{"OWNERME", _("Allowed to (de)owner him/herself")},
     51 	{"PROTECT", _("Allowed to (de)protect users")},
     52 	{"PROTECTME", _("Allowed to (de)protect him/herself")},
     53 	{"SAY", _("Allowed to use SAY and ACT commands")},
     54 	{"SET", _("Allowed to set channel settings")},
     55 	{"SIGNKICK", _("No signed kick when SIGNKICK LEVEL is used")},
     56 	{"TOPIC", _("Allowed to change channel topics")},
     57 	{"UNBAN", _("Allowed to unban users")},
     58 	{"VOICE", _("Allowed to (de)voice users")},
     59 	{"VOICEME", _("Allowed to (de)voice him/herself")}
     60 };
     61 
     62 Privilege::Privilege(const Anope::string &n, const Anope::string &d, int r) : name(n), desc(d), rank(r)
     63 {
     64 	if (this->desc.empty())
     65 		for (unsigned j = 0; j < sizeof(descriptions) / sizeof(*descriptions); ++j)
     66 			if (descriptions[j].name.equals_ci(name))
     67 				this->desc = descriptions[j].desc;
     68 }
     69 
     70 bool Privilege::operator==(const Privilege &other) const
     71 {
     72 	return this->name.equals_ci(other.name);
     73 }
     74 
     75 std::vector<Privilege> PrivilegeManager::Privileges;
     76 
     77 void PrivilegeManager::AddPrivilege(Privilege p)
     78 {
     79 	unsigned i;
     80 	for (i = 0; i < Privileges.size(); ++i)
     81 	{
     82 		Privilege &priv = Privileges[i];
     83 
     84 		if (priv.rank > p.rank)
     85 			break;
     86 	}
     87 
     88 	Privileges.insert(Privileges.begin() + i, p);
     89 }
     90 
     91 void PrivilegeManager::RemovePrivilege(Privilege &p)
     92 {
     93 	std::vector<Privilege>::iterator it = std::find(Privileges.begin(), Privileges.end(), p);
     94 	if (it != Privileges.end())
     95 		Privileges.erase(it);
     96 
     97 	for (registered_channel_map::const_iterator cit = RegisteredChannelList->begin(), cit_end = RegisteredChannelList->end(); cit != cit_end; ++cit)
     98 	{
     99 		cit->second->QueueUpdate();
    100 		cit->second->RemoveLevel(p.name);
    101 	}
    102 }
    103 
    104 Privilege *PrivilegeManager::FindPrivilege(const Anope::string &name)
    105 {
    106 	for (unsigned i = Privileges.size(); i > 0; --i)
    107 		if (Privileges[i - 1].name.equals_ci(name))
    108 			return &Privileges[i - 1];
    109 	return NULL;
    110 }
    111 
    112 std::vector<Privilege> &PrivilegeManager::GetPrivileges()
    113 {
    114 	return Privileges;
    115 }
    116 
    117 void PrivilegeManager::ClearPrivileges()
    118 {
    119 	Privileges.clear();
    120 }
    121 
    122 AccessProvider::AccessProvider(Module *o, const Anope::string &n) : Service(o, "AccessProvider", n)
    123 {
    124 	Providers.push_back(this);
    125 }
    126 
    127 AccessProvider::~AccessProvider()
    128 {
    129 	std::list<AccessProvider *>::iterator it = std::find(Providers.begin(), Providers.end(), this);
    130 	if (it != Providers.end())
    131 		Providers.erase(it);
    132 }
    133 
    134 std::list<AccessProvider *> AccessProvider::Providers;
    135 
    136 const std::list<AccessProvider *>& AccessProvider::GetProviders()
    137 {
    138 	return Providers;
    139 }
    140 
    141 ChanAccess::ChanAccess(AccessProvider *p) : Serializable("ChanAccess"), provider(p)
    142 {
    143 }
    144 
    145 ChanAccess::~ChanAccess()
    146 {
    147 	if (this->ci)
    148 	{
    149 		std::vector<ChanAccess *>::iterator it = std::find(this->ci->access->begin(), this->ci->access->end(), this);
    150 		if (it != this->ci->access->end())
    151 			this->ci->access->erase(it);
    152 
    153 		if (*nc != NULL)
    154 			nc->RemoveChannelReference(this->ci);
    155 		else
    156 		{
    157 			ChannelInfo *c = ChannelInfo::Find(this->mask);
    158 			if (c)
    159 				c->RemoveChannelReference(this->ci->name);
    160 		}
    161 	}
    162 }
    163 
    164 void ChanAccess::SetMask(const Anope::string &m, ChannelInfo *c)
    165 {
    166 	if (*nc != NULL)
    167 		nc->RemoveChannelReference(this->ci);
    168 	else if (!this->mask.empty())
    169 	{
    170 		ChannelInfo *targc = ChannelInfo::Find(this->mask);
    171 		if (targc)
    172 			targc->RemoveChannelReference(this->ci->name);
    173 	}
    174 
    175 	ci = c;
    176 	mask.clear();
    177 	nc = NULL;
    178 
    179 	const NickAlias *na = NickAlias::Find(m);
    180 	if (na != NULL)
    181 	{
    182 		nc = na->nc;
    183 		nc->AddChannelReference(ci);
    184 	}
    185 	else
    186 	{
    187 		mask = m;
    188 
    189 		ChannelInfo *targci = ChannelInfo::Find(mask);
    190 		if (targci != NULL)
    191 			targci->AddChannelReference(ci->name);
    192 	}
    193 }
    194 
    195 const Anope::string &ChanAccess::Mask() const
    196 {
    197 	if (nc)
    198 		return nc->display;
    199 	else
    200 		return mask;
    201 }
    202 
    203 NickCore *ChanAccess::GetAccount() const
    204 {
    205 	return nc;
    206 }
    207 
    208 void ChanAccess::Serialize(Serialize::Data &data) const
    209 {
    210 	data["provider"] << this->provider->name;
    211 	data["ci"] << this->ci->name;
    212 	data["mask"] << this->Mask();
    213 	data["creator"] << this->creator;
    214 	data.SetType("last_seen", Serialize::Data::DT_INT); data["last_seen"] << this->last_seen;
    215 	data.SetType("created", Serialize::Data::DT_INT); data["created"] << this->created;
    216 	data["data"] << this->AccessSerialize();
    217 }
    218 
    219 Serializable* ChanAccess::Unserialize(Serializable *obj, Serialize::Data &data)
    220 {
    221 	Anope::string provider, chan;
    222 
    223 	data["provider"] >> provider;
    224 	data["ci"] >> chan;
    225 
    226 	ServiceReference<AccessProvider> aprovider("AccessProvider", provider);
    227 	ChannelInfo *ci = ChannelInfo::Find(chan);
    228 	if (!aprovider || !ci)
    229 		return NULL;
    230 
    231 	ChanAccess *access;
    232 	if (obj)
    233 		access = anope_dynamic_static_cast<ChanAccess *>(obj);
    234 	else
    235 		access = aprovider->Create();
    236 	access->ci = ci;
    237 	Anope::string m;
    238 	data["mask"] >> m;
    239 	access->SetMask(m, ci);
    240 	data["creator"] >> access->creator;
    241 	data["last_seen"] >> access->last_seen;
    242 	data["created"] >> access->created;
    243 
    244 	Anope::string adata;
    245 	data["data"] >> adata;
    246 	access->AccessUnserialize(adata);
    247 
    248 	if (!obj)
    249 		ci->AddAccess(access);
    250 	return access;
    251 }
    252 
    253 bool ChanAccess::Matches(const User *u, const NickCore *acc, ChannelInfo* &next) const
    254 {
    255 	next = NULL;
    256 
    257 	if (this->nc)
    258 		return this->nc == acc;
    259 
    260 	if (u)
    261 	{
    262 		bool is_mask = this->mask.find_first_of("!@?*") != Anope::string::npos;
    263 		if (is_mask && Anope::Match(u->nick, this->mask))
    264 			return true;
    265 		else if (Anope::Match(u->GetDisplayedMask(), this->mask))
    266 			return true;
    267 	}
    268 
    269 	if (acc)
    270 	{
    271 		for (unsigned i = 0; i < acc->aliases->size(); ++i)
    272 		{
    273 			const NickAlias *na = acc->aliases->at(i);
    274 			if (Anope::Match(na->nick, this->mask))
    275 				return true;
    276 		}
    277 	}
    278 
    279 	if (IRCD->IsChannelValid(this->mask))
    280 	{
    281 		next = ChannelInfo::Find(this->mask);
    282 	}
    283 
    284 	return false;
    285 }
    286 
    287 bool ChanAccess::operator>(const ChanAccess &other) const
    288 {
    289 	const std::vector<Privilege> &privs = PrivilegeManager::GetPrivileges();
    290 	for (unsigned i = privs.size(); i > 0; --i)
    291 	{
    292 		bool this_p = this->HasPriv(privs[i - 1].name),
    293 			other_p = other.HasPriv(privs[i - 1].name);
    294 
    295 		if (!this_p && !other_p)
    296 			continue;
    297 
    298 		return this_p && !other_p;
    299 	}
    300 
    301 	return false;
    302 }
    303 
    304 bool ChanAccess::operator<(const ChanAccess &other) const
    305 {
    306 	const std::vector<Privilege> &privs = PrivilegeManager::GetPrivileges();
    307 	for (unsigned i = privs.size(); i > 0; --i)
    308 	{
    309 		bool this_p = this->HasPriv(privs[i - 1].name),
    310 			other_p = other.HasPriv(privs[i - 1].name);
    311 
    312 		if (!this_p && !other_p)
    313 			continue;
    314 
    315 		return !this_p && other_p;
    316 	}
    317 
    318 	return false;
    319 }
    320 
    321 bool ChanAccess::operator>=(const ChanAccess &other) const
    322 {
    323 	return !(*this < other);
    324 }
    325 
    326 bool ChanAccess::operator<=(const ChanAccess &other) const
    327 {
    328 	return !(*this > other);
    329 }
    330 
    331 AccessGroup::AccessGroup()
    332 {
    333 	this->ci = NULL;
    334 	this->nc = NULL;
    335 	this->super_admin = this->founder = false;
    336 }
    337 
    338 static bool HasPriv(const ChanAccess::Path &path, const Anope::string &name)
    339 {
    340 	if (path.empty())
    341 		return false;
    342 
    343 	for (unsigned int i = 0; i < path.size(); ++i)
    344 	{
    345 		ChanAccess *access = path[i];
    346 
    347 		EventReturn MOD_RESULT;
    348 		FOREACH_RESULT(OnCheckPriv, MOD_RESULT, (access, name));
    349 
    350 		if (MOD_RESULT != EVENT_ALLOW && !access->HasPriv(name))
    351 			return false;
    352 	}
    353 
    354 	return true;
    355 }
    356 
    357 bool AccessGroup::HasPriv(const Anope::string &name) const
    358 {
    359 	if (this->super_admin)
    360 		return true;
    361 	else if (!ci || ci->GetLevel(name) == ACCESS_INVALID)
    362 		return false;
    363 
    364 	/* Privileges prefixed with auto are understood to be given
    365 	 * automatically. Sometimes founders want to not automatically
    366 	 * obtain privileges, so we will let them */
    367 	bool auto_mode = !name.find("AUTO");
    368 
    369 	/* Only grant founder privilege if this isn't an auto mode or if they don't match any entries in this group */
    370 	if ((!auto_mode || paths.empty()) && this->founder)
    371 		return true;
    372 
    373 	EventReturn MOD_RESULT;
    374 	FOREACH_RESULT(OnGroupCheckPriv, MOD_RESULT, (this, name));
    375 	if (MOD_RESULT != EVENT_CONTINUE)
    376 		return MOD_RESULT == EVENT_ALLOW;
    377 
    378 	for (unsigned int i = paths.size(); i > 0; --i)
    379 	{
    380 		const ChanAccess::Path &path = paths[i - 1];
    381 
    382 		if (::HasPriv(path, name))
    383 			return true;
    384 	}
    385 
    386 	return false;
    387 }
    388 
    389 static ChanAccess *HighestInPath(const ChanAccess::Path &path)
    390 {
    391 	ChanAccess *highest = NULL;
    392 
    393 	for (unsigned int i = 0; i < path.size(); ++i)
    394 		if (highest == NULL || *path[i] > *highest)
    395 			highest = path[i];
    396 
    397 	return highest;
    398 }
    399 
    400 const ChanAccess *AccessGroup::Highest() const
    401 {
    402 	ChanAccess *highest = NULL;
    403 
    404 	for (unsigned int i = 0; i < paths.size(); ++i)
    405 	{
    406 		ChanAccess *hip = HighestInPath(paths[i]);
    407 
    408 		if (highest == NULL || *hip > *highest)
    409 			highest = hip;
    410 	}
    411 
    412 	return highest;
    413 }
    414 
    415 bool AccessGroup::operator>(const AccessGroup &other) const
    416 {
    417 	if (other.super_admin)
    418 		return false;
    419 	else if (this->super_admin)
    420 		return true;
    421 	else if (other.founder)
    422 		return false;
    423 	else if (this->founder)
    424 		return true;
    425 
    426 	const std::vector<Privilege> &privs = PrivilegeManager::GetPrivileges();
    427 	for (unsigned i = privs.size(); i > 0; --i)
    428 	{
    429 		bool this_p = this->HasPriv(privs[i - 1].name),
    430 			other_p = other.HasPriv(privs[i - 1].name);
    431 
    432 		if (!this_p && !other_p)
    433 			continue;
    434 
    435 		return this_p && !other_p;
    436 	}
    437 
    438 	return false;
    439 }
    440 
    441 bool AccessGroup::operator<(const AccessGroup &other) const
    442 {
    443 	if (this->super_admin)
    444 		return false;
    445 	else if (other.super_admin)
    446 		return true;
    447 	else if (this->founder)
    448 		return false;
    449 	else if (other.founder)
    450 		return true;
    451 
    452 	const std::vector<Privilege> &privs = PrivilegeManager::GetPrivileges();
    453 	for (unsigned i = privs.size(); i > 0; --i)
    454 	{
    455 		bool this_p = this->HasPriv(privs[i - 1].name),
    456 			other_p = other.HasPriv(privs[i - 1].name);
    457 
    458 		if (!this_p && !other_p)
    459 			continue;
    460 
    461 		return !this_p && other_p;
    462 	}
    463 
    464 	return false;
    465 }
    466 
    467 bool AccessGroup::operator>=(const AccessGroup &other) const
    468 {
    469 	return !(*this < other);
    470 }
    471 
    472 bool AccessGroup::operator<=(const AccessGroup &other) const
    473 {
    474 	return !(*this > other);
    475 }