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