[Bug Fix] Fix IP Exemptions. (#2189)

* [Bug Fix] Fix IP Exemptions.
- IP Exemptions were broken due to GetAccountID() returning 0 in logic somehow, resolved this by setting a variable to GetAccountID() at the beginning of the method.
- Fixed weird IP messages where the long form of IP was displayed instead of the string form.
- Fixes edge case where IP rule may be set to -1 and this will make anyone get instantly kicked if IP Exemptions were enabled as their IP Count would always be greater than -1.

* Update client.cpp

* Update client.cpp

* Update clientlist.cpp

* Update clientlist.cpp
This commit is contained in:
Kinglykrab
2022-05-27 23:57:55 -04:00
committed by GitHub
parent aaaee6c6a4
commit 7de50d0e60
7 changed files with 267 additions and 226 deletions
+110 -109
View File
@@ -721,38 +721,40 @@ bool Client::HandleCharacterCreatePacket(const EQApplicationPacket *app) {
}
bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
if (GetAccountID() == 0) {
LogInfo("Enter world with no logged in account");
auto account_id = GetAccountID();
if (!account_id) {
LogInfo("Enter world with no logged in account.");
eqs->Close();
return true;
}
if(GetAdmin() < 0)
{
LogInfo("Account banned or suspended");
if (GetAdmin() < 0) {
LogInfo("Account [{}] is banned or suspended.", account_id);
eqs->Close();
return true;
}
if (RuleB(World, EnableIPExemptions) || RuleI(World, MaxClientsPerIP) >= 0) {
if (
RuleB(World, EnableIPExemptions) ||
RuleI(World, MaxClientsPerIP) > 0
) {
client_list.GetCLEIP(GetIP()); //Check current CLE Entry IPs against incoming connection
}
EnterWorld_Struct *ew=(EnterWorld_Struct *)app->pBuffer;
strn0cpy(char_name, ew->name, 64);
auto ew = (EnterWorld_Struct *) app->pBuffer;
strn0cpy(char_name, ew->name, sizeof(char_name));
EQApplicationPacket *outapp;
uint32 tmpaccid = 0;
charid = database.GetCharacterInfo(char_name, &tmpaccid, &zone_id, &instance_id);
if (charid == 0) {
uint32 temporary_account_id = 0;
charid = database.GetCharacterInfo(char_name, &temporary_account_id, &zone_id, &instance_id);
if (!charid) {
LogInfo("Could not get CharInfo for [{}]", char_name);
eqs->Close();
return true;
}
// Make sure this account owns this character
if (tmpaccid != GetAccountID()) {
LogInfo("This account does not own the character named [{}]", char_name);
if (temporary_account_id != account_id) {
LogInfo("Account [{}] does not own the character named [{}] from account [{}]", account_id, char_name, temporary_account_id);
eqs->Close();
return true;
}
@@ -761,25 +763,26 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
// (This is a literal translation of the original process..I don't see why it can't be changed to a single-target query over account iteration)
if (!is_player_zoning) {
size_t character_limit = EQ::constants::StaticLookup(eqs->ClientVersion())->CharacterCreationLimit;
if (character_limit > EQ::constants::CHARACTER_CREATION_LIMIT) { character_limit = EQ::constants::CHARACTER_CREATION_LIMIT; }
if (eqs->ClientVersion() == EQ::versions::ClientVersion::Titanium) { character_limit = Titanium::constants::CHARACTER_CREATION_LIMIT; }
if (character_limit > EQ::constants::CHARACTER_CREATION_LIMIT) {
character_limit = EQ::constants::CHARACTER_CREATION_LIMIT;
}
std::string tgh_query = StringFormat(
"SELECT "
"`id`, "
"name, "
"`level`, "
"last_login "
"FROM "
"character_data "
"WHERE `account_id` = %i ORDER BY `name` LIMIT %u", GetAccountID(), character_limit);
auto tgh_results = database.QueryDatabase(tgh_query);
if (eqs->ClientVersion() == EQ::versions::ClientVersion::Titanium) {
character_limit = Titanium::constants::CHARACTER_CREATION_LIMIT;
}
auto query = fmt::format(
"SELECT `id`, `name`, `level`, `last_login` FROM character_data WHERE `account_id` = {} ORDER BY `name` LIMIT {}",
account_id,
character_limit
);
auto results = database.QueryDatabase(query);
/* Check GoHome */
if (ew->return_home && !ew->tutorial) {
bool home_enabled = false;
for (auto row = tgh_results.begin(); row != tgh_results.end(); ++row) {
if (strcasecmp(row[1], char_name) == 0) {
for (auto row : results) {
if (!strcasecmp(row[1], char_name)) {
if (RuleB(World, EnableReturnHomeButton)) {
int now = time(nullptr);
if ((now - atoi(row[3])) >= RuleI(World, MinOfflineTimeToReturnHome)) {
@@ -792,9 +795,8 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
if (home_enabled) {
zone_id = database.MoveCharacterToBind(charid, 4);
}
else {
LogInfo("[{}] is trying to go home before they're able", char_name);
} else {
LogInfo("[{}] is trying to go home before they're able.", char_name);
database.SetHackerFlag(GetAccountName(), char_name, "MQGoHome: player tried to go home before they were able.");
eqs->Close();
return true;
@@ -804,9 +806,12 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
/* Check Tutorial*/
if (RuleB(World, EnableTutorialButton) && (ew->tutorial || StartInTutorial)) {
bool tutorial_enabled = false;
for (auto row = tgh_results.begin(); row != tgh_results.end(); ++row) {
if (strcasecmp(row[1], char_name) == 0) {
if (RuleB(World, EnableTutorialButton) && ((uint8)atoi(row[2]) <= RuleI(World, MaxLevelForTutorial))) {
for (auto row : results) {
if (!strcasecmp(row[1], char_name)) {
if (
RuleB(World, EnableTutorialButton) &&
std::stoi(row[2]) <= RuleI(World, MaxLevelForTutorial)
) {
tutorial_enabled = true;
break;
}
@@ -816,9 +821,8 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
if (tutorial_enabled) {
zone_id = RuleI(World, TutorialZoneID);
database.MoveCharacterToZone(charid, zone_id);
}
else {
LogInfo("[{}] is trying to go to tutorial but are not allowed", char_name);
} else {
LogInfo("[{}] is trying to go to the Tutorial but they are not allowed.", char_name);
database.SetHackerFlag(GetAccountName(), char_name, "MQTutorial: player tried to enter the tutorial without having tutorial enabled for this character.");
eqs->Close();
return true;
@@ -826,17 +830,17 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
}
}
if (zone_id == 0 || !ZoneName(zone_id)) {
if (!zone_id || !ZoneName(zone_id)) {
// This is to save people in an invalid zone, once it's removed from the DB
database.MoveCharacterToZone(charid, ZoneID("arena"));
LogInfo("Zone not found in database zone_id=[{}], moveing char to arena character:[{}]", zone_id, char_name);
LogInfo("Zone [{}] not found, moving [{}] to Arena.", zone_id, char_name);
}
if(instance_id > 0)
{
if (!database.VerifyInstanceAlive(instance_id, GetCharID()) ||
!database.VerifyZoneInstance(zone_id, instance_id))
{
if (instance_id) {
if (
!database.VerifyInstanceAlive(instance_id, GetCharID()) ||
!database.VerifyZoneInstance(zone_id, instance_id)
) {
zone_id = database.MoveCharacterToInstanceSafeReturn(charid, zone_id, instance_id);
instance_id = 0;
}
@@ -845,83 +849,80 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
if(!is_player_zoning) {
database.SetGroupID(char_name, 0, charid);
database.SetLoginFlags(charid, false, false, 1);
}
else{
uint32 groupid = database.GetGroupID(char_name);
if(groupid > 0){
char* leader = 0;
char leaderbuf[64] = {0};
if((leader = database.GetGroupLeaderForLogin(char_name, leaderbuf)) && strlen(leader)>1){
auto outapp3 = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct));
GroupJoin_Struct* gj=(GroupJoin_Struct*)outapp3->pBuffer;
} else {
auto group_id = database.GetGroupID(char_name);
if (group_id) {
auto leader_name = database.GetGroupLeaderForLogin(char_name);
if (!leader_name.empty()) {
auto pack = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct));
auto gj = (GroupJoin_Struct*) pack->pBuffer;
gj->action=8;
strcpy(gj->yourname, char_name);
strcpy(gj->membername, leader);
QueuePacket(outapp3);
safe_delete(outapp3);
strn0cpy(gj->yourname, char_name, sizeof(gj->yourname));
strn0cpy(gj->membername, leader_name.c_str(), sizeof(gj->membername));
QueuePacket(pack);
safe_delete(pack);
}
}
}
outapp = new EQApplicationPacket(OP_MOTD);
std::string tmp;
if (database.GetVariable("MOTD", tmp)) {
outapp->size = tmp.length() + 1;
auto outapp = new EQApplicationPacket(OP_MOTD);
std::string motd_message;
if (database.GetVariable("MOTD", motd_message)) {
outapp->size = motd_message.length() + 1;
outapp->pBuffer = new uchar[outapp->size];
memset(outapp->pBuffer,0,outapp->size);
strcpy((char*)outapp->pBuffer, tmp.c_str());
} else {
// Null Message of the Day. :)
memset(outapp->pBuffer, 0, outapp->size);
strcpy((char*)outapp->pBuffer, motd_message.c_str());
} else { // Null Message of the Day. :)
outapp->size = 1;
outapp->pBuffer = new uchar[outapp->size];
outapp->pBuffer[0] = 0;
}
QueuePacket(outapp);
safe_delete(outapp);
// set mailkey - used for duration of character session
int MailKey = emu_random.Int(1, INT_MAX);
int mail_key = emu_random.Int(1, INT_MAX);
database.SetMailKey(charid, GetIP(), MailKey);
database.SetMailKey(charid, GetIP(), mail_key);
if (UCSServerAvailable_) {
const WorldConfig *Config = WorldConfig::get();
auto config = WorldConfig::get();
std::string buffer;
EQ::versions::UCSVersion ConnectionType = EQ::versions::ucsUnknown;
auto connection_type = EQ::versions::ucsUnknown;
// chat server packet
switch (GetClientVersion()) {
case EQ::versions::ClientVersion::Titanium:
ConnectionType = EQ::versions::ucsTitaniumChat;
break;
case EQ::versions::ClientVersion::SoF:
ConnectionType = EQ::versions::ucsSoFCombined;
break;
case EQ::versions::ClientVersion::SoD:
ConnectionType = EQ::versions::ucsSoDCombined;
break;
case EQ::versions::ClientVersion::UF:
ConnectionType = EQ::versions::ucsUFCombined;
break;
case EQ::versions::ClientVersion::RoF:
ConnectionType = EQ::versions::ucsRoFCombined;
break;
case EQ::versions::ClientVersion::RoF2:
ConnectionType = EQ::versions::ucsRoF2Combined;
break;
default:
ConnectionType = EQ::versions::ucsUnknown;
break;
case EQ::versions::ClientVersion::Titanium:
connection_type = EQ::versions::ucsTitaniumChat;
break;
case EQ::versions::ClientVersion::SoF:
connection_type = EQ::versions::ucsSoFCombined;
break;
case EQ::versions::ClientVersion::SoD:
connection_type = EQ::versions::ucsSoDCombined;
break;
case EQ::versions::ClientVersion::UF:
connection_type = EQ::versions::ucsUFCombined;
break;
case EQ::versions::ClientVersion::RoF:
connection_type = EQ::versions::ucsRoFCombined;
break;
case EQ::versions::ClientVersion::RoF2:
connection_type = EQ::versions::ucsRoF2Combined;
break;
default:
connection_type = EQ::versions::ucsUnknown;
break;
}
buffer = StringFormat("%s,%i,%s.%s,%c%08X",
Config->ChatHost.c_str(),
Config->ChatPort,
Config->ShortName.c_str(),
buffer = fmt::format("{},{},{}.{},{}{:08X}",
config->ChatHost,
config->ChatPort,
config->ShortName,
GetCharName(),
ConnectionType,
MailKey
static_cast<char>(connection_type),
mail_key
);
outapp = new EQApplicationPacket(OP_SetChatServer, (buffer.length() + 1));
@@ -933,21 +934,21 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) {
// mail server packet
switch (GetClientVersion()) {
case EQ::versions::ClientVersion::Titanium:
ConnectionType = EQ::versions::ucsTitaniumMail;
break;
default:
// retain value from previous switch
break;
case EQ::versions::ClientVersion::Titanium:
connection_type = EQ::versions::ucsTitaniumMail;
break;
default:
// retain value from previous switch
break;
}
buffer = StringFormat("%s,%i,%s.%s,%c%08X",
Config->MailHost.c_str(),
Config->MailPort,
Config->ShortName.c_str(),
buffer = fmt::format("{},{},{}.{},{}{:08X}",
config->MailHost,
config->MailPort,
config->ShortName,
GetCharName(),
ConnectionType,
MailKey
static_cast<char>(connection_type),
mail_key
);
outapp = new EQApplicationPacket(OP_SetChatServer2, (buffer.length() + 1));