X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Fextra%2Fm_ldap.cpp;h=80a055f199c08b3739c5ba778c86b367142de988;hb=6ce92e8eb0fa1bf253da2c16d3cd9cdede5899a6;hp=10469f37054dcc55e89a99113550368675ded981;hpb=7010a92426d2c3ab0cea5ba0d36a04bc6b52349f;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/modules/extra/m_ldap.cpp b/src/modules/extra/m_ldap.cpp index 10469f370..80a055f19 100644 --- a/src/modules/extra/m_ldap.cpp +++ b/src/modules/extra/m_ldap.cpp @@ -1,8 +1,11 @@ /* * InspIRCd -- Internet Relay Chat Daemon * - * Copyright (C) 2013-2014 Adam - * Copyright (C) 2003-2014 Anope Team + * Copyright (C) 2019 linuxdaemon + * Copyright (C) 2019 Robby + * Copyright (C) 2016-2019 Sadie Powell + * Copyright (C) 2014, 2016 Attila Molnar + * Copyright (C) 2013-2016 Adam * * 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 @@ -17,17 +20,173 @@ * along with this program. If not, see . */ +/// $LinkerFlags: -llber -lldap_r + +/// $PackageInfo: require_system("arch") libldap +/// $PackageInfo: require_system("centos") openldap-devel +/// $PackageInfo: require_system("debian") libldap2-dev +/// $PackageInfo: require_system("ubuntu") libldap2-dev + #include "inspircd.h" #include "modules/ldap.h" +// Ignore OpenLDAP deprecation warnings on OS X Yosemite and newer. +#if defined __APPLE__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + #include +#ifdef __APPLE__ +# pragma GCC diagnostic pop +#endif + #ifdef _WIN32 # pragma comment(lib, "libldap_r.lib") # pragma comment(lib, "liblber.lib") #endif -/* $LinkerFlags: -lldap_r */ +class LDAPService; + +class LDAPRequest +{ + public: + LDAPService* service; + LDAPInterface* inter; + LDAPMessage* message; /* message returned by ldap_ */ + LDAPResult* result; /* final result */ + struct timeval tv; + QueryType type; + + LDAPRequest(LDAPService* s, LDAPInterface* i) + : service(s) + , inter(i) + , message(NULL) + , result(NULL) + { + type = QUERY_UNKNOWN; + tv.tv_sec = 0; + tv.tv_usec = 100000; + } + + virtual ~LDAPRequest() + { + delete result; + if (message != NULL) + ldap_msgfree(message); + } + + virtual int run() = 0; + virtual std::string info() = 0; +}; + +class LDAPBind : public LDAPRequest +{ + std::string who, pass; + + public: + LDAPBind(LDAPService* s, LDAPInterface* i, const std::string& w, const std::string& p) + : LDAPRequest(s, i) + , who(w) + , pass(p) + { + type = QUERY_BIND; + } + + int run() CXX11_OVERRIDE; + std::string info() CXX11_OVERRIDE; +}; + +class LDAPSearch : public LDAPRequest +{ + std::string base; + int searchscope; + std::string filter; + + public: + LDAPSearch(LDAPService* s, LDAPInterface* i, const std::string& b, int se, const std::string& f) + : LDAPRequest(s, i) + , base(b) + , searchscope(se) + , filter(f) + { + type = QUERY_SEARCH; + } + + int run() CXX11_OVERRIDE; + std::string info() CXX11_OVERRIDE; +}; + +class LDAPAdd : public LDAPRequest +{ + std::string dn; + LDAPMods attributes; + + public: + LDAPAdd(LDAPService* s, LDAPInterface* i, const std::string& d, const LDAPMods& attr) + : LDAPRequest(s, i) + , dn(d) + , attributes(attr) + { + type = QUERY_ADD; + } + + int run() CXX11_OVERRIDE; + std::string info() CXX11_OVERRIDE; +}; + +class LDAPDel : public LDAPRequest +{ + std::string dn; + + public: + LDAPDel(LDAPService* s, LDAPInterface* i, const std::string& d) + : LDAPRequest(s, i) + , dn(d) + { + type = QUERY_DELETE; + } + + int run() CXX11_OVERRIDE; + std::string info() CXX11_OVERRIDE; +}; + +class LDAPModify : public LDAPRequest +{ + std::string base; + LDAPMods attributes; + + public: + LDAPModify(LDAPService* s, LDAPInterface* i, const std::string& b, const LDAPMods& attr) + : LDAPRequest(s, i) + , base(b) + , attributes(attr) + { + type = QUERY_MODIFY; + } + + int run() CXX11_OVERRIDE; + std::string info() CXX11_OVERRIDE; +}; + +class LDAPCompare : public LDAPRequest +{ + std::string dn, attr, val; + + public: + LDAPCompare(LDAPService* s, LDAPInterface* i, const std::string& d, const std::string& a, const std::string& v) + : LDAPRequest(s, i) + , dn(d) + , attr(a) + , val(v) + { + type = QUERY_COMPARE; + } + + int run() CXX11_OVERRIDE; + std::string info() CXX11_OVERRIDE; +}; class LDAPService : public LDAPProvider, public SocketThread { @@ -36,9 +195,9 @@ class LDAPService : public LDAPProvider, public SocketThread time_t last_connect; int searchscope; time_t timeout; - time_t last_timeout_check; - LDAPMod** BuildMods(const LDAPMods& attributes) + public: + static LDAPMod** BuildMods(const LDAPMods& attributes) { LDAPMod** mods = new LDAPMod*[attributes.size() + 1]; memset(mods, 0, sizeof(LDAPMod*) * (attributes.size() + 1)); @@ -69,7 +228,7 @@ class LDAPService : public LDAPProvider, public SocketThread return mods; } - void FreeMods(LDAPMod** mods) + static void FreeMods(LDAPMod** mods) { for (unsigned int i = 0; mods[i] != NULL; ++i) { @@ -86,6 +245,7 @@ class LDAPService : public LDAPProvider, public SocketThread delete[] mods; } + private: void Reconnect() { // Only try one connect a minute. It is an expensive blocking operation @@ -97,61 +257,41 @@ class LDAPService : public LDAPProvider, public SocketThread Connect(); } - void SaveInterface(LDAPInterface* i, LDAPQuery msgid) + int SetOption(int option, const void* value) { - if (i != NULL) + int ret = ldap_set_option(this->con, option, value); + if (ret != LDAP_OPT_SUCCESS) { - this->LockQueue(); - this->queries[msgid] = std::make_pair(ServerInstance->Time(), i); - this->UnlockQueueWakeup(); + ldap_unbind_ext(this->con, NULL, NULL); + this->con = NULL; } + return ret; } - void Timeout() + void QueueRequest(LDAPRequest* r) { - if (last_timeout_check == ServerInstance->Time()) - return; - last_timeout_check = ServerInstance->Time(); - - for (query_queue::iterator it = this->queries.begin(); it != this->queries.end(); ) - { - LDAPQuery msgid = it->first; - time_t created = it->second.first; - LDAPInterface* i = it->second.second; - ++it; - - if (ServerInstance->Time() > created + timeout) - { - LDAPResult* ldap_result = new LDAPResult(); - ldap_result->id = msgid; - ldap_result->error = "Query timed out"; - - this->queries.erase(msgid); - this->results.push_back(std::make_pair(i, ldap_result)); - - this->NotifyParent(); - } - } + this->LockQueue(); + this->queries.push_back(r); + this->UnlockQueueWakeup(); } public: - typedef std::map > query_queue; - typedef std::vector > result_queue; - query_queue queries; - result_queue results; + typedef std::vector query_queue; + query_queue queries, results; + Mutex process_mutex; /* held when processing requests not in either queue */ LDAPService(Module* c, ConfigTag* tag) : LDAPProvider(c, "LDAP/" + tag->getString("id")) - , con(NULL), config(tag), last_connect(0), last_timeout_check(0) + , con(NULL), config(tag), last_connect(0) { std::string scope = config->getString("searchscope"); - if (scope == "base") + if (stdalgo::string::equalsci(scope, "base")) searchscope = LDAP_SCOPE_BASE; - else if (scope == "onelevel") + else if (stdalgo::string::equalsci(scope, "onelevel")) searchscope = LDAP_SCOPE_ONELEVEL; else searchscope = LDAP_SCOPE_SUBTREE; - timeout = config->getInt("timeout", 5); + timeout = config->getDuration("timeout", 5); Connect(); } @@ -160,30 +300,29 @@ class LDAPService : public LDAPProvider, public SocketThread { this->LockQueue(); - for (query_queue::iterator i = this->queries.begin(); i != this->queries.end(); ++i) + for (unsigned int i = 0; i < this->queries.size(); ++i) { - LDAPQuery msgid = i->first; - LDAPInterface* inter = i->second.second; + LDAPRequest* req = this->queries[i]; - ldap_abandon_ext(this->con, msgid, NULL, NULL); + /* queries have no results yet */ + req->result = new LDAPResult(); + req->result->type = req->type; + req->result->error = "LDAP Interface is going away"; + req->inter->OnError(*req->result); - if (inter) - { - LDAPResult r; - r.error = "LDAP Interface is going away"; - inter->OnError(r); - } + delete req; } this->queries.clear(); - for (result_queue::iterator i = this->results.begin(); i != this->results.end(); ++i) + for (unsigned int i = 0; i < this->results.size(); ++i) { - LDAPInterface* inter = i->first; - LDAPResult* r = i->second; + LDAPRequest* req = this->results[i]; - r->error = "LDAP Interface is going away"; - if (inter) - inter->OnError(*r); + /* even though this may have already finished successfully we return that it didn't */ + req->result->error = "LDAP Interface is going away"; + req->inter->OnError(*req->result); + + delete req; } this->results.clear(); @@ -200,334 +339,202 @@ class LDAPService : public LDAPProvider, public SocketThread throw LDAPException("Unable to connect to LDAP service " + this->name + ": " + ldap_err2string(i)); const int version = LDAP_VERSION3; - i = ldap_set_option(this->con, LDAP_OPT_PROTOCOL_VERSION, &version); + i = SetOption(LDAP_OPT_PROTOCOL_VERSION, &version); if (i != LDAP_OPT_SUCCESS) - { - ldap_unbind_ext(this->con, NULL, NULL); - this->con = NULL; throw LDAPException("Unable to set protocol version for " + this->name + ": " + ldap_err2string(i)); - } const struct timeval tv = { 0, 0 }; - i = ldap_set_option(this->con, LDAP_OPT_NETWORK_TIMEOUT, &tv); + i = SetOption(LDAP_OPT_NETWORK_TIMEOUT, &tv); if (i != LDAP_OPT_SUCCESS) - { - ldap_unbind_ext(this->con, NULL, NULL); - this->con = NULL; throw LDAPException("Unable to set timeout for " + this->name + ": " + ldap_err2string(i)); - } } - LDAPQuery BindAsManager(LDAPInterface* i) CXX11_OVERRIDE + void BindAsManager(LDAPInterface* i) CXX11_OVERRIDE { std::string binddn = config->getString("binddn"); std::string bindauth = config->getString("bindauth"); - return this->Bind(i, binddn, bindauth); + this->Bind(i, binddn, bindauth); } - LDAPQuery Bind(LDAPInterface* i, const std::string& who, const std::string& pass) CXX11_OVERRIDE + void Bind(LDAPInterface* i, const std::string& who, const std::string& pass) CXX11_OVERRIDE { - berval cred; - cred.bv_val = strdup(pass.c_str()); - cred.bv_len = pass.length(); - - LDAPQuery msgid; - int ret = ldap_sasl_bind(con, who.c_str(), LDAP_SASL_SIMPLE, &cred, NULL, NULL, &msgid); - free(cred.bv_val); - if (ret != LDAP_SUCCESS) - { - if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT) - { - this->Reconnect(); - return this->Bind(i, who, pass); - } - else - throw LDAPException(ldap_err2string(ret)); - } - - SaveInterface(i, msgid); - return msgid; + LDAPBind* b = new LDAPBind(this, i, who, pass); + QueueRequest(b); } - LDAPQuery Search(LDAPInterface* i, const std::string& base, const std::string& filter) CXX11_OVERRIDE + void Search(LDAPInterface* i, const std::string& base, const std::string& filter) CXX11_OVERRIDE { if (i == NULL) throw LDAPException("No interface"); - LDAPQuery msgid; - int ret = ldap_search_ext(this->con, base.c_str(), searchscope, filter.c_str(), NULL, 0, NULL, NULL, NULL, 0, &msgid); - if (ret != LDAP_SUCCESS) - { - if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT) - { - this->Reconnect(); - return this->Search(i, base, filter); - } - else - throw LDAPException(ldap_err2string(ret)); - } - - SaveInterface(i, msgid); - return msgid; + LDAPSearch* s = new LDAPSearch(this, i, base, searchscope, filter); + QueueRequest(s); } - LDAPQuery Add(LDAPInterface* i, const std::string& dn, LDAPMods& attributes) CXX11_OVERRIDE + void Add(LDAPInterface* i, const std::string& dn, LDAPMods& attributes) CXX11_OVERRIDE { - LDAPMod** mods = this->BuildMods(attributes); - LDAPQuery msgid; - int ret = ldap_add_ext(this->con, dn.c_str(), mods, NULL, NULL, &msgid); - this->FreeMods(mods); - - if (ret != LDAP_SUCCESS) - { - if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT) - { - this->Reconnect(); - return this->Add(i, dn, attributes); - } - else - throw LDAPException(ldap_err2string(ret)); - } - - SaveInterface(i, msgid); - return msgid; + LDAPAdd* add = new LDAPAdd(this, i, dn, attributes); + QueueRequest(add); } - LDAPQuery Del(LDAPInterface* i, const std::string& dn) CXX11_OVERRIDE + void Del(LDAPInterface* i, const std::string& dn) CXX11_OVERRIDE { - LDAPQuery msgid; - int ret = ldap_delete_ext(this->con, dn.c_str(), NULL, NULL, &msgid); - - if (ret != LDAP_SUCCESS) - { - if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT) - { - this->Reconnect(); - return this->Del(i, dn); - } - else - throw LDAPException(ldap_err2string(ret)); - } - - SaveInterface(i, msgid); - return msgid; + LDAPDel* del = new LDAPDel(this, i, dn); + QueueRequest(del); } - LDAPQuery Modify(LDAPInterface* i, const std::string& base, LDAPMods& attributes) CXX11_OVERRIDE + void Modify(LDAPInterface* i, const std::string& base, LDAPMods& attributes) CXX11_OVERRIDE { - LDAPMod** mods = this->BuildMods(attributes); - LDAPQuery msgid; - int ret = ldap_modify_ext(this->con, base.c_str(), mods, NULL, NULL, &msgid); - this->FreeMods(mods); - - if (ret != LDAP_SUCCESS) - { - if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT) - { - this->Reconnect(); - return this->Modify(i, base, attributes); - } - else - throw LDAPException(ldap_err2string(ret)); - } + LDAPModify* mod = new LDAPModify(this, i, base, attributes); + QueueRequest(mod); + } - SaveInterface(i, msgid); - return msgid; + void Compare(LDAPInterface* i, const std::string& dn, const std::string& attr, const std::string& val) CXX11_OVERRIDE + { + LDAPCompare* comp = new LDAPCompare(this, i, dn, attr, val); + QueueRequest(comp); } - LDAPQuery Compare(LDAPInterface* i, const std::string& dn, const std::string& attr, const std::string& val) CXX11_OVERRIDE + private: + void BuildReply(int res, LDAPRequest* req) { - berval cred; - cred.bv_val = strdup(val.c_str()); - cred.bv_len = val.length(); + LDAPResult* ldap_result = req->result = new LDAPResult(); + req->result->type = req->type; - LDAPQuery msgid; - int ret = ldap_compare_ext(con, dn.c_str(), attr.c_str(), &cred, NULL, NULL, &msgid); - free(cred.bv_val); + if (res != LDAP_SUCCESS) + { + ldap_result->error = InspIRCd::Format("%s (%s)", ldap_err2string(res), req->info().c_str()); + return; + } - if (ret != LDAP_SUCCESS) + if (req->message == NULL) { - if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT) - { - this->Reconnect(); - return this->Compare(i, dn, attr, val); - } - else - throw LDAPException(ldap_err2string(ret)); + return; } - SaveInterface(i, msgid); - return msgid; - } + /* a search result */ - void Run() CXX11_OVERRIDE - { - while (!this->GetExitFlag()) + for (LDAPMessage* cur = ldap_first_message(this->con, req->message); cur; cur = ldap_next_message(this->con, cur)) { - this->LockQueue(); - if (this->queries.empty()) + LDAPAttributes attributes; + + char* dn = ldap_get_dn(this->con, cur); + if (dn != NULL) { - this->WaitForQueue(); - this->UnlockQueue(); - continue; + attributes["dn"].push_back(dn); + ldap_memfree(dn); + dn = NULL; } - this->Timeout(); - this->UnlockQueue(); - struct timeval tv = { 1, 0 }; - LDAPMessage* result; - int rtype = ldap_result(this->con, LDAP_RES_ANY, 1, &tv, &result); - if (rtype <= 0 || this->GetExitFlag()) - continue; + BerElement* ber = NULL; - int cur_id = ldap_msgid(result); + for (char* attr = ldap_first_attribute(this->con, cur, &ber); attr; attr = ldap_next_attribute(this->con, cur, ber)) + { + berval** vals = ldap_get_values_len(this->con, cur, attr); + int count = ldap_count_values_len(vals); - this->LockQueue(); + std::vector attrs; + for (int j = 0; j < count; ++j) + attrs.push_back(vals[j]->bv_val); + attributes[attr] = attrs; - query_queue::iterator it = this->queries.find(cur_id); - if (it == this->queries.end()) - { - this->UnlockQueue(); - ldap_msgfree(result); - continue; + ldap_value_free_len(vals); + ldap_memfree(attr); } - LDAPInterface* i = it->second.second; - this->queries.erase(it); + if (ber != NULL) + ber_free(ber, 0); - this->UnlockQueue(); + ldap_result->messages.push_back(attributes); + } + } - LDAPResult* ldap_result = new LDAPResult(); - ldap_result->id = cur_id; + void SendRequests() + { + process_mutex.Lock(); - for (LDAPMessage* cur = ldap_first_message(this->con, result); cur; cur = ldap_next_message(this->con, cur)) - { - int cur_type = ldap_msgtype(cur); + query_queue q; + this->LockQueue(); + queries.swap(q); + this->UnlockQueue(); - LDAPAttributes attributes; + if (q.empty()) + { + process_mutex.Unlock(); + return; + } - { - char* dn = ldap_get_dn(this->con, cur); - if (dn != NULL) - { - attributes["dn"].push_back(dn); - ldap_memfree(dn); - } - } + for (unsigned int i = 0; i < q.size(); ++i) + { + LDAPRequest* req = q[i]; + int ret = req->run(); - switch (cur_type) + if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT) + { + /* try again */ + try { - case LDAP_RES_BIND: - ldap_result->type = LDAPResult::QUERY_BIND; - break; - case LDAP_RES_SEARCH_ENTRY: - ldap_result->type = LDAPResult::QUERY_SEARCH; - break; - case LDAP_RES_ADD: - ldap_result->type = LDAPResult::QUERY_ADD; - break; - case LDAP_RES_DELETE: - ldap_result->type = LDAPResult::QUERY_DELETE; - break; - case LDAP_RES_MODIFY: - ldap_result->type = LDAPResult::QUERY_MODIFY; - break; - case LDAP_RES_SEARCH_RESULT: - // If we get here and ldap_result->type is LDAPResult::QUERY_UNKNOWN - // then the result set is empty - ldap_result->type = LDAPResult::QUERY_SEARCH; - break; - case LDAP_RES_COMPARE: - ldap_result->type = LDAPResult::QUERY_COMPARE; - break; - default: - continue; + Reconnect(); } - - switch (cur_type) + catch (const LDAPException &) { - case LDAP_RES_SEARCH_ENTRY: - { - BerElement* ber = NULL; - for (char* attr = ldap_first_attribute(this->con, cur, &ber); attr; attr = ldap_next_attribute(this->con, cur, ber)) - { - berval** vals = ldap_get_values_len(this->con, cur, attr); - int count = ldap_count_values_len(vals); - - std::vector attrs; - for (int j = 0; j < count; ++j) - attrs.push_back(vals[j]->bv_val); - attributes[attr] = attrs; - - ldap_value_free_len(vals); - ldap_memfree(attr); - } - if (ber != NULL) - ber_free(ber, 0); - - break; - } - case LDAP_RES_BIND: - case LDAP_RES_ADD: - case LDAP_RES_DELETE: - case LDAP_RES_MODIFY: - case LDAP_RES_COMPARE: - { - int errcode = -1; - int parse_result = ldap_parse_result(this->con, cur, &errcode, NULL, NULL, NULL, NULL, 0); - if (parse_result != LDAP_SUCCESS) - { - ldap_result->error = ldap_err2string(parse_result); - } - else - { - if (cur_type == LDAP_RES_COMPARE) - { - if (errcode != LDAP_COMPARE_TRUE) - ldap_result->error = ldap_err2string(errcode); - } - else if (errcode != LDAP_SUCCESS) - ldap_result->error = ldap_err2string(errcode); - } - break; - } - default: - continue; } - ldap_result->messages.push_back(attributes); + ret = req->run(); } - ldap_msgfree(result); + BuildReply(ret, req); + + this->LockQueue(); + this->results.push_back(req); + this->UnlockQueue(); + } + + this->NotifyParent(); + + process_mutex.Unlock(); + } + public: + void Run() CXX11_OVERRIDE + { + while (!this->GetExitFlag()) + { this->LockQueue(); - this->results.push_back(std::make_pair(i, ldap_result)); - this->UnlockQueueWakeup(); + if (this->queries.empty()) + this->WaitForQueue(); + this->UnlockQueue(); - this->NotifyParent(); + SendRequests(); } } void OnNotify() CXX11_OVERRIDE { - LDAPService::result_queue r; + query_queue r; this->LockQueue(); this->results.swap(r); this->UnlockQueue(); - for (LDAPService::result_queue::iterator i = r.begin(); i != r.end(); ++i) + for (unsigned int i = 0; i < r.size(); ++i) { - LDAPInterface* li = i->first; - LDAPResult* res = i->second; + LDAPRequest* req = r[i]; + LDAPInterface* li = req->inter; + LDAPResult* res = req->result; if (!res->error.empty()) li->OnError(*res); else li->OnResult(*res); - delete res; + delete req; } } + + LDAP* GetConnection() + { + return con; + } }; class ModuleLDAP : public Module @@ -545,7 +552,7 @@ class ModuleLDAP : public Module { const reference& tag = i->second; - if (tag->getString("module") != "ldap") + if (!stdalgo::string::equalsci(tag->getString("module"), "ldap")) continue; std::string id = tag->getString("id"); @@ -583,28 +590,36 @@ class ModuleLDAP : public Module for (ServiceMap::iterator it = this->LDAPServices.begin(); it != this->LDAPServices.end(); ++it) { LDAPService* s = it->second; + + s->process_mutex.Lock(); s->LockQueue(); - for (LDAPService::query_queue::iterator it2 = s->queries.begin(); it2 != s->queries.end();) + + for (unsigned int i = s->queries.size(); i > 0; --i) { - int msgid = it2->first; - LDAPInterface* i = it2->second.second; - ++it2; + LDAPRequest* req = s->queries[i - 1]; + LDAPInterface* li = req->inter; - if (i->creator == m) - s->queries.erase(msgid); + if (li->creator == m) + { + s->queries.erase(s->queries.begin() + i - 1); + delete req; + } } + for (unsigned int i = s->results.size(); i > 0; --i) { - LDAPInterface* li = s->results[i - 1].first; - LDAPResult* r = s->results[i - 1].second; + LDAPRequest* req = s->results[i - 1]; + LDAPInterface* li = req->inter; if (li->creator == m) { s->results.erase(s->results.begin() + i - 1); - delete r; + delete req; } } + s->UnlockQueue(); + s->process_mutex.Unlock(); } } @@ -621,8 +636,90 @@ class ModuleLDAP : public Module Version GetVersion() CXX11_OVERRIDE { - return Version("LDAP support", VF_VENDOR); + return Version("Provides the ability for LDAP modules to query a LDAP directory.", VF_VENDOR); } }; +int LDAPBind::run() +{ + berval cred; + cred.bv_val = strdup(pass.c_str()); + cred.bv_len = pass.length(); + + int i = ldap_sasl_bind_s(service->GetConnection(), who.c_str(), LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL); + + free(cred.bv_val); + + return i; +} + +std::string LDAPBind::info() +{ + return "bind dn=" + who; +} + +int LDAPSearch::run() +{ + return ldap_search_ext_s(service->GetConnection(), base.c_str(), searchscope, filter.c_str(), NULL, 0, NULL, NULL, &tv, 0, &message); +} + +std::string LDAPSearch::info() +{ + return "search base=" + base + " filter=" + filter; +} + +int LDAPAdd::run() +{ + LDAPMod** mods = LDAPService::BuildMods(attributes); + int i = ldap_add_ext_s(service->GetConnection(), dn.c_str(), mods, NULL, NULL); + LDAPService::FreeMods(mods); + return i; +} + +std::string LDAPAdd::info() +{ + return "add dn=" + dn; +} + +int LDAPDel::run() +{ + return ldap_delete_ext_s(service->GetConnection(), dn.c_str(), NULL, NULL); +} + +std::string LDAPDel::info() +{ + return "del dn=" + dn; +} + +int LDAPModify::run() +{ + LDAPMod** mods = LDAPService::BuildMods(attributes); + int i = ldap_modify_ext_s(service->GetConnection(), base.c_str(), mods, NULL, NULL); + LDAPService::FreeMods(mods); + return i; +} + +std::string LDAPModify::info() +{ + return "modify base=" + base; +} + +int LDAPCompare::run() +{ + berval cred; + cred.bv_val = strdup(val.c_str()); + cred.bv_len = val.length(); + + int ret = ldap_compare_ext_s(service->GetConnection(), dn.c_str(), attr.c_str(), &cred, NULL, NULL); + + free(cred.bv_val); + + return ret; +} + +std::string LDAPCompare::info() +{ + return "compare dn=" + dn + " attr=" + attr; +} + MODULE_INIT(ModuleLDAP)