]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/modules/extra/m_sqlauth.cpp
Extra checks to not set the ssl marker twice on re-handshake (nonfatal but wasteful)
[user/henk/code/inspircd.git] / src / modules / extra / m_sqlauth.cpp
index f6ac25a5662dfb9ea1c568b77cc7004e265eccbf..36b9b861176fa6e98ce0d44959225a5a2f110d67 100644 (file)
@@ -2,7 +2,7 @@
  *       | Inspire Internet Relay Chat Daemon |
  *       +------------------------------------+
  *
- *  Inspire is copyright (C) 2002-2004 ChatSpike-Dev.
+ *  InspIRCd is copyright (C) 2002-2004 ChatSpike-Dev.
  *                       E-mail:
  *                <brain@chatspike.net>
  *               <Craig@chatspike.net>
@@ -14,6 +14,8 @@
  * ---------------------------------------------------
  */
 
+using namespace std;
+
 #include <stdio.h>
 #include <string>
 #include <stdlib.h>
 #include "channels.h"
 #include "modules.h"
 #include "inspircd.h"
+#include "helperfuncs.h"
 #include "m_sql.h"
 
-/* $ModDesc: An SQL test module */
+/* $ModDesc: Allow/Deny connections based upon an arbitary SQL table */
 
 Server *Srv;
 
@@ -44,6 +47,8 @@ class ModuleSQLAuth : public Module
        std::string passfield;
        std::string encryption;
        std::string killreason;
+       std::string allowpattern;
+       bool WallOperFail;
        unsigned long dbid;
        Module* SQLModule;
 
@@ -58,6 +63,8 @@ class ModuleSQLAuth : public Module
                killreason = Conf->ReadValue("sqlauth","killreason",0); // reason to give when access is denied to a user (put your reg details here)
                encryption = Conf->ReadValue("sqlauth","encryption",0); // name of sql function used to encrypt password, e.g. "md5" or "passwd".
                                                                        // define, but leave blank if no encryption is to be used.
+               WallOperFail = Conf->ReadFlag("sqlauth","verbose",0);   // set to 1 if failed connects should be reported to operators
+               allowpattern = Conf->ReadValue("sqlauth","allowpattern",0);     // allow nicks matching the pattern without requiring auth
                delete Conf;
                SQLModule = Srv->FindModule("m_sql.so");
                if (!SQLModule)
@@ -65,21 +72,32 @@ class ModuleSQLAuth : public Module
                return (SQLModule);
        }
 
-       ModuleSQLAuth()
+       ModuleSQLAuth(Server* Me)
+               : Module::Module(Me)
        {
-               Srv = new Server;
+               Srv = Me;
                ReadConfig();
        }
 
-       virtual void OnRehash()
+       void Implements(char* List)
+       {
+               List[I_OnRehash] = List[I_OnUserRegister] = 1;
+       }
+
+       virtual void OnRehash(std::string parameter)
        {
                ReadConfig();
        }
 
        virtual void OnUserRegister(userrec* user)
        {
+               if ((allowpattern != "") && (Srv->MatchText(user->nick,allowpattern)))
+                       return;
+               
                if (!CheckCredentials(user->nick,user->password))
                {
+                       if (WallOperFail)
+                               WriteOpers("Forbidden connection from %s!%s@%s (invalid login/password)",user->nick,user->ident,user->host);
                        Srv->QuitUser(user,killreason);
                }
        }
@@ -92,62 +110,91 @@ class ModuleSQLAuth : public Module
                if (!SQLModule)
                        return false;
 
+               // sanitize the password (we dont want any mysql insertion exploits!)
+               std::string temp = "";
+               for (unsigned int q = 0; q < password.length(); q++)
+               {
+                       if (password[q] == '\'')
+                       {
+                               temp = temp + "\'";
+                       }
+                       else if (password[q] == '"')
+                       {
+                               temp = temp + "\\\"";
+                       }
+                       else temp = temp + password[q];
+               }
+               password = temp;
+
                // Create a request containing the SQL query and send it to m_sql.so
-               SQLRequest* query = new SQLRequest(SQL_RESULT,1,"SELECT * FROM "+usertable+" WHERE "+userfield+"='"+username+"' AND "+passfield+"="+encmethod+"('"+password+"')");
+               std::string querystr("SELECT * FROM "+usertable+" WHERE "+userfield+"='"+username+"' AND "+passfield+"="+encryption+"('"+password+"')");
+               
+               Srv->Log(DEBUG, "m_sqlauth.so: Query: " + querystr);
+               
+               SQLRequest* query = new SQLRequest(SQL_RESULT,dbid,querystr);
                Request queryrequest((char*)query, this, SQLModule);
                SQLResult* result = (SQLResult*)queryrequest.Send();
 
                // Did we get "OK" as a result?
                if (result->GetType() == SQL_OK)
                {
-
+                       log(DEBUG, "m_sqlauth.so: Query OK");
+                       
                        // if we did, this means we may now request a row... there should be only one row for each user, so,
                        // we don't need to loop to fetch multiple rows.
-                       SQLRequest* rowrequest = new SQLRequest(SQL_ROW,1,"");
+                       SQLRequest* rowrequest = new SQLRequest(SQL_ROW,dbid,"");
                        Request rowquery((char*)rowrequest, this, SQLModule);
                        SQLResult* rowresult = (SQLResult*)rowquery.Send();
 
                        // did we get a row? If we did, we can now do something with the fields
                        if (rowresult->GetType() == SQL_ROW)
                        {
-                               if (rowrequest->GetField(userfield) == username)
+                               log(DEBUG, "m_sqlauth.so: Got row...user '%s'", rowresult->GetField(userfield).c_str());
+                               
+                               if (rowresult->GetField(userfield) == username)
                                {
+                                       log(DEBUG, "m_sqlauth.so: Got correct user...");
                                        // because the query directly asked for the password hash, we do not need to check it -
                                        // if it didnt match it wont be returned in the first place from the SELECT.
                                        // This just checks we didnt get an empty row by accident.
                                        found = true;
                                }
-                               delete rowresult;
                        }
                        else
                        {
+                               log(DEBUG, "m_sqlauth.so: Couldn't find row");
                                // we didn't have a row.
                                found = false;
                        }
+                       
                        delete rowrequest;
-                       delete result;
+                       delete rowresult;
                }
                else
                {
+                       log(DEBUG, "m_sqlauth.so: Query failed");
                        // the query was bad
                        found = false;
                }
+               
                query->SetQueryType(SQL_DONE);
-               query->SetConnID(1);
+               query->SetConnID(dbid);
                Request donerequest((char*)query, this, SQLModule);
                donerequest.Send();
+               
                delete query;
+               delete result;
+               
                return found;
        }
 
        virtual ~ModuleSQLAuth()
        {
-               delete Srv;
        }
        
        virtual Version GetVersion()
        {
-               return Version(1,0,0,1,VF_VENDOR);
+               return Version(1,0,0,2,VF_VENDOR);
        }
        
 };
@@ -163,9 +210,9 @@ class ModuleSQLAuthFactory : public ModuleFactory
        {
        }
        
-       virtual Module * CreateModule()
+       virtual Module * CreateModule(Server* Me)
        {
-               return new ModuleSQLAuth;
+               return new ModuleSQLAuth(Me);
        }
        
 };