X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Fextra%2Fm_ldapoper.cpp;h=1f46361d4d34555b50c71b07f423d506893d6425;hb=a5d110282a864fd2e91b51ce360a977cd0643657;hp=95147c1883c526de8a229da17725577e32191306;hpb=43847ec9c7e1a195163eb4c529f1c92fd1ace0a4;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/modules/extra/m_ldapoper.cpp b/src/modules/extra/m_ldapoper.cpp index 95147c188..1f46361d4 100644 --- a/src/modules/extra/m_ldapoper.cpp +++ b/src/modules/extra/m_ldapoper.cpp @@ -1,26 +1,25 @@ -/* +------------------------------------+ - * | Inspire Internet Relay Chat Daemon | - * +------------------------------------+ +/* + * InspIRCd -- Internet Relay Chat Daemon * - * InspIRCd: (C) 2002-2009 InspIRCd Development Team - * See: http://www.inspircd.org/wiki/index.php/Credits + * Copyright (C) 2009 Robin Burchell + * Copyright (C) 2008 Pippijn van Steenhoven + * Copyright (C) 2008 Craig Edwards + * Copyright (C) 2007 Carsten Valdemar Munk * - * This program is free but copyrighted software; see - * the file COPYING for details. + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. * - * --------------------------------------------------- + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. * - * Taken from the UnrealIRCd 4.0 SVN version, based on - * InspIRCd 1.1.x. - * - * UnrealIRCd 4.0 (C) 2007 Carsten Valdemar Munk - * This program is free but copyrighted software; see - * the file COPYING for details. - * - * --------------------------------------------------- - * Heavily based on SQLauth + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ + #include "inspircd.h" #include "users.h" #include "channels.h" @@ -28,26 +27,97 @@ #include -/* $ModDesc: Allow/Deny connections based upon answer from LDAP server */ +#ifdef _WIN32 +# pragma comment(lib, "libldap.lib") +# pragma comment(lib, "liblber.lib") +#endif + +/* $ModDesc: Adds the ability to authenticate opers via LDAP */ /* $LinkerFlags: -lldap */ +// Duplicated code, also found in cmd_oper and m_sqloper +static bool OneOfMatches(const char* host, const char* ip, const std::string& hostlist) +{ + std::stringstream hl(hostlist); + std::string xhost; + while (hl >> xhost) + { + if (InspIRCd::Match(host, xhost, ascii_case_insensitive_map) || InspIRCd::MatchCIDR(ip, xhost, ascii_case_insensitive_map)) + { + return true; + } + } + return false; +} + +struct RAIILDAPString +{ + char *str; + + RAIILDAPString(char *Str) + : str(Str) + { + } + + ~RAIILDAPString() + { + ldap_memfree(str); + } + + operator char*() + { + return str; + } + + operator std::string() + { + return str; + } +}; + class ModuleLDAPAuth : public Module { std::string base; std::string ldapserver; std::string username; std::string password; + std::string attribute; int searchscope; LDAP *conn; + bool HandleOper(LocalUser* user, const std::string& opername, const std::string& inputpass) + { + OperIndex::iterator it = ServerInstance->Config->oper_blocks.find(opername); + if (it == ServerInstance->Config->oper_blocks.end()) + return false; + + ConfigTag* tag = it->second->oper_block; + if (!tag) + return false; + + std::string acceptedhosts = tag->getString("host"); + std::string hostname = user->ident + "@" + user->host; + if (!OneOfMatches(hostname.c_str(), user->GetIPString(), acceptedhosts)) + return false; + + if (!LookupOper(opername, inputpass)) + return false; + + user->Oper(it->second); + return true; + } + public: - ModuleLDAPAuth(InspIRCd* Me) - : Module(Me) + ModuleLDAPAuth() + : conn(NULL) + { + } + + void init() { - conn = NULL; - Implementation eventlist[] = { I_OnRehash, I_OnPassCompare }; - ServerInstance->Modules->Attach(eventlist, this, 2); - OnRehash(NULL,""); + Implementation eventlist[] = { I_OnRehash, I_OnPreCommand }; + ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation)); + OnRehash(NULL); } virtual ~ModuleLDAPAuth() @@ -56,15 +126,16 @@ public: ldap_unbind_ext(conn, NULL, NULL); } - virtual void OnRehash(User* user, const std::string ¶meter) + virtual void OnRehash(User* user) { - ConfigReader Conf(ServerInstance); + ConfigTag* tag = ServerInstance->Config->ConfValue("ldapoper"); - base = Conf.ReadValue("ldapoper", "baserdn", 0); - ldapserver = Conf.ReadValue("ldapoper", "server", 0); - std::string scope = Conf.ReadValue("ldapoper", "searchscope", 0); - username = Conf.ReadValue("ldapoper", "binddn", 0); - password = Conf.ReadValue("ldapoper", "bindauth", 0); + base = tag->getString("baserdn"); + ldapserver = tag->getString("server"); + std::string scope = tag->getString("searchscope"); + username = tag->getString("binddn"); + password = tag->getString("bindauth"); + attribute = tag->getString("attribute"); if (scope == "base") searchscope = LDAP_SCOPE_BASE; @@ -97,22 +168,17 @@ public: return true; } - virtual int OnPassCompare(Extensible* ex, const std::string &data, const std::string &input, const std::string &hashtype) + ModResult OnPreCommand(std::string& command, std::vector& parameters, LocalUser* user, bool validated, const std::string& original_line) { - User* user = dynamic_cast(ex); - if (hashtype == "ldap") + if (validated && command == "OPER" && parameters.size() >= 2) { - if (LookupOper(user, data, input)) - { - /* This is an ldap oper and has been found, claim the OPER command */ - return 1; - } + if (HandleOper(user, parameters[0], parameters[1])) + return MOD_RES_DENY; } - /* We don't know this oper! */ - return 0; + return MOD_RES_PASSTHRU; } - bool LookupOper(User* user, const std::string &what, const std::string &opassword) + bool LookupOper(const std::string& opername, const std::string& opassword) { if (conn == NULL) if (!Connect()) @@ -127,14 +193,26 @@ public: if ((res = ldap_sasl_bind_s(conn, username.c_str(), LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL)) != LDAP_SUCCESS) { - free(authpass); - ldap_unbind_ext(conn, NULL, NULL); - conn = NULL; - return false; + if (res == LDAP_SERVER_DOWN) + { + // Attempt to reconnect if the connection dropped + ServerInstance->SNO->WriteToSnoMask('a', "LDAP server has gone away - reconnecting..."); + Connect(); + res = ldap_sasl_bind_s(conn, username.c_str(), LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL); + } + + if (res != LDAP_SUCCESS) + { + free(authpass); + ldap_unbind_ext(conn, NULL, NULL); + conn = NULL; + return false; + } } free(authpass); LDAPMessage *msg, *entry; + std::string what = attribute + "=" + opername; if ((res = ldap_search_ext_s(conn, base.c_str(), searchscope, what.c_str(), NULL, 0, NULL, NULL, NULL, 0, &msg)) != LDAP_SUCCESS) { return false; @@ -152,7 +230,8 @@ public: authpass = strdup(opassword.c_str()); cred.bv_val = authpass; cred.bv_len = opassword.length(); - if ((res = ldap_sasl_bind_s(conn, ldap_get_dn(conn, entry), LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL)) == LDAP_SUCCESS) + RAIILDAPString DN(ldap_get_dn(conn, entry)); + if ((res = ldap_sasl_bind_s(conn, DN, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL)) == LDAP_SUCCESS) { free(authpass); ldap_msgfree(msg); @@ -168,7 +247,7 @@ public: virtual Version GetVersion() { - return Version("$Id$", VF_VENDOR, API_VERSION); + return Version("Adds the ability to authenticate opers via LDAP", VF_VENDOR); } };