/** Tag name */
const char* tag;
/** One or more items within tag */
- char* items[17];
+ char* items[18];
/** One or more defaults for items within tags */
- char* items_default[17];
+ char* items_default[18];
/** One or more data types */
- int datatype[17];
+ int datatype[18];
/** Initialization function */
MultiNotify init_function;
/** Validation function */
*/
char restartpass[MAXBUF];
+ /** The hash method for *BOTH* the die and restart passwords.
+ */
+ char powerhash[MAXBUF];
+
/** The pathname and filename of the message of the
* day file, as defined by the administrator.
*/
*/
long Duration(const std::string &str);
- /** Attempt to compare an oper password to a string from the config file.
+ /** Attempt to compare a password to a string from the config file.
* This will be passed to handling modules which will compare the data
* against possible hashed equivalents in the input string.
+ * @param ex The object (user, server, whatever) causing the comparison.
* @param data The data from the config file
* @param input The data input by the oper
- * @param tagnum the tag number of the oper's tag in the config file
+ * @param hashtype The hash from the config file
* @return 0 if the strings match, 1 or -1 if they do not
*/
- int OperPassCompare(const char* data,const char* input, int tagnum);
+ int PassCompare(Extensible* ex, const char* data,const char* input, const char* hashtype);
/** Check if a given server is a uline.
* An empty string returns true, this is by design.
I_OnDelLine, I_OnExpireLine, I_OnCleanup, I_OnUserPostNick, I_OnAccessCheck, I_On005Numeric, I_OnKill, I_OnRemoteKill, I_OnLoadModule, I_OnUnloadModule,
I_OnBackgroundTimer, I_OnPreCommand, I_OnCheckReady, I_OnCheckInvite, I_OnRawMode,
I_OnCheckKey, I_OnCheckLimit, I_OnCheckBan, I_OnStats, I_OnChangeLocalUserHost, I_OnChangeLocalUserGecos, I_OnLocalTopicChange,
- I_OnPostLocalTopicChange, I_OnEvent, I_OnRequest, I_OnOperCompre, I_OnGlobalOper, I_OnPostConnect, I_OnAddBan, I_OnDelBan,
+ I_OnPostLocalTopicChange, I_OnEvent, I_OnRequest, I_OnGlobalOper, I_OnPostConnect, I_OnAddBan, I_OnDelBan,
I_OnRawSocketAccept, I_OnRawSocketClose, I_OnRawSocketWrite, I_OnRawSocketRead, I_OnChangeLocalUserGECOS, I_OnUserRegister,
- I_OnOperCompare, I_OnChannelPreDelete, I_OnChannelDelete, I_OnPostOper, I_OnSyncOtherMetaData, I_OnSetAway, I_OnCancelAway, I_OnUserList,
+ I_OnChannelPreDelete, I_OnChannelDelete, I_OnPostOper, I_OnSyncOtherMetaData, I_OnSetAway, I_OnCancelAway, I_OnUserList,
I_OnPostCommand, I_OnPostJoin, I_OnWhoisLine, I_OnBuildExemptList, I_OnRawSocketConnect, I_OnGarbageCollect, I_OnBufferFlushed,
- I_OnText, I_OnReadConfig, I_OnDownloadFile,
+ I_OnText, I_OnReadConfig, I_OnDownloadFile, I_OnPassCompare,
I_END
};
*/
virtual char* OnRequest(Request* request);
- /** Called whenever an oper password is to be compared to what a user has input.
+ /** Called whenever a password check is to be made. Replaces the old OldOperCompare API.
* The password field (from the config file) is in 'password' and is to be compared against
- * 'input'. This method allows for encryption of oper passwords and much more besides.
- * You should return a nonzero value if you want to allow the comparison or zero if you wish
- * to do nothing.
- * @param password The oper's password
- * @param input The password entered
- * @param tagnumber The tag number (from the configuration file) of this oper's tag
- * @return 1 to match the passwords, 0 to do nothing. -1 to not match, and not continue.
- */
- virtual int OnOperCompare(const std::string &password, const std::string &input, int tagnumber);
+ * 'input'. This method allows for encryption of passwords (oper, connect:allow, die/restart, etc).
+ * You should return a nonzero value to override the normal comparison, or zero to pass it on.
+ * @param ex The object that's causing the authentication (User* for <oper> <connect:allow> etc, Server* for <link>).
+ * @param password The password from the configuration file (the password="" value).
+ * @param input The password entered by the user or whoever.
+ * @param hashtype The hash value from the config
+ * @return 0 to do nothing (pass on to next module/default), 1 == password is OK, -1 == password is not OK
+ */
+ virtual int OnPassCompare(Extensible* ex, const std::string &password, const std::string &input, const std::string& hashtype);
/** Called whenever a user is given usermode +o, anywhere on the network.
* You cannot override this and prevent it from happening as it is already happened and
*/
std::string pass;
+ /** (Optional) Hash Method for this line
+ */
+ std::string hash;
+
/** Threshold value for flood disconnect
*/
unsigned int threshold;
*/
ConnectClass(const ConnectClass* source) : classbase(), type(source->type), name(source->name),
registration_timeout(source->registration_timeout), flood(source->flood), host(source->host),
- pingtime(source->pingtime), pass(source->pass), threshold(source->threshold), sendqmax(source->sendqmax),
+ pingtime(source->pingtime), pass(source->pass), hash(source->hash), threshold(source->threshold), sendqmax(source->sendqmax),
recvqmax(source->recvqmax), maxlocal(source->maxlocal), maxglobal(source->maxglobal), maxchans(source->maxchans),
port(source->port), RefCount(0), disabled(false), limit(0)
{
/** Create a new connect class with no settings.
*/
- ConnectClass() : type(CC_DENY), name("unnamed"), registration_timeout(0), flood(0), host(""), pingtime(0), pass(""),
+ ConnectClass() : type(CC_DENY), name("unnamed"), registration_timeout(0), flood(0), host(""), pingtime(0), pass(""), hash(""),
threshold(0), sendqmax(0), recvqmax(0), maxlocal(0), maxglobal(0), RefCount(0), disabled(false), limit(0)
{
}
* @param hst The IP mask to allow
* @param ping The ping frequency
* @param pas The password to be used
+ * @param hsh The hash to be used
* @param thres The flooding threshold
* @param sendq The maximum sendq value
* @param recvq The maximum recvq value
* @param maxg The maximum global sessions
*/
ConnectClass(const std::string &thename, unsigned int timeout, unsigned int fld, const std::string &hst, unsigned int ping,
- const std::string &pas, unsigned int thres, unsigned long sendq, unsigned long recvq,
+ const std::string &pas, const std::string &hsh, unsigned int thres, unsigned long sendq, unsigned long recvq,
unsigned long maxl, unsigned long maxg, unsigned int maxc, int p = 0) :
- type(CC_ALLOW), name(thename), registration_timeout(timeout), flood(fld), host(hst), pingtime(ping), pass(pas),
+ type(CC_ALLOW), name(thename), registration_timeout(timeout), flood(fld), host(hst), pingtime(ping), pass(pas), hash(hsh),
threshold(thres), sendqmax(sendq), recvqmax(recvq), maxlocal(maxl), maxglobal(maxg), maxchans(maxc), port(p), RefCount(0), disabled(false), limit(0) { }
/** Create a new connect class to DENY connections
* @param hst The IP mask to deny
*/
ConnectClass(const std::string &thename, const std::string &hst) : type(CC_DENY), name(thename), registration_timeout(0),
- flood(0), host(hst), pingtime(0), pass(""), threshold(0), sendqmax(0), recvqmax(0), maxlocal(0), maxglobal(0), maxchans(0), port(0), RefCount(0), disabled(false), limit(0)
+ flood(0), host(hst), pingtime(0), pass(""), hash(""), threshold(0), sendqmax(0), recvqmax(0), maxlocal(0), maxglobal(0), maxchans(0), port(0), RefCount(0), disabled(false), limit(0)
{
}
*/
ConnectClass(const std::string &thename, const ConnectClass* source) : type(source->type), name(thename),
registration_timeout(source->registration_timeout), flood(source->flood), host(source->host),
- pingtime(source->pingtime), pass(source->pass), threshold(source->threshold), sendqmax(source->sendqmax),
+ pingtime(source->pingtime), pass(source->pass), hash(source->hash), threshold(source->threshold), sendqmax(source->sendqmax),
recvqmax(source->recvqmax), maxlocal(source->maxlocal), maxglobal(source->maxglobal), maxchans(source->maxchans),
port(source->port), RefCount(0), disabled(false), limit(0)
{
return pass;
}
+ /** Returns the hash or an empty string
+ */
+ const std::string& GetHash()
+ {
+ return hash;
+ }
+
/** Returns the flood threshold value
*/
unsigned int GetThreshold()
#include <dlfcn.h>
#endif
-int InspIRCd::OperPassCompare(const char* data,const char* input, int tagnumber)
+int InspIRCd::PassCompare(Extensible* ex, const char* data,const char* input, const char* hashtype)
{
int MOD_RESULT = 0;
- FOREACH_RESULT_I(this,I_OnOperCompare,OnOperCompare(data, input, tagnumber))
+ FOREACH_RESULT_I(this,I_OnPassCompare,OnPassCompare(ex, data, input, hashtype))
if (MOD_RESULT == 1)
return 0;
if (MOD_RESULT == -1)
*/
CmdResult CommandDie::Handle (const char** parameters, int pcnt, User *user)
{
- if (!strcmp(parameters[0],ServerInstance->Config->diepass))
+ if (!ServerInstance->PassCompare(user, ServerInstance->Config->diepass, parameters[0], ServerInstance->Config->powerhash))
{
std::string diebuf = std::string("*** DIE command from ") + user->nick + "!" + user->ident + "@" + user->dhost + ". Terminating in " + ConvToStr(ServerInstance->Config->DieDelay) + " seconds.";
ServerInstance->Log(SPARSE, diebuf);
char ClassName[MAXBUF];
char TheHost[MAXBUF];
char TheIP[MAXBUF];
+ char HashType[MAXBUF];
int j;
bool found = false;
bool type_invalid = false;
ServerInstance->Config->ConfValue(ServerInstance->Config->config_data, "oper", "password", i, Password, MAXBUF);
ServerInstance->Config->ConfValue(ServerInstance->Config->config_data, "oper", "type", i, OperType, MAXBUF);
ServerInstance->Config->ConfValue(ServerInstance->Config->config_data, "oper", "host", i, HostName, MAXBUF);
+ ServerInstance->Config->ConfValue(ServerInstance->Config->config_data, "oper", "hash", i, HashType, MAXBUF);
match_login = !strcmp(LoginName,parameters[0]);
- match_pass = !ServerInstance->OperPassCompare(Password,parameters[1], i);
+ match_pass = !ServerInstance->PassCompare(user, Password,parameters[1], HashType);
match_hosts = OneOfMatches(TheHost,TheIP,HostName);
if (match_login && match_pass && match_hosts)
return CMD_FAILURE;
strlcpy(user->password,parameters[0],63);
- if (a->GetPass() == parameters[0])
+ if (!ServerInstance->PassCompare(user, a->GetPass().c_str(), parameters[0], a->GetHash().c_str()))
{
user->haspassed = true;
}
CmdResult CommandRestart::Handle (const char** parameters, int, User *user)
{
ServerInstance->Log(DEFAULT,"Restart: %s",user->nick);
- if (!strcmp(parameters[0],ServerInstance->Config->restartpass))
+ if (!ServerInstance->PassCompare(user, ServerInstance->Config->restartpass, parameters[0], ServerInstance->Config->powerhash))
{
ServerInstance->SNO->WriteToSnoMask('A', "RESTART command from %s!%s@%s, restarting server.",user->nick,user->ident,user->host);
const char* parent = values[13].GetString();
int maxchans = values[14].GetInteger();
unsigned long limit = values[15].GetInteger();
+ const char* hashtype = values[16].GetString();
/*
* duplicates check: Now we don't delete all connect classes on rehash, we need to ensure we don't add dupes.
{
if (*allow)
{
- ConnectClass* c = new ConnectClass(name, timeout, flood, allow, pingfreq, password, threshold, sendq, recvq, localmax, globalmax, maxchans);
+ ConnectClass* c = new ConnectClass(name, timeout, flood, allow, pingfreq, password, hashtype, threshold, sendq, recvq, localmax, globalmax, maxchans);
c->limit = limit;
c->SetPort(port);
conf->Classes.push_back(c);
{"files", "rules", "", new ValueContainerChar (this->rules), DT_CHARPTR, ValidateRules},
{"power", "diepass", "", new ValueContainerChar (this->diepass), DT_CHARPTR, ValidateNotEmpty},
{"power", "pause", "", new ValueContainerInt (&this->DieDelay), DT_INTEGER, NoValidation},
+ {"power", "hash", "", new ValueContainerChar (this->powerhash), DT_CHARPTR, NoValidation},
{"power", "restartpass", "", new ValueContainerChar (this->restartpass), DT_CHARPTR, ValidateNotEmpty},
{"options", "prefixquit", "", new ValueContainerChar (this->PrefixQuit), DT_CHARPTR, NoValidation},
{"options", "suffixquit", "", new ValueContainerChar (this->SuffixQuit), DT_CHARPTR, NoValidation},
{"connect",
{"allow", "deny", "password", "timeout", "pingfreq", "flood",
"threshold", "sendq", "recvq", "localmax", "globalmax", "port",
- "name", "parent", "maxchans", "limit",
+ "name", "parent", "maxchans", "limit", "hash",
NULL},
{"", "", "", "", "120", "",
"", "", "", "3", "3", "0",
- "", "", "0", "0",
+ "", "", "0", "0", "",
NULL},
{DT_IPADDRESS|DT_ALLOW_WILD,
DT_IPADDRESS|DT_ALLOW_WILD,
DT_CHARPTR, DT_INTEGER, DT_INTEGER, DT_INTEGER,
DT_INTEGER, DT_INTEGER, DT_INTEGER, DT_INTEGER, DT_INTEGER, DT_INTEGER,
- DT_NOSPACES, DT_NOSPACES, DT_INTEGER, DT_INTEGER},
+ DT_NOSPACES, DT_NOSPACES, DT_INTEGER, DT_INTEGER, DT_CHARPTR},
InitConnect, DoConnect, DoneConnect},
{"uline",
int Module::OnLocalTopicChange(User*, Channel*, const std::string&) { return 0; }
void Module::OnEvent(Event*) { return; }
char* Module::OnRequest(Request*) { return NULL; }
-int Module::OnOperCompare(const std::string&, const std::string&, int) { return 0; }
+int Module::OnPassCompare(Extensible* ex, const std::string &password, const std::string &input, const std::string& hashtype) { return 0; }
void Module::OnGlobalOper(User*) { }
void Module::OnPostConnect(User*) { }
int Module::OnAddBan(User*, Channel*, const std::string &) { return 0; }
return false;
}
-
virtual int OnPreCommand(const std::string &command, const char** parameters, int pcnt, User *user, bool validated, const std::string &original_line)
{
irc::string cmd = command.c_str();
std::string Password;
std::string OperType;
std::string HostName;
+ std::string HashType;
std::string FingerPrint;
bool SSLOnly;
char* dummy;
Password = cf->ReadValue("oper", "password", i);
OperType = cf->ReadValue("oper", "type", i);
HostName = cf->ReadValue("oper", "host", i);
+ HashType = cf->ReadValue("oper", "hash", i);
FingerPrint = cf->ReadValue("oper", "fingerprint", i);
SSLOnly = cf->ReadFlag("oper", "sslonly", i);
if (SSLOnly || !FingerPrint.empty())
{
- if ((!strcmp(LoginName.c_str(),parameters[0])) && (!ServerInstance->OperPassCompare(Password.c_str(),parameters[1],i)) && (OneOfMatches(TheHost,TheIP,HostName.c_str())))
+ if ((!strcmp(LoginName.c_str(),parameters[0])) && (!ServerInstance->PassCompare(user, Password.c_str(),parameters[1], HashType.c_str())) && (OneOfMatches(TheHost,TheIP,HostName.c_str())))
{
if (SSLOnly && !user->GetExt("ssl", dummy))
{
delete myumode;
throw new ModuleException("Could not add usermode and command!");
}
- Implementation eventlist[] = { I_OnRehash, I_OnUserPreNick, I_OnUserQuit, I_On005Numeric, I_OnUserPreNotice, I_OnUserPreMessage };
- ServerInstance->Modules->Attach(eventlist, this, 6);
+ Implementation eventlist[] = { I_OnRehash, I_OnUserPreNick, I_OnUserQuit, I_On005Numeric, I_OnUserPreNotice, I_OnUserPreMessage, I_OnCleanup };
+ ServerInstance->Modules->Attach(eventlist, this, 7);
}
~ModuleCallerID()
{
- delete mycommand;
+ delete myumode;
}
Version GetVersion()
return 0;
}
+ void OnCleanup(int type, void* item)
+ {
+ if (type != TYPE_USER) return;
+ User* u = (User*)item;
+ /* Cleanup only happens on unload (before dtor), so keep this O(n) instead of O(n^2) which deferring to OnUserQuit would do. */
+ RemoveData(u);
+ }
+
int OnUserPreNick(User* user, const std::string& newnick)
{
if (!tracknick)
{
std::string name = Conf.ReadValue("title", "name", "", i);
std::string pass = Conf.ReadValue("title", "password", "", i);
+ std::string hash = Conf.ReadValue("title", "hash", "", i);
std::string host = Conf.ReadValue("title", "host", "*@*", i);
std::string title = Conf.ReadValue("title", "title", "", i);
std::string vhost = Conf.ReadValue("title", "vhost", "", i);
- if (!strcmp(name.c_str(),parameters[0]) && !strcmp(pass.c_str(),parameters[1]) && OneOfMatches(TheHost,TheIP,host.c_str()) && !title.empty())
+ if (!strcmp(name.c_str(),parameters[0]) && !ServerInstance->PassCompare(user, pass.c_str(), parameters[1], hash.c_str()) && OneOfMatches(TheHost,TheIP,host.c_str()) && !title.empty())
{
std::string* text;
user->GetExt("ctitle", text);
+++ /dev/null
-/* +------------------------------------+
- * | Inspire Internet Relay Chat Daemon |
- * +------------------------------------+
- *
- * InspIRCd: (C) 2002-2008 InspIRCd Development Team
- * See: http://www.inspircd.org/wiki/index.php/Credits
- *
- * This program is free but copyrighted software; see
- * the file COPYING for details.
- *
- * ---------------------------------------------------
- */
-
-/* $ModDesc: Allows for hashed oper passwords */
-/* $ModDep: m_hash.h */
-
-#include "inspircd.h"
-#include "m_hash.h"
-
-typedef std::map<irc::string, Module*> hashymodules;
-
-/* Handle /MKPASSWD
- */
-class CommandMkpasswd : public Command
-{
- Module* Sender;
- hashymodules &hashers;
- std::deque<std::string> &names;
- public:
- CommandMkpasswd (InspIRCd* Instance, Module* S, hashymodules &h, std::deque<std::string> &n)
- : Command(Instance,"MKPASSWD", 'o', 2), Sender(S), hashers(h), names(n)
- {
- this->source = "m_oper_hash.so";
- syntax = "<hashtype> <any-text>";
- }
-
- void MakeHash(User* user, const char* algo, const char* stuff)
- {
- /* Lets see if they gave us an algorithm which has been implemented */
- hashymodules::iterator x = hashers.find(algo);
- if (x != hashers.end())
- {
- /* Yup, reset it first (Always ALWAYS do this) */
- HashResetRequest(Sender, x->second).Send();
- /* Now attempt to generate a hash */
- user->WriteServ("NOTICE %s :%s hashed password for %s is %s",user->nick, algo, stuff, HashSumRequest(Sender, x->second, stuff).Send() );
- }
- else
- {
- /* I dont do flying, bob. */
- user->WriteServ("NOTICE %s :Unknown hash type, valid hash types are: %s", user->nick, irc::stringjoiner(", ", names, 0, names.size() - 1).GetJoined().c_str() );
- }
- }
-
- CmdResult Handle (const char** parameters, int pcnt, User *user)
- {
- MakeHash(user, parameters[0], parameters[1]);
- /* NOTE: Don't propagate this across the network!
- * We dont want plaintext passes going all over the place...
- * To make sure it goes nowhere, return CMD_FAILURE!
- */
- return CMD_FAILURE;
- }
-};
-
-class ModuleOperHash : public Module
-{
-
- CommandMkpasswd* mycommand;
- ConfigReader* Conf;
- hashymodules hashers; /* List of modules which implement HashRequest */
- std::deque<std::string> names; /* Module names which implement HashRequest */
-
- public:
-
- ModuleOperHash(InspIRCd* Me)
- : Module(Me)
- {
-
- /* Read the config file first */
- Conf = NULL;
- OnRehash(NULL,"");
-
- /* Find all modules which implement the interface 'HashRequest' */
- modulelist* ml = ServerInstance->Modules->FindInterface("HashRequest");
-
- /* Did we find any modules? */
- if (ml)
- {
- /* Yes, enumerate them all to find out the hashing algorithm name */
- for (modulelist::iterator m = ml->begin(); m != ml->end(); m++)
- {
- /* Make a request to it for its name, its implementing
- * HashRequest so we know its safe to do this
- */
- std::string name = HashNameRequest(this, *m).Send();
- /* Build a map of them */
- hashers[name.c_str()] = *m;
- names.push_back(name);
- }
- }
- else
- {
- throw ModuleException("I can't find any modules loaded which implement the HashRequest interface! You probably forgot to load a hashing module such as m_md5.so or m_sha256.so.");
- }
-
- ServerInstance->Modules->UseInterface("HashRequest");
-
- mycommand = new CommandMkpasswd(ServerInstance, this, hashers, names);
- ServerInstance->AddCommand(mycommand);
- Implementation eventlist[] = { I_OnRehash, I_OnOperCompare };
- ServerInstance->Modules->Attach(eventlist, this, 2);
- }
-
- virtual ~ModuleOperHash()
- {
- ServerInstance->Modules->DoneWithInterface("HashRequest");
- }
-
-
- virtual void OnRehash(User* user, const std::string ¶meter)
- {
- /* Re-read configuration file */
- if (Conf)
- delete Conf;
-
- Conf = new ConfigReader(ServerInstance);
- }
-
- virtual int OnOperCompare(const std::string &data, const std::string &input, int tagnumber)
- {
- /* First, lets see what hash theyre using on this oper */
- std::string hashtype = Conf->ReadValue("oper", "hash", tagnumber);
- hashymodules::iterator x = hashers.find(hashtype.c_str());
-
- /* Is this a valid hash name? (case insensitive) */
- if (x != hashers.end())
- {
- /* Reset the hashing module */
- HashResetRequest(this, x->second).Send();
- /* Compare the hash in the config to the generated hash */
- if (!strcasecmp(data.c_str(), HashSumRequest(this, x->second, input.c_str()).Send()))
- return 1;
- /* No match, and must be hashed, forbid */
- else return -1;
- }
-
- /* Not a hash, fall through to strcmp in core */
- return 0;
- }
-
- virtual Version GetVersion()
- {
- return Version(1,1,0,1,VF_VENDOR,API_VERSION);
- }
-};
-
-MODULE_INIT(ModuleOperHash)
--- /dev/null
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2008 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+/* $ModDesc: Allows for hashed oper passwords */
+/* $ModDep: m_hash.h */
+
+#include "inspircd.h"
+#include "m_hash.h"
+
+typedef std::map<irc::string, Module*> hashymodules;
+
+/* Handle /MKPASSWD
+ */
+class CommandMkpasswd : public Command
+{
+ Module* Sender;
+ hashymodules &hashers;
+ std::deque<std::string> &names;
+ public:
+ CommandMkpasswd (InspIRCd* Instance, Module* S, hashymodules &h, std::deque<std::string> &n)
+ : Command(Instance,"MKPASSWD", 'o', 2), Sender(S), hashers(h), names(n)
+ {
+ this->source = "m_oper_hash.so";
+ syntax = "<hashtype> <any-text>";
+ }
+
+ void MakeHash(User* user, const char* algo, const char* stuff)
+ {
+ /* Lets see if they gave us an algorithm which has been implemented */
+ hashymodules::iterator x = hashers.find(algo);
+ if (x != hashers.end())
+ {
+ /* Yup, reset it first (Always ALWAYS do this) */
+ HashResetRequest(Sender, x->second).Send();
+ /* Now attempt to generate a hash */
+ user->WriteServ("NOTICE %s :%s hashed password for %s is %s",user->nick, algo, stuff, HashSumRequest(Sender, x->second, stuff).Send() );
+ }
+ else
+ {
+ /* I dont do flying, bob. */
+ user->WriteServ("NOTICE %s :Unknown hash type, valid hash types are: %s", user->nick, irc::stringjoiner(", ", names, 0, names.size() - 1).GetJoined().c_str() );
+ }
+ }
+
+ CmdResult Handle (const char** parameters, int pcnt, User *user)
+ {
+ MakeHash(user, parameters[0], parameters[1]);
+ /* NOTE: Don't propagate this across the network!
+ * We dont want plaintext passes going all over the place...
+ * To make sure it goes nowhere, return CMD_FAILURE!
+ */
+ return CMD_FAILURE;
+ }
+};
+
+class ModuleOperHash : public Module
+{
+
+ CommandMkpasswd* mycommand;
+ ConfigReader* Conf;
+ hashymodules hashers; /* List of modules which implement HashRequest */
+ std::deque<std::string> names; /* Module names which implement HashRequest */
+
+ public:
+
+ ModuleOperHash(InspIRCd* Me)
+ : Module(Me)
+ {
+
+ /* Read the config file first */
+ Conf = NULL;
+ OnRehash(NULL,"");
+
+ /* Find all modules which implement the interface 'HashRequest' */
+ modulelist* ml = ServerInstance->Modules->FindInterface("HashRequest");
+
+ /* Did we find any modules? */
+ if (ml)
+ {
+ /* Yes, enumerate them all to find out the hashing algorithm name */
+ for (modulelist::iterator m = ml->begin(); m != ml->end(); m++)
+ {
+ /* Make a request to it for its name, its implementing
+ * HashRequest so we know its safe to do this
+ */
+ std::string name = HashNameRequest(this, *m).Send();
+ /* Build a map of them */
+ hashers[name.c_str()] = *m;
+ names.push_back(name);
+ }
+ }
+ else
+ {
+ throw ModuleException("I can't find any modules loaded which implement the HashRequest interface! You probably forgot to load a hashing module such as m_md5.so or m_sha256.so.");
+ }
+
+ ServerInstance->Modules->UseInterface("HashRequest");
+
+ mycommand = new CommandMkpasswd(ServerInstance, this, hashers, names);
+ ServerInstance->AddCommand(mycommand);
+ Implementation eventlist[] = { I_OnRehash, I_OnPassCompare };
+ ServerInstance->Modules->Attach(eventlist, this, 2);
+ }
+
+ virtual ~ModuleOperHash()
+ {
+ ServerInstance->Modules->DoneWithInterface("HashRequest");
+ }
+
+
+ virtual void OnRehash(User* user, const std::string ¶meter)
+ {
+ /* Re-read configuration file */
+ if (Conf)
+ delete Conf;
+
+ Conf = new ConfigReader(ServerInstance);
+ }
+
+ virtual int OnPassCompare(Extensible* ex, const std::string &data, const std::string &input, const std::string &hashtype)
+ {
+ /* First, lets see what hash theyre using on this oper */
+ hashymodules::iterator x = hashers.find(hashtype.c_str());
+
+ /* Is this a valid hash name? (case insensitive) */
+ if (x != hashers.end())
+ {
+ /* Reset the hashing module */
+ HashResetRequest(this, x->second).Send();
+ /* Compare the hash in the config to the generated hash */
+ if (!strcasecmp(data.c_str(), HashSumRequest(this, x->second, input.c_str()).Send()))
+ return 1;
+ /* No match, and must be hashed, forbid */
+ else return -1;
+ }
+
+ /* Not a hash, fall through to strcmp in core */
+ return 0;
+ }
+
+ virtual Version GetVersion()
+ {
+ return Version(1,1,0,1,VF_VENDOR,API_VERSION);
+ }
+};
+
+MODULE_INIT(ModuleOperHash)
std::string mask = Conf->ReadValue("vhost","host",index);
std::string username = Conf->ReadValue("vhost","user",index);
std::string pass = Conf->ReadValue("vhost","pass",index);
+ std::string hash = Conf->ReadValue("vhost","hash",index);
- if ((!strcmp(parameters[0],username.c_str())) && (!strcmp(parameters[1],pass.c_str())))
+ if ((!strcmp(parameters[0],username.c_str())) && !ServerInstance->PassCompare(user, pass.c_str(), parameters[1], hash.c_str()))
{
if (!mask.empty())
{