X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fusers.cpp;h=7029accc052a6c38ae6ee23cafb5f943c59d2671;hb=d494fa6e094e85cd29235e995fb2b447d6e1f168;hp=df21dbeeed346dcfbdd841f011ca01d607823736;hpb=bc444b242fabb8ae8b5ca58c2c903b75c02e9756;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/users.cpp b/src/users.cpp index df21dbeee..7029accc0 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -4,7 +4,7 @@ * Copyright (C) 2019 linuxdaemon * Copyright (C) 2018 systocrat * Copyright (C) 2018 Dylan Frank - * Copyright (C) 2013, 2016-2020 Sadie Powell + * Copyright (C) 2013, 2016-2021 Sadie Powell * Copyright (C) 2013 Daniel Vassdal * Copyright (C) 2013 ChrisTX * Copyright (C) 2013 Adam @@ -16,9 +16,9 @@ * Copyright (C) 2009 Uli Schlachter * Copyright (C) 2008 Thomas Stagner * Copyright (C) 2008 John Brooks - * Copyright (C) 2007-2009 Robin Burchell * Copyright (C) 2007, 2009 Dennis Friis - * Copyright (C) 2006-2009 Craig Edwards + * Copyright (C) 2006-2009 Robin Burchell + * Copyright (C) 2004, 2006-2009 Craig Edwards * * 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 @@ -425,6 +425,26 @@ void User::Oper(OperInfo* info) FOREACH_MOD(OnPostOper, (this, oper->name, opername)); } +namespace +{ + bool ParseModeList(std::bitset<64>& modeset, ConfigTag* tag, const std::string& field) + { + std::string modes; + bool hasmodes = tag->readString(field, modes); + for (std::string::const_iterator iter = modes.begin(); iter != modes.end(); ++iter) + { + const char& chr = *iter; + if (chr == '*') + modeset.set(); + else if (ModeParser::IsModeChar(chr)) + modeset.set(chr - 'A'); + else + ServerInstance->Logs->Log("CONFIG", LOG_DEFAULT, "'%c' is not a valid value for , ignoring...", chr, field.c_str()); + } + return hasmodes; + } +} + void OperInfo::init() { AllowedOperCommands.Clear(); @@ -434,6 +454,7 @@ void OperInfo::init() AllowedSnomasks.reset(); AllowedUserModes['o' - 'A'] = true; // Call me paranoid if you want. + bool defaultsnomasks = true; for(std::vector >::iterator iter = class_blocks.begin(); iter != class_blocks.end(); ++iter) { ConfigTag* tag = *iter; @@ -441,36 +462,15 @@ void OperInfo::init() AllowedOperCommands.AddList(tag->getString("commands")); AllowedPrivs.AddList(tag->getString("privs")); - const std::string umodes = tag->getString("usermodes"); - for (std::string::const_iterator c = umodes.begin(); c != umodes.end(); ++c) - { - const char& chr = *c; - if (chr == '*') - this->AllowedUserModes.set(); - else if (ModeParser::IsModeChar(chr)) - this->AllowedUserModes[chr - 'A'] = true; - } - - const std::string cmodes = tag->getString("chanmodes"); - for (std::string::const_iterator c = cmodes.begin(); c != cmodes.end(); ++c) - { - const char& chr = *c; - if (chr == '*') - this->AllowedChanModes.set(); - else if (ModeParser::IsModeChar(chr)) - this->AllowedChanModes[chr - 'A'] = true; - } - - const std::string snomasks = tag->getString("snomasks", "*"); - for (std::string::const_iterator c = snomasks.begin(); c != snomasks.end(); ++c) - { - const char& chr = *c; - if (chr == '*') - this->AllowedSnomasks.set(); - else if (ModeParser::IsModeChar(chr)) - this->AllowedSnomasks[chr - 'A'] = true; - } + ParseModeList(AllowedChanModes, tag, "chanmodes"); + ParseModeList(AllowedUserModes, tag, "usermodes"); + if (ParseModeList(AllowedSnomasks, tag, "snomasks")) + defaultsnomasks = false; } + + // Compatibility for older configs that don't have the snomasks field. + if (defaultsnomasks) + AllowedSnomasks.set(); } void User::UnOper() @@ -1075,6 +1075,10 @@ void User::ChangeRealHost(const std::string& host, bool resetdisplay) if (!changehost) return; + // Don't call the OnChangeRealHost event when initialising a user. + if (!realhost.empty()) + FOREACH_MOD(OnChangeRealHost, (this, host)); + realhost = host; this->InvalidateCache(); } @@ -1101,10 +1105,10 @@ bool User::ChangeIdent(const std::string& newident) */ void LocalUser::SetClass(const std::string &explicit_name) { - ConnectClass *found = NULL; - - ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEBUG, "Setting connect class for UID %s", this->uuid.c_str()); + ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEBUG, "Setting connect class for %s (%s) ...", + this->uuid.c_str(), this->GetFullRealHost().c_str()); + ConnectClass *found = NULL; if (!explicit_name.empty()) { for (ServerConfig::ClassVector::const_iterator i = ServerInstance->Config->Classes.begin(); i != ServerInstance->Config->Classes.end(); ++i) @@ -1113,7 +1117,8 @@ void LocalUser::SetClass(const std::string &explicit_name) if (explicit_name == c->name) { - ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEBUG, "Explicitly set to %s", explicit_name.c_str()); + ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEBUG, "Connect class explicitly set to %s", + explicit_name.c_str()); found = c; } } @@ -1123,31 +1128,43 @@ void LocalUser::SetClass(const std::string &explicit_name) for (ServerConfig::ClassVector::const_iterator i = ServerInstance->Config->Classes.begin(); i != ServerInstance->Config->Classes.end(); ++i) { ConnectClass* c = *i; - ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEBUG, "Checking %s", c->GetName().c_str()); + ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEBUG, "Checking the %s connect class ...", + c->GetName().c_str()); ModResult MOD_RESULT; FIRST_MOD_RESULT(OnSetConnectClass, MOD_RESULT, (this,c)); if (MOD_RESULT == MOD_RES_DENY) continue; + if (MOD_RESULT == MOD_RES_ALLOW) { - ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEBUG, "Class forced by module to %s", c->GetName().c_str()); + ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEBUG, "The %s connect class was explicitly chosen by a module", + c->GetName().c_str()); found = c; break; } if (c->type == CC_NAMED) + { + ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEBUG, "The %s connect class is not suitable as neither nor are set", + c->GetName().c_str()); continue; + } bool regdone = (registered != REG_NONE); if (c->config->getBool("registered", regdone) != regdone) + { + ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEBUG, "The %s connect class is not suitable as it requires that the user is %s", + c->GetName().c_str(), regdone ? "not fully connected" : "fully connected"); continue; + } /* check if host matches.. */ if (!InspIRCd::MatchCIDR(this->GetIPString(), c->GetHost(), NULL) && !InspIRCd::MatchCIDR(this->GetRealHost(), c->GetHost(), NULL)) { - ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEBUG, "No host match (for %s)", c->GetHost().c_str()); + ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEBUG, "The %s connect class is not suitable as neither the host (%s) nor the IP (%s) matches %s", + c->GetName().c_str(), this->GetRealHost().c_str(), this->GetIPString().c_str(), c->GetHost().c_str()); continue; } @@ -1157,31 +1174,29 @@ void LocalUser::SetClass(const std::string &explicit_name) */ if (c->limit && (c->GetReferenceCount() >= c->limit)) { - ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEBUG, "OOPS: Connect class limit (%lu) hit, denying", c->limit); + ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEBUG, "The %s connect class is not suitable as it has reached its user limit (%lu)", + c->GetName().c_str(), c->limit); continue; } - /* if it requires a port ... */ - if (!c->ports.empty()) + /* if it requires a port and our port doesn't match, fail */ + if (!c->ports.empty() && !c->ports.count(this->server_sa.port())) { - /* and our port doesn't match, fail. */ - if (!c->ports.count(this->server_sa.port())) - { - ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEBUG, "Requires a different port, skipping"); - continue; - } + ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEBUG, "The %s connect class is not suitable as the connection port (%d) is not any of %s", + c->GetName().c_str(), this->server_sa.port(), stdalgo::string::join(c->ports).c_str()); + continue; } - if (regdone && !c->password.empty()) + if (regdone && !c->password.empty() && !ServerInstance->PassCompare(this, c->password, password, c->passwordhash)) { - if (!ServerInstance->PassCompare(this, c->password, password, c->passwordhash)) - { - ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEBUG, "Bad password, skipping"); - continue; - } + ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEBUG, "The %s connect class is not suitable as requires a password and %s", + c->GetName().c_str(), password.empty() ? "one was not provided" : "the provided password was incorrect"); + continue; } /* we stop at the first class that meets ALL critera. */ + ServerInstance->Logs->Log("CONNECTCLASS", LOG_DEBUG, "The %s connect class is suitable for %s (%s)", + c->GetName().c_str(), this->uuid.c_str(), this->GetFullRealHost().c_str()); found = c; break; }