/* +------------------------------------+ * | Inspire Internet Relay Chat Daemon | * +------------------------------------+ * * InspIRCd: (C) 2002-2010 InspIRCd Development Team * See: http://wiki.inspircd.org/Credits * * This program is free but copyrighted software; see * the file COPYING for details. * * --------------------------------------------------- */ #include "m_accounts.h" /* $ModDesc: Provides some basic NickServ functionality even if services are down */ /* TODO: [x] get the data from services and store it in a map [x] find a way to handle NickAlias ? [x] add a /login function [ ] use the server password on connect [x] only activate when services are down? make a config option for it ??? [ ] find a way to handle encrypted passwords [ ] port some encryption modules from anope (each mod as a seperate class ?) [ ] password changing ? */ /** Handle /LOGIN */ NickCore *FindCore(const std::string &nick) { core_hash::iterator iter = accountlist.find(nick); if (iter == accountlist.end()) { return NULL; } return iter->second; } class CommandLogin : public Command { public: CommandLogin(Module* Creator) : Command(Creator,"LOGIN", 1) { syntax = " "; TRANSLATE3(TR_TEXT, TR_TEXT, TR_END); } CmdResult Handle (const std::vector ¶meters, User *user) { // 1. check if the given username exists NickCore *nc = FindCore(parameters[0]); if (!nc) { user->WriteServ("NOTICE %s :*** Account %s not registered", user->nick.c_str(), parameters[0].c_str()); return CMD_FAILURE; } if (parameters.size() == 1) { if (CheckFingerprint(user, nc, this->creator)) { user->WriteServ("NOTICE %s :*** Fingerprint matches!", user->nick.c_str()); LoginUser(user, nc->display, this->creator); return CMD_SUCCESS; } user->WriteNumeric(ERR_NEEDMOREPARAMS, "%s %s :Not enough parameters.", user->nick.c_str(), this->name.c_str()); user->WriteNumeric(RPL_SYNTAX, "%s :SYNTAX %s %s", user->nick.c_str(), this->name.c_str(), this->syntax.c_str()); return CMD_FAILURE; } if (CheckPassword(nc, parameters[1])) { user->WriteServ("NOTICE %s :*** Password matches!", user->nick.c_str()); LoginUser(user, nc->display, this->creator); return CMD_SUCCESS; } else { user->WriteServ("NOTICE %s :*** Wrong password!", user->nick.c_str()); } return CMD_FAILURE; } }; class CommandAcc : public Command { public: CommandAcc(Module* Creator) : Command(Creator, "ACC", 3) { this->flags_needed = FLAG_SERVERONLY; TRANSLATE3(TR_TEXT, TR_TEXT, TR_END); } CmdResult Handle (const std::vector& parameters, User *user) { ServerInstance->Logs->Log("m_accounts", DEBUG, "RECEVEIVED ENCAP: parameters[0] = %s, parameters[1] = %s, parameters[2] = %s", parameters[0].c_str(), parameters[1].c_str(), parameters[2].c_str()); if (parameters[0] == "NC+") // add a new nickcore { // split the password in hash and pass size_t pos = parameters[2].find(":"); if (pos == std::string::npos) { ServerInstance->Logs->Log("m_accounts", DEBUG, "Received invalid password field, ignoring last message"); return CMD_SUCCESS; } // now create a new nickcore and insert it into the list NickCore *nc = new NickCore(); accountlist[parameters[1]] = nc; nc->display.assign(parameters[1]); nc->hash.assign(parameters[2].begin(), parameters[2].begin()+pos); nc->pass.assign(parameters[2].begin()+pos+1, parameters[2].end());; } else if (parameters[0] == "NC-") // delete the nickcore { accountlist.erase(parameters[1]); } else if (parameters[0] == "NCc") // rename the nickcore, that happens when a nick from the nickgroup gets dropped/expired { core_hash::iterator iter = accountlist.find(parameters[1]); if (iter != accountlist.end()) { accountlist[parameters[2]] = iter->second; accountlist.erase(parameters[1]); } else { ServerInstance->Logs->Log("m_accounts", DEBUG, "Error: Received update for nonexistant NickCore"); } } else if (parameters[0] == "ACCESS+") // add a single entry to the list { core_hash::iterator iter = accountlist.find(parameters[1]); iter->second->access.push_back(parameters[2]); } else if (parameters[0] == "ACCESS-") // delete a single entry from the list { core_hash::iterator iter = accountlist.find(parameters[1]); if (iter != accountlist.end()) { for (unsigned i = 0; i < iter->second->access.size(); ++i) { if (iter->second->access[i] == parameters[2]) iter->second->access.erase(iter->second->access.begin()+i); } } else { ServerInstance->Logs->Log("m_accounts", DEBUG, "Error: Received ACCESS- for nonexistant NickCore"); } } else if (parameters[0] == "ACCESS--") // delete the complete access list { NickCore *nc = FindCore(parameters[1]); if (nc) nc->access.clear(); else ServerInstance->Logs->Log("m_accounts", DEBUG, "Error: Received ACESS-- for nonexistant NickCore"); } else if (parameters[0] == "ALIAS") // add a new nickalias { if (parameters[1] == parameters[2]) return CMD_SUCCESS; // nothing to do (we should never reach this point) NickCore *nc = FindCore(parameters[1]); if (nc) { NickCore *nc2 = new NickCore(); accountlist[parameters[2]] = nc2; nc2->display = parameters[1]; nc2->hash = nc->hash; nc2->pass = nc->pass; } else { ServerInstance->Logs->Log("m_accounts", DEBUG, "Error: Received ALIAS for nonexistant NickCore"); return CMD_SUCCESS; } } return CMD_SUCCESS; } }; class ModuleAccounts : public Module { CommandLogin cmd_login; CommandAcc cmd_acc; public: ModuleAccounts() : cmd_login(this), cmd_acc(this) { ServerInstance->AddCommand(&cmd_login); ServerInstance->AddCommand(&cmd_acc); Implementation eventlist[] = { I_OnUserPreCommand, I_OnUserRegister }; ServerInstance->Modules->Attach(eventlist, this, 2); } ModResult OnUserRegister(LocalUser *user) { NickCore *nc = FindCore(user->nick); if (!nc) return MOD_RES_PASSTHRU; if ((!user->password.empty() && CheckPassword(nc, user->password)) || CheckFingerprint(user, nc, this)) LoginUser(User, nc->display, this) return MOD_RES_PASSTHRU; } ModResult OnPreCommand(std::string &command, std::vector ¶meters, LocalUser *user, bool validated, const std::string &original_line) { bool IsIdentified; if (command != "NICK") return MOD_RES_PASSTRU; NickCore *nc = FindCore(user->nick); // nick not registered if (!nc) return MOD_RES_PASSTRU; // auto-ghost old nick ? // auto-identify return MOD_RES_PASSTRU; } virtual ~ModuleAccounts() { } virtual Version GetVersion() { return Version("$Id$"); } }; MODULE_INIT(ModuleAccounts)