diff options
author | Adam <Adam@anope.org> | 2011-04-03 18:07:58 -0400 |
---|---|---|
committer | Adam <Adam@anope.org> | 2011-04-03 18:07:58 -0400 |
commit | 905207093b89a3c71ee3732d051555870c4d39f5 (patch) | |
tree | f940bf01272cae4a118a30e0701200e0f55a68fd | |
parent | d1328d876a988329b3bdeb94999cfd696e6aa7a5 (diff) |
Made LDAP support recover, release, resetpass, etc.
-rw-r--r-- | data/example.conf | 77 | ||||
-rw-r--r-- | include/extern.h | 1 | ||||
-rw-r--r-- | include/modules.h | 15 | ||||
-rw-r--r-- | modules/core/enc_md5.cpp | 28 | ||||
-rw-r--r-- | modules/core/enc_none.cpp | 28 | ||||
-rw-r--r-- | modules/core/enc_old.cpp | 28 | ||||
-rw-r--r-- | modules/core/enc_sha1.cpp | 29 | ||||
-rw-r--r-- | modules/core/enc_sha256.cpp | 31 | ||||
-rw-r--r-- | modules/core/ns_ghost.cpp | 56 | ||||
-rw-r--r-- | modules/core/ns_group.cpp | 23 | ||||
-rw-r--r-- | modules/core/ns_identify.cpp | 24 | ||||
-rw-r--r-- | modules/core/ns_recover.cpp | 18 | ||||
-rw-r--r-- | modules/core/ns_release.cpp | 17 | ||||
-rw-r--r-- | modules/extra/m_ldap_authentication.cpp (renamed from modules/extra/ns_identify_ldap.cpp) | 154 | ||||
-rw-r--r-- | modules/extra/m_xmlrpc_main.cpp | 15 | ||||
-rw-r--r-- | src/encrypt.cpp | 23 |
16 files changed, 319 insertions, 248 deletions
diff --git a/data/example.conf b/data/example.conf index a677e3067..f05969403 100644 --- a/data/example.conf +++ b/data/example.conf @@ -2024,7 +2024,7 @@ m_helpchan /* * m_ldap * - * This module allows other modules to use LDAP. + * This module allows other modules to use LDAP. By itself, this module does nothing useful. */ #module { name = "m_ldap" } ldap @@ -2034,10 +2034,47 @@ ldap } /* + * m_ldap_authentication + * + * This module allows many commands such as IDENTIFY, RELEASE, RECOVER, GHOST, etc. use + * LDAP to authenticate users. Requires m_ldap. +*/ +#module { name = "m_ldap_authentication" } +m_ldap_authentication +{ + /* + * The distinguished name we should bind to when a user tries to identify. + */ + binddn = "ou=users,dc=anope,dc=org" + + /* + * The attribute value used for account names. + */ + username_attribute = "uid" + + /* + * The attribute value used for email addresses. + * This directive is optional. + */ + email_attribute = "email" + + /* + * Enable to have this module disable /nickserv register. + */ + disable_ns_register = true + + /* + * The reason to give the users who try to /ns register. + */ + disable_reason = "Registration has been disabled." + #disable_reason = "To register on this network visit http://some.misconfigured.site/register" +} + +/* * m_ldap_oper * * This module dynamically ties users to Anope opertypes when they identify - * via LDAP group membership. + * via LDAP group membership. Requires m_ldap. * * Note that this doesn't give the user privileges on the IRCd, only in Services. */ @@ -2129,42 +2166,6 @@ m_xmlrpc #module { name = "m_xmlrpc_main" } /* - * ns_identify_ldap - * - * Allows you to use a LDAP server for authentication of users. - */ -#module { name = "ns_identify_ldap" } -ns_identify_ldap -{ - /* - * The distinguished name we should bind to when a user tries to identify. - */ - binddn = "ou=users,dc=anope,dc=org" - - /* - * The attribute value used for account names. - */ - username_attribute = "uid" - - /* - * The attribute value used for email addresses. - * This directive is optional. - */ - email_attribute = "email" - - /* - * Enable to have this module disable /nickserv register. - */ - disable_ns_register = true - - /* - * The reason to give the users who try to /ns register. - */ - disable_reason = "Registration has been disabled." - #disable_reason = "To register on this network visit http://some.misconfigured.site/register" -} - -/* * ns_maxemail * * Limits how many times the same email address may be used in Anope diff --git a/include/extern.h b/include/extern.h index 8c351eecf..0b29c0d03 100644 --- a/include/extern.h +++ b/include/extern.h @@ -118,7 +118,6 @@ E void HostServSyncVhosts(NickAlias *na); /**** encrypt.c ****/ E int enc_encrypt(const Anope::string &src, Anope::string &dest); E int enc_decrypt(const Anope::string &src, Anope::string &dest); -E int enc_check_password(Anope::string &plaintext, Anope::string &password); /**** hostserv.c ****/ E void get_hostserv_stats(long *nrec, long *memuse); diff --git a/include/modules.h b/include/modules.h index 0918a67f8..51a550316 100644 --- a/include/modules.h +++ b/include/modules.h @@ -404,7 +404,6 @@ class CoreExport Module : public Extensible */ virtual EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) { return EVENT_CONTINUE; } virtual EventReturn OnDecrypt(const Anope::string &hashm, const Anope::string &src, Anope::string &dest) { return EVENT_CONTINUE; } - virtual EventReturn OnCheckPassword(const Anope::string &hashm, Anope::string &plaintext, Anope::string &password) { return EVENT_CONTINUE; } /** Called on fantasy command * @param command The command @@ -923,6 +922,16 @@ class CoreExport Module : public Extensible */ virtual void OnFindCore(const Anope::string &nick) { } + /** Check whether a users password is correct. + * @param u The user + * @param command The command the user is doing + * @param params Command params + * @param account The account the password should be checked against + * @param password The password + * @return EVENT_ALLOW to allow the password, EVENT_STOP to stop processing completely + */ + virtual EventReturn OnCheckAuthentication(User *u, Command *c, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) { return EVENT_CONTINUE; } + /** Called when we get informed about a users SSL fingerprint * when we call this, the fingerprint should already be stored in the user struct * @param u pointer to the user @@ -1077,7 +1086,7 @@ enum Implementation I_OnDelNick, I_OnDelCore, I_OnChangeCoreDisplay, I_OnNickClearAccess, I_OnNickAddAccess, I_OnNickEraseAccess, I_OnNickClearCert, I_OnNickAddCert, I_OnNickEraseCert, - I_OnNickInfo, I_OnFindNick, I_OnFindCore, + I_OnNickInfo, I_OnFindNick, I_OnFindCore, I_OnCheckAuthentication, /* ChanServ */ I_OnChanForbidden, I_OnChanSuspend, I_OnChanDrop, I_OnPreChanExpire, I_OnChanExpire, I_OnAccessAdd, I_OnAccessChange, @@ -1115,7 +1124,7 @@ enum Implementation I_OnReload, I_OnPreServerConnect, I_OnNewServer, I_OnServerConnect, I_OnPreUplinkSync, I_OnServerDisconnect, I_OnPreCommandRun, I_OnPreCommand, I_OnPostCommand, I_OnPreDatabaseExpire, I_OnPreRestart, I_OnRestart, I_OnPreShutdown, I_OnShutdown, I_OnSignal, I_OnServerQuit, I_OnTopicUpdated, - I_OnEncrypt, I_OnEncryptCheckLen, I_OnDecrypt, I_OnCheckPassword, + I_OnEncrypt, I_OnDecrypt, I_OnChannelModeSet, I_OnChannelModeUnset, I_OnUserModeSet, I_OnUserModeUnset, I_OnChannelModeAdd, I_OnUserModeAdd, I_OnMLock, I_OnUnMLock, I_OnServerSync, I_OnUplinkSync, I_OnBotPrivmsg, I_OnPrivmsg, I_OnObjectDestroy, I_END diff --git a/modules/core/enc_md5.cpp b/modules/core/enc_md5.cpp index a57ed86ad..0cf38e4fb 100644 --- a/modules/core/enc_md5.cpp +++ b/modules/core/enc_md5.cpp @@ -320,9 +320,8 @@ class EMD5 : public Module this->SetAuthor("Anope"); this->SetType(ENCRYPTION); - ModuleManager::Attach(I_OnEncrypt, this); - ModuleManager::Attach(I_OnDecrypt, this); - ModuleManager::Attach(I_OnCheckPassword, this); + Implementation i[] = { I_OnEncrypt, I_OnDecrypt, I_OnCheckAuthentication }; + ModuleManager::Attach(i, this, 3); } EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) @@ -348,22 +347,33 @@ class EMD5 : public Module return EVENT_STOP; } - EventReturn OnCheckPassword(const Anope::string &hashm, Anope::string &plaintext, Anope::string &password) + EventReturn OnCheckAuthentication(User *u, Command *c, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) { - if (!hashm.equals_cs("md5")) + NickAlias *na = findnick(account); + NickCore *nc = na ? na->nc : NULL; + if (na == NULL) + return EVENT_CONTINUE; + + size_t pos = nc->pass.find(':'); + if (pos == Anope::string::npos) + return EVENT_CONTINUE; + Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos); + if (!hash_method.equals_cs("md5")) return EVENT_CONTINUE; + Anope::string buf; - this->OnEncrypt(plaintext, buf); - if (password.equals_cs(buf)) + this->OnEncrypt(password, buf); + if (nc->pass.equals_cs(buf)) { /* if we are NOT the first module in the list, * we want to re-encrypt the pass with the new encryption */ if (!this->name.equals_ci(Config->EncModuleList.front())) - enc_encrypt(plaintext, password); + enc_encrypt(password, nc->pass); return EVENT_ALLOW; } - return EVENT_STOP; + + return EVENT_CONTINUE; } }; diff --git a/modules/core/enc_none.cpp b/modules/core/enc_none.cpp index 79c047c3f..c1b403235 100644 --- a/modules/core/enc_none.cpp +++ b/modules/core/enc_none.cpp @@ -17,9 +17,8 @@ class ENone : public Module this->SetAuthor("Anope"); this->SetType(ENCRYPTION); - ModuleManager::Attach(I_OnEncrypt, this); - ModuleManager::Attach(I_OnDecrypt, this); - ModuleManager::Attach(I_OnCheckPassword, this); + Implementation i[] = { I_OnEncrypt, I_OnDecrypt, I_OnCheckAuthentication }; + ModuleManager::Attach(i, this, 3); } EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) @@ -43,22 +42,33 @@ class ENone : public Module return EVENT_ALLOW; } - EventReturn OnCheckPassword(const Anope::string &hashm, Anope::string &plaintext, Anope::string &password) + EventReturn OnCheckAuthentication(User *u, Command *c, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) { - if (!hashm.equals_cs("plain")) + NickAlias *na = findnick(account); + NickCore *nc = na ? na->nc : NULL; + if (na == NULL) + return EVENT_CONTINUE; + + size_t pos = nc->pass.find(':'); + if (pos == Anope::string::npos) return EVENT_CONTINUE; + Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos); + if (!hash_method.equals_cs("plain")) + return EVENT_CONTINUE; + Anope::string buf; - this->OnEncrypt(plaintext, buf); - if (password.equals_cs(buf)) + this->OnEncrypt(password, buf); + if (nc->pass.equals_cs(buf)) { /* if we are NOT the first module in the list, * we want to re-encrypt the pass with the new encryption */ if (!this->name.equals_ci(Config->EncModuleList.front())) - enc_encrypt(plaintext, password); + enc_encrypt(password, nc->pass); return EVENT_ALLOW; } - return EVENT_STOP; + + return EVENT_CONTINUE; } }; diff --git a/modules/core/enc_old.cpp b/modules/core/enc_old.cpp index 52ba4734c..5fb863110 100644 --- a/modules/core/enc_old.cpp +++ b/modules/core/enc_old.cpp @@ -325,9 +325,8 @@ class EOld : public Module this->SetAuthor("Anope"); this->SetType(ENCRYPTION); - ModuleManager::Attach(I_OnEncrypt, this); - ModuleManager::Attach(I_OnDecrypt, this); - ModuleManager::Attach(I_OnCheckPassword, this); + Implementation i[] = { I_OnEncrypt, I_OnDecrypt, I_OnCheckAuthentication }; + ModuleManager::Attach(i, this, 3); } EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) @@ -358,22 +357,33 @@ class EOld : public Module return EVENT_STOP; } - EventReturn OnCheckPassword(const Anope::string &hashm, Anope::string &plaintext, Anope::string &password) + EventReturn OnCheckAuthentication(User *u, Command *c, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) { - if (!hashm.equals_cs("oldmd5")) + NickAlias *na = findnick(account); + NickCore *nc = na ? na->nc : NULL; + if (na == NULL) + return EVENT_CONTINUE; + + size_t pos = nc->pass.find(':'); + if (pos == Anope::string::npos) + return EVENT_CONTINUE; + Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos); + if (!hash_method.equals_cs("oldmd5")) return EVENT_CONTINUE; + Anope::string buf; - this->OnEncrypt(plaintext, buf); - if (password.equals_cs(buf)) + this->OnEncrypt(password, buf); + if (nc->pass.equals_cs(buf)) { /* if we are NOT the first module in the list, * we want to re-encrypt the pass with the new encryption */ if (!this->name.equals_ci(Config->EncModuleList.front())) - enc_encrypt(plaintext, password); + enc_encrypt(password, nc->pass); return EVENT_ALLOW; } - return EVENT_STOP; + + return EVENT_CONTINUE; } }; diff --git a/modules/core/enc_sha1.cpp b/modules/core/enc_sha1.cpp index 8dc3b57ab..8ec387d0d 100644 --- a/modules/core/enc_sha1.cpp +++ b/modules/core/enc_sha1.cpp @@ -173,10 +173,8 @@ class ESHA1 : public Module this->SetAuthor("Anope"); this->SetType(ENCRYPTION); - ModuleManager::Attach(I_OnEncrypt, this); - ModuleManager::Attach(I_OnEncryptCheckLen, this); - ModuleManager::Attach(I_OnDecrypt, this); - ModuleManager::Attach(I_OnCheckPassword, this); + Implementation i[] = { I_OnEncrypt, I_OnDecrypt, I_OnCheckAuthentication }; + ModuleManager::Attach(i, this, 3); } EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) @@ -202,22 +200,33 @@ class ESHA1 : public Module return EVENT_STOP; } - EventReturn OnCheckPassword(const Anope::string &hashm, Anope::string &plaintext, Anope::string &password) + EventReturn OnCheckAuthentication(User *u, Command *c, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) { - if (!hashm.equals_cs("sha1")) + NickAlias *na = findnick(account); + NickCore *nc = na ? na->nc : NULL; + if (na == NULL) + return EVENT_CONTINUE; + + size_t pos = nc->pass.find(':'); + if (pos == Anope::string::npos) + return EVENT_CONTINUE; + Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos); + if (!hash_method.equals_cs("sha1")) return EVENT_CONTINUE; + Anope::string buf; - this->OnEncrypt(plaintext, buf); - if (password.equals_cs(buf)) + this->OnEncrypt(password, buf); + if (nc->pass.equals_cs(buf)) { /* when we are NOT the first module in the list, * we want to re-encrypt the pass with the new encryption */ if (!this->name.equals_ci(Config->EncModuleList.front())) - enc_encrypt(plaintext, password); + enc_encrypt(password, nc->pass); return EVENT_ALLOW; } - return EVENT_STOP; + + return EVENT_CONTINUE; } }; diff --git a/modules/core/enc_sha256.cpp b/modules/core/enc_sha256.cpp index 45fc3433c..06154ada0 100644 --- a/modules/core/enc_sha256.cpp +++ b/modules/core/enc_sha256.cpp @@ -252,9 +252,8 @@ class ESHA256 : public Module this->SetAuthor("Anope"); this->SetType(ENCRYPTION); - ModuleManager::Attach(I_OnEncrypt, this); - ModuleManager::Attach(I_OnDecrypt, this); - ModuleManager::Attach(I_OnCheckPassword, this); + Implementation i[] = { I_OnEncrypt, I_OnDecrypt, I_OnCheckAuthentication }; + ModuleManager::Attach(i, this, 3); use_iv = false; } @@ -287,26 +286,36 @@ class ESHA256 : public Module return EVENT_STOP; } - EventReturn OnCheckPassword(const Anope::string &hashm, Anope::string &plaintext, Anope::string &password) + EventReturn OnCheckAuthentication(User *u, Command *c, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) { - if (!hashm.equals_cs("sha256")) + NickAlias *na = findnick(account); + NickCore *nc = na ? na->nc : NULL; + if (na == NULL) + return EVENT_CONTINUE; + + size_t pos = nc->pass.find(':'); + if (pos == Anope::string::npos) + return EVENT_CONTINUE; + Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos); + if (!hash_method.equals_cs("sha256")) return EVENT_CONTINUE; - Anope::string buf; - GetIVFromPass(password); + GetIVFromPass(nc->pass); use_iv = true; - this->OnEncrypt(plaintext, buf); + Anope::string buf; + this->OnEncrypt(password, buf); - if (password.equals_cs(buf)) + if (nc->pass.equals_cs(buf)) { /* if we are NOT the first module in the list, * we want to re-encrypt the pass with the new encryption */ if (!this->name.equals_ci(Config->EncModuleList.front())) - enc_encrypt(plaintext, password); + enc_encrypt(password, nc->pass); return EVENT_ALLOW; } - return EVENT_STOP; + + return EVENT_CONTINUE; } }; diff --git a/modules/core/ns_ghost.cpp b/modules/core/ns_ghost.cpp index dbc11e5f6..d8e0faf64 100644 --- a/modules/core/ns_ghost.cpp +++ b/modules/core/ns_ghost.cpp @@ -25,7 +25,7 @@ class CommandNSGhost : public Command CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &nick = params[0]; - Anope::string pass = params.size() > 1 ? params[1] : ""; + const Anope::string &pass = params.size() > 1 ? params[1] : ""; User *u = source.u; User *user = finduser(nick); @@ -41,28 +41,46 @@ class CommandNSGhost : public Command source.Reply(_(NICK_X_SUSPENDED), na->nick.c_str()); else if (nick.equals_ci(u->nick)) source.Reply(_("You can't ghost yourself!")); - else if ((u->Account() == na->nc || (!na->nc->HasFlag(NI_SECURE) && is_on_access(u, na->nc))) || - (!pass.empty() && enc_check_password(pass, na->nc->pass) == 1) || - (!u->fingerprint.empty() && na->nc->FindCert(u->fingerprint))) + else { - if (!user->IsIdentified() && FindCommand(NickServ, "RECOVER")) - source.Reply(_("You may not ghost an unidentified user, use RECOVER instead.")); - else + bool ok = false; + if (u->Account() == na->nc) + ok = true; + else if (!na->nc->HasFlag(NI_SECURE) && is_on_access(u, na->nc)) + ok = true; + else if (!u->fingerprint.empty() && na->nc->FindCert(u->fingerprint)) + ok = true; + else if (!pass.empty()) { - Log(LOG_COMMAND, u, this) << "for " << nick; - Anope::string buf = "GHOST command used by " + u->nick; - kill_user(Config->s_NickServ, user, buf); - source.Reply(_("Ghost with your nick has been killed."), nick.c_str()); + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(u, this, params, na->nc->display, pass)); + if (MOD_RESULT == EVENT_STOP) + return MOD_CONT; + else if (MOD_RESULT == EVENT_ALLOW) + ok = true; } - } - else - { - source.Reply(_(ACCESS_DENIED)); - if (!pass.empty()) + + if (ok) + { + if (!user->IsIdentified() && FindCommand(NickServ, "RECOVER")) + source.Reply(_("You may not ghost an unidentified user, use RECOVER instead.")); + else + { + Log(LOG_COMMAND, u, this) << "for " << nick; + Anope::string buf = "GHOST command used by " + u->nick; + kill_user(Config->s_NickServ, user, buf); + source.Reply(_("Ghost with your nick has been killed."), nick.c_str()); + } + } + else { - Log(LOG_COMMAND, u, this) << "with an invalid password for " << nick; - if (bad_password(u)) - return MOD_STOP; + source.Reply(_(ACCESS_DENIED)); + if (!pass.empty()) + { + Log(LOG_COMMAND, u, this) << "with an invalid password for " << nick; + if (bad_password(u)) + return MOD_STOP; + } } } diff --git a/modules/core/ns_group.cpp b/modules/core/ns_group.cpp index 4b0fda4c4..463d36be6 100644 --- a/modules/core/ns_group.cpp +++ b/modules/core/ns_group.cpp @@ -27,7 +27,7 @@ class CommandNSGroup : public Command User *u = source.u; const Anope::string &nick = params[0]; - Anope::string pass = params.size() > 1 ? params[1] : ""; + const Anope::string &pass = params.size() > 1 ? params[1] : ""; if (readonly) { @@ -82,8 +82,19 @@ class CommandNSGroup : public Command "for more information."), target->nick.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); else { - if ((!pass.empty() && enc_check_password(pass, target->nc->pass)) || - (!u->fingerprint.empty() && target->nc->FindCert(u->fingerprint))) + bool ok = false; + if (!u->fingerprint.empty() && target->nc->FindCert(u->fingerprint)) + ok = true; + else if (!pass.empty()) + { + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(u, this, params, target->nc->display, pass)); + if (MOD_RESULT == EVENT_STOP) + return MOD_CONT; + else if (MOD_RESULT == EVENT_ALLOW) + ok = true; + } + if (ok) { /* If the nick is already registered, drop it. * If not, check that it is valid. @@ -122,13 +133,9 @@ class CommandNSGroup : public Command check_memos(u); } - else if (pass.empty()) - { - this->OnSyntaxError(source, ""); - } else { - Log(LOG_COMMAND, u, this) << "failed group for " << target->nick << " (invalid password)"; + Log(LOG_COMMAND, u, this) << "failed group for " << target->nick; source.Reply(_(PASSWORD_INCORRECT)); if (bad_password(u)) return MOD_STOP; diff --git a/modules/core/ns_identify.cpp b/modules/core/ns_identify.cpp index 742fe986a..15f2ade94 100644 --- a/modules/core/ns_identify.cpp +++ b/modules/core/ns_identify.cpp @@ -30,30 +30,28 @@ class CommandNSIdentify : public Command Anope::string pass = params[params.size() - 1]; NickAlias *na = findnick(nick); - if (!na) - source.Reply(_(NICK_NOT_REGISTERED)); - else if (na->HasFlag(NS_FORBIDDEN)) + if (na && na->HasFlag(NS_FORBIDDEN)) source.Reply(_(NICK_X_FORBIDDEN), na->nick.c_str()); - else if (na->nc->HasFlag(NI_SUSPENDED)) + else if (na && na->nc->HasFlag(NI_SUSPENDED)) source.Reply(_(NICK_X_SUSPENDED), na->nick.c_str()); - /* You can now identify for other nicks without logging out first, - * however you can not identify again for the group you're already - * identified as - */ - else if (u->Account() && u->Account() == na->nc) + else if (u->Account() && na && u->Account() == na->nc) source.Reply(_("You are already identified.")); else { - int res = enc_check_password(pass, na->nc->pass); - if (!res) + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(u, this, params, nick, pass)); + if (MOD_RESULT == EVENT_STOP) + return MOD_CONT; + + if (!na) + source.Reply(_(NICK_X_NOT_REGISTERED), nick.c_str()); + else if (MOD_RESULT != EVENT_ALLOW) { Log(LOG_COMMAND, u, this) << "and failed to identify"; source.Reply(_(PASSWORD_INCORRECT)); if (bad_password(u)) return MOD_STOP; } - else if (res == -1) - source.Reply(_("Sorry, identification failed.")); else { if (u->IsIdentified()) diff --git a/modules/core/ns_recover.cpp b/modules/core/ns_recover.cpp index 416b0e184..d78955f51 100644 --- a/modules/core/ns_recover.cpp +++ b/modules/core/ns_recover.cpp @@ -27,7 +27,7 @@ class CommandNSRecover : public Command User *u = source.u; const Anope::string &nick = params[0]; - Anope::string pass = params.size() > 1 ? params[1] : ""; + const Anope::string &pass = params.size() > 1 ? params[1] : ""; NickAlias *na; User *u2; @@ -43,9 +43,12 @@ class CommandNSRecover : public Command source.Reply(_("You can't recover yourself!")); else if (!pass.empty()) { - int res = enc_check_password(pass, na->nc->pass); + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(u, this, params, na->nc->display, pass)); + if (MOD_RESULT == EVENT_STOP) + return MOD_CONT; - if (res == 1) + if (MOD_RESULT == EVENT_ALLOW) { u2->SendMessage(NickServ, _(FORCENICKCHANGE_NOW)); u2->Collide(na); @@ -58,12 +61,9 @@ class CommandNSRecover : public Command else { source.Reply(_(ACCESS_DENIED)); - if (!res) - { - Log(LOG_COMMAND, u, this) << "with invalid password for " << nick; - if (bad_password(u)) - return MOD_STOP; - } + Log(LOG_COMMAND, u, this) << "with invalid password for " << nick; + if (bad_password(u)) + return MOD_STOP; } } else diff --git a/modules/core/ns_release.cpp b/modules/core/ns_release.cpp index 94a778218..94126eef8 100644 --- a/modules/core/ns_release.cpp +++ b/modules/core/ns_release.cpp @@ -39,8 +39,12 @@ class CommandNSRelease : public Command source.Reply(_("Nick \002%s\002 isn't being held."), nick.c_str()); else if (!pass.empty()) { - int res = enc_check_password(pass, na->nc->pass); - if (res == 1) + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(u, this, params, na->nc->display, pass)); + if (MOD_RESULT == EVENT_STOP) + return MOD_CONT; + + if (MOD_RESULT == EVENT_ALLOW) { Log(LOG_COMMAND, u, this) << "released " << na->nick; na->Release(); @@ -49,12 +53,9 @@ class CommandNSRelease : public Command else { source.Reply(_(ACCESS_DENIED)); - if (!res) - { - Log(LOG_COMMAND, u, this) << "invalid password for " << nick; - if (bad_password(u)) - return MOD_STOP; - } + Log(LOG_COMMAND, u, this) << "invalid password for " << nick; + if (bad_password(u)) + return MOD_STOP; } } else diff --git a/modules/extra/ns_identify_ldap.cpp b/modules/extra/m_ldap_authentication.cpp index 8a65c5438..fa60247e5 100644 --- a/modules/extra/ns_identify_ldap.cpp +++ b/modules/extra/m_ldap_authentication.cpp @@ -6,24 +6,21 @@ static Anope::string email_attribute; struct IdentifyInfo { dynamic_reference<User> user; + dynamic_reference<Command> command; + std::vector<Anope::string> params; Anope::string account; Anope::string pass; - IdentifyInfo(User *u, const Anope::string &a, const Anope::string &p) : user(u), account(a), pass(p) { } + IdentifyInfo(User *u, Command *c, const std::vector<Anope::string> &pa, const Anope::string &a, const Anope::string &p) : user(u), command(c), params(pa), account(a), pass(p) { } }; -class IdentifyInterface : public LDAPInterface, public Command +class IdentifyInterface : public LDAPInterface { std::map<LDAPQuery, IdentifyInfo *> requests; public: - IdentifyInterface(Module *m) : LDAPInterface(m), Command("IDENTIFY", 0, 0) - { - this->service = NickServ; - } - - CommandReturn Execute(CommandSource &, const std::vector<Anope::string> &) { return MOD_STOP; } + IdentifyInterface(Module *m) : LDAPInterface(m) { } void Add(LDAPQuery id, IdentifyInfo *ii) { @@ -41,28 +38,34 @@ class IdentifyInterface : public LDAPInterface, public Command IdentifyInfo *ii = it->second; this->requests.erase(it); + if (!ii->user || !ii->command) + { + delete this; + return; + } + User *u = *ii->user; - NickAlias *na = findnick(ii->account); + Command *c = *ii->command; + + u->Extend("m_ldap_authentication_authenticated"); - if (!na) + NickAlias *na = findnick(ii->account); + if (na == NULL) { na = new NickAlias(ii->account, new NickCore(ii->account)); - enc_encrypt(ii->pass, na->nc->pass); - - Anope::string last_usermask = u->GetIdent() + "@" + u->GetDisplayedHost(); - na->last_usermask = last_usermask; - na->last_realname = u->realname; if (Config->NSAddAccessOnReg) na->nc->AddAccess(create_mask(u)); - u->SendMessage(NickServ, _("Your account \002%s\002 has been successfully created."), ii->account.c_str()); + u->SendMessage(NickServ, _("Your account \002%s\002 has been successfully created."), na->nick.c_str()); } - if (u->Account()) - Log(LOG_COMMAND, u, this) << "to log out of account " << u->Account()->display; - Log(LOG_COMMAND, u, this) << "and identified for account " << na->nc->display << " using LDAP"; - u->SendMessage(NickServ, _("Password accepted - you are now recognized.")); - u->Identify(na); + enc_encrypt(ii->pass, na->nc->pass); + + Anope::string params; + for (unsigned i = 0; i < ii->params.size(); ++i) + params += ii->params[i] + " "; + mod_run_cmd(c->service, u, NULL, c, c->name, params); + delete ii; } @@ -74,17 +77,22 @@ class IdentifyInterface : public LDAPInterface, public Command IdentifyInfo *ii = it->second; this->requests.erase(it); - if (!ii->user) + if (!ii->user || !ii->command) { - delete this; + delete ii; return; } User *u = *ii->user; + Command *c = *ii->command; + + u->Extend("m_ldap_authentication_error"); + + Anope::string params; + for (unsigned i = 0; i < ii->params.size(); ++i) + params += ii->params[i] + " "; + mod_run_cmd(c->service, u, NULL, c, c->name, params); - Log(LOG_COMMAND, u, this) << "and failed to identify for account " << ii->account << ". LDAP error: " << r.getError(); - u->SendMessage(NickServ, _(PASSWORD_INCORRECT)); - bad_password(u); delete ii; } }; @@ -121,19 +129,19 @@ class OnIdentifyInterface : public LDAPInterface { u->Account()->email = email; u->SendMessage(NickServ, _("Your email has been updated to \002%s\002"), email.c_str()); - Log() << "ns_identify_ldap: Updated email address for " << u->nick << " (" << u->Account()->display << ") to " << email; + Log() << "m_ldap_authentication: Updated email address for " << u->nick << " (" << u->Account()->display << ") to " << email; } } catch (const LDAPException &ex) { - Log() << "ns_identify_ldap: " << ex.GetReason(); + Log() << "m_ldap_authentication: " << ex.GetReason(); } } void OnError(const LDAPResult &r) { this->requests.erase(r.id); - Log() << "ns_identify_ldap: " << r.error; + Log() << "m_ldap_authentication: " << r.error; } }; @@ -154,8 +162,9 @@ class NSIdentifyLDAP : public Module this->SetAuthor("Anope"); this->SetType(SUPPORTED); - Implementation i[] = { I_OnReload, I_OnPreCommand, I_OnNickIdentify }; - ModuleManager::Attach(i, this, 3); + Implementation i[] = { I_OnReload, I_OnPreCommand, I_OnCheckAuthentication, I_OnNickIdentify }; + ModuleManager::Attach(i, this, 4); + ModuleManager::SetPriority(this, PRIORITY_FIRST); OnReload(false); } @@ -164,57 +173,56 @@ class NSIdentifyLDAP : public Module { ConfigReader config; - this->binddn = config.ReadValue("ns_identify_ldap", "binddn", "", 0); - this->username_attribute = config.ReadValue("ns_identify_ldap", "username_attribute", "", 0); - email_attribute = config.ReadValue("ns_identify_ldap", "email_attribute", "", 0); - this->disable_register = config.ReadFlag("ns_identify_ldap", "disable_ns_register", "false", 0); - this->disable_reason = config.ReadValue("ns_identify_ldap", "disable_reason", "", 0); + this->binddn = config.ReadValue("m_ldap_authentication", "binddn", "", 0); + this->username_attribute = config.ReadValue("m_ldap_authentication", "username_attribute", "", 0); + email_attribute = config.ReadValue("m_ldap_authentication", "email_attribute", "", 0); + this->disable_register = config.ReadFlag("m_ldap_authentication", "disable_ns_register", "false", 0); + this->disable_reason = config.ReadValue("m_ldap_authentication", "disable_reason", "", 0); } EventReturn OnPreCommand(CommandSource &source, Command *command, const std::vector<Anope::string> ¶ms) { - if (command->service == NickServ) + if (this->disable_register && command->service == NickServ && command->name == "REGISTER") { - if (this->disable_register && command->name == "REGISTER") - { - source.Reply(_(this->disable_reason.c_str())); - return EVENT_STOP; - } - else if (command->name == "IDENTIFY" && !params.empty() && this->ldap) - { - Anope::string account = params.size() > 1 ? params[0] : source.u->nick; - Anope::string pass = params.size() > 1 ? params[1] : params[0]; - - NickAlias *na = findnick(account); - if (na) - { - account = na->nc->display; - - if (na->HasFlag(NS_FORBIDDEN) || na->nc->HasFlag(NI_SUSPENDED) || source.u->Account() == na->nc) - return EVENT_CONTINUE; - } - - IdentifyInfo *ii = new IdentifyInfo(source.u, account, pass); - try - { - Anope::string full_binddn = this->username_attribute + "=" + account + "," + this->binddn; - LDAPQuery id = this->ldap->Bind(&this->iinterface, full_binddn, pass); - this->iinterface.Add(id, ii); - } - catch (const LDAPException &ex) - { - delete ii; - Log() << "ns_identify_ldap: " << ex.GetReason(); - return EVENT_CONTINUE; - } - - return EVENT_STOP; - } + source.Reply(_(this->disable_reason.c_str())); + return EVENT_STOP; } return EVENT_CONTINUE; } + EventReturn OnCheckAuthentication(User *u, Command *c, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) + { + if (u == NULL || c == NULL || !this->ldap) + return EVENT_CONTINUE; + else if (u->GetExt("m_ldap_authentication_authenticated")) + { + u->Shrink("m_ldap_authentication_authenticated"); + return EVENT_ALLOW; + } + else if (u->GetExt("m_ldap_authentication_error")) + { + u->Shrink("m_ldap_authentication_error"); + return EVENT_CONTINUE;; + } + + IdentifyInfo *ii = new IdentifyInfo(u, c, params, account, password); + try + { + Anope::string full_binddn = this->username_attribute + "=" + account + "," + this->binddn; + LDAPQuery id = this->ldap->Bind(&this->iinterface, full_binddn, password); + this->iinterface.Add(id, ii); + } + catch (const LDAPException &ex) + { + delete ii; + Log() << "ns_identify_ldap: " << ex.GetReason(); + return EVENT_CONTINUE; + } + + return EVENT_STOP; + } + void OnNickIdentify(User *u) { if (email_attribute.empty() || !this->ldap) @@ -227,7 +235,7 @@ class NSIdentifyLDAP : public Module } catch (const LDAPException &ex) { - Log() << "ns_identify_ldap: " << ex.GetReason(); + Log() << "m_ldap_authentication: " << ex.GetReason(); } } }; diff --git a/modules/extra/m_xmlrpc_main.cpp b/modules/extra/m_xmlrpc_main.cpp index 33cf3818c..593aba6ef 100644 --- a/modules/extra/m_xmlrpc_main.cpp +++ b/modules/extra/m_xmlrpc_main.cpp @@ -113,13 +113,18 @@ class MyXMLRPCEvent : public XMLRPCEvent if (!na) request->reply("error", "Invalid account"); - else if (enc_check_password(password, na->nc->pass) == 1) + else { - request->reply("result", "Success"); - request->reply("account", na->nc->display); + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(NULL, NULL, std::vector<Anope::string>(), na->nc->display, password)); + if (MOD_RESULT == EVENT_ALLOW) + { + request->reply("result", "Success"); + request->reply("account", na->nc->display); + } + else + request->reply("error", "Invalid password"); } - else - request->reply("error", "Invalid password"); } } diff --git a/src/encrypt.cpp b/src/encrypt.cpp index 8063a6567..2414bf7bc 100644 --- a/src/encrypt.cpp +++ b/src/encrypt.cpp @@ -50,26 +50,3 @@ int enc_decrypt(const Anope::string &src, Anope::string &dest) return -1; } -/** - * Check an input password `plaintext' against a stored, encrypted password - * `password'. Return value is: - * 1 if the password matches - * 0 if the password does not match - * 0 if an error occurred while checking - **/ -int enc_check_password(Anope::string &plaintext, Anope::string &password) -{ - size_t pos = password.find(':'); - if (pos == Anope::string::npos) - { - Log() << "Error: enc_check_password() called with invalid password string (" << password << ")"; - return 0; - } - Anope::string hashm(password.begin(), password.begin() + pos); - - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnCheckPassword, OnCheckPassword(hashm, plaintext, password)); - if (MOD_RESULT == EVENT_ALLOW) - return 1; - return 0; -} |