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)
92 SQL.SetProvider("SQL/" + Conf.ReadValue("sqlauth", "dbid", 0)); /* Database ID, given to the SQL service provider */
93 freeformquery = Conf.ReadValue("sqlauth", "query", 0); /* Field name where username can be found */
94 killreason = Conf.ReadValue("sqlauth", "killreason", 0); /* Reason to give when access is denied to a user (put your reg details here) */
95 allowpattern = Conf.ReadValue("sqlauth", "allowpattern",0 ); /* Allow nicks matching this pattern without requiring auth */
96 verbose = Conf.ReadFlag("sqlauth", "verbose", 0); /* Set to true if failed connects should be reported to operators */
100 ModResult OnUserRegister(LocalUser* user)
102 // Note this is their initial (unresolved) connect block
103 ConfigTag* tag = user->MyClass->config;
104 if (!tag->getBool("usesqlauth", true))
105 return MOD_RES_PASSTHRU;
107 if (!allowpattern.empty() && InspIRCd::Match(user->nick,allowpattern))
108 return MOD_RES_PASSTHRU;
110 if (pendingExt.get(user))
111 return MOD_RES_PASSTHRU;
113 pendingExt.set(user, AUTH_STATE_BUSY);
116 SQL->PopulateUserInfo(user, userinfo);
117 userinfo["pass"] = user->password;
119 HashProvider* md5 = ServerInstance->Modules->FindDataService<HashProvider>("hash/md5");
121 userinfo["md5pass"] = md5->hexsum(user->password);
123 HashProvider* sha256 = ServerInstance->Modules->FindDataService<HashProvider>("hash/sha256");
125 userinfo["sha256pass"] = sha256->hexsum(user->password);
127 SQL->submit(new AuthQuery(this, user->uuid, pendingExt, verbose), freeformquery, userinfo);
129 return MOD_RES_PASSTHRU;
132 ModResult OnCheckReady(LocalUser* user)
134 switch (pendingExt.get(user))
136 case AUTH_STATE_NONE:
137 return MOD_RES_PASSTHRU;
138 case AUTH_STATE_BUSY:
140 case AUTH_STATE_FAIL:
141 ServerInstance->Users->QuitUser(user, killreason);
144 return MOD_RES_PASSTHRU;
149 return Version("Allow/Deny connections based upon an arbitary SQL table", VF_VENDOR);
153 MODULE_INIT(ModuleSQLAuth)