]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/extra/m_sqlauth.cpp
Fixed removal of mesh linking from core
[user/henk/code/inspircd.git] / src / modules / extra / m_sqlauth.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 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: Allow/Deny connections based upon an arbitary SQL table */
39
40 Server *Srv;
41
42 class ModuleSQLAuth : public Module
43 {
44         ConfigReader* Conf;
45         std::string usertable;
46         std::string userfield;
47         std::string passfield;
48         std::string encryption;
49         std::string killreason;
50         std::string allowpattern;
51         bool WallOperFail;
52         unsigned long dbid;
53         Module* SQLModule;
54
55  public:
56         bool ReadConfig()
57         {
58                 Conf = new ConfigReader();
59                 usertable = Conf->ReadValue("sqlauth","usertable",0);   // user table name
60                 dbid = Conf->ReadInteger("sqlauth","dbid",0,true);      // database id of a database configured in m_sql (see m_sql config)
61                 userfield = Conf->ReadValue("sqlauth","userfield",0);   // field name where username can be found
62                 passfield = Conf->ReadValue("sqlauth","passfield",0);   // field name where password can be found
63                 killreason = Conf->ReadValue("sqlauth","killreason",0); // reason to give when access is denied to a user (put your reg details here)
64                 encryption = Conf->ReadValue("sqlauth","encryption",0); // name of sql function used to encrypt password, e.g. "md5" or "passwd".
65                                                                         // define, but leave blank if no encryption is to be used.
66                 WallOperFail = Conf->ReadFlag("sqlauth","verbose",0);   // set to 1 if failed connects should be reported to operators
67                 allowpattern = Conf->ReadValue("sqlauth","allowpattern",0);     // allow nicks matching the pattern without requiring auth
68                 delete Conf;
69                 SQLModule = Srv->FindModule("m_sql.so");
70                 if (!SQLModule)
71                         Srv->Log(DEFAULT,"WARNING: m_sqlauth.so could not initialize because m_sql.so is not loaded. Load the module and rehash your server.");
72                 return (SQLModule);
73         }
74
75         ModuleSQLAuth()
76         {
77                 Srv = new Server;
78                 ReadConfig();
79         }
80
81         virtual void OnRehash()
82         {
83                 ReadConfig();
84         }
85
86         virtual void OnUserRegister(userrec* user)
87         {
88                 if ((allowpattern != "") && (Srv->MatchText(user->nick,allowpattern)))
89                         return;
90                 
91                 if (!CheckCredentials(user->nick,user->password))
92                 {
93                         if (WallOperFail)
94                                 WriteOpers("Forbidden connection from %s!%s@%s (invalid login/password)",user->nick,user->ident,user->host);
95                         Srv->QuitUser(user,killreason);
96                 }
97         }
98
99         bool CheckCredentials(std::string username, std::string password)
100         {
101                 bool found = false;
102
103                 // is the sql module loaded? If not, we don't attempt to do anything.
104                 if (!SQLModule)
105                         return false;
106
107                 // sanitize the password (we dont want any mysql insertion exploits!)
108                 std::string temp = "";
109                 for (unsigned int q = 0; q < password.length(); q++)
110                 {
111                         if (password[q] == '\'')
112                         {
113                                 temp = temp + "\'";
114                         }
115                         else if (password[q] == '"')
116                         {
117                                 temp = temp + "\\\"";
118                         }
119                         else temp = temp + password[q];
120                 }
121                 password = temp;
122
123                 // Create a request containing the SQL query and send it to m_sql.so
124                 SQLRequest* query = new SQLRequest(SQL_RESULT,dbid,"SELECT * FROM "+usertable+" WHERE "+userfield+"='"+username+"' AND "+passfield+"="+encryption+"('"+password+"')");
125                 Request queryrequest((char*)query, this, SQLModule);
126                 SQLResult* result = (SQLResult*)queryrequest.Send();
127
128                 // Did we get "OK" as a result?
129                 if (result->GetType() == SQL_OK)
130                 {
131
132                         // if we did, this means we may now request a row... there should be only one row for each user, so,
133                         // we don't need to loop to fetch multiple rows.
134                         SQLRequest* rowrequest = new SQLRequest(SQL_ROW,dbid,"");
135                         Request rowquery((char*)rowrequest, this, SQLModule);
136                         SQLResult* rowresult = (SQLResult*)rowquery.Send();
137
138                         // did we get a row? If we did, we can now do something with the fields
139                         if (rowresult->GetType() == SQL_ROW)
140                         {
141                                 if (rowresult->GetField(userfield) == username)
142                                 {
143                                         // because the query directly asked for the password hash, we do not need to check it -
144                                         // if it didnt match it wont be returned in the first place from the SELECT.
145                                         // This just checks we didnt get an empty row by accident.
146                                         found = true;
147                                 }
148                                 delete rowresult;
149                         }
150                         else
151                         {
152                                 // we didn't have a row.
153                                 found = false;
154                         }
155                         delete rowrequest;
156                         delete result;
157                 }
158                 else
159                 {
160                         // the query was bad
161                         found = false;
162                 }
163                 query->SetQueryType(SQL_DONE);
164                 query->SetConnID(dbid);
165                 Request donerequest((char*)query, this, SQLModule);
166                 donerequest.Send();
167                 delete query;
168                 return found;
169         }
170
171         virtual ~ModuleSQLAuth()
172         {
173                 delete Srv;
174         }
175         
176         virtual Version GetVersion()
177         {
178                 return Version(1,0,0,1,VF_VENDOR);
179         }
180         
181 };
182
183 class ModuleSQLAuthFactory : public ModuleFactory
184 {
185  public:
186         ModuleSQLAuthFactory()
187         {
188         }
189         
190         ~ModuleSQLAuthFactory()
191         {
192         }
193         
194         virtual Module * CreateModule()
195         {
196                 return new ModuleSQLAuth;
197         }
198         
199 };
200
201
202 extern "C" void * init_module( void )
203 {
204         return new ModuleSQLAuthFactory;
205 }
206