]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/users.cpp
mlock: handle case where no mlock has been set on a channel yet
[user/henk/code/inspircd.git] / src / users.cpp
index 81f83058387fc544245ec01bbb1d4395c9da344c..2ee389c86ff36b5abb69ad005c61fde720b3515a 100644 (file)
@@ -1,16 +1,28 @@
-/*       +------------------------------------+
- *       | Inspire Internet Relay Chat Daemon |
- *       +------------------------------------+
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
+ *
+ *   Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
+ *   Copyright (C) 2006-2009 Robin Burchell <robin+git@viroteck.net>
+ *   Copyright (C) 2006-2007, 2009 Dennis Friis <peavey@inspircd.org>
+ *   Copyright (C) 2008 John Brooks <john.brooks@dereferenced.net>
+ *   Copyright (C) 2008 Thomas Stagner <aquanight@inspircd.org>
+ *   Copyright (C) 2008 Oliver Lupton <oliverlupton@gmail.com>
+ *   Copyright (C) 2003-2008 Craig Edwards <craigedwards@brainbox.cc>
  *
- *  InspIRCd: (C) 2002-2010 InspIRCd Development Team
- * See: http://wiki.inspircd.org/Credits
+ * 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 free but copyrighted software; see
- *            the file COPYING for details.
+ * 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 <http://www.gnu.org/licenses/>.
  */
 
+
 #include "inspircd.h"
 #include <stdarg.h>
 #include "socketengine.h"
@@ -113,6 +125,8 @@ void LocalUser::StartDNSLookup()
        catch (CoreException& e)
        {
                ServerInstance->Logs->Log("USERS", DEBUG,"Error in resolver: %s",e.GetReason());
+               dns_done = true;
+               ServerInstance->stats->statsDnsBad++;
        }
 }
 
@@ -191,6 +205,7 @@ User::User(const std::string &uid, const std::string& sid, int type)
        signon = idle_lastmsg = 0;
        registered = 0;
        quietquit = quitting = exempt = dns_done = false;
+       quitting_sendq = false;
        client_sa.sa.sa_family = AF_UNSPEC;
 
        ServerInstance->Logs->Log("USERS", DEBUG, "New UUID for user: %s", uuid.c_str());
@@ -511,25 +526,19 @@ eol_found:
                if (user->quitting)
                        return;
        }
