]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/configreader.cpp
Add support for blocking tag messages with the deaf mode.
[user/henk/code/inspircd.git] / src / configreader.cpp
index 52217722cc5b07f16cf9fdd63aa0dde659f0427b..2cd17e844bcd0b62e7f42281395ac1fd1f0d8461 100644 (file)
@@ -1,12 +1,21 @@
 /*
  * InspIRCd -- Internet Relay Chat Daemon
  *
- *   Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
- *   Copyright (C) 2007-2009 Robin Burchell <robin+git@viroteck.net>
- *   Copyright (C) 2006-2009 Dennis Friis <peavey@inspircd.org>
- *   Copyright (C) 2006-2008 Craig Edwards <craigedwards@brainbox.cc>
+ *   Copyright (C) 2019 Matt Schatz <genius3000@g3k.solutions>
+ *   Copyright (C) 2013-2016 Attila Molnar <attilamolnar@hush.com>
+ *   Copyright (C) 2013-2014, 2016-2021 Sadie Powell <sadie@witchery.services>
+ *   Copyright (C) 2013 Daniel Vassdal <shutter@canternet.org>
+ *   Copyright (C) 2012 Robby <robby@chatbelgie.be>
+ *   Copyright (C) 2012 Justin Crawford <Justasic@Gmail.com>
+ *   Copyright (C) 2012 DjSlash <djslash@djslash.org>
+ *   Copyright (C) 2012 ChrisTX <xpipe@hotmail.de>
+ *   Copyright (C) 2009-2011 Daniel De Graaf <danieldg@inspircd.org>
+ *   Copyright (C) 2009 Uli Schlachter <psychon@inspircd.org>
  *   Copyright (C) 2008 Thomas Stagner <aquanight@inspircd.org>
- *   Copyright (C) 2006 Oliver Lupton <oliverlupton@gmail.com>
+ *   Copyright (C) 2007-2010 Robin Burchell <robin+git@viroteck.net>
+ *   Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
+ *   Copyright (C) 2006-2008 Craig Edwards <brain@inspircd.org>
+ *   Copyright (C) 2006 Oliver Lupton <om@inspircd.org>
  *
  * 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
 #include <iostream>
 
 ServerLimits::ServerLimits(ConfigTag* tag)
-       : NickMax(tag->getUInt("maxnick", 30))
-       , ChanMax(tag->getUInt("maxchan", 64))
-       , MaxModes(tag->getUInt("maxmodes", 20))
-       , IdentMax(tag->getUInt("maxident", 10))
-       , MaxQuit(tag->getUInt("maxquit", 255))
-       , MaxTopic(tag->getUInt("maxtopic", 307))
-       , MaxKick(tag->getUInt("maxkick", 255))
-       , MaxReal(tag->getUInt("maxreal", tag->getUInt("maxgecos", 128)))
-       , MaxAway(tag->getUInt("maxaway", 200))
-       , MaxLine(tag->getUInt("maxline", 512))
-       , MaxHost(tag->getUInt("maxhost", 64))
+       : MaxLine(tag->getUInt("maxline", 512, 512))
+       , NickMax(tag->getUInt("maxnick", 30, 1, MaxLine))
+       , ChanMax(tag->getUInt("maxchan", 64, 1, MaxLine))
+       , MaxModes(tag->getUInt("maxmodes", 20, 1))
+       , IdentMax(tag->getUInt("maxident", 10, 1))
+       , MaxQuit(tag->getUInt("maxquit", 255, 0, MaxLine))
+       , MaxTopic(tag->getUInt("maxtopic", 307, 1, MaxLine))
+       , MaxKick(tag->getUInt("maxkick", 255, 1, MaxLine))
+       , MaxReal(tag->getUInt("maxreal", tag->getUInt("maxgecos", 128), 1, MaxLine))
+       , MaxAway(tag->getUInt("maxaway", 200, 1, MaxLine))
+       , MaxHost(tag->getUInt("maxhost", 64, 1, MaxLine))
 {
 }
 
 ServerConfig::ServerPaths::ServerPaths(ConfigTag* tag)
-       : Config(tag->getString("configdir", INSPIRCD_CONFIG_PATH))
-       , Data(tag->getString("datadir", INSPIRCD_DATA_PATH))
-       , Log(tag->getString("logdir", INSPIRCD_LOG_PATH))
-       , Module(tag->getString("moduledir", INSPIRCD_MODULE_PATH))
+       : Config(tag->getString("configdir", INSPIRCD_CONFIG_PATH, 1))
+       , Data(tag->getString("datadir", INSPIRCD_DATA_PATH, 1))
+       , Log(tag->getString("logdir", INSPIRCD_LOG_PATH, 1))
+       , Module(tag->getString("moduledir", INSPIRCD_MODULE_PATH, 1))
+       , Runtime(tag->getString("runtimedir", INSPIRCD_RUNTIME_PATH, 1))
 {
 }
 
@@ -72,46 +82,31 @@ ServerConfig::~ServerConfig()
        delete EmptyTag;
 }
 
-bool ServerConfig::ApplyDisabledCommands()
-{
-       // Enable everything first.
-       const CommandParser::CommandMap& commands = ServerInstance->Parser.GetCommands();
-       for (CommandParser::CommandMap::const_iterator x = commands.begin(); x != commands.end(); ++x)
-               x->second->Disable(false);
-
-       // Now disable the commands specified in the config.
-       std::string command;
-       irc::spacesepstream commandlist(ConfValue("disabled")->getString("commands"));
-       while (commandlist.GetToken(command))
-       {
-               Command* handler = ServerInstance->Parser.GetHandler(command);
-               if (!handler)
-               {
-                       ServerInstance->Logs->Log("CONFIG", LOG_DEBUG, "Unable to disable the %s command as it does not exist!", command.c_str());
-                       continue;
-               }
-
-               ServerInstance->Logs->Log("CONFIG", LOG_DEBUG, "The %s command has been disabled", command.c_str());
-               handler->Disable(true);
-       }
-       return true;
-}
-
 static void ReadXLine(ServerConfig* conf, const std::string& tag, const std::string& key, XLineFactory* make)
 {
+       insp::flat_set<std::string> configlines;
+
        ConfigTagList tags = conf->ConfTags(tag);
        for(ConfigIter i = tags.first; i != tags.second; ++i)
        {
                ConfigTag* ctag = i->second;
-               std::string mask;
-               if (!ctag->readString(key, mask))
-                       throw CoreException("<"+tag+":"+key+"> missing at " + ctag->getTagLocation());
-               std::string reason = ctag->getString("reason", "<Config>");
-               XLine* xl = make->Generate(ServerInstance->Time(), 0, "<Config>", reason, mask);
+
+               const std::string mask = ctag->getString(key);
+               if (mask.empty())
+                       throw CoreException("<" + tag + ":" + key + "> missing at " + ctag->getTagLocation());
+
+               const std::string reason = ctag->getString("reason");
+               if (reason.empty())
+                       throw CoreException("<" + tag + ":reason> missing at " + ctag->getTagLocation());
+
+               XLine* xl = make->Generate(ServerInstance->Time(), 0, ServerInstance->Config->ServerName, reason, mask);
                xl->from_config = true;
+               configlines.insert(xl->Displayable());
                if (!ServerInstance->XLines->AddLine(xl, NULL))
                        delete xl;
        }
+
+       ServerInstance->XLines->ExpireRemovedConfigLines(make->GetType(), configlines);
 }
 
 typedef std::map<std::string, ConfigTag*> LocalIndex;
@@ -180,22 +175,23 @@ void ServerConfig::CrossCheckOperClassType()
 
 void ServerConfig::CrossCheckConnectBlocks(ServerConfig* current)
 {
-       typedef std::map<std::string, ConnectClass*> ClassMap;
+       typedef std::map<std::pair<std::string, char>, ConnectClass*> ClassMap;
        ClassMap oldBlocksByMask;
        if (current)
        {
                for(ClassVector::iterator i = current->Classes.begin(); i != current->Classes.end(); ++i)
                {
                        ConnectClass* c = *i;
-                       if (c->name.compare(0, 8, "unnamed-", 8))
-                       {
-                               oldBlocksByMask["n" + c->name] = c;
-                       }
-                       else if (c->type == CC_ALLOW || c->type == CC_DENY)
+                       switch (c->type)
                        {
-                               std::string typeMask = (c->type == CC_ALLOW) ? "a" : "d";
-                               typeMask += c->host;
-                               oldBlocksByMask[typeMask] = c;
+                               case CC_ALLOW:
+                               case CC_DENY:
+                                       oldBlocksByMask[std::make_pair(c->host, c->type)] = c;
+                                       break;
+
+                               case CC_NAMED:
+                                       oldBlocksByMask[std::make_pair(c->name, c->type)] = c;
+                                       break;
                        }
                }
        }
@@ -243,24 +239,17 @@ void ServerConfig::CrossCheckConnectBlocks(ServerConfig* current)
                        }
 
                        std::string name = tag->getString("name");
-                       std::string mask, typeMask;
+                       std::string mask;
                        char type;
 
                        if (tag->readString("allow", mask, false))
-                       {
                                type = CC_ALLOW;
-                               typeMask = 'a' + mask;
-                       }
                        else if (tag->readString("deny", mask, false))
-                       {
                                type = CC_DENY;
-                               typeMask = 'd' + mask;
-                       }
                        else if (!name.empty())
                        {
                                type = CC_NAMED;
                                mask = name;
-                               typeMask = 'n' + mask;
                        }
                        else
                        {
@@ -268,13 +257,7 @@ void ServerConfig::CrossCheckConnectBlocks(ServerConfig* current)
                        }
 
                        if (name.empty())
-                       {
                                name = "unnamed-" + ConvToStr(i);
-                       }
-                       else
-                       {
-                               typeMask = 'n' + name;
-                       }
 
                        if (names.find(name) != names.end())
                                throw CoreException("Two connect classes with name \"" + name + "\" defined!");
@@ -311,6 +294,14 @@ void ServerConfig::CrossCheckConnectBlocks(ServerConfig* current)
                        me->maxconnwarn = tag->getBool("maxconnwarn", me->maxconnwarn);
                        me->limit = tag->getUInt("limit", me->limit);
                        me->resolvehostnames = tag->getBool("resolvehostnames", me->resolvehostnames);
+                       me->password = tag->getString("password", me->password);
+
+                       me->passwordhash = tag->getString("hash", me->passwordhash);
+                       if (!me->password.empty() && (me->passwordhash.empty() || stdalgo::string::equalsci(me->passwordhash, "plaintext")))
+                       {
+                               ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEFAULT, "<connect> tag '%s' at %s contains an plain text password, this is insecure!",
+                                       name.c_str(), tag->getTagLocation().c_str());
+                       }
 
                        std::string ports = tag->getString("port");
                        if (!ports.empty())
@@ -320,7 +311,7 @@ void ServerConfig::CrossCheckConnectBlocks(ServerConfig* current)
                                        me->ports.insert(port);
                        }
 
-                       ClassMap::iterator oldMask = oldBlocksByMask.find(typeMask);
+                       ClassMap::iterator oldMask = oldBlocksByMask.find(std::make_pair(me->name, me->type));
                        if (oldMask != oldBlocksByMask.end())
                        {
                                ConnectClass* old = oldMask->second;
@@ -334,6 +325,23 @@ void ServerConfig::CrossCheckConnectBlocks(ServerConfig* current)
        }
 }
 
+static std::string GetServerHost()
+{
+#ifndef _WIN32
+       char hostname[256];
+       if (gethostname(hostname, sizeof(hostname)) == 0)
+       {
+               std::string name(hostname);
+               if (name.find('.') == std::string::npos)
+                       name.push_back('.');
+
+               if (name.length() <= ServerInstance->Config->Limits.MaxHost && InspIRCd::IsHost(name))
+                       return name;
+       }
+#endif
+       return "irc.example.com";
+}
+
 void ServerConfig::Fill()
 {
        ConfigTag* options = ConfValue("options");
@@ -341,13 +349,13 @@ void ServerConfig::Fill()
        ConfigTag* server = ConfValue("server");
        if (sid.empty())
        {
-               ServerName = server->getString("name", "irc.example.com", InspIRCd::IsHost);
+               ServerName = server->getString("name", GetServerHost(), InspIRCd::IsHost);
 
                sid = server->getString("id");
                if (!sid.empty() && !InspIRCd::IsSID(sid))
                        throw CoreException(sid + " is not a valid server ID. A server ID must be 3 characters long, with the first character a digit and the next two characters a digit or letter.");
 
-               CaseMapping = options->getString("casemapping", "rfc1459");
+               CaseMapping = options->getString("casemapping", "rfc1459", 1);
                if (CaseMapping == "ascii")
                        national_case_insensitive_map = ascii_case_insensitive_map;
                else if (CaseMapping == "rfc1459")
@@ -366,18 +374,19 @@ void ServerConfig::Fill()
                        throw CoreException("You must restart to change the server id");
 
                std::string casemapping = options->getString("casemapping");
-               if (!casemapping.empty() && casemapping != CaseMapping)
+               // Ignore this value if CaseMapping is set to something the core doesn't provide (i.e., m_nationalchars).
+               if (!casemapping.empty() && casemapping != CaseMapping && (CaseMapping == "ascii" || CaseMapping == "rfc1459"))
                        throw CoreException("You must restart to change the server casemapping");
 
        }
        SoftLimit = ConfValue("performance")->getUInt("softlimit", (SocketEngine::GetMaxFds() > 0 ? SocketEngine::GetMaxFds() : LONG_MAX), 10);
        CCOnConnect = ConfValue("performance")->getBool("clonesonconnect", true);
        MaxConn = ConfValue("performance")->getUInt("somaxconn", SOMAXCONN);
+       TimeSkipWarn = ConfValue("performance")->getDuration("timeskipwarn", 2, 0, 30);
        XLineMessage = options->getString("xlinemessage", options->getString("moronbanner", "You're banned!"));
-       ServerDesc = server->getString("description", "Configure Me");
-       Network = server->getString("network", "Network");
+       ServerDesc = server->getString("description", "Configure Me", 1);
+       Network = server->getString("network", "Network", 1);
        NetBufferSize = ConfValue("performance")->getInt("netbuffersize", 10240, 1024, 65534);
-       DisabledDontExist = ConfValue("disabled")->getBool("fakenonexistant");
        CustomVersion = security->getString("customversion");
        HideBans = security->getBool("hidebans");
        HideServer = security->getString("hideserver", security->getString("hidewhois"));
@@ -413,13 +422,12 @@ void ServerConfig::Fill()
                        SocketEngine::Close(socktest);
        }
 
-       ServerInstance->XLines->ClearConfigLines();
        ReadXLine(this, "badip", "ipmask", ServerInstance->XLines->GetFactory("Z"));
        ReadXLine(this, "badnick", "nick", ServerInstance->XLines->GetFactory("Q"));
        ReadXLine(this, "badhost", "host", ServerInstance->XLines->GetFactory("K"));
        ReadXLine(this, "exception", "host", ServerInstance->XLines->GetFactory("E"));
 
-       const std::string restrictbannedusers = options->getString("restrictbannedusers", "yes");
+       const std::string restrictbannedusers = options->getString("restrictbannedusers", "yes", 1);
        if (stdalgo::string::equalsci(restrictbannedusers, "no"))
                RestrictBannedUsers = ServerConfig::BUT_NORMAL;
        else if (stdalgo::string::equalsci(restrictbannedusers, "silent"))
@@ -428,25 +436,6 @@ void ServerConfig::Fill()
                RestrictBannedUsers =  ServerConfig::BUT_RESTRICT_NOTIFY;
        else
                throw CoreException(restrictbannedusers + " is an invalid <options:restrictbannedusers> value, at " + options->getTagLocation());
-
-       DisabledUModes.reset();
-       std::string modes = ConfValue("disabled")->getString("usermodes");
-       for (std::string::const_iterator p = modes.begin(); p != modes.end(); ++p)
-       {
-               // Complain when the character is not a valid mode character.
-               if (!ModeParser::IsModeChar(*p))
-                       throw CoreException("Invalid usermode " + std::string(1, *p) + " was found.");
-               DisabledUModes.set(*p - 'A');
-       }
-
-       DisabledCModes.reset();
-       modes = ConfValue("disabled")->getString("chanmodes");
-       for (std::string::const_iterator p = modes.begin(); p != modes.end(); ++p)
-       {
-               if (!ModeParser::IsModeChar(*p))
-                       throw CoreException("Invalid chanmode " + std::string(1, *p) + " was found.");
-               DisabledCModes.set(*p - 'A');
-       }
 }
 
 // WARNING: it is not safe to use most of the codebase in this function, as it
@@ -525,20 +514,19 @@ void ServerConfig::Apply(ServerConfig* old, const std::string &useruid)
                // On first run, ports are bound later on
                FailedPortList pl;
                ServerInstance->BindPorts(pl);
-               if (pl.size())
+               if (!pl.empty())
                {
-                       errstr << "Not all your client ports could be bound." << std::endl
-                               << "The following port(s) failed to bind:" << std::endl;
-
-                       int j = 1;
-                       for (FailedPortList::iterator i = pl.begin(); i != pl.end(); i++, j++)
+                       errstr << "Warning! Some of your listener" << (pl.size() == 1 ? "s" : "") << " failed to bind:" << std::endl;
+                       for (FailedPortList::const_iterator iter = pl.begin(); iter != pl.end(); ++iter)
                        {
-                               errstr << j << ".\tAddress: " << i->first.str() << "\tReason: " << strerror(i->second) << std::endl;
+                               const FailedPort& fp = *iter;
+                               errstr << "  " << fp.sa.str() << ": " << strerror(fp.error) << std::endl
+                                       << "  " << "Created from <bind> tag at " << fp.tag->getTagLocation() << std::endl;
                        }
                }
        }
 
-       User* user = useruid.empty() ? NULL : ServerInstance->FindNick(useruid);
+       User* user = useruid.empty() ? NULL : ServerInstance->FindUUID(useruid);
 
        if (!valid)
        {
@@ -565,16 +553,6 @@ void ServerConfig::Apply(ServerConfig* old, const std::string &useruid)
        errstr.clear();
        errstr.str(std::string());
 
-       // Re-parse our MOTD and RULES files for colors -- Justasic
-       for (ClassVector::const_iterator it = this->Classes.begin(), it_end = this->Classes.end(); it != it_end; ++it)
-       {
-               ConfigTag *tag = (*it)->config;
-
-               ConfigFileCache::iterator file = this->Files.find(tag->getString("motd", "motd"));
-               if (file != this->Files.end())
-                       InspIRCd::ProcessColors(file->second);
-       }
-
        /* No old configuration -> initial boot, nothing more to do here */
        if (!old)
        {
@@ -732,8 +710,7 @@ void ConfigReaderThread::Finish()
                ServerInstance->Users.RehashCloneCounts();
                ServerInstance->XLines->CheckELines();
                ServerInstance->XLines->ApplyLines();
-               Config->ApplyDisabledCommands();
-               User* user = ServerInstance->FindNick(TheUserUID);
+               User* user = ServerInstance->FindUUID(TheUserUID);
 
                ConfigStatus status(user);
                const ModuleManager::ModuleMap& mods = ServerInstance->Modules->GetModules();