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