diff options
-rw-r--r-- | extras/m_sqloper.schema.sql | 23 | ||||
-rw-r--r-- | src/modules/extra/m_sqloper.cpp | 225 |
2 files changed, 248 insertions, 0 deletions
diff --git a/extras/m_sqloper.schema.sql b/extras/m_sqloper.schema.sql new file mode 100644 index 000000000..d4da959c2 --- /dev/null +++ b/extras/m_sqloper.schema.sql @@ -0,0 +1,23 @@ +-- MySQL dump 9.11 +-- +-- Host: localhost Database: brain +-- ------------------------------------------------------ +-- Server version 4.0.20 + +-- +-- Table structure for table `ircd_opers` +-- + +CREATE TABLE ircd_opers ( + id bigint(20) NOT NULL auto_increment, + username text, + password text, + type text, + PRIMARY KEY (id) +) TYPE=MyISAM; + +-- +-- Dumping data for table `ircd_opers` +-- + + diff --git a/src/modules/extra/m_sqloper.cpp b/src/modules/extra/m_sqloper.cpp new file mode 100644 index 000000000..fde524567 --- /dev/null +++ b/src/modules/extra/m_sqloper.cpp @@ -0,0 +1,225 @@ +/* +------------------------------------+ + * | Inspire Internet Relay Chat Daemon | + * +------------------------------------+ + * + * Inspire is copyright (C) 2002-2004 ChatSpike-Dev. + * E-mail: + * <brain@chatspike.net> + * <Craig@chatspike.net> + * + * Written by Craig Edwards, Craig McLure, and others. + * This program is free but copyrighted software; see + * the file COPYING for details. + * + * --------------------------------------------------- + */ + +#include <stdio.h> +#include <string> +#include <stdlib.h> +#include <time.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> +#include <poll.h> +#include "users.h" +#include "channels.h" +#include "modules.h" +#include "inspircd.h" +#include "m_sql.h" + +/* $ModDesc: Allows storage of oper credentials in an SQL table */ + +Server *Srv; + +class ModuleSQLOper : public Module +{ + ConfigReader* Conf; + unsigned long dbid; + Module* SQLModule; + + public: + bool ReadConfig() + { + dbid = Conf->ReadInteger("sqloper","dbid",0,true); // database id of a database configured in m_sql (see m_sql config) + SQLModule = Srv->FindModule("m_sql.so"); + if (!SQLModule) + Srv->Log(DEFAULT,"WARNING: m_sqloper.so could not initialize because m_sql.so is not loaded. Load the module and rehash your server."); + return (SQLModule); + } + + ModuleSQLOper() + { + Srv = new Server; + Conf = new ConfigReader(); + ReadConfig(); + } + + virtual void OnRehash() + { + delete Conf; + Conf = new ConfigReader(); + ReadConfig(); + } + + virtual int OnPreCommand(std::string command, char **parameters, int pcnt, userrec *user) + { + if (command == "OPER") + { + if (LookupOper(parameters[0],parameters[1],user)) + return 1; + } + return 0; + } + + bool LookupOper(std::string username, std::string password, userrec* user) + { + bool found = false; + + // is the sql module loaded? If not, we don't attempt to do anything. + if (!SQLModule) + return false; + + // sanitize the password (we dont want any mysql insertion exploits!) + std::string temp = ""; + for (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; + temp = ""; + for (int v = 0; v < username.length(); v++) + { + if (username[v] == '\'') + { + temp = temp + "\'"; + } + if (username[v] == '"') + { + temp = temp + "\\\""; + } + else temp = temp + username[v]; + } + username = temp; + + // Create a request containing the SQL query and send it to m_sql.so + SQLRequest* query = new SQLRequest(SQL_RESULT,dbid,"SELECT username,password,type FROM ircd_opers WHERE username='"+username+"' AND password=md5('"+password+"')"); + Request queryrequest((char*)query, this, SQLModule); + SQLResult* result = (SQLResult*)queryrequest.Send(); + + // Did we get "OK" as a result? + if (result->GetType() == SQL_OK) + { + Srv->Log(DEBUG,"An SQL based oper exists"); + // 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,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 (rowresult->GetField("username") == username) + { + found = true; + // oper up the user. + for (int j =0; j < Conf->Enumerate("type"); j++) + { + std::string TypeName = Conf->ReadValue("type","name",j); + if (TypeName == rowresult->GetField("type")) + { + /* found this oper's opertype */ + Srv->MeshSendAll("| "+std::string(user->nick)+" "+TypeName); + std::string HostName = Conf->ReadValue("type","host",j); + Srv->ChangeHost(user,HostName); + strlcpy(user->oper,TypeName.c_str(),NICKMAX); + WriteOpers("*** %s (%s@%s) is now an IRC operator of type %s",user->nick,user->ident,user->host,rowresult->GetField("type").c_str()); + WriteServ(user->fd,"381 %s :You are now an IRC operator of type %s",user->nick,rowresult->GetField("type").c_str()); + if (!strchr(user->modes,'o')) + { + strcat(user->modes,"o"); + WriteServ(user->fd,"MODE %s :+o",user->nick); + Srv->MeshSendAll("M "+std::string(user->nick)+" +o"); + Module* Logger = Srv->FindModule("m_sqllog.so"); + if (Logger) + Logger->OnOper(user); + log(DEFAULT,"OPER: %s!%s@%s opered as type: %s",user->nick,user->ident,user->host,rowresult->GetField("type").c_str()); + } + break; + } + } + + } + delete rowresult; + } + else + { + // we didn't have a row. + found = false; + } + delete rowrequest; + delete result; + } + else + { + // the query was bad + found = false; + } + query->SetQueryType(SQL_DONE); + query->SetConnID(dbid); + Request donerequest((char*)query, this, SQLModule); + donerequest.Send(); + delete query; + return found; + } + + virtual ~ModuleSQLOper() + { + delete Conf; + delete Srv; + } + + virtual Version GetVersion() + { + return Version(1,0,0,1,VF_VENDOR); + } + +}; + +class ModuleSQLOperFactory : public ModuleFactory +{ + public: + ModuleSQLOperFactory() + { + } + + ~ModuleSQLOperFactory() + { + } + + virtual Module * CreateModule() + { + return new ModuleSQLOper; + } + +}; + + +extern "C" void * init_module( void ) +{ + return new ModuleSQLOperFactory; +} + |