]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_ldapoper.cpp
m_httpd: use http_response_str() instead of Response().
[user/henk/code/inspircd.git] / src / modules / m_ldapoper.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2013 Adam <Adam@anope.org>
5  *   Copyright (C) 2009 Robin Burchell <robin+git@viroteck.net>
6  *   Copyright (C) 2008 Pippijn van Steenhoven <pip88nl@gmail.com>
7  *   Copyright (C) 2008 Craig Edwards <craigedwards@brainbox.cc>
8  *   Copyright (C) 2007 Carsten Valdemar Munk <carsten.munk+inspircd@gmail.com>
9  *
10  * This file is part of InspIRCd.  InspIRCd is free software: you can
11  * redistribute it and/or modify it under the terms of the GNU General Public
12  * License as published by the Free Software Foundation, version 2.
13  *
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
17  * details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  */
22
23
24 #include "inspircd.h"
25 #include "modules/ldap.h"
26
27 namespace
28 {
29         Module* me;
30 }
31
32 class LDAPOperBase : public LDAPInterface
33 {
34  protected:
35         const std::string uid;
36         const std::string opername;
37         const std::string password;
38
39         void Fallback(User* user)
40         {
41                 if (!user)
42                         return;
43
44                 Command* oper_command = ServerInstance->Parser.GetHandler("OPER");
45                 if (!oper_command)
46                         return;
47
48                 CommandBase::Params params;
49                 params.push_back(opername);
50                 params.push_back(password);
51                 ClientProtocol::TagMap tags;
52                 oper_command->Handle(user, CommandBase::Params(params, tags));
53         }
54
55         void Fallback()
56         {
57                 User* user = ServerInstance->FindUUID(uid);
58                 Fallback(user);
59         }
60
61  public:
62         LDAPOperBase(Module* mod, const std::string& uuid, const std::string& oper, const std::string& pass)
63                 : LDAPInterface(mod)
64                 , uid(uuid), opername(oper), password(pass)
65         {
66         }
67
68         void OnError(const LDAPResult& err) CXX11_OVERRIDE
69         {
70                 ServerInstance->SNO->WriteToSnoMask('a', "Error searching LDAP server: %s", err.getError().c_str());
71                 Fallback();
72                 delete this;
73         }
74 };
75
76 class BindInterface : public LDAPOperBase
77 {
78  public:
79         BindInterface(Module* mod, const std::string& uuid, const std::string& oper, const std::string& pass)
80                 : LDAPOperBase(mod, uuid, oper, pass)
81         {
82         }
83
84         void OnResult(const LDAPResult& r) CXX11_OVERRIDE
85         {
86                 User* user = ServerInstance->FindUUID(uid);
87                 ServerConfig::OperIndex::const_iterator iter = ServerInstance->Config->oper_blocks.find(opername);
88
89                 if (!user || iter == ServerInstance->Config->oper_blocks.end())
90                 {
91                         Fallback();
92                         delete this;
93                         return;
94                 }
95
96                 OperInfo* ifo = iter->second;
97                 user->Oper(ifo);
98                 delete this;
99         }
100 };
101
102 class SearchInterface : public LDAPOperBase
103 {
104         const std::string provider;
105
106         bool HandleResult(const LDAPResult& result)
107         {
108                 dynamic_reference<LDAPProvider> LDAP(me, provider);
109                 if (!LDAP || result.empty())
110                         return false;
111
112                 try
113                 {
114                         const LDAPAttributes& attr = result.get(0);
115                         std::string bindDn = attr.get("dn");
116                         if (bindDn.empty())
117                                 return false;
118
119                         LDAP->Bind(new BindInterface(this->creator, uid, opername, password), bindDn, password);
120                 }
121                 catch (LDAPException& ex)
122                 {
123                         ServerInstance->SNO->WriteToSnoMask('a', "Error searching LDAP server: " + ex.GetReason());
124                 }
125
126                 return true;
127         }
128
129  public:
130         SearchInterface(Module* mod, const std::string& prov, const std::string &uuid, const std::string& oper, const std::string& pass)
131                 : LDAPOperBase(mod, uuid, oper, pass)
132                 , provider(prov)
133         {
134         }
135
136         void OnResult(const LDAPResult& result) CXX11_OVERRIDE
137         {
138                 if (!HandleResult(result))
139                         Fallback();
140                 delete this;
141         }
142 };
143
144 class AdminBindInterface : public LDAPInterface
145 {
146         const std::string provider;
147         const std::string user;
148         const std::string opername;
149         const std::string password;
150         const std::string base;
151         const std::string what;
152
153  public:
154         AdminBindInterface(Module* c, const std::string& p, const std::string& u, const std::string& o, const std::string& pa, const std::string& b, const std::string& w)
155                 : LDAPInterface(c), provider(p), user(u), opername(p), password(pa), base(b), what(w)
156         {
157         }
158
159         void OnResult(const LDAPResult& r) CXX11_OVERRIDE
160         {
161                 dynamic_reference<LDAPProvider> LDAP(me, provider);
162                 if (LDAP)
163                 {
164                         try
165                         {
166                                 LDAP->Search(new SearchInterface(this->creator, provider, user, opername, password), base, what);
167                         }
168                         catch (LDAPException& ex)
169                         {
170                                 ServerInstance->SNO->WriteToSnoMask('a', "Error searching LDAP server: " + ex.GetReason());
171                         }
172                 }
173                 delete this;
174         }
175
176         void OnError(const LDAPResult& err) CXX11_OVERRIDE
177         {
178                 ServerInstance->SNO->WriteToSnoMask('a', "Error binding as manager to LDAP server: " + err.getError());
179                 delete this;
180         }
181 };
182
183 class ModuleLDAPAuth : public Module
184 {
185         dynamic_reference<LDAPProvider> LDAP;
186         std::string base;
187         std::string attribute;
188
189  public:
190         ModuleLDAPAuth()
191                 : LDAP(this, "LDAP")
192         {
193                 me = this;
194         }
195
196         void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
197         {
198                 ConfigTag* tag = ServerInstance->Config->ConfValue("ldapoper");
199
200                 LDAP.SetProvider("LDAP/" + tag->getString("dbid"));
201                 base = tag->getString("baserdn");
202                 attribute = tag->getString("attribute");
203         }
204
205         ModResult OnPreCommand(std::string& command, CommandBase::Params& parameters, LocalUser* user, bool validated) CXX11_OVERRIDE
206         {
207                 if (validated && command == "OPER" && parameters.size() >= 2)
208                 {
209                         const std::string& opername = parameters[0];
210                         const std::string& password = parameters[1];
211
212                         ServerConfig::OperIndex::const_iterator it = ServerInstance->Config->oper_blocks.find(opername);
213                         if (it == ServerInstance->Config->oper_blocks.end())
214                                 return MOD_RES_PASSTHRU;
215
216                         ConfigTag* tag = it->second->oper_block;
217                         if (!tag)
218                                 return MOD_RES_PASSTHRU;
219
220                         std::string acceptedhosts = tag->getString("host");
221                         std::string hostname = user->ident + "@" + user->GetRealHost();
222                         if (!InspIRCd::MatchMask(acceptedhosts, hostname, user->GetIPString()))
223                                 return MOD_RES_PASSTHRU;
224
225                         if (!LDAP)
226                                 return MOD_RES_PASSTHRU;
227
228                         try
229                         {
230                                 std::string what = attribute + "=" + opername;
231                                 LDAP->BindAsManager(new AdminBindInterface(this, LDAP.GetProvider(), user->uuid, opername, password, base, what));
232                                 return MOD_RES_DENY;
233                         }
234                         catch (LDAPException& ex)
235                         {
236                                 ServerInstance->SNO->WriteToSnoMask('a', "LDAP exception: " + ex.GetReason());
237                         }
238                 }
239
240                 return MOD_RES_PASSTHRU;
241         }
242
243         Version GetVersion() CXX11_OVERRIDE
244         {
245                 return Version("Adds the ability to authenticate opers via LDAP", VF_VENDOR);
246         }
247 };
248
249 MODULE_INIT(ModuleLDAPAuth)