Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* ns_ldap.c - Allows auth via an ldap server
- *
- * (C) 2003-2009 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- *
- * Send bug reports to the Anope Coder instead of the module
- * author, because any changes since the inclusion into anope
- * are not supported by the original author.
- *
- */
- /*************************************************************************/
- #include "module.h"
- #include <ldap.h>
- #include <vector>
- #include <list>
- #define AUTHOR "Rob"
- #define VERSION "$Id$"
- /* Default database name */
- #define DEFAULT_DB_NAME "ns_ldap.db"
- extern int allow_ignore;
- int mLoadData();
- int mLoadConfig();
- /*************************************************************************/
- std::string NSLdapDBName = "ns_ldap.db";
- static Module *me;
- /*************************************************************************/
- class LdapSingleton
- {
- public:
- static LdapSingleton* instance()
- {
- static LdapSingleton* pInstance = NULL;
- if (pInstance == NULL)
- {
- pInstance = new LdapSingleton();
- }
- return pInstance;
- }
- virtual ~LdapSingleton() { }
- std::string getLastEmail() {
- return lastEmail;
- }
- bool validatePassword(std::string username, std::string password) {
- bool valid = false;
- if (con == NULL) { connectToLdap(); }
- if (con == NULL) { return valid; }
- std::vector<std::string> attrs;
- attrs.push_back("email");
- if(bindToLdap()) {
- LDAPMessage *res = doLdapSearch(userDN,userPrefix+username,attrs);
- if(res) {
- if(ldap_count_entries(con, res) == 1) {
- LDAPMessage *entry = NULL;
- if ((entry = ldap_first_entry(con, res)) != NULL) {
- if(doLdapAuth(username,password,entry)) {
- lastEmail = getAttribute(entry,"email");
- valid = true;
- }
- }
- }
- ldap_msgfree(res);
- }
- unbindFromLdap();
- }
- return valid;
- }
- std::list<std::string> getGroups(std::string uid) {
- std::list<std::string> ret;
- if (con == NULL) { connectToLdap(); }
- if (con == NULL) { return ret; }
- if(bindToLdap()) {
- LDAPMessage *res = doLdapSearch(groupDN,groupPrefix+userPrefix+uid+","+userDN);
- if(res) {
- LDAPMessage *entry = NULL;
- for(entry = ldap_first_entry(con, res) ; entry != NULL ; entry = ldap_next_entry(con, entry)) {
- std::string group = getAttribute(entry,"cn");
- if(group!="") {
- ret.push_back(group);
- }
- }
- ldap_msgfree(res);
- }
- unbindFromLdap();
- }
- return ret;
- }
- private:
- LdapSingleton()
- {
- con = NULL;
- ldapURI="ldap://";
- userDN="";
- groupDN="";
- ldapDN="";
- ldapPW="";
- userPrefix="uid=";
- groupPrefix="member=";
- searchscope = LDAP_SCOPE_SUBTREE;
- lastEmail = "";
- }
- void connectToLdap()
- {
- int ret = -1;
- int version = LDAP_VERSION3;
- ret = ldap_initialize(&con, ldapURI.c_str());
- if (ret == LDAP_SUCCESS)
- {
- ret = ldap_set_option( con, LDAP_OPT_PROTOCOL_VERSION, &version );
- if (ret != LDAP_OPT_SUCCESS)
- {
- ldap_unbind_ext(con, NULL, NULL);
- con = NULL;
- }
- }
- else
- {
- con = NULL;
- }
- }
- bool doLdapAuth(std::string username, std::string password, LDAPMessage *entry) {
- bool valid = false;
- struct berval cred;
- cred.bv_val = strdup(password.c_str());
- cred.bv_len = password.length();
- if (ldap_sasl_bind_s(con, ldap_get_dn(con, entry), LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL) == LDAP_SUCCESS) {
- valid = true;
- } else {
- valid = false;
- }
- free(cred.bv_val);
- return valid;
- }
- LDAPMessage *doLdapSearch(std::string DN, std::string filter) {
- LDAPMessage *res = NULL;
- if ( ldap_search_ext_s(con, DN.c_str(), searchscope, filter.c_str(), NULL, 0, NULL, NULL, NULL, 0, &res) != LDAP_SUCCESS) {
- res = NULL;
- }
- return res;
- }
- LDAPMessage *doLdapSearch(std::string DN, std::string filter, std::vector<std::string> attrs) {
- LDAPMessage *res = NULL;
- const int numAttrs = attrs.size();
- char **c_attrs;
- int i = 0;
- c_attrs = (char **)malloc(sizeof(char *)*(numAttrs+1));
- for(std::vector<std::string>::iterator it = attrs.begin() ; it != attrs.end() ; ++it) {
- c_attrs[i] = sstrdup((*it).c_str());
- ++i;
- }
- c_attrs[i] = NULL;
- if ( ldap_search_ext_s(con, DN.c_str(), searchscope, filter.c_str(), c_attrs, 0, NULL, NULL, NULL, 0, &res) != LDAP_SUCCESS) {
- res = NULL;
- }
- for(i = 0 ; i < numAttrs ; ++i) {
- free(c_attrs[i]);
- }
- free(c_attrs);
- return res;
- }
- bool bindToLdap() {
- return bindToLdap(ldapDN,ldapPW);
- }
- bool bindToLdap(std::string bindDN, std::string password) {
- struct berval cred;
- bool bound = false;
- cred.bv_len = password.length();
- cred.bv_val = strdup(password.c_str());
- if (con == NULL) { connectToLdap(); }
- if (con == NULL) { return bound; }
- if ( ldap_sasl_bind_s(con, bindDN.c_str(), LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL) == LDAP_SUCCESS) {
- bound = true;
- } else {
- Alog() << "Search bind failed.";
- }
- if(cred.bv_val) {
- free(cred.bv_val);
- }
- return bound;
- }
- void unbindFromLdap() {
- if(con) {
- ldap_unbind_ext(con, NULL, NULL);
- con = NULL;
- }
- }
- std::string getAttribute(LDAPMessage *e, std::string name) {
- BerElement *ber;
- struct berval **vals;
- char *a;
- std::string ret;
- for ( a = ldap_first_attribute( con, e, &ber ) ; a != NULL; a = ldap_next_attribute( con, e, ber ) )
- {
- /* For each attribute, print the attribute name and values. */
- if( (vals = ldap_get_values_len(con,e,a))) {
- int size = ldap_count_values_len(vals);
- for(int i = 0; i < size ; i++) {
- if(strcmp(a,name.c_str())==0) {
- ret = vals[i]->bv_val;
- break;
- }
- }
- ldap_value_free_len(vals);
- }
- ldap_memfree( a );
- }
- return ret;
- }
- LDAP *con;
- std::string ldapURI;
- std::string ldapDN;
- std::string userDN;
- std::string groupDN;
- std::string ldapPW;
- std::string userPrefix;
- std::string groupPrefix;
- int searchscope;
- std::string lastEmail;
- };
- class CommandNSLdapUid : public Command
- {
- private:
- CommandReturn DoSet(User *u, std::vector<std::string> ¶ms)
- {
- if (params.size() != 2)
- {
- OnSyntaxError(u);
- return MOD_CONT;
- }
- NickAlias *na = NULL;
- if (u->IsIdentified())
- {
- if ((na = findnick(u->nick)))
- {
- char *uid = sstrdup(params[1].c_str());
- if (na->nc->Extend("ns_ldap_uid", new ExtensibleItemPointerArray<char>(uid)))
- {
- u->SendMessage(Config.s_NickServ, "LDAP uid [%s] has been linked to this nick",uid);
- }
- else
- {
- free(uid);
- u->SendMessage(Config.s_NickServ, "An LDAP uid has already been linked to this nick, please remove it first.");
- }
- }
- else
- {
- notice_lang(Config.s_NickServ, u, NICK_X_NOT_REGISTERED, u->nick);
- }
- }
- else
- {
- notice_lang(Config.s_NickServ,u,NICK_IDENTIFY_REQUIRED,Config.s_NickServ);
- }
- return MOD_CONT;
- }
- CommandReturn DoDel(User *u, std::vector<std::string> ¶ms)
- {
- NickAlias *na = NULL;
- char *c;
- if ((na = findnick(u->nick)))
- {
- if (na->nc->GetExtArray("ns_ldap_uid", c))
- {
- delete [] c;
- na->nc->Shrink("ns_ldap_uid");
- u->SendMessage(Config.s_NickServ, "LDAP uid has been unlinked from this nick.");
- }
- else
- {
- u->SendMessage(Config.s_NickServ, "No LDAP uid has been linked to this nick.");
- }
- }
- else
- {
- notice_lang(Config.s_NickServ, u, NICK_X_NOT_REGISTERED, u->nick);
- }
- return MOD_CONT;
- }
- CommandReturn DoView(User *u, std::vector<std::string> ¶ms)
- {
- NickAlias *na = NULL;
- char *c;
- if ((na = findnick(u->nick)))
- {
- if (na->nc->GetExtArray("ns_ldap_uid", c))
- {
- u->SendMessage(Config.s_NickServ, "LDAP uid [%s] is linked to this nick.",c);
- }
- else
- {
- u->SendMessage(Config.s_NickServ, "No LDAP uid has been linked to this nick.");
- }
- }
- else
- {
- notice_lang(Config.s_NickServ, u, NICK_X_NOT_REGISTERED, u->nick);
- }
- return MOD_CONT;
- }
- public:
- CommandNSLdapUid() : Command("ldap", 1, 2)
- {
- }
- CommandReturn Execute(User *u, std::vector<std::string> ¶ms)
- {
- const char *cmd = params[0].c_str();
- if (!strcasecmp(cmd, "SET"))
- return this->DoSet(u, params);
- else if (!strcasecmp(cmd, "DEL"))
- return this->DoDel(u, params);
- else if (!strcasecmp(cmd, "VIEW"))
- return this->DoView(u,params);
- else
- this->OnSyntaxError(u);
- return MOD_CONT;
- }
- bool OnHelp(User *u, const std::string &subcommand)
- {
- OnSyntaxError(u);
- u->SendMessage(Config.s_NickServ, "Sets the uid for the ldap account when");
- u->SendMessage(Config.s_NickServ, "using the lid command.");
- u->SendMessage(Config.s_NickServ, "LDAP SET uid - Sets the user id");
- u->SendMessage(Config.s_NickServ, "LDAP DEL - Clears any uid currently set");
- u->SendMessage(Config.s_NickServ, "LDAP VIEW - View the current UID");
- return true;
- }
- void OnSyntaxError(User *u)
- {
- u->SendMessage(Config.s_NickServ, "Syntax: LDAP [SET|DEL|VIEW] <ldap_uid>");
- }
- };
- class CommandNSLdapId : public Command
- {
- private:
- CommandReturn DoId(User *u, std::vector<std::string> ¶ms)
- {
- return MOD_CONT;
- }
- public:
- CommandNSLdapId(const std::string &cname) : Command(cname, 1, 1)
- {
- this->SetFlag(CFLAG_ALLOW_UNREGISTERED);
- }
- void NickNotRegistered(User *u, std::vector<std::string> ¶ms)
- {
- NickRequest *nr = NULL;
- if ((nr = findrequestnick(u->nick)))
- notice_lang(Config.s_NickServ, u, NICK_IS_PREREG);
- else
- {
- if (LdapSingleton::instance()->validatePassword(u->nick,params[0]) == 1)
- {
- Command *c = findCommand(NICKSERV,"register");
- Alog() << "ns_ldap: Successfully identified" << u->nick << "using ldap";
- if (c)
- {
- std::vector<std::string> param2;
- param2.push_back(params[0]);
- param2.push_back(LdapSingleton::instance()->getLastEmail());
- int retVal = c->Execute(u, param2);
- if (retVal == MOD_CONT)
- {
- Command *current = c->next;
- while (current && retVal == MOD_CONT)
- {
- retVal = current->Execute(u, param2);
- current = current->next;
- }
- }
- char *uid = sstrdup(u->nick);
- NickAlias *na;
- if( (na = findnick(u->nick)) ) {
- na->nc->Extend("ns_ldap_uid", new ExtensibleItemPointerArray<char>(uid));
- OnSuccessfullID(na);
- }
- }
- else
- {
- Alog() << "ns_ldap: oh-ho unable to find 'register' in the nickserv command table! is it loaded?";
- }
- } else {
- notice_lang(Config.s_NickServ, u, NICK_NOT_REGISTERED);
- }
- }
- }
- CommandReturn Execute(User *u, std::vector<std::string> ¶ms)
- {
- allow_ignore = 0;
- char *username = NULL;
- std::string password;
- NickAlias *na = NULL;
- password = params[0];
- if ((na = findnick(u->nick)))
- {
- if (u->IsIdentified())
- {
- notice_lang(Config.s_NickServ, u, NICK_ALREADY_IDENTIFIED);
- }
- else
- {
- if (na->nc->GetExtArray("ns_ldap_uid", username))
- {
- if (LdapSingleton::instance()->validatePassword(username,password) == 1)
- {
- Alog() << "ns_ldap: Successfully identified " << username << " using ldap";
- std::vector<std::string> param2;
- std::string pass = na->nc->pass;
- param2.push_back(pass);
- int retVal = MOD_CONT;
- Command *current = this->next;
- while (current && retVal == MOD_CONT)
- {
- retVal = current->Execute(u, param2);
- current = current->next;
- }
- OnSuccessfullID(na);
- }
- else
- {
- notice_lang(Config.s_NickServ, u, NICK_IDENTIFY_FAILED);
- Alog() << "ns_ldap: Failed to identify " << username << " using ldap";
- }
- }
- else { /* Let normal services ID take this one... */
- int retVal = MOD_CONT;
- Command *current = this->next;
- while (current && retVal == MOD_CONT) {
- retVal = current->Execute(u, params);
- current = current->next;
- }
- }
- }
- }
- else
- {
- NickNotRegistered(u,params);
- }
- return MOD_STOP;
- }
- void OnSuccessfullID(NickAlias *na) {
- char *username = NULL;
- na->nc->GetExtArray("ns_ldap_uid", username);
- std::stringstream istream;
- std::list<std::string> group = LdapSingleton::instance()->getGroups(username);
- for(std::list<std::string>::iterator it = group.begin() ; it != group.end() ; ++it) {
- istream << "[" << (*it) << "]";
- }
- std::string group_list = istream.str().c_str();
- if(group_list != "") {
- na->nc->Extend("ns_ldap_groups", new ExtensibleItemPointerArray<char>(sstrdup(group_list.c_str())));
- }
- }
- bool OnHelp(User *u, const std::string &subcommand)
- {
- OnSyntaxError(u);
- u->SendMessage(Config.s_NickServ, "Identify to this nick using your LDAP account");
- u->SendMessage(Config.s_NickServ, "in order for this to work you must have");
- u->SendMessage(Config.s_NickServ, "previosuly setup your luid with the ldap command.");
- return true;
- }
- void OnSyntaxError(User *u)
- {
- u->SendMessage(Config.s_NickServ, "Syntax: LID ldap_password");
- }
- };
- class NSLdap : public Module
- {
- public:
- NSLdap(const std::string &modname, const std::string &creator) : Module(modname, creator)
- {
- int status;
- me = this;
- this->SetAuthor(AUTHOR);
- this->SetVersion(VERSION);
- this->SetType(SUPPORTED);
- mLoadConfig();
- mLoadData();
- status = this->AddCommand(NICKSERV, new CommandNSLdapUid());
- status = this->AddCommand(NICKSERV, new CommandNSLdapId("id"));
- status = this->AddCommand(NICKSERV, new CommandNSLdapId("identify"));
- ModuleManager::Attach(I_OnSaveDatabase, this);
- ModuleManager::Attach(I_OnReload, this);
- }
- ~NSLdap() {
- }
- void OnReload(bool starting)
- {
- Alog() << "ns_ldap: Reloading configuration directives...";
- int ret = mLoadConfig();
- if (ret)
- Alog() << "ns_ldap: ERROR: An error has occured while reloading the configuration file";
- }
- void OnSaveDatabase() {
- NickCore *nc = NULL;
- int i = 0;
- FILE *out;
- if (!(out = fopen(NSLdapDBName.c_str(), "w"))) {
- Alog() << "os_info: ERROR: can not open the database file!";
- ircdproto->SendGlobops(findbot(Config.s_OperServ), "ns_ldap: ERROR: can not open the database file (%s)!",NSLdapDBName.c_str());
- } else {
- for (i = 0; i < 1024; ++i) {
- for (nc = nclists[i]; nc; nc = nc->next) {
- char *c;
- if (nc->GetExtArray("ns_ldap_uid", c))
- fprintf(out, "%s %s\n", nc->display, c);
- }
- }
- fclose(out);
- }
- }
- };
- /**
- * Stolen from os_info, should really make this better.
- **/
- int mLoadData() {
- int ret = 0;
- FILE *in;
- NickAlias *na = NULL;
- char *nick = NULL;
- char *uid = NULL;
- char buffer[2000];
- if (!(in = fopen(NSLdapDBName.c_str(), "r"))) {
- ret = 1;
- } else {
- while (fgets(buffer, 1500, in)) {
- if( (nick = myStrGetToken(buffer, ' ', 0)) ) {
- if( (uid = myStrGetToken(buffer, ' ', 1)) ) {
- int len = strlen(uid);
- uid[len - 1] = '\0';
- if ((na = findnick(nick))) {
- Alog() << "Added Nick [" << nick << "] Uid [" << uid << "]";
- na->nc->Extend("ns_ldap_uid", new ExtensibleItemPointerArray<char>(strdup(uid)));
- }
- delete [] uid;
- }
- delete [] nick;
- }
- }
- fclose(in);
- }
- return ret;
- }
- int mLoadConfig()
- {
- ConfigReader config;
- NSLdapDBName = config.ReadValue("ns_ldap", "database", "ns_ldap.db", 0);
- Alog() << "ns_ldap: Directive NSLdapDBName loaded (" << NSLdapDBName.c_str() << ")...";
- return 0;
- }
- MODULE_INIT(NSLdap)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement