X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Fm_hostchange.cpp;h=201c4b59b3abad3eaa4114ae004cd695d6e77e01;hb=9a312de26b742e9c399a84a70b175a88fb4bc1ac;hp=a9bacb8677c147fe76436cf26a871fda01f98634;hpb=3a554ef1e9be9dbcf3de3301a4a6c2938d643bea;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/modules/m_hostchange.cpp b/src/modules/m_hostchange.cpp index a9bacb867..201c4b59b 100644 --- a/src/modules/m_hostchange.cpp +++ b/src/modules/m_hostchange.cpp @@ -1,168 +1,238 @@ -/* +------------------------------------+ - * | Inspire Internet Relay Chat Daemon | - * +------------------------------------+ +/* + * InspIRCd -- Internet Relay Chat Daemon * - * InspIRCd: (C) 2002-2007 InspIRCd Development Team - * See: http://www.inspircd.org/wiki/index.php/Credits + * Copyright (C) 2005-2007 Craig Edwards + * Copyright (C) 2007 Dennis Friis + * Copyright (C) 2007 Robin Burchell * - * This program is free but copyrighted software; see - * the file COPYING for details. + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. * - * --------------------------------------------------- + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ -#include -#include "users.h" -#include "channels.h" -#include "modules.h" -#include "inspircd.h" -/* $ModDesc: Provides masking of user hostnames in a different way to m_cloaking */ +#include "inspircd.h" +#include "modules/account.h" -/** Holds information on a host set by m_hostchange - */ -class Host : public classbase +// Holds information about a rule. +class HostRule { public: - std::string action; - std::string newhost; -}; + enum HostChangeAction + { + // Add the user's account name to their hostname. + HCA_ADDACCOUNT, -typedef std::map hostchanges_t; + // Add the user's nickname to their hostname. + HCA_ADDNICK, + + // Set the user's hostname to the specific value. + HCA_SET + }; -class ModuleHostChange : public Module -{ private: + HostChangeAction action; + std::string host; + std::string mask; + insp::flat_set ports; + std::string prefix; + std::string suffix; - - ConfigReader *Conf; - hostchanges_t hostchanges; - std::string MySuffix; - public: - ModuleHostChange(InspIRCd* Me) - : Module::Module(Me) + HostRule(const std::string& Host, const std::string& Mask, const insp::flat_set& Ports) + : action(HCA_SET) + , host(Host) + , mask(Mask) + , ports(Ports) { - - Conf = new ConfigReader(ServerInstance); - OnRehash(""); } - - virtual ~ModuleHostChange() + + HostRule(HostChangeAction Action, const std::string& Mask, const insp::flat_set& Ports, const std::string& Prefix, const std::string& Suffix) + : action(Action) + , mask(Mask) + , ports(Ports) + , prefix(Prefix) + , suffix(Suffix) { - DELETE(Conf); } - Priority Prioritize() + HostChangeAction GetAction() const { - return (Priority)ServerInstance->PriorityAfter("m_cloaking.so"); + return action; } - void Implements(char* List) + const std::string& GetHost() const { - List[I_OnRehash] = List[I_OnUserConnect] = 1; + return host; } - virtual void OnRehash(const std::string ¶meter) + bool Matches(LocalUser* user) const { - DELETE(Conf); - Conf = new ConfigReader(ServerInstance); - MySuffix = Conf->ReadValue("host","suffix",0); - for (hostchanges_t::iterator i = hostchanges.begin(); i != hostchanges.end(); i++) - { - DELETE(i->second); - } - hostchanges.clear(); - for (int index = 0; index < Conf->Enumerate("hostchange"); index++) - { - std::string mask = Conf->ReadValue("hostchange","mask",index); - std::string action = Conf->ReadValue("hostchange","action",index); - std::string newhost = Conf->ReadValue("hostchange","value",index); - Host* x = new Host; - x->action = action; - x->newhost = newhost; - hostchanges[mask] = x; - } + if (!ports.empty() && !ports.count(user->GetServerPort())) + return false; + + if (InspIRCd::MatchCIDR(user->MakeHost(), mask)) + return true; + + return InspIRCd::MatchCIDR(user->MakeHostIP(), mask); } - - virtual Version GetVersion() + + void Wrap(const std::string& value, std::string& out) const { - // returns the version number of the module to be - // listed in /MODULES - return Version(1,1,0,1,VF_VENDOR,API_VERSION); + if (!prefix.empty()) + out.append(prefix); + + out.append(value); + + if (!suffix.empty()) + out.append(suffix); } - - virtual void OnUserConnect(userrec* user) +}; + +typedef std::vector HostRules; + +class ModuleHostChange : public Module +{ +private: + std::bitset hostmap; + HostRules hostrules; + + std::string CleanName(const std::string& name) { - for (hostchanges_t::iterator i = hostchanges.begin(); i != hostchanges.end(); i++) + std::string buffer; + buffer.reserve(name.length()); + for (std::string::const_iterator iter = name.begin(); iter != name.end(); ++iter) { - if (ServerInstance->MatchText(std::string(user->ident)+"@"+std::string(user->host),i->first)) + if (hostmap.test(static_cast(*iter))) { - Host* h = (Host*)i->second; - // host of new user matches a hostchange tag's mask - std::string newhost = ""; - if (h->action == "set") - { - newhost = h->newhost; - } - else if (h->action == "suffix") - { - newhost = MySuffix; - } - else if (h->action == "addnick") - { - // first take their nick and strip out non-dns, leaving just [A-Z0-9\-] - std::string complete = ""; - std::string old = user->nick; - for (unsigned int j = 0; j < old.length(); j++) - { - if (((old[j] >= 'A') && (old[j] <= 'Z')) || - ((old[j] >= 'a') && (old[j] <= 'z')) || - ((old[j] >= '0') && (old[j] <= '9')) || - (old[j] == '-')) - { - complete = complete + old[j]; - } - } - if (complete == "") - complete = "i-have-a-lame-nick"; - newhost = complete + "." + MySuffix; - } - if (newhost != "") - { - user->WriteServ("NOTICE "+std::string(user->nick)+" :Setting your virtual host: " + newhost); - if (!user->ChangeDisplayedHost(newhost.c_str())) - user->WriteServ("NOTICE "+std::string(user->nick)+" :Could not set your virtual host: " + newhost); - return; - } + buffer.push_back(*iter); } } + return buffer; } -}; - -// stuff down here is the module-factory stuff. For basic modules you can ignore this. -class ModuleHostChangeFactory : public ModuleFactory -{ public: - ModuleHostChangeFactory() + void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE { + HostRules rules; + + ConfigTagList tags = ServerInstance->Config->ConfTags("hostchange"); + for (ConfigIter i = tags.first; i != tags.second; ++i) + { + ConfigTag* tag = i->second; + + // Ensure that we have the parameter. + const std::string mask = tag->getString("mask"); + if (mask.empty()) + throw ModuleException(" is a mandatory field, at " + tag->getTagLocation()); + + insp::flat_set ports; + const std::string portlist = tag->getString("ports"); + if (!ports.empty()) + { + irc::portparser portrange(portlist, false); + while (int port = portrange.GetToken()) + ports.insert(port); + } + + // Determine what type of host rule this is. + const std::string action = tag->getString("action"); + if (stdalgo::string::equalsci(action, "addaccount")) + { + // The hostname is in the format [prefix][suffix]. + rules.push_back(HostRule(HostRule::HCA_ADDACCOUNT, mask, ports, tag->getString("prefix"), tag->getString("suffix"))); + } + else if (stdalgo::string::equalsci(action, "addnick")) + { + // The hostname is in the format [prefix][suffix]. + rules.push_back(HostRule(HostRule::HCA_ADDNICK, mask, ports, tag->getString("prefix"), tag->getString("suffix"))); + } + else if (stdalgo::string::equalsci(action, "set")) + { + // Ensure that we have the parameter. + const std::string value = tag->getString("value"); + if (value.empty()) + throw ModuleException(" is a mandatory field when using the 'set' action, at " + tag->getTagLocation()); + + // The hostname is in the format . + rules.push_back(HostRule(mask, value, ports)); + continue; + } + else + { + throw ModuleException(action + " is an invalid type, at " + tag->getTagLocation()); + } + } + + const std::string hmap = ServerInstance->Config->ConfValue("hostname")->getString("charmap", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.-_/0123456789"); + hostmap.reset(); + for (std::string::const_iterator iter = hmap.begin(); iter != hmap.end(); ++iter) + hostmap.set(static_cast(*iter)); + hostrules.swap(rules); } - - ~ModuleHostChangeFactory() + + Version GetVersion() CXX11_OVERRIDE { + return Version("Provides rule-based masking of user hostnames", VF_VENDOR); } - - virtual Module * CreateModule(InspIRCd* Me) + + void OnUserConnect(LocalUser* user) CXX11_OVERRIDE { - return new ModuleHostChange(Me); - } - -}; + for (HostRules::const_iterator iter = hostrules.begin(); iter != hostrules.end(); ++iter) + { + const HostRule& rule = *iter; + if (!rule.Matches(user)) + continue; + + std::string newhost; + if (rule.GetAction() == HostRule::HCA_ADDACCOUNT) + { + // Retrieve the account name. + const AccountExtItem* accountext = GetAccountExtItem(); + const std::string* accountptr = accountext ? accountext->get(user) : NULL; + if (!accountptr) + continue; + // Remove invalid hostname characters. + std::string accountname = CleanName(*accountptr); + if (accountname.empty()) + continue; -extern "C" void * init_module( void ) -{ - return new ModuleHostChangeFactory; -} + // Create the hostname. + rule.Wrap(accountname, newhost); + } + else if (rule.GetAction() == HostRule::HCA_ADDNICK) + { + // Remove invalid hostname characters. + const std::string nickname = CleanName(user->nick); + if (nickname.empty()) + continue; + + // Create the hostname. + rule.Wrap(nickname, newhost); + } + else if (rule.GetAction() == HostRule::HCA_SET) + { + newhost.assign(rule.GetHost()); + } + + if (!newhost.empty()) + { + user->WriteNotice("Setting your virtual host: " + newhost); + if (!user->ChangeDisplayedHost(newhost)) + user->WriteNotice("Could not set your virtual host: " + newhost); + return; + } + } + } +}; +MODULE_INIT(ModuleHostChange)