]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/extra/m_sqloper.cpp
6451b0ed4d5c21ced35365e0790f37f9a287ab5e
[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
38 /* $ModDesc: Allows storage of oper credentials in an SQL table */
39
40 Server *Srv;
41
42 class ModuleSQLOper : public Module
43 {
44         ConfigReader* Conf;
45         unsigned long dbid;
46         Module* SQLModule;
47
48  public:
49         bool ReadConfig()
50         {
51                 dbid = Conf->ReadInteger("sqloper","dbid",0,true);      // database id of a database configured in m_sql (see m_sql config)
52                 SQLModule = Srv->FindModule("m_sql.so");
53                 if (!SQLModule)
54                         Srv->Log(DEFAULT,"WARNING: m_sqloper.so could not initialize because m_sql.so is not loaded. Load the module and rehash your server.");
55                 return (SQLModule);
56         }
57
58         ModuleSQLOper(Server* Me)
59                 : Module::Module(Me)
60         {
61                 Srv = Me;
62                 Conf = new ConfigReader();
63                 ReadConfig();
64         }
65
66         virtual void OnRehash(std::string parameter)
67         {
68                 delete Conf;
69                 Conf = new ConfigReader();
70                 ReadConfig();
71         }
72
73         void Implements(char* List)
74         {
75                 List[I_OnRehash] = List[I_OnPreCommand] = 1;
76         }
77
78         virtual int OnPreCommand(std::string command, char **parameters, int pcnt, userrec *user)
79         {
80                 if (command == "OPER")
81                 {
82                         if (LookupOper(parameters[0],parameters[1],user))
83                                 return 1;
84                 }
85                 return 0;
86         }
87
88         bool LookupOper(std::string username, std::string password, userrec* user)
89         {
90                 bool found = false;
91
92                 // is the sql module loaded? If not, we don't attempt to do anything.
93                 if (!SQLModule)
94                         return false;
95
96                 // sanitize the password (we dont want any mysql insertion exploits!)
97                 std::string temp = "";
98                 for (unsigned int q = 0; q < password.length(); q++)
99                 {
100                         if (password[q] == '\'')
101                         {
102                                 temp = temp + "\'";
103                         }
104                         else if (password[q] == '"')
105                         {
106                                 temp = temp + "\\\"";
107                         }
108                         else temp = temp + password[q];
109                 }
110                 password = temp;
111                 temp = "";
112                 for (unsigned int v = 0; v < username.length(); v++)
113                 {
114                         if (username[v] == '\'')
115                         {
116                                 temp = temp + "\'";
117                         }
118                         if (username[v] == '"')
119                         {
120                                 temp = temp + "\\\"";
121                         }
122                         else temp = temp + username[v];
123                 }
124                 username = temp;
125
126                 // Create a request containing the SQL query and send it to m_sql.so
127                 SQLRequest* query = new SQLRequest(SQL_RESULT,dbid,"SELECT username,password,hostname,type FROM ircd_opers WHERE username='"+username+"' AND password=md5('"+password+"')");
128                 Request queryrequest((char*)query, this, SQLModule);
129                 SQLResult* result = (SQLResult*)queryrequest.Send();
130
131                 // Did we get "OK" as a result?
132                 if (result->GetType() == SQL_OK)
133                 {
134                         Srv->Log(DEBUG,"An SQL based oper exists");
135                         // if we did, this means we may now request a row... there should be only one row for each user, so,
136                         // we don't need to loop to fetch multiple rows.
137                         SQLRequest* rowrequest = new SQLRequest(SQL_ROW,dbid,"");
138                         Request rowquery((char*)rowrequest, this, SQLModule);
139                         SQLResult* rowresult = (SQLResult*)rowquery.Send();
140
141                         // did we get a row? If we did, we can now do something with the fields
142                         if (rowresult->GetType() == SQL_ROW)
143                         {
144                                 if (rowresult->GetField("username") == username)
145                                 {
146                                         found = true;
147                                         // oper up the user.
148                                         for (int j =0; j < Conf->Enumerate("type"); j++)
149                                         {
150                                                 std::string TypeName = Conf->ReadValue("type","name",j);
151                                                 std::string pattern = std::string(user->ident) + "@" + std::string(user->host);
152                                                 if ((TypeName == rowresult->GetField("type")) && (Srv->MatchText(pattern,rowresult->GetField("hostname"))));
153                                                 {
154                                                         /* found this oper's opertype */
155                                                         std::string HostName = Conf->ReadValue("type","host",j);
156                                                         if (HostName != "")
157                                                                 Srv->ChangeHost(user,HostName);
158                                                         strlcpy(user->oper,TypeName.c_str(),NICKMAX);
159                                                         WriteOpers("*** %s (%s@%s) is now an IRC operator of type %s",user->nick,user->ident,user->host,rowresult->GetField("type").c_str());
160                                                         WriteServ(user->fd,"381 %s :You are now an IRC operator of type %s",user->nick,rowresult->GetField("type").c_str());
161                                                         if (!strchr(user->modes,'o'))
162                                                         {
163                                                                 strcat(user->modes,"o");
164                                                                 WriteServ(user->fd,"MODE %s :+o",user->nick);
165                                                                 Module* Logger = Srv->FindModule("m_sqllog.so");
166                                                                 if (Logger)
167                                                                         Logger->OnOper(user,rowresult->GetField("type"));
168                                                                 AddOper(user);
169                                                                 log(DEFAULT,"OPER: %s!%s@%s opered as type: %s",user->nick,user->ident,user->host,rowresult->GetField("type").c_str());
170                                                         }
171                                                         break;
172                                                 }
173                                         }
174
175                                 }
176                                 delete rowresult;
177                         }
178                         else
179                         {
180                                 // we didn't have a row.
181                                 found = false;
182                         }
183                         delete rowrequest;
184                         delete result;
185                 }
186                 else
187                 {
188                         // the query was bad
189                         found = false;
190                 }
191                 query->SetQueryType(SQL_DONE);
192                 query->SetConnID(dbid);
193                 Request donerequest((char*)query, this, SQLModule);
194                 donerequest.Send();
195                 delete query;
196                 return found;
197         }
198
199         virtual ~ModuleSQLOper()
200         {
201                 delete Conf;
202         }
203         
204         virtual Version GetVersion()
205         {
206                 return Version(1,0,0,1,VF_VENDOR);
207         }
208         
209 };
210
211 class ModuleSQLOperFactory : public ModuleFactory
212 {
213  public:
214         ModuleSQLOperFactory()
215         {
216         }
217         
218         ~ModuleSQLOperFactory()
219         {
220         }
221         
222         virtual Module * CreateModule(Server* Me)
223         {
224                 return new ModuleSQLOper(Me);
225         }
226         
227 };
228
229
230 extern "C" void * init_module( void )
231 {
232         return new ModuleSQLOperFactory;
233 }
234