2 * InspIRCd -- Internet Relay Chat Daemon
4 * Copyright (C) 2009 Robin Burchell <robin+git@viroteck.net>
5 * Copyright (C) 2008 Pippijn van Steenhoven <pip88nl@gmail.com>
6 * Copyright (C) 2008 Craig Edwards <craigedwards@brainbox.cc>
7 * Copyright (C) 2007 Carsten Valdemar Munk <carsten.munk+inspircd@gmail.com>
9 * This file is part of InspIRCd. InspIRCd is free software: you can
10 * redistribute it and/or modify it under the terms of the GNU General Public
11 * License as published by the Free Software Foundation, version 2.
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
31 # pragma comment(lib, "ldap.lib")
32 # pragma comment(lib, "lber.lib")
35 /* $LinkerFlags: -lldap */
41 RAIILDAPString(char *Str)
56 operator std::string()
62 class ModuleLDAPAuth : public Module
65 std::string ldapserver;
68 std::string attribute;
72 bool HandleOper(LocalUser* user, const std::string& opername, const std::string& inputpass)
74 OperIndex::iterator it = ServerInstance->Config->oper_blocks.find(opername);
75 if (it == ServerInstance->Config->oper_blocks.end())
78 ConfigTag* tag = it->second->oper_block;
82 std::string acceptedhosts = tag->getString("host");
83 std::string hostname = user->ident + "@" + user->host;
84 if (!InspIRCd::MatchMask(acceptedhosts, hostname, user->GetIPString()))
87 if (!LookupOper(opername, inputpass))
90 user->Oper(it->second);
103 ldap_unbind_ext(conn, NULL, NULL);
106 void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
108 ConfigTag* tag = ServerInstance->Config->ConfValue("ldapoper");
110 base = tag->getString("baserdn");
111 ldapserver = tag->getString("server");
112 std::string scope = tag->getString("searchscope");
113 username = tag->getString("binddn");
114 password = tag->getString("bindauth");
115 attribute = tag->getString("attribute");
118 searchscope = LDAP_SCOPE_BASE;
119 else if (scope == "onelevel")
120 searchscope = LDAP_SCOPE_ONELEVEL;
121 else searchscope = LDAP_SCOPE_SUBTREE;
129 ldap_unbind_ext(conn, NULL, NULL);
130 int res, v = LDAP_VERSION3;
131 res = ldap_initialize(&conn, ldapserver.c_str());
132 if (res != LDAP_SUCCESS)
138 res = ldap_set_option(conn, LDAP_OPT_PROTOCOL_VERSION, (void *)&v);
139 if (res != LDAP_SUCCESS)
141 ldap_unbind_ext(conn, NULL, NULL);
148 ModResult OnPreCommand(std::string& command, std::vector<std::string>& parameters, LocalUser* user, bool validated, const std::string& original_line) CXX11_OVERRIDE
150 if (validated && command == "OPER" && parameters.size() >= 2)
152 if (HandleOper(user, parameters[0], parameters[1]))
155 return MOD_RES_PASSTHRU;
158 bool LookupOper(const std::string& opername, const std::string& opassword)
165 char* authpass = strdup(password.c_str());
166 // bind anonymously if no bind DN and authentication are given in the config
168 cred.bv_val = authpass;
169 cred.bv_len = password.length();
171 if ((res = ldap_sasl_bind_s(conn, username.c_str(), LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL)) != LDAP_SUCCESS)
173 if (res == LDAP_SERVER_DOWN)
175 // Attempt to reconnect if the connection dropped
176 ServerInstance->SNO->WriteToSnoMask('a', "LDAP server has gone away - reconnecting...");
178 res = ldap_sasl_bind_s(conn, username.c_str(), LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL);
181 if (res != LDAP_SUCCESS)
184 ldap_unbind_ext(conn, NULL, NULL);
191 LDAPMessage *msg, *entry;
192 std::string what = attribute + "=" + opername;
193 if ((res = ldap_search_ext_s(conn, base.c_str(), searchscope, what.c_str(), NULL, 0, NULL, NULL, NULL, 0, &msg)) != LDAP_SUCCESS)
197 if (ldap_count_entries(conn, msg) > 1)
202 if ((entry = ldap_first_entry(conn, msg)) == NULL)
207 authpass = strdup(opassword.c_str());
208 cred.bv_val = authpass;
209 cred.bv_len = opassword.length();
210 RAIILDAPString DN(ldap_get_dn(conn, entry));
211 if ((res = ldap_sasl_bind_s(conn, DN, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL)) == LDAP_SUCCESS)
225 Version GetVersion() CXX11_OVERRIDE
227 return Version("Adds the ability to authenticate opers via LDAP", VF_VENDOR);
232 MODULE_INIT(ModuleLDAPAuth)