Anope IRC Services  Version 2.0
m_ldap_authentication.cpp
Go to the documentation of this file.
1 #include "module.h"
2 #include "modules/ldap.h"
3 
4 static Module *me;
5 
11 
13 {
17  bool admin_bind;
19 
20  IdentifyInfo(User *u, IdentifyRequest *r, ServiceReference<LDAPProvider> &lp) : user(u), req(r), lprov(lp), admin_bind(true)
21  {
22  req->Hold(me);
23  }
24 
26  {
27  req->Release(me);
28  }
29 };
30 
32 {
33  std::map<LDAPQuery, IdentifyInfo *> requests;
34 
35  public:
37 
38  void Add(LDAPQuery id, IdentifyInfo *ii)
39  {
40  std::map<LDAPQuery, IdentifyInfo *>::iterator it = this->requests.find(id);
41  if (it != this->requests.end())
42  delete it->second;
43  this->requests[id] = ii;
44  }
45 
47  {
48  std::map<LDAPQuery, IdentifyInfo *>::iterator it = this->requests.find(r.id);
49  if (it == this->requests.end())
50  return;
51  IdentifyInfo *ii = it->second;
52  this->requests.erase(it);
53 
54  if (!ii->lprov)
55  {
56  delete ii;
57  return;
58  }
59 
60  switch (r.type)
61  {
63  {
64  if (!r.empty())
65  {
66  try
67  {
68  const LDAPAttributes &attr = r.get(0);
69  ii->dn = attr.get("dn");
70  Log(LOG_DEBUG) << "m_ldap_authenticationn: binding as " << ii->dn;
71  LDAPQuery id = ii->lprov->Bind(this, ii->dn, ii->req->GetPassword());
72  this->Add(id, ii);
73  return;
74  }
75  catch (const LDAPException &ex)
76  {
77  Log(this->owner) << "Error binding after search: " << ex.GetReason();
78  }
79  }
80  break;
81  }
83  {
84  if (ii->admin_bind)
85  {
86  Anope::string sf = search_filter.replace_all_cs("%account", ii->req->GetAccount()).replace_all_cs("%object_class", object_class);
87  try
88  {
89  Log(LOG_DEBUG) << "m_ldap_authentication: searching for " << sf;
90  LDAPQuery id = ii->lprov->Search(this, basedn, sf);
91  this->Add(id, ii);
92  ii->admin_bind = false;
93  return;
94  }
95  catch (const LDAPException &ex)
96  {
97  Log(this->owner) << "Unable to search for " << sf << ": " << ex.GetReason();
98  }
99  }
100  else
101  {
102  NickAlias *na = NickAlias::Find(ii->req->GetAccount());
103  if (na == NULL)
104  {
105  na = new NickAlias(ii->req->GetAccount(), new NickCore(ii->req->GetAccount()));
106  na->last_realname = ii->user ? ii->user->realname : ii->req->GetAccount();
107  FOREACH_MOD(OnNickRegister, (ii->user, na, ii->req->GetPassword()));
108  BotInfo *NickServ = Config->GetClient("NickServ");
109  if (ii->user && NickServ)
110  ii->user->SendMessage(NickServ, _("Your account \002%s\002 has been successfully created."), na->nick.c_str());
111  }
112  // encrypt and store the password in the nickcore
113  Anope::Encrypt(ii->req->GetPassword(), na->nc->pass);
114 
115  na->nc->Extend<Anope::string>("m_ldap_authentication_dn", ii->dn);
116  ii->req->Success(me);
117  }
118  break;
119  }
120  default:
121  break;
122  }
123 
124  delete ii;
125  }
126 
128  {
129  std::map<LDAPQuery, IdentifyInfo *>::iterator it = this->requests.find(r.id);
130  if (it == this->requests.end())
131  return;
132  IdentifyInfo *ii = it->second;
133  this->requests.erase(it);
134  delete ii;
135  }
136 };
137 
139 {
140  std::map<LDAPQuery, Anope::string> requests;
141 
142  public:
144 
145  void Add(LDAPQuery id, const Anope::string &nick)
146  {
147  this->requests[id] = nick;
148  }
149 
151  {
152  std::map<LDAPQuery, Anope::string>::iterator it = this->requests.find(r.id);
153  if (it == this->requests.end())
154  return;
155  User *u = User::Find(it->second);
156  this->requests.erase(it);
157 
158  if (!u || !u->Account() || r.empty())
159  return;
160 
161  try
162  {
163  const LDAPAttributes &attr = r.get(0);
164  Anope::string email = attr.get(email_attribute);
165 
166  if (!email.equals_ci(u->Account()->email))
167  {
168  u->Account()->email = email;
169  BotInfo *NickServ = Config->GetClient("NickServ");
170  if (NickServ)
171  u->SendMessage(NickServ, _("Your email has been updated to \002%s\002"), email.c_str());
172  Log(this->owner) << "Updated email address for " << u->nick << " (" << u->Account()->display << ") to " << email;
173  }
174  }
175  catch (const LDAPException &ex)
176  {
177  Log(this->owner) << ex.GetReason();
178  }
179  }
180 
182  {
183  this->requests.erase(r.id);
184  Log(this->owner) << r.error;
185  }
186 };
187 
189 {
190  public:
192 
194  {
195  Log(this->owner) << "Successfully added newly created account to LDAP";
196  }
197 
199  {
200  Log(this->owner) << "Error adding newly created account to LDAP: " << r.getError();
201  }
202 };
203 
204 class NSIdentifyLDAP : public Module
205 {
210 
212 
216  public:
217  NSIdentifyLDAP(const Anope::string &modname, const Anope::string &creator) :
218  Module(modname, creator, EXTRA | VENDOR), ldap("LDAPProvider", "ldap/main"), iinterface(this), oninterface(this), orinterface(this),
219  dn(this, "m_ldap_authentication_dn")
220  {
221 
222  me = this;
223 
225  }
226 
228  {
229  Configuration::Block *conf = Config->GetModule(this);
230 
231  basedn = conf->Get<const Anope::string>("basedn");
232  search_filter = conf->Get<const Anope::string>("search_filter");
233  object_class = conf->Get<const Anope::string>("object_class");
234  username_attribute = conf->Get<const Anope::string>("username_attribute");
235  this->password_attribute = conf->Get<const Anope::string>("password_attribute");
236  email_attribute = conf->Get<const Anope::string>("email_attribute");
237  this->disable_register_reason = conf->Get<const Anope::string>("disable_register_reason");
238  this->disable_email_reason = conf->Get<const Anope::string>("disable_email_reason");
239 
240  if (!email_attribute.empty())
241  /* Don't complain to users about how they need to update their email, we will do it for them */
242  config->GetModule("nickserv")->Set("forceemail", "false");
243  }
244 
245  EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> &params) anope_override
246  {
247  if (!this->disable_register_reason.empty())
248  {
249  if (command->name == "nickserv/register" || command->name == "nickserv/group")
250  {
251  source.Reply(this->disable_register_reason);
252  return EVENT_STOP;
253  }
254  }
255 
256  if (!email_attribute.empty() && !this->disable_email_reason.empty() && command->name == "nickserv/set/email")
257  {
258  source.Reply(this->disable_email_reason);
259  return EVENT_STOP;
260  }
261 
262  return EVENT_CONTINUE;
263  }
264 
266  {
267  if (!this->ldap)
268  return;
269 
270  IdentifyInfo *ii = new IdentifyInfo(u, req, this->ldap);
271  try
272  {
273  LDAPQuery id = this->ldap->BindAsAdmin(&this->iinterface);
274  this->iinterface.Add(id, ii);
275  }
276  catch (const LDAPException &ex)
277  {
278  delete ii;
279  Log(this) << ex.GetReason();
280  }
281  }
282 
284  {
285  if (email_attribute.empty() || !this->ldap)
286  return;
287 
288  Anope::string *d = dn.Get(u->Account());
289  if (!d || d->empty())
290  return;
291 
292  try
293  {
294  LDAPQuery id = this->ldap->Search(&this->oninterface, *d, "(" + email_attribute + "=*)");
295  this->oninterface.Add(id, u->nick);
296  }
297  catch (const LDAPException &ex)
298  {
299  Log(this) << ex.GetReason();
300  }
301  }
302 
304  {
305  if (!this->disable_register_reason.empty() || !this->ldap)
306  return;
307 
308  try
309  {
310  this->ldap->BindAsAdmin(NULL);
311 
312  LDAPMods attributes;
313  attributes.resize(4);
314 
315  attributes[0].name = "objectClass";
316  attributes[0].values.push_back("top");
317  attributes[0].values.push_back(object_class);
318 
319  attributes[1].name = username_attribute;
320  attributes[1].values.push_back(na->nick);
321 
322  if (!na->nc->email.empty())
323  {
324  attributes[2].name = email_attribute;
325  attributes[2].values.push_back(na->nc->email);
326  }
327 
328  attributes[3].name = this->password_attribute;
329  attributes[3].values.push_back(pass);
330 
331  Anope::string new_dn = username_attribute + "=" + na->nick + "," + basedn;
332  this->ldap->Add(&this->orinterface, new_dn, attributes);
333  }
334  catch (const LDAPException &ex)
335  {
336  Log(this) << ex.GetReason();
337  }
338  }
339 };
340 
Serialize::Reference< NickCore > nc
Definition: account.h:47
void Release(Module *m)
Definition: account.cpp:37
Definition: bots.h:24
static NickAlias * Find(const Anope::string &nick)
Definition: nickalias.cpp:121
Anope::string disable_email_reason
Anope::string password_attribute
void Hold(Module *m)
Definition: account.cpp:32
ServiceReference< LDAPProvider > ldap
void push_back(char c)
Definition: anope.h:142
Anope::string nick
Definition: account.h:37
static bool SetPriority(Module *mod, Implementation i, Priority s, Module **modules=NULL, size_t sz=1)
void OnResult(const LDAPResult &r) anope_override
void OnNickRegister(User *, NickAlias *na, const Anope::string &pass) anope_override
IdentifyInterface iinterface
void Add(LDAPQuery id, IdentifyInfo *ii)
Definition: users.h:34
PrimitiveExtensibleItem< Anope::string > dn
void OnResult(const LDAPResult &r) anope_override
static Anope::string basedn
Reference< User > user
void OnError(const LDAPResult &r) anope_override
void Add(LDAPQuery id, const Anope::string &nick)
bool equals_ci(const char *_str) const
Definition: anope.h:78
IdentifyRequest * req
NSIdentifyLDAP(const Anope::string &modname, const Anope::string &creator)
const Anope::string & GetPassword() const
Definition: account.h:251
#define FOREACH_MOD(ename, args)
Definition: modules.h:62
const Anope::string & get(const Anope::string &attr) const
Definition: ldap.h:45
IdentifyInfo(User *u, IdentifyRequest *r, ServiceReference< LDAPProvider > &lp)
ServiceReference< LDAPProvider > lprov
static Anope::string object_class
EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector< Anope::string > &params) anope_override
void OnResult(const LDAPResult &r) anope_override
OnIdentifyInterface oninterface
OnRegisterInterface orinterface
Definition: Config.cs:26
static Anope::string search_filter
void OnError(const LDAPResult &r) anope_override
string replace_all_cs(const string &_orig, const string &_repl) const
Definition: anope.h:229
int LDAPQuery
Definition: ldap.h:4
void OnReload(Configuration::Conf *config) anope_override
Anope::string name
Definition: service.h:123
Anope::string display
Definition: account.h:113
#define anope_override
Definition: services.h:56
bool empty() const
Definition: anope.h:126
std::map< LDAPQuery, IdentifyInfo * > requests
static Module * me
std::vector< LDAPModification > LDAPMods
Definition: ldap.h:27
EventReturn
Definition: modules.h:129
#define MODULE_INIT(x)
Definition: modules.h:45
Module * owner
Definition: ldap.h:112
void Success(Module *m)
Definition: account.cpp:48
Anope::string realname
Definition: users.h:71
Anope::string nick
Definition: users.h:62
static User * Find(const Anope::string &name, bool nick_only=false)
Definition: users.cpp:815
Anope::string disable_register_reason
static Anope::string email_attribute
void OnCheckAuthentication(User *u, IdentifyRequest *req) anope_override
NickCore * Account() const
Definition: users.cpp:422
static Anope::string username_attribute
T * Get(const Extensible *obj) const
Definition: extensible.h:103
virtual const Anope::string & GetReason() const
Definition: anope.h:672
Anope::string last_realname
Definition: account.h:39
CoreExport void Encrypt(const Anope::string &src, Anope::string &dest)
Definition: misc.cpp:511
const char * c_str() const
Definition: anope.h:117
std::map< LDAPQuery, Anope::string > requests
Definition: logger.h:53
T Get(const Anope::string &tag)
Definition: config.h:44
void OnNickIdentify(User *u) anope_override
Anope::string email
Definition: account.h:116
void SendMessage(BotInfo *source, const char *fmt,...)
Definition: users.cpp:320
#define _(x)
Definition: services.h:50
void OnError(const LDAPResult &r) anope_override
Definition: modules.h:163
const Anope::string & GetAccount() const
Definition: account.h:250