]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/extra/m_sqloper.cpp
f1d54e70ab362fc97ea0473291337f8c53534d24
[user/henk/code/inspircd.git] / src / modules / extra / m_sqloper.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd is copyright (C) 2002-2004 ChatSpike-Dev.
6  *                       E-mail:
7  *                <brain@chatspike.net>
8  *                <Craig@chatspike.net>
9  *     
10  * Written by Craig Edwards, Craig McLure, and others.
11  * This program is free but copyrighted software; see
12  *            the file COPYING for details.
13  *
14  * ---------------------------------------------------
15  */
16
17 using namespace std;
18
19 #include <stdio.h>
20 #include <string>
21 #include <stdlib.h>
22 #include <time.h>
23 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <sys/time.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <poll.h>
31 #include "users.h"
32 #include "channels.h"
33 #include "modules.h"
34 #include "inspircd.h"
35 #include "helperfuncs.h"
36 #include "m_sql.h"
37 #include "cmd_oper.h"
38
39 /* $ModDesc: Allows storage of oper credentials in an SQL table */
40
41 /* Required for the FOREACH_MOD alias (OnOper event) */
42 extern int MODCOUNT;
43 extern ServerConfig* Config;
44 extern std::vector<Module*> modules;
45 extern std::vector<ircd_module*> factory;
46
47 class ModuleSQLOper : public Module
48 {
49         Server* Srv;
50         ConfigReader* Conf;
51         unsigned long dbid;
52         Module* SQLModule;
53
54  public:
55         bool ReadConfig()
56         {
57                 dbid = Conf->ReadInteger("sqloper","dbid",0,true);      // database id of a database configured in m_sql (see m_sql config)
58                 SQLModule = Srv->FindModule("m_sql.so");
59                 if (!SQLModule)
60                         Srv->Log(DEFAULT,"WARNING: m_sqloper.so could not initialize because m_sql.so is not loaded. Load the module and rehash your server.");
61                 return (SQLModule);
62         }
63
64         ModuleSQLOper(Server* Me)
65                 : Module::Module(Me)
66         {
67                 Srv = Me;
68                 Conf = new ConfigReader();
69                 ReadConfig();
70         }
71
72         virtual void OnRehash(std::string parameter)
73         {
74                 delete Conf;
75                 Conf = new ConfigReader();
76                 ReadConfig();
77         }
78
79         void Implements(char* List)
80         {
81                 List[I_OnRehash] = List[I_OnPreCommand] = 1;
82         }
83
84         virtual int OnPreCommand(std::string command, char **parameters, int pcnt, userrec *user, bool validated)
85         {
86                 if ((command == "OPER") && (validated))
87                 {
88                         if (LookupOper(parameters[0],parameters[1],user))
89                                 return 1;
90                 }
91                 return 0;
92         }
93
94         bool LookupOper(std::string username, std::string password, userrec* user)
95         {
96                 bool found = false;
97
98                 // is the sql module loaded? If not, we don't attempt to do anything.
99                 if (!SQLModule)
100                         return false;
101
102                 // sanitize the password (we dont want any mysql insertion exploits!)
103                 std::string temp = "";
104                 for (unsigned int q = 0; q < password.length(); q++)
105                 {
106                         if (password[q] == '\'')
107                         {
108                                 temp = temp + "\'";
109                         }
110                         else if (password[q] == '"')
111                         {
112                                 temp = temp + "\\\"";
113                         }
114                         else temp = temp + password[q];
115                 }
116                 password = temp;
117                 temp = "";
118                 for (unsigned int v = 0; v < username.length(); v++)
119                 {
120                         if (username[v] == '\'')
121                         {
122                                 temp = temp + "\'";
123                         }
124                         if (username[v] == '"')
125                         {
126                                 temp = temp + "\\\"";
127                         }
128                         else temp = temp + username[v];
129                 }
130                 username = temp;
131
132                 // Create a request containing the SQL query and send it to m_sql.so
133                 SQLRequest* query = new SQLRequest(SQL_RESULT,dbid,"SELECT username,password,hostname,type FROM ircd_opers WHERE username='"+username+"' AND password=md5('"+password+"')");
134                 Request queryrequest((char*)query, this, SQLModule);
135                 SQLResult* result = (SQLResult*)queryrequest.Send();
136
137                 // Did we get "OK" as a result?
138                 if (result->GetType() == SQL_OK)
139                 {
140                         Srv->Log(DEBUG,"An SQL based oper exists");
141                         // if we did, this means we may now request a row... there should be only one row for each user, so,
142                         // we don't need to loop to fetch multiple rows.
143                         SQLRequest* rowrequest = new SQLRequest(SQL_ROW,dbid,"");
144                         Request rowquery((char*)rowrequest, this, SQLModule);
145                         SQLResult* rowresult = (SQLResult*)rowquery.Send();
146
147                         // did we get a row? If we did, we can now do something with the fields
148                         if (rowresult->GetType() == SQL_ROW)
149                         {
150                                 if (rowresult->GetField("username") == username)
151                                 {
152                                         found = true;
153                                         // oper up the user.
154                                         
155                                         for (int j =0; j < Conf->Enumerate("type"); j++)
156                                         {
157                                                 std::string TypeName = Conf->ReadValue("type","name",j);
158                                                 Srv->Log(DEBUG,"Scanning opertype: "+TypeName);
159                                                 std::string pattern = std::string(user->ident) + "@" + std::string(user->host);
160                                                         
161                                                 if((TypeName == rowresult->GetField("type")) && OneOfMatches(pattern.c_str(), rowresult->GetField("hostname").c_str()))
162                                                 {
163                                                         /* found this oper's opertype */
164                                                         Srv->Log(DEBUG,"Host and type match: "+TypeName+" "+rowresult->GetField("type"));
165                                                         std::string HostName = Conf->ReadValue("type","host",j);
166                                                         
167                                                         if(HostName != "")
168                                                                 Srv->ChangeHost(user,HostName);
169                                                                 
170                                                         strlcpy(user->oper,rowresult->GetField("type").c_str(),NICKMAX-1);
171                                                         WriteOpers("*** %s (%s@%s) is now an IRC operator of type %s",user->nick,user->ident,user->host,rowresult->GetField("type").c_str());
172                                                         WriteServ(user->fd,"381 %s :You are now an IRC operator of type %s",user->nick,rowresult->GetField("type").c_str());
173                                                         if(!strchr(user->modes,'o'))
174                                                         {
175                                                                 strcat(user->modes,"o");
176                                                                 WriteServ(user->fd,"MODE %s :+o",user->nick);
177                                                                 FOREACH_MOD(I_OnOper,OnOper(user,rowresult->GetField("type")));
178                                                                 AddOper(user);
179                                                                 FOREACH_MOD(I_OnPostOper,OnPostOper(user,rowresult->GetField("type")));
180                                                                 log(DEFAULT,"OPER: %s!%s@%s opered as type: %s",user->nick,user->ident,user->host,rowresult->GetField("type").c_str());
181                                                         }
182                                                                 
183                                                         break;
184                                                 }
185                                         }
186                                 }
187                                 
188                                 delete rowresult;
189                         }
190                         else
191                         {
192                                 // we didn't have a row.
193                                 found = false;
194                         }
195                         
196                         delete rowrequest;
197                         delete result;
198                 }
199                 else
200                 {
201                         // the query was bad
202                         found = false;
203                 }
204                 query->SetQueryType(SQL_DONE);
205                 query->SetConnID(dbid);
206                 Request donerequest((char*)query, this, SQLModule);
207                 donerequest.Send();
208                 delete query;
209                 return found;
210         }
211
212         virtual ~ModuleSQLOper()
213         {
214                 delete Conf;
215         }
216         
217         virtual Version GetVersion()
218         {
219                 return Version(1,0,0,1,VF_VENDOR);
220         }
221         
222 };
223
224 class ModuleSQLOperFactory : public ModuleFactory
225 {
226  public:
227         ModuleSQLOperFactory()
228         {
229         }
230         
231         ~ModuleSQLOperFactory()
232         {
233         }
234         
235         virtual Module * CreateModule(Server* Me)
236         {
237                 return new ModuleSQLOper(Me);
238         }
239         
240 };
241
242
243 extern "C" void * init_module( void )
244 {
245         return new ModuleSQLOperFactory;
246 }
247