summaryrefslogtreecommitdiff
path: root/modules/extra/m_ldap.cpp
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2011-04-27 10:56:20 -0400
committerAdam <Adam@anope.org>2011-05-16 04:09:07 -0400
commit284af258bf3c4dc7f409722d66bb0ac59e01e37d (patch)
tree5649a27a7a247c2609a4ef13b52a357765cbdfcc /modules/extra/m_ldap.cpp
parente7887c1f013248274574ab8e3167f742ccb3d69b (diff)
Added more useful functions to our LDAP API, allow adding newly registered accounts to LDAP, removed some unnecessary OnPre events and fixed unloading all modules
Diffstat (limited to 'modules/extra/m_ldap.cpp')
-rw-r--r--modules/extra/m_ldap.cpp152
1 files changed, 146 insertions, 6 deletions
diff --git a/modules/extra/m_ldap.cpp b/modules/extra/m_ldap.cpp
index 157bc70ac..188c9d02f 100644
--- a/modules/extra/m_ldap.cpp
+++ b/modules/extra/m_ldap.cpp
@@ -10,16 +10,57 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
{
Anope::string server;
int port;
+ Anope::string admin_binddn;
+ Anope::string admin_pass;
LDAP *con;
+ LDAPMod **BuildMods(const LDAPMods &attributes)
+ {
+ LDAPMod **mods = new LDAPMod*[attributes.size() + 1];
+ memset(mods, 0, sizeof(LDAPMod*) * (attributes.size() + 1));
+ for (unsigned x = 0; x < attributes.size(); ++x)
+ {
+ const LDAPModification &l = attributes[x];
+ mods[x] = new LDAPMod();
+
+ if (l.op == LDAPModification::LDAP_ADD)
+ mods[x]->mod_op = LDAP_MOD_ADD;
+ else if (l.op == LDAPModification::LDAP_DEL)
+ mods[x]->mod_op = LDAP_MOD_DELETE;
+ else if (l.op == LDAPModification::LDAP_REPLACE)
+ mods[x]->mod_op = LDAP_MOD_REPLACE;
+ else if (l.op != 0)
+ throw LDAPException("Unknown LDAP operation");
+ mods[x]->mod_type = strdup(l.name.c_str());
+ mods[x]->mod_values = new char*[l.values.size() + 1];
+ memset(mods[x]->mod_values, 0, sizeof(char *) * (l.values.size() + 1));
+ for (unsigned j = 0, c = 0; j < l.values.size(); ++j)
+ if (!l.values[j].empty())
+ mods[x]->mod_values[c++] = strdup(l.values[j].c_str());
+ }
+ return mods;
+ }
+
+ void FreeMods(LDAPMod **mods)
+ {
+ for (int i = 0; mods[i] != NULL; ++i)
+ {
+ free(mods[i]->mod_type);
+ for (int j = 0; mods[i]->mod_values[j] != NULL; ++j)
+ free(mods[i]->mod_values[j]);
+ delete [] mods[i]->mod_values;
+ }
+ delete [] mods;
+ }
+
public:
typedef std::map<int, 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) : LDAPProvider(o, "ldap/" + n), server(s), port(po)
+ LDAPService(Module *o, const Anope::string &n, const Anope::string &s, int po, const Anope::string &b, const Anope::string &p) : LDAPProvider(o, "ldap/" + n), server(s), port(po), admin_binddn(b), admin_pass(p)
{
if (ldap_initialize(&this->con, this->server.c_str()) != LDAP_SUCCESS)
throw LDAPException("Unable to connect to LDAP service " + this->name + ": " + Anope::LastError());
@@ -52,6 +93,11 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
ldap_unbind_ext(this->con, NULL, NULL);
}
+
+ LDAPQuery BindAsAdmin(LDAPInterface *i)
+ {
+ return this->Bind(i, this->admin_binddn, this->admin_pass);
+ }
LDAPQuery Bind(LDAPInterface *i, const Anope::string &who, const Anope::string &pass)
{
@@ -94,6 +140,67 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
return msgid;
}
+ LDAPQuery Add(LDAPInterface *i, const Anope::string &dn, LDAPMods &attributes)
+ {
+ 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)
+ throw LDAPException(ldap_err2string(ret));
+
+ if (i != NULL)
+ {
+ this->Lock();
+ this->queries[msgid] = i;
+ this->Unlock();
+ }
+ this->Wakeup();
+
+ return msgid;
+ }
+
+ LDAPQuery Del(LDAPInterface *i, const Anope::string &dn)
+ {
+ LDAPQuery msgid;
+ int ret = ldap_delete_ext(this->con, dn.c_str(), NULL, NULL, &msgid);
+
+ if (ret != LDAP_SUCCESS)
+ throw LDAPException(ldap_err2string(ret));
+
+ if (i != NULL)
+ {
+ this->Lock();
+ this->queries[msgid] = i;
+ this->Unlock();
+ }
+ this->Wakeup();
+
+ return msgid;
+ }
+
+ LDAPQuery Modify(LDAPInterface *i, const Anope::string &base, LDAPMods &attributes)
+ {
+ 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)
+ throw LDAPException(ldap_err2string(ret));
+
+ if (i != NULL)
+ {
+ this->Lock();
+ this->queries[msgid] = i;
+ this->Unlock();
+ }
+ this->Wakeup();
+
+ return msgid;
+ }
+
void Run()
{
while (!this->GetExitState())
@@ -121,6 +228,7 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
if (it == this->queries.end())
{
this->Unlock();
+ ldap_msgfree(result);
continue;
}
LDAPInterface *i = it->second;
@@ -140,9 +248,30 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
switch (cur_type)
{
case LDAP_RES_BIND:
- {
ldap_result->type = LDAPResult::QUERY_BIND;
+ break;
+ case LDAP_RES_SEARCH_ENTRY:
+ ldap_result->type = LDAPResult::QUERY_SEARCH;
+ case LDAP_RES_SEARCH_RESULT:
+ 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;
+ default:
+ Log(LOG_DEBUG) << "m_ldap: Unknown msg type " << cur_type;
+ continue;
+ }
+ switch (cur_type)
+ {
+ 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)
@@ -153,8 +282,6 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
}
case LDAP_RES_SEARCH_ENTRY:
{
- ldap_result->type = LDAPResult::QUERY_SEARCH;
-
BerElement *ber = NULL;
for (char *attr = ldap_first_attribute(this->con, cur, &ber); attr; attr = ldap_next_attribute(this->con, cur, ber))
{
@@ -173,8 +300,19 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
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:
- Log(LOG_DEBUG) << "m_ldap: Unknown msg type " << cur_type;
continue;
}
@@ -262,10 +400,12 @@ class ModuleLDAP : public Module, public Pipe
{
Anope::string server = config.ReadValue("ldap", "server", "127.0.0.1", i);
int port = config.ReadInteger("ldap", "port", "389", i, true);
+ Anope::string admin_binddn = config.ReadValue("ldap", "admin_binddn", "", i);
+ Anope::string admin_password = config.ReadValue("ldap", "admin_password", "", i);
try
{
- LDAPService *ss = new LDAPService(this, connname, server, port);
+ LDAPService *ss = new LDAPService(this, connname, server, port, admin_binddn, admin_password);
this->LDAPServices.insert(std::make_pair(connname, ss));
ModuleManager::RegisterService(ss);