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