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