X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Fextra%2Fm_ldapoper.cpp;h=1f46361d4d34555b50c71b07f423d506893d6425;hb=88dccdd5f04e9244323de0eb197590ab8e7292fd;hp=2166b0823725cd393efedda8646fb24873d9e292;hpb=c05ad37bfd03486475889485606ed5cffc7bf5a2;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/modules/extra/m_ldapoper.cpp b/src/modules/extra/m_ldapoper.cpp index 2166b0823..1f46361d4 100644 --- a/src/modules/extra/m_ldapoper.cpp +++ b/src/modules/extra/m_ldapoper.cpp @@ -28,28 +28,95 @@ #include #ifdef _WIN32 -# pragma comment(lib, "ldap.lib") -# pragma comment(lib, "lber.lib") +# 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() - { - conn = NULL; - Implementation eventlist[] = { I_OnRehash, I_OnPassCompare }; - ServerInstance->Modules->Attach(eventlist, this, 2); + : conn(NULL) + { + } + + void init() + { + Implementation eventlist[] = { I_OnRehash, I_OnPreCommand }; + ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation)); OnRehash(NULL); } @@ -61,13 +128,14 @@ public: virtual void OnRehash(User* user) { - ConfigReader Conf; + 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; @@ -100,21 +168,17 @@ public: return true; } - virtual ModResult 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) { - if (hashtype == "ldap") + if (validated && command == "OPER" && parameters.size() >= 2) { - if (LookupOper(data, input)) - /* This is an ldap oper and has been found, claim the OPER command */ - return MOD_RES_ALLOW; - else + if (HandleOper(user, parameters[0], parameters[1])) return MOD_RES_DENY; } - /* We don't know this oper! */ return MOD_RES_PASSTHRU; } - bool LookupOper(const std::string &what, const std::string &opassword) + bool LookupOper(const std::string& opername, const std::string& opassword) { if (conn == NULL) if (!Connect()) @@ -148,6 +212,7 @@ public: 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; @@ -165,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);