X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fusers.cpp;h=1da7a974c933d85e62fccabc15ca97f97ac66f9f;hb=f3f2388a81b6463e1229fa5bf2b8c427440bf406;hp=72a6c23af9e0bcd49a0e4a0530fb73b760a27ea7;hpb=bb39d78be61e45555cdd87985e26ea07b725fabf;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/users.cpp b/src/users.cpp index 72a6c23af..1da7a974c 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -4,8 +4,7 @@ * Copyright (C) 2019 linuxdaemon * Copyright (C) 2018 systocrat * Copyright (C) 2018 Dylan Frank - * Copyright (C) 2014 satmd - * Copyright (C) 2013-2014, 2016-2019 Sadie Powell + * Copyright (C) 2013, 2016-2020 Sadie Powell * Copyright (C) 2013 Daniel Vassdal * Copyright (C) 2013 ChrisTX * Copyright (C) 2013 Adam @@ -229,6 +228,19 @@ bool LocalUser::HasPrivPermission(const std::string& privstr) return oper->AllowedPrivs.Contains(privstr); } +bool User::HasSnomaskPermission(char chr) const +{ + return true; +} + +bool LocalUser::HasSnomaskPermission(char chr) const +{ + if (!this->IsOper() || !ModeParser::IsModeChar(chr)) + return false; + + return this->oper->AllowedSnomasks[chr - 'A']; +} + void UserIOHandler::OnDataReady() { if (user->quitting) @@ -419,6 +431,7 @@ void OperInfo::init() AllowedPrivs.Clear(); AllowedUserModes.reset(); AllowedChanModes.reset(); + AllowedSnomasks.reset(); AllowedUserModes['o' - 'A'] = true; // Call me paranoid if you want. for(std::vector >::iterator iter = class_blocks.begin(); iter != class_blocks.end(); ++iter) @@ -428,30 +441,34 @@ void OperInfo::init() AllowedOperCommands.AddList(tag->getString("commands")); AllowedPrivs.AddList(tag->getString("privs")); - std::string modes = tag->getString("usermodes"); - for (std::string::const_iterator c = modes.begin(); c != modes.end(); ++c) + const std::string umodes = tag->getString("usermodes"); + for (std::string::const_iterator c = umodes.begin(); c != umodes.end(); ++c) { - if (*c == '*') - { + const char& chr = *c; + if (chr == '*') this->AllowedUserModes.set(); - } - else if (*c >= 'A' && *c <= 'z') - { - this->AllowedUserModes[*c - 'A'] = true; - } + else if (ModeParser::IsModeChar(chr)) + this->AllowedUserModes[chr - 'A'] = true; } - modes = tag->getString("chanmodes"); - for (std::string::const_iterator c = modes.begin(); c != modes.end(); ++c) + const std::string cmodes = tag->getString("chanmodes"); + for (std::string::const_iterator c = cmodes.begin(); c != cmodes.end(); ++c) { - if (*c == '*') - { + const char& chr = *c; + if (chr == '*') this->AllowedChanModes.set(); - } - else if (*c >= 'A' && *c <= 'z') - { - this->AllowedChanModes[*c - 'A'] = true; - } + 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; } } } @@ -568,7 +585,7 @@ void LocalUser::FullConnect() /* * You may be thinking "wtf, we checked this in User::AddClient!" - and yes, we did, BUT. * At the time AddClient is called, we don't have a resolved host, by here we probably do - which - * may put the user into a totally seperate class with different restrictions! so we *must* check again. + * may put the user into a totally separate class with different restrictions! so we *must* check again. * Don't remove this! -- w00t */ MyClass = NULL; @@ -999,8 +1016,8 @@ bool User::ChangeRealName(const std::string& real) FIRST_MOD_RESULT(OnPreChangeRealName, MOD_RESULT, (IS_LOCAL(this), real)); if (MOD_RESULT == MOD_RES_DENY) return false; - FOREACH_MOD(OnChangeRealName, (this, real)); } + FOREACH_MOD(OnChangeRealName, (this, real)); this->realname.assign(real, 0, ServerInstance->Config->Limits.MaxReal); return true; @@ -1058,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(); } @@ -1084,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) @@ -1096,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; } } @@ -1106,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)) + !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; } @@ -1140,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; }