-       // Add pseudo-penalty so that we continue processing after sendq recedes
-       if (user->CommandFloodPenalty == 0 && getSendQSize() >= sendqmax)
-               user->CommandFloodPenalty++;
        if (user->CommandFloodPenalty >= penaltymax && !user->MyClass->fakelag)
                ServerInstance->Users->QuitUser(user, "Excess Flood");
 }
 
 void UserIOHandler::AddWriteBuf(const std::string &data)
 {
+       if (user->quitting_sendq)
+               return;
        if (!user->quitting && getSendQSize() + data.length() > user->MyClass->GetSendqHardMax() &&
                !user->HasPrivPermission("users/flood/increased-buffers"))
        {
-               /*
-                * Quit the user FIRST, because otherwise we could recurse
-                * here and hit the same limit.
-                */
-               ServerInstance->Users->QuitUser(user, "SendQ exceeded");
-               ServerInstance->SNO->WriteToSnoMask('a', "User %s SendQ exceeds connect class maximum of %lu",
-                       user->nick.c_str(), user->MyClass->GetSendqHardMax());
+               user->quitting_sendq = true;
+               ServerInstance->GlobalCulls.AddSQItem(user);
                return;
        }
 
@@ -649,7 +658,7 @@ void OperInfo::init()
                        {
                                this->AllowedUserModes.set();
                        }
-                       else
+                       else if (*c >= 'A' && *c < 'z')
                        {
                                this->AllowedUserModes[*c - 'A'] = true;
                        }
@@ -661,7 +670,7 @@ void OperInfo::init()
                        {
                                this->AllowedChanModes.set();
                        }
-                       else
+                       else if (*c >= 'A' && *c < 'z')
                        {
                                this->AllowedChanModes[*c - 'A'] = true;
                        }
@@ -727,6 +736,7 @@ void LocalUser::CheckClass()
        if (!a)
        {
                ServerInstance->Users->QuitUser(this, "Access denied by configuration");
+               return;
        }
        else if (a->type == CC_DENY)
        {
@@ -736,13 +746,15 @@ void LocalUser::CheckClass()
        else if ((a->GetMaxLocal()) && (ServerInstance->Users->LocalCloneCount(this) > a->GetMaxLocal()))
        {
                ServerInstance->Users->QuitUser(this, "No more connections allowed from your host via this connect class (local)");
-               ServerInstance->SNO->WriteToSnoMask('a', "WARNING: maximum LOCAL connections (%ld) exceeded for IP %s", a->GetMaxLocal(), this->GetIPString());
+               if (a->maxconnwarn)
+                       ServerInstance->SNO->WriteToSnoMask('a', "WARNING: maximum LOCAL connections (%ld) exceeded for IP %s", a->GetMaxLocal(), this->GetIPString());
                return;
        }
        else if ((a->GetMaxGlobal()) && (ServerInstance->Users->GlobalCloneCount(this) > a->GetMaxGlobal()))
        {
                ServerInstance->Users->QuitUser(this, "No more connections allowed from your host via this connect class (global)");
-               ServerInstance->SNO->WriteToSnoMask('a', "WARNING: maximum GLOBAL connections (%ld) exceeded for IP %s", a->GetMaxGlobal(), this->GetIPString());
+               if (a->maxconnwarn)
+                       ServerInstance->SNO->WriteToSnoMask('a', "WARNING: maximum GLOBAL connections (%ld) exceeded for IP %s", a->GetMaxGlobal(), this->GetIPString());
                return;
        }
 
@@ -781,6 +793,7 @@ void LocalUser::FullConnect()
         * may put the user into a totally seperate class with different restrictions! so we *must* check again.
         * Don't remove this! -- w00t
         */
+       MyClass = NULL;
        SetClass();
        CheckClass();
        CheckLines();
@@ -815,6 +828,9 @@ void LocalUser::FullConnect()
        if (!MOD_RESULT)
                ServerInstance->CallCommandHandler(command, parameters, this);
 
+       if (ServerInstance->Config->RawLog)
+               WriteServ("PRIVMSG %s :*** Raw I/O logging is enabled on this server. All messages, passwords, and commands are being recorded.", nick.c_str());
+
        /*
         * We don't set REG_ALL until triggering OnUserConnect, so some module events don't spew out stuff
         * for a user that doesn't exist yet.
@@ -825,10 +841,12 @@ void LocalUser::FullConnect()
 
        FOREACH_MOD(I_OnPostConnect,OnPostConnect(this));
 
-       ServerInstance->SNO->WriteToSnoMask('c',"Client connecting on port %d: %s!%s@%s [%s] [%s]",
-               this->GetServerPort(), this->nick.c_str(), this->ident.c_str(), this->host.c_str(), this->GetIPString(), this->fullname.c_str());
+       ServerInstance->SNO->WriteToSnoMask('c',"Client connecting on port %d (class %s): %s!%s@%s [%s] [%s]",
+               this->GetServerPort(), this->MyClass->name.c_str(), this->nick.c_str(), this->ident.c_str(), this->host.c_str(), this->GetIPString(), this->fullname.c_str());
        ServerInstance->Logs->Log("BANCACHE", DEBUG, "BanCache: Adding NEGATIVE hit for %s", this->GetIPString());
        ServerInstance->BanCache->AddHit(this->GetIPString(), "", "");
+       // reset the flood penalty (which could have been raised due to things like auto +x)
+       CommandFloodPenalty = 0;
 }
 
 void User::InvalidateCache()
@@ -1019,7 +1037,7 @@ void LocalUser::Write(const std::string& text)
                return;
        }
 
-       ServerInstance->Logs->Log("USEROUTPUT", DEBUG,"C[%s] O %s", uuid.c_str(), text.c_str());
+       ServerInstance->Logs->Log("USEROUTPUT", RAWIO, "C[%s] O %s", uuid.c_str(), text.c_str());
 
        eh.AddWriteBuf(text);
        eh.AddWriteBuf(wide_newline);
@@ -1392,7 +1410,9 @@ void User::DoHostCycle(const std::string &quitline)
                {
                        for(unsigned int i=0; i < memb->modes.length(); i++)
                                modeline.append(" ").append(nick);
-                       snprintf(buffer, MAXBUF, ":%s MODE %s +%s", GetFullHost().c_str(), c->name.c_str(), modeline.c_str());
+                       snprintf(buffer, MAXBUF, ":%s MODE %s +%s",
+                               ServerInstance->Config->CycleHostsFromUser ? GetFullHost().c_str() : ServerInstance->Config->ServerName.c_str(),
+                               c->name.c_str(), modeline.c_str());
                        modeline = buffer;
                }
 
@@ -1533,7 +1553,7 @@ void User::SplitChanList(User* dest, const std::string &cl)
                }
        }
 
-       if (line.length())
+       if (line.length() != prefix.str().length())
        {
                ServerInstance->SendWhoisLine(this, dest, 319, "%s", line.c_str());
        }
@@ -1591,7 +1611,7 @@ void LocalUser::SetClass(const std::string &explicit_name)
                                continue;
 
                        /* check if host matches.. */
-                       if (c->GetHost().length() && !InspIRCd::MatchCIDR(this->GetIPString(), c->GetHost(), NULL) &&
+                       if (!InspIRCd::MatchCIDR(this->GetIPString(), c->GetHost(), NULL) &&
                            !InspIRCd::MatchCIDR(this->host, c->GetHost(), NULL))
                        {
                                ServerInstance->Logs->Log("CONNECTCLASS", DEBUG, "No host match (for %s)", c->GetHost().c_str());
@@ -1619,9 +1639,9 @@ void LocalUser::SetClass(const std::string &explicit_name)
                                        continue;
                        }
 
-                       if (!c->config->getString("pass").empty())
+                       if (regdone && !c->config->getString("password").empty())
                        {
-                               if (ServerInstance->PassCompare(this, c->config->getString("pass"), password, c->config->getString("hash")))
+                               if (ServerInstance->PassCompare(this, c->config->getString("password"), password, c->config->getString("hash")))
                                {
                                        ServerInstance->Logs->Log("CONNECTCLASS", DEBUG, "Bad password, skipping");
                                        continue;
@@ -1687,7 +1707,7 @@ const std::string& FakeUser::GetFullRealHost()
 ConnectClass::ConnectClass(ConfigTag* tag, char t, const std::string& mask)
        : config(tag), type(t), fakelag(true), name("unnamed"), registration_timeout(0), host(mask),
        pingtime(0), softsendqmax(0), hardsendqmax(0), recvqmax(0),
-       penaltythreshold(0), commandrate(0), maxlocal(0), maxglobal(0), maxchans(0), limit(0)
+       penaltythreshold(0), commandrate(0), maxlocal(0), maxglobal(0), maxconnwarn(true), maxchans(0), limit(0)
 {
 }
 
@@ -1696,13 +1716,16 @@ ConnectClass::ConnectClass(ConfigTag* tag, char t, const std::string& mask, cons
        registration_timeout(parent.registration_timeout), host(mask), pingtime(parent.pingtime),
        softsendqmax(parent.softsendqmax), hardsendqmax(parent.hardsendqmax), recvqmax(parent.recvqmax),
        penaltythreshold(parent.penaltythreshold), commandrate(parent.commandrate),
-       maxlocal(parent.maxlocal), maxglobal(parent.maxglobal), maxchans(parent.maxchans),
+       maxlocal(parent.maxlocal), maxglobal(parent.maxglobal), maxconnwarn(parent.maxconnwarn), maxchans(parent.maxchans),
        limit(parent.limit)
 {
 }
 
 void ConnectClass::Update(const ConnectClass* src)
 {
+       config = src->config;
+       type = src->type;
+       fakelag = src->fakelag;
        name = src->name;
        registration_timeout = src->registration_timeout;
        host = src->host;
@@ -1711,7 +1734,10 @@ void ConnectClass::Update(const ConnectClass* src)
        hardsendqmax = src->hardsendqmax;
        recvqmax = src->recvqmax;
        penaltythreshold = src->penaltythreshold;
+       commandrate = src->commandrate;
        maxlocal = src->maxlocal;
        maxglobal = src->maxglobal;
+       maxconnwarn = src->maxconnwarn;
+       maxchans = src->maxchans;
        limit = src->limit;
 }