X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Fextra%2Fm_ldapauth.cpp;h=827179f84ebb0c225d39ff262cc1c5baf82968c5;hb=c202dea024542b9c6c6b771bb9a3a081d9eacdc5;hp=5d4d90d44122fc1ed12ab9f2e91cc8d588e49922;hpb=e031d194181e09eb9d802f18a415422bb1e61d1c;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/modules/extra/m_ldapauth.cpp b/src/modules/extra/m_ldapauth.cpp index 5d4d90d44..827179f84 100644 --- a/src/modules/extra/m_ldapauth.cpp +++ b/src/modules/extra/m_ldapauth.cpp @@ -35,9 +35,62 @@ # pragma comment(lib, "lber.lib") #endif -/* $ModDesc: Allow/Deny connections based upon answer from LDAP server */ /* $LinkerFlags: -lldap */ +struct RAIILDAPString +{ + char *str; + + RAIILDAPString(char *Str) + : str(Str) + { + } + + ~RAIILDAPString() + { + ldap_memfree(str); + } + + operator char*() + { + return str; + } + + operator std::string() + { + return str; + } +}; + +struct RAIILDAPMessage +{ + RAIILDAPMessage() + { + } + + ~RAIILDAPMessage() + { + dealloc(); + } + + void dealloc() + { + ldap_msgfree(msg); + } + + operator LDAPMessage*() + { + return msg; + } + + LDAPMessage **operator &() + { + return &msg; + } + + LDAPMessage *msg; +}; + class ModuleLDAPAuth : public Module { LocalIntExt ldapAuthed; @@ -65,11 +118,10 @@ public: conn = NULL; } - void init() + void init() CXX11_OVERRIDE { - Implementation eventlist[] = { I_OnCheckReady, I_OnRehash,I_OnUserRegister, I_OnUserConnect }; - ServerInstance->Modules->Attach(eventlist, this, 4); - OnRehash(NULL); + ServerInstance->Modules->AddService(ldapAuthed); + ServerInstance->Modules->AddService(ldapVhost); } ~ModuleLDAPAuth() @@ -78,7 +130,7 @@ public: ldap_unbind_ext(conn, NULL, NULL); } - void OnRehash(User* user) + void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE { ConfigTag* tag = ServerInstance->Config->ConfValue("ldapauth"); whitelistedcidrs.clear(); @@ -156,7 +208,7 @@ public: std::string> &replacements) { std::string result; - result.reserve(MAXBUF); + result.reserve(text.length()); for (unsigned int i = 0; i < text.length(); ++i) { char c = text[i]; @@ -178,7 +230,7 @@ public: return result; } - virtual void OnUserConnect(LocalUser *user) + void OnUserConnect(LocalUser *user) CXX11_OVERRIDE { std::string* cc = ldapVhost.get(user); if (cc) @@ -188,7 +240,7 @@ public: } } - ModResult OnUserRegister(LocalUser* user) + ModResult OnUserRegister(LocalUser* user) CXX11_OVERRIDE { if ((!allowpattern.empty()) && (InspIRCd::Match(user->nick,allowpattern))) { @@ -253,7 +305,7 @@ public: } } - LDAPMessage *msg, *entry; + RAIILDAPMessage msg; std::string what = (attribute + "=" + (useusername ? user->ident : user->nick)); if ((res = ldap_search_ext_s(conn, base.c_str(), searchscope, what.c_str(), NULL, 0, NULL, NULL, NULL, 0, &msg)) != LDAP_SUCCESS) { @@ -262,6 +314,11 @@ public: size_t pos = user->password.find(":"); if (pos != std::string::npos) { + // manpage says we must deallocate regardless of success or failure + // since we're about to do another query (and reset msg), first + // free the old one. + msg.dealloc(); + std::string cutpassword = user->password.substr(0, pos); res = ldap_search_ext_s(conn, base.c_str(), searchscope, cutpassword.c_str(), NULL, 0, NULL, NULL, NULL, 0, &msg); @@ -284,23 +341,23 @@ public: { if (verbose) ServerInstance->SNO->WriteToSnoMask('c', "Forbidden connection from %s (LDAP search returned more than one result: %s)", user->GetFullRealHost().c_str(), ldap_err2string(res)); - ldap_msgfree(msg); return false; } + + LDAPMessage *entry; if ((entry = ldap_first_entry(conn, msg)) == NULL) { if (verbose) ServerInstance->SNO->WriteToSnoMask('c', "Forbidden connection from %s (LDAP search returned no results: %s)", user->GetFullRealHost().c_str(), ldap_err2string(res)); - ldap_msgfree(msg); return false; } cred.bv_val = (char*)user->password.data(); cred.bv_len = user->password.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) { if (verbose) ServerInstance->SNO->WriteToSnoMask('c', "Forbidden connection from %s (%s)", user->GetFullRealHost().c_str(), ldap_err2string(res)); - ldap_msgfree(msg); return false; } @@ -317,9 +374,9 @@ public: attr_value.bv_val = const_cast(val.c_str()); attr_value.bv_len = val.length(); - ServerInstance->Logs->Log("m_ldapauth", DEBUG, "LDAP compare: %s=%s", attr.c_str(), val.c_str()); + ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "LDAP compare: %s=%s", attr.c_str(), val.c_str()); - authed = (ldap_compare_ext_s(conn, ldap_get_dn(conn, entry), attr.c_str(), &attr_value, NULL, NULL) == LDAP_COMPARE_TRUE); + authed = (ldap_compare_ext_s(conn, DN, attr.c_str(), &attr_value, NULL, NULL) == LDAP_COMPARE_TRUE); if (authed) break; @@ -329,14 +386,13 @@ public: { if (verbose) ServerInstance->SNO->WriteToSnoMask('c', "Forbidden connection from %s (Lacks required LDAP attributes)", user->GetFullRealHost().c_str()); - ldap_msgfree(msg); return false; } } if (!vhost.empty()) { - irc::commasepstream stream(ldap_get_dn(conn, entry)); + irc::commasepstream stream(DN); // mashed map of key:value parts of the DN std::map dnParts; @@ -357,21 +413,19 @@ public: ldapVhost.set(user, SafeReplace(vhost, dnParts)); } - ldap_msgfree(msg); ldapAuthed.set(user,1); return true; } - ModResult OnCheckReady(LocalUser* user) + ModResult OnCheckReady(LocalUser* user) CXX11_OVERRIDE { return ldapAuthed.get(user) ? MOD_RES_PASSTHRU : MOD_RES_DENY; } - Version GetVersion() + Version GetVersion() CXX11_OVERRIDE { return Version("Allow/Deny connections based upon answer from LDAP server", VF_VENDOR); } - }; MODULE_INIT(ModuleLDAPAuth)