-/* +------------------------------------+
- * | Inspire Internet Relay Chat Daemon |
- * +------------------------------------+
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
*
- * InspIRCd: (C) 2002-2009 InspIRCd Development Team
- * See: http://wiki.inspircd.org/Credits
+ * Copyright (C) 2009 Robin Burchell <robin+git@viroteck.net>
+ * Copyright (C) 2008 Pippijn van Steenhoven <pip88nl@gmail.com>
+ * Copyright (C) 2008 Craig Edwards <craigedwards@brainbox.cc>
+ * Copyright (C) 2007 Carsten Valdemar Munk <carsten.munk+inspircd@gmail.com>
*
- * 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 <http://www.gnu.org/licenses/>.
*/
+
#include "inspircd.h"
#include "users.h"
#include "channels.h"
#include <ldap.h>
-/* $ModDesc: Allow/Deny connections based upon answer from LDAP server */
+#ifdef _WIN32
+# pragma comment(lib, "ldap.lib")
+# pragma comment(lib, "lber.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)
{
- conn = NULL;
- Implementation eventlist[] = { I_OnRehash, I_OnPassCompare };
- ServerInstance->Modules->Attach(eventlist, this, 2);
+ }
+
+ void init()
+ {
+ Implementation eventlist[] = { I_OnRehash, I_OnPreCommand };
+ ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
OnRehash(NULL);
}
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;
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<std::string>& parameters, LocalUser* user, bool validated, const std::string& original_line)
{
- User* user = dynamic_cast<User*>(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())
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;
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);
virtual Version GetVersion()
{
- return Version("$Id$", VF_VENDOR, API_VERSION);
+ return Version("Adds the ability to authenticate opers via LDAP", VF_VENDOR);
}
};