diff options
| author | Adam <Adam@anope.org> | 2015-10-27 18:57:37 -0400 |
|---|---|---|
| committer | Adam <Adam@anope.org> | 2015-10-27 18:58:48 -0400 |
| commit | 64dac60071fab652745a6e7a06cf6b7bdbbd3625 (patch) | |
| tree | f8f30161150451672b381f6370a8fdcab654bbb8 /modules/extra | |
| parent | 162fdbe5815bbdf187f549fefac94ff476d72e62 (diff) | |
| parent | 830361e97d03c74e54cb1cf1bbf329dffdeb66f7 (diff) | |
Merge branch '2.0' into 2.1
Diffstat (limited to 'modules/extra')
| -rw-r--r-- | modules/extra/m_ldap.cpp | 665 | ||||
| -rw-r--r-- | modules/extra/m_ldap_authentication.cpp | 152 | ||||
| -rw-r--r-- | modules/extra/m_ldap_oper.cpp | 43 | ||||
| -rw-r--r-- | modules/extra/m_ssl_openssl.cpp | 18 | ||||
| -rw-r--r-- | modules/extra/stats/irc2sql/irc2sql.cpp | 11 | ||||
| -rw-r--r-- | modules/extra/stats/irc2sql/irc2sql.h | 3 | ||||
| -rw-r--r-- | modules/extra/stats/m_chanstats.cpp | 9 |
7 files changed, 439 insertions, 462 deletions
diff --git a/modules/extra/m_ldap.cpp b/modules/extra/m_ldap.cpp index 8309a5cc5..71c31b9ac 100644 --- a/modules/extra/m_ldap.cpp +++ b/modules/extra/m_ldap.cpp @@ -1,3 +1,14 @@ +/* + * + * (C) 2011-2015 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + */ + /* RequiredLibraries: ldap_r,lber */ /* RequiredWindowsLibraries: libldap_r,liblber */ @@ -5,21 +16,136 @@ #include "modules/ldap.h" #include <ldap.h> +class LDAPService; static Pipe *me; +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 (inter != NULL) + inter->OnDelete(); + if (message != NULL) + ldap_msgfree(message); + } + + virtual int run() = 0; +}; + +class LDAPBind : public LDAPRequest +{ + Anope::string who, pass; + + public: + LDAPBind(LDAPService *s, LDAPInterface *i, const Anope::string &w, const Anope::string &p) + : LDAPRequest(s, i) + , who(w) + , pass(p) + { + type = QUERY_BIND; + } + + int run() anope_override; +}; + +class LDAPSearch : public LDAPRequest +{ + Anope::string base; + Anope::string filter; + + public: + LDAPSearch(LDAPService *s, LDAPInterface *i, const Anope::string &b, const Anope::string &f) + : LDAPRequest(s, i) + , base(b) + , filter(f) + { + type = QUERY_SEARCH; + } + + int run() anope_override; +}; + +class LDAPAdd : public LDAPRequest +{ + Anope::string dn; + LDAPMods attributes; + + public: + LDAPAdd(LDAPService *s, LDAPInterface *i, const Anope::string &d, const LDAPMods &attr) + : LDAPRequest(s, i) + , dn(d) + , attributes(attr) + { + type = QUERY_ADD; + } + + int run() anope_override; +}; + +class LDAPDel : public LDAPRequest +{ + Anope::string dn; + + public: + LDAPDel(LDAPService *s, LDAPInterface *i, const Anope::string &d) + : LDAPRequest(s, i) + , dn(d) + { + type = QUERY_DELETE; + } + + int run() anope_override; +}; + +class LDAPModify : public LDAPRequest +{ + Anope::string base; + LDAPMods attributes; + + public: + LDAPModify(LDAPService *s, LDAPInterface *i, const Anope::string &b, const LDAPMods &attr) + : LDAPRequest(s, i) + , base(b) + , attributes(attr) + { + type = QUERY_MODIFY; + } + + int run() anope_override; +}; + class LDAPService : public LDAPProvider, public Thread, public Condition { Anope::string server; - int port; Anope::string admin_binddn; Anope::string admin_pass; - time_t timeout; LDAP *con; time_t last_connect; - 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)); @@ -46,7 +172,7 @@ class LDAPService : public LDAPProvider, public Thread, public Condition return mods; } - void FreeMods(LDAPMod **mods) + static void FreeMods(LDAPMod **mods) { for (int i = 0; mods[i] != NULL; ++i) { @@ -58,26 +184,8 @@ class LDAPService : public LDAPProvider, public Thread, public Condition delete [] mods; } - void Reconnect() - { - /* Only try one connect a minute. It is an expensive blocking operation */ - if (last_connect > Anope::CurTime - 60) - throw LDAPException("Unable to connect to LDAP service " + this->name + ": reconnecting too fast"); - last_connect = Anope::CurTime; - - ldap_unbind_ext(this->con, NULL, NULL); - int i = ldap_initialize(&this->con, this->server.c_str()); - if (i != LDAP_SUCCESS) - throw LDAPException("Unable to connect to LDAP service " + this->name + ": " + ldap_err2string(i)); - } - - public: - typedef std::map<LDAPQuery, std::pair<time_t, LDAPInterface *> > query_queue; - typedef std::vector<std::pair<LDAPInterface *, LDAPResult *> > result_queue; - query_queue queries; - result_queue results; - - LDAPService(Module *o, const Anope::string &n, const Anope::string &s, int po, const Anope::string &b, const Anope::string &p, time_t t) : LDAPProvider(o, n), server(s), port(po), admin_binddn(b), admin_pass(p), timeout(t), last_connect(0) + private: + void Connect() { int i = ldap_initialize(&this->con, this->server.c_str()); if (i != LDAP_SUCCESS) @@ -94,366 +202,243 @@ class LDAPService : public LDAPProvider, public Thread, public Condition throw LDAPException("Unable to set timeout for " + this->name + ": " + ldap_err2string(i)); } + void Reconnect() + { + /* Only try one connect a minute. It is an expensive blocking operation */ + if (last_connect > Anope::CurTime - 60) + throw LDAPException("Unable to connect to LDAP service " + this->name + ": reconnecting too fast"); + last_connect = Anope::CurTime; + + ldap_unbind_ext(this->con, NULL, NULL); + + Connect(); + } + + void QueueRequest(LDAPRequest *r) + { + this->Lock(); + this->queries.push_back(r); + this->Wakeup(); + this->Unlock(); + } + + public: + typedef std::vector<LDAPRequest *> query_queue; + query_queue queries, results; + Mutex process_mutex; /* held when processing requests not in either queue */ + + LDAPService(Module *o, const Anope::string &n, const Anope::string &s, const Anope::string &b, const Anope::string &p) : LDAPProvider(o, n), server(s), admin_binddn(b), admin_pass(p), last_connect(0) + { + Connect(); + } + ~LDAPService() { + /* At this point the thread has stopped so we don't need to hold process_mutex */ + this->Lock(); - for (query_queue::iterator it = this->queries.begin(), it_end = this->queries.end(); it != it_end; ++it) + for (unsigned int i = 0; i < this->queries.size(); ++i) { - LDAPQuery msgid = it->first; - LDAPInterface *i = it->second.second; + LDAPRequest *req = this->queries[i]; + + /* queries have no results yet */ + req->result = new LDAPResult(); + req->result->type = req->type; + req->result->error = "LDAP Interface is going away"; + if (req->inter) + req->inter->OnError(*req->result); - ldap_abandon_ext(this->con, msgid, NULL, NULL); - if (i) - i->OnDelete(); + delete req; } this->queries.clear(); - for (result_queue::iterator it = this->results.begin(), it_end = this->results.end(); it != it_end; ++it) + for (unsigned int i = 0; i < this->results.size(); ++i) { - LDAPInterface *i = it->first; - LDAPResult *r = it->second; + LDAPRequest *req = this->results[i]; - r->error = "LDAP Interface is going away"; - if (i) - i->OnError(*r); + /* even though this may have already finished successfully we return that it didn't */ + req->result->error = "LDAP Interface is going away"; + if (req->inter) + req->inter->OnError(*req->result); - delete r; + delete req; } - this->results.clear(); this->Unlock(); ldap_unbind_ext(this->con, NULL, NULL); } - - LDAPQuery BindAsAdmin(LDAPInterface *i) + + void BindAsAdmin(LDAPInterface *i) override { - return this->Bind(i, this->admin_binddn, this->admin_pass); + this->Bind(i, this->admin_binddn, this->admin_pass); } - LDAPQuery Bind(LDAPInterface *i, const Anope::string &who, const Anope::string &pass) override + void Bind(LDAPInterface *i, const Anope::string &who, const Anope::string &pass) 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)); - } - - if (i != NULL) - { - this->Lock(); - this->queries[msgid] = std::make_pair(Anope::CurTime, i); - this->Unlock(); - } - this->Wakeup(); - - return msgid; + LDAPBind *b = new LDAPBind(this, i, who, pass); + QueueRequest(b); } - LDAPQuery Search(LDAPInterface *i, const Anope::string &base, const Anope::string &filter) override + void Search(LDAPInterface *i, const Anope::string &base, const Anope::string &filter) override { if (i == NULL) throw LDAPException("No interface"); - LDAPQuery msgid; - int ret = ldap_search_ext(this->con, base.c_str(), LDAP_SCOPE_SUBTREE, 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)); - } - - this->Lock(); - this->queries[msgid] = std::make_pair(Anope::CurTime, i); - this->Unlock(); - this->Wakeup(); - - return msgid; + LDAPSearch *s = new LDAPSearch(this, i, base, filter); + QueueRequest(s); } - LDAPQuery Add(LDAPInterface *i, const Anope::string &dn, LDAPMods &attributes) override + void Add(LDAPInterface *i, const Anope::string &dn, LDAPMods &attributes) 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)); - } + LDAPAdd *add = new LDAPAdd(this, i, dn, attributes); + QueueRequest(add); + } - if (i != NULL) - { - this->Lock(); - this->queries[msgid] = std::make_pair(Anope::CurTime, i); - this->Unlock(); - } - this->Wakeup(); + void Del(LDAPInterface *i, const Anope::string &dn) anope_override + { + LDAPDel *del = new LDAPDel(this, i, dn); + QueueRequest(del); + } - return msgid; + void Modify(LDAPInterface *i, const Anope::string &base, LDAPMods &attributes) anope_override + { + LDAPModify *mod = new LDAPModify(this, i, base, attributes); + QueueRequest(mod); } - LDAPQuery Del(LDAPInterface *i, const Anope::string &dn) override + private: + void BuildReply(int res, LDAPRequest *req) { - LDAPQuery msgid; - int ret = ldap_delete_ext(this->con, dn.c_str(), NULL, NULL, &msgid); + LDAPResult *ldap_result = req->result = new LDAPResult(); + req->result->type = req->type; - if (ret != LDAP_SUCCESS) + if (res != LDAP_SUCCESS) { - if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT) - { - this->Reconnect(); - return this->Del(i, dn); - } - else - throw LDAPException(ldap_err2string(ret)); + ldap_result->error = ldap_err2string(res); + return; } - if (i != NULL) + if (req->message == NULL) { - this->Lock(); - this->queries[msgid] = std::make_pair(Anope::CurTime, i); - this->Unlock(); + return; } - this->Wakeup(); - return msgid; - } + /* a search result */ - LDAPQuery Modify(LDAPInterface *i, const Anope::string &base, LDAPMods &attributes) 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) + for (LDAPMessage *cur = ldap_first_message(this->con, req->message); cur; cur = ldap_next_message(this->con, cur)) { - if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT) + LDAPAttributes attributes; + + char *dn = ldap_get_dn(this->con, cur); + if (dn != NULL) { - this->Reconnect(); - return this->Modify(i, base, attributes); + attributes["dn"].push_back(dn); + ldap_memfree(dn); + dn = NULL; } - else - throw LDAPException(ldap_err2string(ret)); - } - - if (i != NULL) - { - this->Lock(); - this->queries[msgid] = std::make_pair(Anope::CurTime, i); - this->Unlock(); - } - this->Wakeup(); - - return msgid; - } - private: - void Timeout() - { - this->Lock(); - for (query_queue::iterator it = this->queries.begin(), it_end = this->queries.end(); it != it_end;) - { - LDAPQuery msgid = it->first; - time_t created = it->second.first; - LDAPInterface *i = it->second.second; - ++it; + BerElement *ber = NULL; - if (Anope::CurTime > created + timeout) + for (char *attr = ldap_first_attribute(this->con, cur, &ber); attr; attr = ldap_next_attribute(this->con, cur, ber)) { - LDAPResult *ldap_result = new LDAPResult(); - ldap_result->id = msgid; - ldap_result->error = "Query timed out"; + berval **vals = ldap_get_values_len(this->con, cur, attr); + int count = ldap_count_values_len(vals); - this->queries.erase(msgid); - this->results.push_back(std::make_pair(i, ldap_result)); + std::vector<Anope::string> attrs; + for (int j = 0; j < count; ++j) + attrs.push_back(vals[j]->bv_val); + attributes[attr] = attrs; - me->Notify(); + ldap_value_free_len(vals); + ldap_memfree(attr); } + + if (ber != NULL) + ber_free(ber, 0); + + ldap_result->messages.push_back(attributes); } - this->Unlock(); } - public: - void Run() override + void SendRequests() { - while (!this->GetExitState()) - { - if (this->queries.empty()) - { - this->Lock(); - this->Wait(); - this->Unlock(); - continue; - } - else - this->Timeout(); - - struct timeval tv = { 1, 0 }; - LDAPMessage *result; - int rtype = ldap_result(this->con, LDAP_RES_ANY, 1, &tv, &result); - if (rtype <= 0) - continue; - - int cur_id = ldap_msgid(result); - - this->Lock(); + process_mutex.Lock(); - query_queue::iterator it = this->queries.find(cur_id); - if (it == this->queries.end()) - { - this->Unlock(); - ldap_msgfree(result); - continue; - } - LDAPInterface *i = it->second.second; - this->queries.erase(it); + query_queue q; + this->Lock(); + queries.swap(q); + this->Unlock(); - this->Unlock(); + if (q.empty()) + { + process_mutex.Unlock(); + return; + } - LDAPResult *ldap_result = new LDAPResult(); - ldap_result->id = cur_id; + for (unsigned int i = 0; i < q.size(); ++i) + { + LDAPRequest *req = q[i]; + int ret = req->run(); - for (LDAPMessage *cur = ldap_first_message(this->con, result); cur; cur = ldap_next_message(this->con, cur)) + if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT) { - int cur_type = ldap_msgtype(cur); - - LDAPAttributes attributes; - - char *dn = ldap_get_dn(this->con, cur); - if (dn != NULL) - { - attributes["dn"].push_back(dn); - ldap_memfree(dn); - dn = NULL; - } - - switch (cur_type) + /* 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; - default: - Log(LOG_DEBUG) << "m_ldap: Unknown msg type " << cur_type; - continue; + Reconnect(); } - - switch (cur_type) + catch (const LDAPException &) { - case LDAP_RES_BIND: - { - 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 (errcode != LDAP_SUCCESS) - ldap_result->error = ldap_err2string(errcode); - break; - } - 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<Anope::string> 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_ADD: - case LDAP_RES_DELETE: - case LDAP_RES_MODIFY: - { - 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 (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->Lock(); + results.push_back(req); + this->Unlock(); + } + + me->Notify(); + + process_mutex.Unlock(); + } + public: + void Run() anope_override + { + while (!this->GetExitState()) + { this->Lock(); - this->results.push_back(std::make_pair(i, ldap_result)); + /* Queries can be non empty if one is pushed during SendRequests() */ + if (queries.empty()) + this->Wait(); this->Unlock(); - me->Notify(); + SendRequests(); } } + + LDAP* GetConnection() + { + return con; + } }; class ModuleLDAP : public Module, public Pipe , public EventHook<Event::ModuleUnload> { std::map<Anope::string, LDAPService *> LDAPServices; + public: ModuleLDAP(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR) { me = this; - } ~ModuleLDAP() @@ -490,6 +475,8 @@ class ModuleLDAP : public Module, public Pipe s->SetExitState(); s->Wakeup(); + s->Join(); + delete s; this->LDAPServices.erase(cname); } } @@ -503,14 +490,12 @@ class ModuleLDAP : public Module, public Pipe if (this->LDAPServices.find(connname) == this->LDAPServices.end()) { const Anope::string &server = ldap->Get<Anope::string>("server", "127.0.0.1"); - int port = ldap->Get<int>("port", "389"); const Anope::string &admin_binddn = ldap->Get<Anope::string>("admin_binddn"); - const Anope::string &admin_password = ldap->Get<Anope::string>("admin_password"); - time_t timeout = ldap->Get<time_t>("timeout", "5"); + const Anope::string &admin_password = ldap->GetAnope::string>("admin_password"); try { - LDAPService *ss = new LDAPService(this, connname, server, port, admin_binddn, admin_password, timeout); + LDAPService *ss = new LDAPService(this, connname, server, admin_binddn, admin_password); ss->Start(); this->LDAPServices.insert(std::make_pair(connname, ss)); @@ -529,31 +514,35 @@ class ModuleLDAP : public Module, public Pipe for (std::map<Anope::string, LDAPService *>::iterator it = this->LDAPServices.begin(); it != this->LDAPServices.end(); ++it) { LDAPService *s = it->second; + + s->process_mutex.Lock(); s->Lock(); - for (LDAPService::query_queue::iterator it2 = s->queries.begin(); it2 != s->queries.end();) + + for (unsigned int i = s->queries.size(); i > 0; --i) { - LDAPQuery msgid = it2->first; - LDAPInterface *i = it2->second.second; - ++it2; + LDAPRequest *req = s->queries[i - 1]; + LDAPInterface *li = req->inter; - if (i && i->owner == m) + if (li && li->owner == m) { - i->OnDelete(); - s->queries.erase(msgid); + s->queries.erase(s->queries.begin() + i - 1); + delete req; } } - for (unsigned i = s->results.size(); i > 0; --i) + 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 && li->owner == m) { s->results.erase(s->results.begin() + i - 1); - delete r; + delete req; } } + s->Unlock(); + s->process_mutex.Unlock(); } } @@ -563,15 +552,16 @@ class ModuleLDAP : public Module, public Pipe { LDAPService *s = it->second; - LDAPService::result_queue results; + LDAPService::query_queue results; s->Lock(); results.swap(s->results); s->Unlock(); - for (unsigned i = 0; i < results.size(); ++i) + for (unsigned int i = 0; i < results.size(); ++i) { - LDAPInterface *li = results[i].first; - LDAPResult *r = results[i].second; + LDAPRequest *req = results[i]; + LDAPInterface *li = req->inter; + LDAPResult *r = req->result; if (li != NULL) { @@ -584,11 +574,50 @@ class ModuleLDAP : public Module, public Pipe li->OnResult(*r); } - delete r; + delete req; } } } }; +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; +} + +int LDAPSearch::run() +{ + return ldap_search_ext_s(service->GetConnection(), base.c_str(), LDAP_SCOPE_SUBTREE, filter.c_str(), NULL, 0, NULL, NULL, &tv, 0, &message); +} + +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; +} + +int LDAPDel::run() +{ + return ldap_delete_ext_s(service->GetConnection(), dn.c_str(), NULL, NULL); +} + +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; +} + MODULE_INIT(ModuleLDAP) diff --git a/modules/extra/m_ldap_authentication.cpp b/modules/extra/m_ldap_authentication.cpp index f5b03a606..dd63fd3fb 100644 --- a/modules/extra/m_ldap_authentication.cpp +++ b/modules/extra/m_ldap_authentication.cpp @@ -31,36 +31,29 @@ struct IdentifyInfo class IdentifyInterface : public LDAPInterface { - std::map<LDAPQuery, IdentifyInfo *> requests; + IdentifyInfo *ii; public: - IdentifyInterface(Module *m) : LDAPInterface(m) { } + IdentifyInterface(Module *m, IdentifyInfo *i) : LDAPInterface(m), ii(i) { } - void Add(LDAPQuery id, IdentifyInfo *ii) + ~IdentifyInterface() { - std::map<LDAPQuery, IdentifyInfo *>::iterator it = this->requests.find(id); - if (it != this->requests.end()) - delete it->second; - this->requests[id] = ii; + delete ii; } - void OnResult(const LDAPResult &r) override + void OnDelete() anope_override { - std::map<LDAPQuery, IdentifyInfo *>::iterator it = this->requests.find(r.id); - if (it == this->requests.end()) - return; - IdentifyInfo *ii = it->second; - this->requests.erase(it); + delete this; + } + void OnResult(const LDAPResult &r) override + { if (!ii->lprov) - { - delete ii; return; - } switch (r.type) { - case LDAPResult::QUERY_SEARCH: + case QUERY_SEARCH: { if (!r.empty()) { @@ -69,9 +62,9 @@ class IdentifyInterface : public LDAPInterface const LDAPAttributes &attr = r.get(0); ii->dn = attr.get("dn"); Log(LOG_DEBUG) << "m_ldap_authenticationn: binding as " << ii->dn; - LDAPQuery id = ii->lprov->Bind(this, ii->dn, ii->req->GetPassword()); - this->Add(id, ii); - return; + + ii->lprov->Bind(new IdentifyInterface(this->owner, ii), ii->dn, ii->req->GetPassword()); + ii = NULL; } catch (const LDAPException &ex) { @@ -80,7 +73,7 @@ class IdentifyInterface : public LDAPInterface } break; } - case LDAPResult::QUERY_BIND: + case QUERY_BIND: { if (ii->admin_bind) { @@ -88,10 +81,9 @@ class IdentifyInterface : public LDAPInterface try { Log(LOG_DEBUG) << "m_ldap_authentication: searching for " << sf; - LDAPQuery id = ii->lprov->Search(this, basedn, sf); - this->Add(id, ii); + ii->lprov->Search(new IdentifyInterface(this->owner, ii), basedn, sf); ii->admin_bind = false; - return; + ii = NULL; } catch (const LDAPException &ex) { @@ -121,40 +113,28 @@ class IdentifyInterface : public LDAPInterface default: break; } - - delete ii; } void OnError(const LDAPResult &r) override { - std::map<LDAPQuery, IdentifyInfo *>::iterator it = this->requests.find(r.id); - if (it == this->requests.end()) - return; - IdentifyInfo *ii = it->second; - this->requests.erase(it); - delete ii; } }; class OnIdentifyInterface : public LDAPInterface { - std::map<LDAPQuery, Anope::string> requests; + Anope::string uid; public: - OnIdentifyInterface(Module *m) : LDAPInterface(m) { } + OnIdentifyInterface(Module *m, const Anope::string &i) : LDAPInterface(m), uid(i) { } - void Add(LDAPQuery id, const Anope::string &nick) + void OnDelete() anope_override { - this->requests[id] = nick; + delete this; } void OnResult(const LDAPResult &r) override { - std::map<LDAPQuery, Anope::string>::iterator it = this->requests.find(r.id); - if (it == this->requests.end()) - return; - User *u = User::Find(it->second); - this->requests.erase(it); + User *u = User::Find(uid); if (!u || !u->Account() || r.empty()) return; @@ -181,7 +161,6 @@ class OnIdentifyInterface : public LDAPInterface void OnError(const LDAPResult &r) override { - this->requests.erase(r.id); Log(this->owner) << r.error; } }; @@ -202,15 +181,13 @@ class OnRegisterInterface : public LDAPInterface } }; -class NSIdentifyLDAP : public Module +class ModuleLDAPAuthentication : public Module , public EventHook<Event::PreCommand> , public EventHook<Event::CheckAuthentication> , public EventHook<Event::NickIdentify> , public EventHook<NickServ::Event::NickRegister> { ServiceReference<LDAPProvider> ldap; - IdentifyInterface iinterface; - OnIdentifyInterface oninterface; OnRegisterInterface orinterface; PrimitiveExtensibleItem<Anope::string> dn; @@ -218,29 +195,18 @@ class NSIdentifyLDAP : public Module Anope::string password_attribute; Anope::string disable_register_reason; Anope::string disable_email_reason; - public: - NSIdentifyLDAP(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR) + public: + ModuleLDAPAuthentication(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR) , EventHook<Event::PreCommand>("OnPreCommand", EventHook<Event::PreCommand>::Priority::FIRST) , EventHook<Event::CheckAuthentication>("OnCheckAuthentication", EventHook<Event::CheckAuthentication>::Priority::FIRST) , EventHook<Event::NickIdentify>("OnNickIdentify", EventHook<Event::NickIdentify>::Priority::FIRST) , EventHook<NickServ::Event::NickRegister>("OnNickRegister", EventHook<NickServ::Event::NickRegister>::Priority::FIRST) , ldap("LDAPProvider", "ldap/main") - , iinterface(this) - , oninterface(this) , orinterface(this) , dn(this, "m_ldap_authentication_dn") { - me = this; -<<<<<<< HEAD -======= - } - - void Prioritize() anope_override - { - ModuleManager::SetPriority(this, PRIORITY_FIRST); ->>>>>>> 2.0 } void OnReload(Configuration::Conf *config) override @@ -287,16 +253,7 @@ class NSIdentifyLDAP : public Module return; IdentifyInfo *ii = new IdentifyInfo(u, req, this->ldap); - try - { - LDAPQuery id = this->ldap->BindAsAdmin(&this->iinterface); - this->iinterface.Add(id, ii); - } - catch (const LDAPException &ex) - { - delete ii; - Log(this) << ex.GetReason(); - } + this->ldap->BindAsAdmin(new IdentifyInterface(this, ii)); } void OnNickIdentify(User *u) override @@ -308,57 +265,38 @@ class NSIdentifyLDAP : public Module if (!d || d->empty()) return; - try - { - LDAPQuery id = this->ldap->Search(&this->oninterface, *d, "(" + email_attribute + "=*)"); - this->oninterface.Add(id, u->nick); - } - catch (const LDAPException &ex) - { - Log(this) << ex.GetReason(); - } + this->ldap->Search(new OnIdentifyInterface(this, u->GetUID()), *d, "(" + email_attribute + "=*)"); } -<<<<<<< HEAD - void OnNickRegister(User *, NickServ::Nick *na) override -======= - void OnNickRegister(User *, NickAlias *na, const Anope::string &pass) anope_override ->>>>>>> 2.0 + void OnNickRegister(User *, NickServ::Nick *na, const Anope::string &pass) override { if (!this->disable_register_reason.empty() || !this->ldap) return; - try - { - this->ldap->BindAsAdmin(NULL); - - LDAPMods attributes; - attributes.resize(4); + this->ldap->BindAsAdmin(NULL); - attributes[0].name = "objectClass"; - attributes[0].values.push_back("top"); - attributes[0].values.push_back(object_class); + LDAPMods attributes; + attributes.resize(4); - attributes[1].name = username_attribute; - attributes[1].values.push_back(na->GetNick()); - - if (!na->GetAccount()->GetEmail().empty()) - { - attributes[2].name = email_attribute; - attributes[2].values.push_back(na->GetAccount()->GetEmail()); - } + attributes[0].name = "objectClass"; + attributes[0].values.push_back("top"); + attributes[0].values.push_back(object_class); - attributes[3].name = this->password_attribute; - attributes[3].values.push_back(pass); + attributes[1].name = username_attribute; + attributes[1].values.push_back(na->GetNick()); - Anope::string new_dn = username_attribute + "=" + na->GetNick() + "," + basedn; - this->ldap->Add(&this->orinterface, new_dn, attributes); - } - catch (const LDAPException &ex) + if (!na->GetAccount()->GetEmail().empty()) { - Log(this) << ex.GetReason(); + attributes[2].name = email_attribute; + attributes[2].values.push_back(na->GetAccount()->GetEmail()); } + + attributes[3].name = this->password_attribute; + attributes[3].values.push_back(pass); + + Anope::string new_dn = username_attribute + "=" + na->GetNick() + "," + basedn; + this->ldap->Add(&this->orinterface, new_dn, attributes); } }; -MODULE_INIT(NSIdentifyLDAP) +MODULE_INIT(ModuleLDAPAuthentication) diff --git a/modules/extra/m_ldap_oper.cpp b/modules/extra/m_ldap_oper.cpp index 221e16f98..31653544e 100644 --- a/modules/extra/m_ldap_oper.cpp +++ b/modules/extra/m_ldap_oper.cpp @@ -6,27 +6,15 @@ static Anope::string opertype_attribute; class IdentifyInterface : public LDAPInterface { - std::map<LDAPQuery, Anope::string> requests; + Reference<User> u; public: - IdentifyInterface(Module *m) : LDAPInterface(m) + IdentifyInterface(Module *m, User *user) : LDAPInterface(m), u(user) { } - void Add(LDAPQuery id, const Anope::string &nick) - { - this->requests[id] = nick; - } - void OnResult(const LDAPResult &r) override { - std::map<LDAPQuery, Anope::string>::iterator it = this->requests.find(r.id); - if (it == this->requests.end()) - return; - User *u = User::Find(it->second); - this->requests.erase(it); - - if (!u || !u->Account()) return; @@ -50,11 +38,8 @@ class IdentifyInterface : public LDAPInterface o = new Oper(u->nick, ot); my_opers.insert(o); nc->o = o; -<<<<<<< HEAD - Log(this->owner) << "m_ldap_oper: Tied " << u->nick << " (" << nc->GetDisplay() << ") to opertype " << ot->GetName(); -======= - Log(this->owner) << "Tied " << u->nick << " (" << nc->display << ") to opertype " << ot->GetName(); ->>>>>>> 2.0 + + Log(this->owner) << "Tied " << u->nick << " (" << nc->GetDisplay() << ") to opertype " << ot->GetName(); } } catch (const LDAPException &ex) @@ -68,18 +53,18 @@ class IdentifyInterface : public LDAPInterface } nc->o = NULL; -<<<<<<< HEAD - Log() << "Removed services operator from " << u->nick << " (" << nc->GetDisplay() << ")"; -======= - Log(this->owner) << "Removed services operator from " << u->nick << " (" << nc->display << ")"; ->>>>>>> 2.0 + Log(this->owner) << "Removed services operator from " << u->nick << " (" << nc->GetDisplay() << ")"; } } } void OnError(const LDAPResult &r) override { - this->requests.erase(r.id); + } + + void OnDelete() anope_override + { + delete this; } }; @@ -88,16 +73,15 @@ class LDAPOper : public Module , public EventHook<Event::DelCore> { ServiceReference<LDAPProvider> ldap; - IdentifyInterface iinterface; Anope::string binddn; Anope::string password; Anope::string basedn; Anope::string filter; public: - LDAPOper(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR) + LDAPOper(const Anope::string &modname, const Anope::string &creator) + : Module(modname, creator, EXTRA | VENDOR) , ldap("LDAPProvider", "ldap/main") - , iinterface(this) { } @@ -128,8 +112,7 @@ class LDAPOper : public Module if (!this->binddn.empty()) this->ldap->Bind(NULL, this->binddn.replace_all_cs("%a", u->Account()->GetDisplay()), this->password.c_str()); - LDAPQuery id = this->ldap->Search(&this->iinterface, this->basedn, this->filter.replace_all_cs("%a", u->Account()->GetDisplay())); - this->iinterface.Add(id, u->nick); + this->ldap->Search(new IdentifyInterface(this, u), this->basedn, this->filter.replace_all_cs("%a", u->Account()->GetDisplay())); } catch (const LDAPException &ex) { diff --git a/modules/extra/m_ssl_openssl.cpp b/modules/extra/m_ssl_openssl.cpp index 748f467cf..c5e2feefc 100644 --- a/modules/extra/m_ssl_openssl.cpp +++ b/modules/extra/m_ssl_openssl.cpp @@ -105,6 +105,10 @@ class SSLModule : public Module if (!client_ctx || !server_ctx) throw ModuleException("Error initializing SSL CTX"); + long opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_CIPHER_SERVER_PREFERENCE; + SSL_CTX_set_options(client_ctx, opts); + SSL_CTX_set_options(server_ctx, opts); + SSL_CTX_set_mode(client_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); SSL_CTX_set_mode(server_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); @@ -160,6 +164,20 @@ class SSLModule : public Module Log() << "Unable to open private key " << this->keyfile; } + // Allow disabling SSLv3 + if (!config->Get<Anope::string>("sslv3").empty()) + { + if (config->Get<bool>("sslv3")) + { + SSL_CTX_clear_options(client_ctx, SSL_OP_NO_SSLv3); + SSL_CTX_clear_options(server_ctx, SSL_OP_NO_SSLv3); + } + else + { + SSL_CTX_set_options(client_ctx, SSL_OP_NO_SSLv3); + SSL_CTX_set_options(server_ctx, SSL_OP_NO_SSLv3); + } + } } void OnPreServerConnect() override diff --git a/modules/extra/stats/irc2sql/irc2sql.cpp b/modules/extra/stats/irc2sql/irc2sql.cpp index fbb56f4a7..e0c03edbd 100644 --- a/modules/extra/stats/irc2sql/irc2sql.cpp +++ b/modules/extra/stats/irc2sql/irc2sql.cpp @@ -131,6 +131,15 @@ void IRC2SQL::OnUserNickChange(User *u, const Anope::string &oldnick) this->RunQuery(query); } +void IRC2SQL::OnUserAway(User *u, const Anope::string &message) +{ + query = "UPDATE `" + prefix + "user` SET away=@away@, awaymsg=@awaymsg@ WHERE nick=@nick@"; + query.SetValue("away", (!message.empty()) ? "Y" : "N"); + query.SetValue("awaymsg", message); + query.SetValue("nick", u->nick); + this->RunQuery(query); +} + void IRC2SQL::OnFingerprint(User *u) { query = "UPDATE `" + prefix + "user` SET secure=@secure@, fingerprint=@fingerprint@ WHERE nick=@nick@"; @@ -243,7 +252,7 @@ void IRC2SQL::OnLeaveChannel(User *u, Channel *c) this->RunQuery(query); } -void IRC2SQL::OnTopicUpdated(Channel *c, const Anope::string &user, const Anope::string &topic) +void IRC2SQL::OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic) { query = "UPDATE `" + prefix + "chan` " "SET topic=@topic@, topicauthor=@author@, topictime=FROM_UNIXTIME(@time@) " diff --git a/modules/extra/stats/irc2sql/irc2sql.h b/modules/extra/stats/irc2sql/irc2sql.h index 175e37681..b73e95cf1 100644 --- a/modules/extra/stats/irc2sql/irc2sql.h +++ b/modules/extra/stats/irc2sql/irc2sql.h @@ -55,6 +55,7 @@ class IRC2SQL : public Module void OnUserConnect(User *u, bool &exempt) override; void OnUserQuit(User *u, const Anope::string &msg) override; void OnUserNickChange(User *u, const Anope::string &oldnick) override; + void OnUserAway(User *u, const Anope::string &message) override; void OnFingerprint(User *u) override; void OnUserModeSet(const MessageSource &setter, User *u, const Anope::string &mname) override; void OnUserModeUnset(const MessageSource &setter, User *u, const Anope::string &mname) override; @@ -69,7 +70,7 @@ class IRC2SQL : public Module EventReturn OnChannelModeSet(Channel *c, const MessageSource &setter, ChannelMode *mode, const Anope::string ¶m) override; EventReturn OnChannelModeUnset(Channel *c, const MessageSource &setter, ChannelMode *mode, const Anope::string ¶m) override; - void OnTopicUpdated(Channel *c, const Anope::string &user, const Anope::string &topic) override; + void OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic) override; void OnBotNotice(User *u, ServiceBot *bi, Anope::string &message) override; }; diff --git a/modules/extra/stats/m_chanstats.cpp b/modules/extra/stats/m_chanstats.cpp index 0278f7805..687c077b5 100644 --- a/modules/extra/stats/m_chanstats.cpp +++ b/modules/extra/stats/m_chanstats.cpp @@ -424,7 +424,7 @@ class MChanstats : public Module "END;"; this->RunQuery(query); - /* dont prepend any database prefix to events so we can always delete/change old events */ + /* don't prepend any database prefix to events so we can always delete/change old events */ if (this->HasEvent("chanstats_event_cleanup_daily")) { query = "DROP EVENT chanstats_event_cleanup_daily"; @@ -517,14 +517,13 @@ class MChanstats : public Module info.AddOption(_("Chanstats")); } - void OnTopicUpdated(Channel *c, const Anope::string &user, const Anope::string &topic) override + void OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic) override { - User *u = User::Find(user); - if (!u || !u->Account() || !c->ci || !cs_stats.HasExt(c->ci)) + if (!source || !source->Account() || !c->ci || !cs_stats.HasExt(c->ci)) return; query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);"; query.SetValue("channel", c->name); - query.SetValue("nick", GetDisplay(u)); + query.SetValue("nick", GetDisplay(source)); this->RunQuery(query); } |
