2 * InspIRCd -- Internet Relay Chat Daemon
4 * Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
6 * This file is part of InspIRCd. InspIRCd is free software: you can
7 * redistribute it and/or modify it under the terms of the GNU General Public
8 * License as published by the Free Software Foundation, version 2.
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "modules/sql.h"
22 #include "modules/hash.h"
23 #include "modules/ssl.h"
31 class AuthQuery : public SQL::Query
34 const std::string uid;
35 LocalIntExt& pendingExt;
37 AuthQuery(Module* me, const std::string& u, LocalIntExt& e, bool v)
45 void OnResult(SQL::Result& res) CXX11_OVERRIDE
47 User* user = ServerInstance->FindNick(uid);
52 pendingExt.set(user, AUTH_STATE_NONE);
57 ServerInstance->SNO->WriteGlobalSno('a', "Forbidden connection from %s (SQL query returned no matches)", user->GetFullRealHost().c_str());
58 pendingExt.set(user, AUTH_STATE_FAIL);
62 void OnError(SQL::Error& error) CXX11_OVERRIDE
64 User* user = ServerInstance->FindNick(uid);
67 pendingExt.set(user, AUTH_STATE_FAIL);
69 ServerInstance->SNO->WriteGlobalSno('a', "Forbidden connection from %s (SQL query failed: %s)", user->GetFullRealHost().c_str(), error.ToString());
73 class ModuleSQLAuth : public Module
75 LocalIntExt pendingExt;
76 dynamic_reference<SQL::Provider> SQL;
78 std::string freeformquery;
79 std::string killreason;
80 std::string allowpattern;
85 : pendingExt("sqlauth-wait", ExtensionItem::EXT_USER, this)
90 void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
92 ConfigTag* conf = ServerInstance->Config->ConfValue("sqlauth");
93 std::string dbid = conf->getString("dbid");
95 SQL.SetProvider("SQL");
97 SQL.SetProvider("SQL/" + dbid);
98 freeformquery = conf->getString("query");
99 killreason = conf->getString("killreason");
100 allowpattern = conf->getString("allowpattern");
101 verbose = conf->getBool("verbose");
104 ModResult OnUserRegister(LocalUser* user) CXX11_OVERRIDE
106 // Note this is their initial (unresolved) connect block
107 ConfigTag* tag = user->MyClass->config;
108 if (!tag->getBool("usesqlauth", true))
109 return MOD_RES_PASSTHRU;
111 if (!allowpattern.empty() && InspIRCd::Match(user->nick,allowpattern))
112 return MOD_RES_PASSTHRU;
114 if (pendingExt.get(user))
115 return MOD_RES_PASSTHRU;
119 ServerInstance->SNO->WriteGlobalSno('a', "Forbiding connection from %s (SQL database not present)", user->GetFullRealHost().c_str());
120 ServerInstance->Users->QuitUser(user, killreason);
121 return MOD_RES_PASSTHRU;
124 pendingExt.set(user, AUTH_STATE_BUSY);
126 SQL::ParamMap userinfo;
127 SQL::PopulateUserInfo(user, userinfo);
128 userinfo["pass"] = user->password;
130 HashProvider* md5 = ServerInstance->Modules->FindDataService<HashProvider>("hash/md5");
132 userinfo["md5pass"] = md5->Generate(user->password);
134 HashProvider* sha256 = ServerInstance->Modules->FindDataService<HashProvider>("hash/sha256");
136 userinfo["sha256pass"] = sha256->Generate(user->password);
138 const std::string certfp = SSLClientCert::GetFingerprint(&user->eh);
139 userinfo["certfp"] = certfp;
141 SQL->Submit(new AuthQuery(this, user->uuid, pendingExt, verbose), freeformquery, userinfo);
143 return MOD_RES_PASSTHRU;
146 ModResult OnCheckReady(LocalUser* user) CXX11_OVERRIDE
148 switch (pendingExt.get(user))
150 case AUTH_STATE_NONE:
151 return MOD_RES_PASSTHRU;
152 case AUTH_STATE_BUSY:
154 case AUTH_STATE_FAIL:
155 ServerInstance->Users->QuitUser(user, killreason);
158 return MOD_RES_PASSTHRU;
161 Version GetVersion() CXX11_OVERRIDE
163 return Version("Allow/Deny connections based upon an arbitrary SQL table", VF_VENDOR);
167 MODULE_INIT(ModuleSQLAuth)