2 * InspIRCd -- Internet Relay Chat Daemon
4 * Copyright (C) 2017-2020 Sadie Powell <sadie@witchery.services>
5 * Copyright (C) 2014, 2018 Attila Molnar <attilamolnar@hush.com>
6 * Copyright (C) 2013-2014 Adam <Adam@anope.org>
8 * This file is part of InspIRCd. InspIRCd is free software: you can
9 * redistribute it and/or modify it under the terms of the GNU General Public
10 * License as published by the Free Software Foundation, version 2.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "modules/ldap.h"
30 class LDAPOperBase : public LDAPInterface
33 const std::string uid;
34 const std::string opername;
35 const std::string password;
37 void Fallback(User* user)
42 Command* oper_command = ServerInstance->Parser.GetHandler("OPER");
46 CommandBase::Params params;
47 params.push_back(opername);
48 params.push_back(password);
49 ClientProtocol::TagMap tags;
50 oper_command->Handle(user, CommandBase::Params(params, tags));
55 User* user = ServerInstance->FindUUID(uid);
60 LDAPOperBase(Module* mod, const std::string& uuid, const std::string& oper, const std::string& pass)
62 , uid(uuid), opername(oper), password(pass)
66 void OnError(const LDAPResult& err) CXX11_OVERRIDE
68 ServerInstance->SNO->WriteToSnoMask('a', "Error searching LDAP server: %s", err.getError().c_str());
74 class BindInterface : public LDAPOperBase
77 BindInterface(Module* mod, const std::string& uuid, const std::string& oper, const std::string& pass)
78 : LDAPOperBase(mod, uuid, oper, pass)
82 void OnResult(const LDAPResult& r) CXX11_OVERRIDE
84 User* user = ServerInstance->FindUUID(uid);
85 ServerConfig::OperIndex::const_iterator iter = ServerInstance->Config->oper_blocks.find(opername);
87 if (!user || iter == ServerInstance->Config->oper_blocks.end())
94 OperInfo* ifo = iter->second;
100 class SearchInterface : public LDAPOperBase
102 const std::string provider;
104 bool HandleResult(const LDAPResult& result)
106 dynamic_reference<LDAPProvider> LDAP(me, provider);
107 if (!LDAP || result.empty())
112 const LDAPAttributes& attr = result.get(0);
113 std::string bindDn = attr.get("dn");
117 LDAP->Bind(new BindInterface(this->creator, uid, opername, password), bindDn, password);
119 catch (LDAPException& ex)
121 ServerInstance->SNO->WriteToSnoMask('a', "Error searching LDAP server: " + ex.GetReason());
128 SearchInterface(Module* mod, const std::string& prov, const std::string &uuid, const std::string& oper, const std::string& pass)
129 : LDAPOperBase(mod, uuid, oper, pass)
134 void OnResult(const LDAPResult& result) CXX11_OVERRIDE
136 if (!HandleResult(result))
142 class AdminBindInterface : public LDAPInterface
144 const std::string provider;
145 const std::string user;
146 const std::string opername;
147 const std::string password;
148 const std::string base;
149 const std::string what;
152 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)
163 void OnResult(const LDAPResult& r) CXX11_OVERRIDE
165 dynamic_reference<LDAPProvider> LDAP(me, provider);
170 LDAP->Search(new SearchInterface(this->creator, provider, user, opername, password), base, what);
172 catch (LDAPException& ex)
174 ServerInstance->SNO->WriteToSnoMask('a', "Error searching LDAP server: " + ex.GetReason());
180 void OnError(const LDAPResult& err) CXX11_OVERRIDE
182 ServerInstance->SNO->WriteToSnoMask('a', "Error binding as manager to LDAP server: " + err.getError());
187 class ModuleLDAPOper : public Module
189 dynamic_reference<LDAPProvider> LDAP;
191 std::string attribute;
200 void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
202 ConfigTag* tag = ServerInstance->Config->ConfValue("ldapoper");
204 LDAP.SetProvider("LDAP/" + tag->getString("dbid"));
205 base = tag->getString("baserdn");
206 attribute = tag->getString("attribute");
209 ModResult OnPreCommand(std::string& command, CommandBase::Params& parameters, LocalUser* user, bool validated) CXX11_OVERRIDE
211 if (validated && command == "OPER" && parameters.size() >= 2)
213 const std::string& opername = parameters[0];
214 const std::string& password = parameters[1];
216 ServerConfig::OperIndex::const_iterator it = ServerInstance->Config->oper_blocks.find(opername);
217 if (it == ServerInstance->Config->oper_blocks.end())
218 return MOD_RES_PASSTHRU;
220 ConfigTag* tag = it->second->oper_block;
222 return MOD_RES_PASSTHRU;
224 std::string acceptedhosts = tag->getString("host");
225 if (!InspIRCd::MatchMask(acceptedhosts, user->MakeHost(), user->MakeHostIP()))
226 return MOD_RES_PASSTHRU;
229 return MOD_RES_PASSTHRU;
233 std::string what = attribute + "=" + opername;
234 LDAP->BindAsManager(new AdminBindInterface(this, LDAP.GetProvider(), user->uuid, opername, password, base, what));
237 catch (LDAPException& ex)
239 ServerInstance->SNO->WriteToSnoMask('a', "LDAP exception: " + ex.GetReason());
243 return MOD_RES_PASSTHRU;
246 Version GetVersion() CXX11_OVERRIDE
248 return Version("Allows server operators to be authenticated against an LDAP database.", VF_VENDOR);
252 MODULE_INIT(ModuleLDAPOper)