summaryrefslogtreecommitdiff
path: root/modules/sql_authentication.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/sql_authentication.cpp')
-rw-r--r--modules/sql_authentication.cpp159
1 files changed, 159 insertions, 0 deletions
diff --git a/modules/sql_authentication.cpp b/modules/sql_authentication.cpp
new file mode 100644
index 000000000..54307496c
--- /dev/null
+++ b/modules/sql_authentication.cpp
@@ -0,0 +1,159 @@
+/*
+ *
+ * (C) 2012-2024 Anope Team
+ * Contact us at team@anope.org
+ *
+ * Please read COPYING and README for further details.
+ */
+
+#include "module.h"
+#include "modules/sql.h"
+
+static Module *me;
+
+class SQLAuthenticationResult final
+ : public SQL::Interface
+{
+ Reference<User> user;
+ IdentifyRequest *req;
+
+public:
+ SQLAuthenticationResult(User *u, IdentifyRequest *r) : SQL::Interface(me), user(u), req(r)
+ {
+ req->Hold(me);
+ }
+
+ ~SQLAuthenticationResult()
+ {
+ req->Release(me);
+ }
+
+ void OnResult(const SQL::Result &r) override
+ {
+ if (r.Rows() == 0)
+ {
+ Log(LOG_DEBUG) << "sql_authentication: Unsuccessful authentication for " << req->GetAccount();
+ delete this;
+ return;
+ }
+
+ Log(LOG_DEBUG) << "sql_authentication: Successful authentication for " << req->GetAccount();
+
+ Anope::string email;
+ try
+ {
+ email = r.Get(0, "email");
+ }
+ catch (const SQL::Exception &) { }
+
+ NickAlias *na = NickAlias::Find(req->GetAccount());
+ BotInfo *NickServ = Config->GetClient("NickServ");
+ if (na == NULL)
+ {
+ na = new NickAlias(req->GetAccount(), new NickCore(req->GetAccount()));
+ FOREACH_MOD(OnNickRegister, (user, na, ""));
+ if (user && NickServ)
+ user->SendMessage(NickServ, _("Your account \002%s\002 has been successfully created."), na->nick.c_str());
+ }
+
+ if (!email.empty() && email != na->nc->email)
+ {
+ na->nc->email = email;
+ if (user && NickServ)
+ user->SendMessage(NickServ, _("Your email has been updated to \002%s\002."), email.c_str());
+ }
+
+ req->Success(me);
+ delete this;
+ }
+
+ void OnError(const SQL::Result &r) override
+ {
+ Log(this->owner) << "sql_authentication: Error executing query " << r.GetQuery().query << ": " << r.GetError();
+ delete this;
+ }
+};
+
+class ModuleSQLAuthentication final
+ : public Module
+{
+ Anope::string engine;
+ Anope::string query;
+ Anope::string disable_reason, disable_email_reason;
+
+ ServiceReference<SQL::Provider> SQL;
+
+public:
+ ModuleSQLAuthentication(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR)
+ {
+ me = this;
+
+ }
+
+ void OnReload(Configuration::Conf *conf) override
+ {
+ Configuration::Block *config = conf->GetModule(this);
+ this->engine = config->Get<const Anope::string>("engine");
+ this->query = config->Get<const Anope::string>("query");
+ this->disable_reason = config->Get<const Anope::string>("disable_reason");
+ this->disable_email_reason = config->Get<Anope::string>("disable_email_reason");
+
+ this->SQL = ServiceReference<SQL::Provider>("SQL::Provider", this->engine);
+ }
+
+ EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> &params) override
+ {
+ if (!this->disable_reason.empty() && (command->name == "nickserv/register" || command->name == "nickserv/group"))
+ {
+ source.Reply(this->disable_reason);
+ return EVENT_STOP;
+ }
+
+ if (!this->disable_email_reason.empty() && command->name == "nickserv/set/email")
+ {
+ source.Reply(this->disable_email_reason);
+ return EVENT_STOP;
+ }
+
+ return EVENT_CONTINUE;
+ }
+
+ void OnCheckAuthentication(User *u, IdentifyRequest *req) override
+ {
+ if (!this->SQL)
+ {
+ Log(this) << "Unable to find SQL engine";
+ return;
+ }
+
+ SQL::Query q(this->query);
+ q.SetValue("a", req->GetAccount());
+ q.SetValue("p", req->GetPassword());
+ if (u)
+ {
+ q.SetValue("n", u->nick);
+ q.SetValue("i", u->ip.addr());
+ }
+ else
+ {
+ q.SetValue("n", "");
+ q.SetValue("i", "");
+ }
+
+
+ this->SQL->Run(new SQLAuthenticationResult(u, req), q);
+
+ Log(LOG_DEBUG) << "sql_authentication: Checking authentication for " << req->GetAccount();
+ }
+
+ void OnPreNickExpire(NickAlias *na, bool &expire) override
+ {
+ // We can't let nicks expire if they still have a group or
+ // there will be a zombie account left over that can't be
+ // authenticated to.
+ if (na->nick == na->nc->display && na->nc->aliases->size() > 1)
+ expire = false;
+ }
+};
+
+MODULE_INIT(ModuleSQLAuthentication)