1 /* +------------------------------------+
2 * | Inspire Internet Relay Chat Daemon |
3 * +------------------------------------+
5 * InspIRCd: (C) 2002-2010 InspIRCd Development Team
6 * See: http://wiki.inspircd.org/Credits
8 * This program is free but copyrighted software; see
9 * the file COPYING for details.
11 * ---------------------------------------------------
18 /* $ModDesc: Allow/Deny connections based upon an arbitary SQL table */
26 class AuthQuery : public SQLQuery
29 const std::string uid;
30 LocalIntExt& pendingExt;
32 AuthQuery(Module* me, const std::string& u, LocalIntExt& e, bool v)
33 : SQLQuery(me), uid(u), pendingExt(e), verbose(v)
37 void OnResult(SQLResult& res)
39 User* user = ServerInstance->FindNick(uid);
44 pendingExt.set(user, AUTH_STATE_NONE);
49 ServerInstance->SNO->WriteGlobalSno('a', "Forbidden connection from %s!%s@%s (SQL query returned no matches)", user->nick.c_str(), user->ident.c_str(), user->host.c_str());
50 pendingExt.set(user, AUTH_STATE_FAIL);
54 void OnError(SQLerror& error)
56 User* user = ServerInstance->FindNick(uid);
59 pendingExt.set(user, AUTH_STATE_FAIL);
61 ServerInstance->SNO->WriteGlobalSno('a', "Forbidden connection from %s!%s@%s (SQL query failed: %s)", user->nick.c_str(), user->ident.c_str(), user->host.c_str(), error.Str());
65 class ModuleSQLAuth : public Module
67 LocalIntExt pendingExt;
68 dynamic_reference<SQLProvider> SQL;
70 std::string freeformquery;
71 std::string killreason;
72 std::string allowpattern;
76 ModuleSQLAuth() : pendingExt("sqlauth-wait", this), SQL(this, "SQL")
82 ServerInstance->Modules->AddService(pendingExt);
84 Implementation eventlist[] = { I_OnUserDisconnect, I_OnCheckReady, I_OnRehash, I_OnUserRegister };
85 ServerInstance->Modules->Attach(eventlist, this, 4);
88 void OnRehash(User* user)
90 ConfigTag* conf = ServerInstance->Config->ConfValue("sqlauth");
91 std::string dbid = conf->getString("dbid");
93 SQL.SetProvider("SQL");
95 SQL.SetProvider("SQL/" + dbid);
96 freeformquery = conf->getString("query");
97 killreason = conf->getString("killreason");
98 allowpattern = conf->getString("allowpattern");
99 verbose = conf->getBool("verbose");
102 ModResult OnUserRegister(LocalUser* user)
104 // Note this is their initial (unresolved) connect block
105 ConfigTag* tag = user->MyClass->config;
106 if (!tag->getBool("usesqlauth", true))
107 return MOD_RES_PASSTHRU;
109 if (!allowpattern.empty() && InspIRCd::Match(user->nick,allowpattern))
110 return MOD_RES_PASSTHRU;
112 if (pendingExt.get(user))
113 return MOD_RES_PASSTHRU;
117 ServerInstance->SNO->WriteGlobalSno('a', "Forbiding connection from %s!%s@%s (SQL database not present)",
118 user->nick.c_str(), user->ident.c_str(), user->host.c_str());
119 ServerInstance->Users->QuitUser(user, killreason);
120 return MOD_RES_PASSTHRU;
123 pendingExt.set(user, AUTH_STATE_BUSY);
126 SQL->PopulateUserInfo(user, userinfo);
127 userinfo["pass"] = user->password;
129 HashProvider* md5 = ServerInstance->Modules->FindDataService<HashProvider>("hash/md5");
131 userinfo["md5pass"] = md5->hexsum(user->password);
133 HashProvider* sha256 = ServerInstance->Modules->FindDataService<HashProvider>("hash/sha256");
135 userinfo["sha256pass"] = sha256->hexsum(user->password);
137 SQL->submit(new AuthQuery(this, user->uuid, pendingExt, verbose), freeformquery, userinfo);
139 return MOD_RES_PASSTHRU;
142 ModResult OnCheckReady(LocalUser* user)
144 switch (pendingExt.get(user))
146 case AUTH_STATE_NONE:
147 return MOD_RES_PASSTHRU;
148 case AUTH_STATE_BUSY:
150 case AUTH_STATE_FAIL:
151 ServerInstance->Users->QuitUser(user, killreason);
154 return MOD_RES_PASSTHRU;
159 return Version("Allow/Deny connections based upon an arbitary SQL table", VF_VENDOR);
163 MODULE_INIT(ModuleSQLAuth)