1 /* +------------------------------------+
2 * | Inspire Internet Relay Chat Daemon |
3 * +------------------------------------+
5 * InspIRCd is copyright (C) 2002-2004 ChatSpike-Dev.
7 * <brain@chatspike.net>
8 * <Craig@chatspike.net>
10 * Written by Craig Edwards, Craig McLure, and others.
11 * This program is free but copyrighted software; see
12 * the file COPYING for details.
14 * ---------------------------------------------------
23 #include <sys/types.h>
24 #include <sys/socket.h>
35 #include "helperfuncs.h"
38 /* $ModDesc: Allow/Deny connections based upon an arbitary SQL table */
40 class ModuleSQLAuth : public Module
44 std::string usertable;
45 std::string userfield;
46 std::string passfield;
47 std::string encryption;
48 std::string killreason;
49 std::string allowpattern;
57 Conf = new ConfigReader();
58 usertable = Conf->ReadValue("sqlauth","usertable",0); // user table name
59 dbid = Conf->ReadInteger("sqlauth","dbid",0,true); // database id of a database configured in m_sql (see m_sql config)
60 userfield = Conf->ReadValue("sqlauth","userfield",0); // field name where username can be found
61 passfield = Conf->ReadValue("sqlauth","passfield",0); // field name where password can be found
62 killreason = Conf->ReadValue("sqlauth","killreason",0); // reason to give when access is denied to a user (put your reg details here)
63 encryption = Conf->ReadValue("sqlauth","encryption",0); // name of sql function used to encrypt password, e.g. "md5" or "passwd".
64 // define, but leave blank if no encryption is to be used.
65 WallOperFail = Conf->ReadFlag("sqlauth","verbose",0); // set to 1 if failed connects should be reported to operators
66 allowpattern = Conf->ReadValue("sqlauth","allowpattern",0); // allow nicks matching the pattern without requiring auth
68 SQLModule = Srv->FindModule("m_sql.so");
70 Srv->Log(DEFAULT,"WARNING: m_sqlauth.so could not initialize because m_sql.so is not loaded. Load the module and rehash your server.");
74 ModuleSQLAuth(Server* Me)
81 void Implements(char* List)
83 List[I_OnRehash] = List[I_OnUserRegister] = 1;
86 virtual void OnRehash(std::string parameter)
91 virtual void OnUserRegister(userrec* user)
93 if ((allowpattern != "") && (Srv->MatchText(user->nick,allowpattern)))
96 if (!CheckCredentials(user->nick,user->password))
99 WriteOpers("Forbidden connection from %s!%s@%s (invalid login/password)",user->nick,user->ident,user->host);
100 Srv->QuitUser(user,killreason);
104 bool CheckCredentials(std::string username, std::string password)
108 // is the sql module loaded? If not, we don't attempt to do anything.
112 // sanitize the password (we dont want any mysql insertion exploits!)
113 std::string temp = "";
114 for (unsigned int q = 0; q < password.length(); q++)
116 if (password[q] == '\'')
120 else if (password[q] == '"')
122 temp = temp + "\\\"";
124 else temp = temp + password[q];
128 // Create a request containing the SQL query and send it to m_sql.so
129 std::string querystr("SELECT * FROM "+usertable+" WHERE "+userfield+"='"+username+"' AND "+passfield+"="+encryption+"('"+password+"')");
131 Srv->Log(DEBUG, "m_sqlauth.so: Query: " + querystr);
133 SQLRequest* query = new SQLRequest(SQL_RESULT,dbid,querystr);
134 Request queryrequest((char*)query, this, SQLModule);
135 SQLResult* result = (SQLResult*)queryrequest.Send();
137 // Did we get "OK" as a result?
138 if (result->GetType() == SQL_OK)
140 log(DEBUG, "m_sqlauth.so: Query OK");
142 // if we did, this means we may now request a row... there should be only one row for each user, so,
143 // we don't need to loop to fetch multiple rows.
144 SQLRequest* rowrequest = new SQLRequest(SQL_ROW,dbid,"");
145 Request rowquery((char*)rowrequest, this, SQLModule);
146 SQLResult* rowresult = (SQLResult*)rowquery.Send();
148 // did we get a row? If we did, we can now do something with the fields
149 if (rowresult->GetType() == SQL_ROW)
151 log(DEBUG, "m_sqlauth.so: Got row...user '%s'", rowresult->GetField(userfield).c_str());
153 if (rowresult->GetField(userfield) == username)
155 log(DEBUG, "m_sqlauth.so: Got correct user...");
156 // because the query directly asked for the password hash, we do not need to check it -
157 // if it didnt match it wont be returned in the first place from the SELECT.
158 // This just checks we didnt get an empty row by accident.
164 log(DEBUG, "m_sqlauth.so: Couldn't find row");
165 // we didn't have a row.
174 log(DEBUG, "m_sqlauth.so: Query failed");
179 query->SetQueryType(SQL_DONE);
180 query->SetConnID(dbid);
181 Request donerequest((char*)query, this, SQLModule);
190 virtual ~ModuleSQLAuth()
194 virtual Version GetVersion()
196 return Version(1,0,0,2,VF_VENDOR);
201 class ModuleSQLAuthFactory : public ModuleFactory
204 ModuleSQLAuthFactory()
208 ~ModuleSQLAuthFactory()
212 virtual Module * CreateModule(Server* Me)
214 return new ModuleSQLAuth(Me);
220 extern "C" void * init_module( void )
222 return new ModuleSQLAuthFactory;