From 8cf8c37c2ae1a991efb1de64bcbe0164f638a79a Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Tue, 4 Oct 2016 17:22:58 -0500 Subject: [PATCH 1/4] tightening things up as i consider the best way to nuke non correlated people from orbit --- .../src/shared/ClientConnection.cpp | 27 +++++---- .../src/shared/ConfigLoginServer.cpp | 2 +- .../LoginServer/src/shared/LoginServer.cpp | 58 ++++++++++--------- 3 files changed, 48 insertions(+), 39 deletions(-) diff --git a/engine/server/application/LoginServer/src/shared/ClientConnection.cpp b/engine/server/application/LoginServer/src/shared/ClientConnection.cpp index 4af007c3..0cb75726 100755 --- a/engine/server/application/LoginServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/LoginServer/src/shared/ClientConnection.cpp @@ -59,23 +59,23 @@ ClientConnection::~ClientConnection() void ClientConnection::onConnectionClosed() { // client has disconnected - if (m_clientId) + if (m_stationId) { - if (m_stationId) - { - DEBUG_REPORT_LOG(true, ("Client %lu disconnected\n", m_stationId)); - LOG("LoginClientConnection", - ("onConnectionClosed() for stationId (%lu) at IP (%s)", m_stationId, getRemoteAddress().c_str())); - } - - LoginServer::getInstance().removeClient(m_clientId); + DEBUG_REPORT_LOG(true, ("Client %lu disconnected\n", m_stationId)); + LOG("LoginClientConnection", ("onConnectionClosed() for stationId (%lu) at IP (%s)", m_stationId, getRemoteAddress().c_str())); } - if (!m_isValidated) { + LoginServer::getInstance().removeClient(m_clientId); + + if ((ConfigLoginServer::getValidateStationKey() || ConfigLoginServer::getDoSessionLogin()) && !m_isValidated) + { SessionApiClient *session = LoginServer::getInstance().getSessionApiClient(); if (session) + { session->dropClient(this); + } } + } //----------------------------------------------------------------------- @@ -194,7 +194,7 @@ void ClientConnection::validateClient(const std::string & id, const std::string if (!authURL.empty()) { // create the object - webAPI api(authURL); + webAPI api(authURL); // TODO: is loginserver single threaded? if so then let's make this static, and clear/reset it each run // add our data api.addJsonData("user_name", id); @@ -239,7 +239,8 @@ void ClientConnection::validateClient(const std::string & id, const std::string { if (suid == 0) { - if (uname.length() > MAX_ACCOUNT_NAME_LENGTH) { + if (uname.length() > MAX_ACCOUNT_NAME_LENGTH) + { uname.resize(MAX_ACCOUNT_NAME_LENGTH); } @@ -288,6 +289,8 @@ void ClientConnection::onCharacterDeletedFromCluster(const NetworkId & character if(f != m_charactersPendingDeletion.end()) { m_charactersPendingDeletion.erase(f); + + // TODO: send api request and decrement # characters on this account/subaccount } DeleteCharacterReplyMessage reply(DeleteCharacterReplyMessage::rc_OK); diff --git a/engine/server/application/LoginServer/src/shared/ConfigLoginServer.cpp b/engine/server/application/LoginServer/src/shared/ConfigLoginServer.cpp index 9b1d6c07..9c4dcd04 100755 --- a/engine/server/application/LoginServer/src/shared/ConfigLoginServer.cpp +++ b/engine/server/application/LoginServer/src/shared/ConfigLoginServer.cpp @@ -94,7 +94,7 @@ void ConfigLoginServer::install(void) KEY_BOOL (developmentMode, true); KEY_INT (databaseThreads, 1); KEY_BOOL (compressClientNetworkTraffic, true); - KEY_INT (metricsListenerPort, 2201); + KEY_INT (metricsListenerPort, 0); // defaults to 2201 but we don't use it KEY_FLOAT (defaultDBQueueUpdateTimeLimit, 0.25f); KEY_INT (disconnectSleepTime, 30000); KEY_INT (clusterGroup,1); diff --git a/engine/server/application/LoginServer/src/shared/LoginServer.cpp b/engine/server/application/LoginServer/src/shared/LoginServer.cpp index 6e41ffc5..d6525d55 100755 --- a/engine/server/application/LoginServer/src/shared/LoginServer.cpp +++ b/engine/server/application/LoginServer/src/shared/LoginServer.cpp @@ -160,7 +160,6 @@ LoginServer::LoginServer() : if (ConfigLoginServer::getDevelopmentMode()) { setup.port = ConfigLoginServer::getCentralServicePort(); - //setup.maxConnections = 1000; m_centralService = new Service(ConnectionAllocator(), setup); } @@ -219,6 +218,7 @@ int LoginServer::addClient(ClientConnection & client) { DEBUG_FATAL(client.getIsValidated(), ("Tried to add an already validated client?!")); //Perhaps add a debug only check to make sure a client connection isn't in twice...I'm not sure how that could happen. + static int nextClientId = 0; int tmp = ++nextClientId; m_clientMap[tmp] = &client; @@ -250,7 +250,7 @@ ClientConnection* LoginServer::getUnvalidatedClient(int clientId) void LoginServer::removeClient(int clientId) { - if (clientId) // yeah why bother if it's 0 or null? i realize 0 is a valid int but since previously the warning below fired if it was 0....yeah, no + if (clientId) // yeah why bother if it's null? { std::map::iterator i = m_clientMap.find(clientId); if (i != m_clientMap.end()) @@ -264,7 +264,7 @@ void LoginServer::removeClient(int clientId) } else { - WARNING_STRICT_FATAL(true, ("Tried to remove a client with client id == 0")); + DEBUG_WARNING(true, ("Tried to remove a client with client id == 0 (possibly DoS attack?)")); } } @@ -903,6 +903,7 @@ void LoginServer::receiveMessage(const MessageDispatch::Emitter & source, const if (conn) { // current restriction is that once per account event or item cannot require a "consuming" account feature id + // TODO: looks like this is where vet rewards are consumed...the one per account thing, here - session auth may be enough? uint32 const requiredAccountFeatureId = msg->getAccountFeatureId(); bool const consumeAccountFeatureId = msg->getConsumeAccountFeatureId(); if ((msg->getConsumeEvent() || msg->getConsumeItem()) && (requiredAccountFeatureId > 0) && consumeAccountFeatureId) @@ -1172,21 +1173,25 @@ void LoginServer::run(void) unsigned long totalTime = 0; // load authentication data and bind the monitor to the port - CMonitorAPI * mon = new CMonitorAPI("metricsAuthentication.cfg", ConfigLoginServer::getMetricsListenerPort()); - getInstance().m_soeMonitor = mon; - const char *masterChannel = "Population"; - mon->add(masterChannel, WORLD_COUNT_CHANNEL); - std::string host = NetworkHandler::getHostName().c_str(); - size_t dotPos = host.find("."); - if (dotPos != host.npos) - { - host = host.substr(0, dotPos - 1); - } - char tmpBuf[1024]; - IGNORE_RETURN(snprintf(tmpBuf, sizeof(tmpBuf), "LoginServer version %s on %s", ApplicationVersion::getInternalVersion(), host.c_str())); - mon->setDescription(WORLD_COUNT_CHANNEL, tmpBuf); + const int port = ConfigLoginServer::getMetricsListenerPort(); - mon->add("Galaxies", CLUSTER_COUNT_CHANNEL); + if (port) { + CMonitorAPI *mon = new CMonitorAPI("metricsAuthentication.cfg", ConfigLoginServer::getMetricsListenerPort()); + getInstance().m_soeMonitor = mon; + const char *masterChannel = "Population"; + mon->add(masterChannel, WORLD_COUNT_CHANNEL); + std::string host = NetworkHandler::getHostName().c_str(); + size_t dotPos = host.find("."); + if (dotPos != host.npos) { + host = host.substr(0, dotPos - 1); + } + char tmpBuf[1024]; + IGNORE_RETURN(snprintf(tmpBuf, sizeof(tmpBuf), "LoginServer version %s on %s", ApplicationVersion::getInternalVersion(), host + .c_str())); + mon->setDescription(WORLD_COUNT_CHANNEL, tmpBuf); + + mon->add("Galaxies", CLUSTER_COUNT_CHANNEL); + } while (!getInstance().done) { @@ -1224,16 +1229,17 @@ void LoginServer::run(void) NetworkHandler::clearBytesThisFrame(); - mon->set(WORLD_COUNT_CHANNEL, static_cast(getInstance().m_clientMap.size())); - int count = 0; - ClusterListType::const_iterator i; - for (i = getInstance().m_clusterList.begin(); i != getInstance().m_clusterList.end(); ++i) - { - if ((*i)->m_connected) - ++count; + if (port) { + mon->set(WORLD_COUNT_CHANNEL, static_cast(getInstance().m_clientMap.size())); + int count = 0; + ClusterListType::const_iterator i; + for (i = getInstance().m_clusterList.begin(); i != getInstance().m_clusterList.end(); ++i) { + if ((*i)->m_connected) + ++count; + } + mon->set(CLUSTER_COUNT_CHANNEL, count); + mon->Update(); } - mon->set(CLUSTER_COUNT_CHANNEL, count); - mon->Update(); } NetworkHandler::update(); From 69cdb67d7cd9e7680fe7675adf60ab3437cba268 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Wed, 5 Oct 2016 10:26:49 -0500 Subject: [PATCH 2/4] cleanup? neeed to investigate how best to close hanging open connections here or in udp lib, also a method to bypass service callbacks when blocking ddoses --- .../LoginServer/src/shared/LoginServer.cpp | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/engine/server/application/LoginServer/src/shared/LoginServer.cpp b/engine/server/application/LoginServer/src/shared/LoginServer.cpp index d6525d55..df7e0cfd 100755 --- a/engine/server/application/LoginServer/src/shared/LoginServer.cpp +++ b/engine/server/application/LoginServer/src/shared/LoginServer.cpp @@ -14,7 +14,11 @@ #include "ConsoleManager.h" #include "CSToolConnection.h" #include "DatabaseConnection.h" + +#ifdef _DEBUG #include "LoginServerRemoteDebugSetup.h" +#endif + #include "MonAPI2/MonitorAPI.h" #include "PingConnection.h" #include "PurgeManager.h" @@ -250,21 +254,14 @@ ClientConnection* LoginServer::getUnvalidatedClient(int clientId) void LoginServer::removeClient(int clientId) { - if (clientId) // yeah why bother if it's null? + std::map::iterator i = m_clientMap.find(clientId); + if (i != m_clientMap.end()) { - std::map::iterator i = m_clientMap.find(clientId); - if (i != m_clientMap.end()) + if (i->second->getIsValidated()) { - if (i->second->getIsValidated()) - { - IGNORE_RETURN(m_validatedClientMap.erase(i->second->getStationId())); - } - IGNORE_RETURN(m_clientMap.erase(clientId)); + IGNORE_RETURN(m_validatedClientMap.erase(i->second->getStationId())); } - } - else - { - DEBUG_WARNING(true, ("Tried to remove a client with client id == 0 (possibly DoS attack?)")); + IGNORE_RETURN(m_clientMap.erase(clientId)); } } @@ -1160,7 +1157,11 @@ void LoginServer::validateAccountForTransfer(const TransferRequestMoveValidation void LoginServer::run(void) { NetworkHandler::install(); + +#ifdef _DEBUG LoginServerRemoteDebugSetup::install(); +#endif + DatabaseConnection::getInstance().connect(); DatabaseConnection::getInstance().requestClusterList(); SetupSharedLog::install("LoginServer"); @@ -1246,7 +1247,10 @@ void LoginServer::run(void) ConsoleManager::remove(); DatabaseConnection::getInstance().disconnect(); + +#ifdef _DEBUG LoginServerRemoteDebugSetup::remove(); +#endif SetupSharedLog::remove(); NetworkHandler::remove(); From 4a89f376e807374a835bb56f39fdda548c9a0ce1 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Wed, 5 Oct 2016 10:29:54 -0500 Subject: [PATCH 3/4] hopefully fix a mistake --- .../server/application/LoginServer/src/shared/LoginServer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/engine/server/application/LoginServer/src/shared/LoginServer.cpp b/engine/server/application/LoginServer/src/shared/LoginServer.cpp index df7e0cfd..eacfee13 100755 --- a/engine/server/application/LoginServer/src/shared/LoginServer.cpp +++ b/engine/server/application/LoginServer/src/shared/LoginServer.cpp @@ -1175,9 +1175,10 @@ void LoginServer::run(void) // load authentication data and bind the monitor to the port const int port = ConfigLoginServer::getMetricsListenerPort(); + CMonitorAPI *mon = nullptr; if (port) { - CMonitorAPI *mon = new CMonitorAPI("metricsAuthentication.cfg", ConfigLoginServer::getMetricsListenerPort()); + mon = new CMonitorAPI("metricsAuthentication.cfg", ConfigLoginServer::getMetricsListenerPort()); getInstance().m_soeMonitor = mon; const char *masterChannel = "Population"; mon->add(masterChannel, WORLD_COUNT_CHANNEL); From bde2d642edebd66f94ae125f7ce21f8c57cf69e7 Mon Sep 17 00:00:00 2001 From: DarthArgus Date: Wed, 5 Oct 2016 21:28:28 -0500 Subject: [PATCH 4/4] cleanup --- .../LoginServer/src/shared/LoginServer.cpp | 20 +------------------ .../3rd/library/udplibrary/UdpLibrary.cpp | 2 +- .../3rd/library/udplibrary/UdpLibrary.hpp | 2 +- 3 files changed, 3 insertions(+), 21 deletions(-) diff --git a/engine/server/application/LoginServer/src/shared/LoginServer.cpp b/engine/server/application/LoginServer/src/shared/LoginServer.cpp index eacfee13..17e7e760 100755 --- a/engine/server/application/LoginServer/src/shared/LoginServer.cpp +++ b/engine/server/application/LoginServer/src/shared/LoginServer.cpp @@ -1076,25 +1076,7 @@ void LoginServer::validateAccount(const StationId& stationId, uint32 clusterId, // Check cluster npe user limit if (cle->m_numTutorialPlayers > cle->m_onlineTutorialLimit) { - canCreateRegular = false; - canCreateJedi = false; - } - - // limit login/character creation based on subscription feature bits - if (((subscriptionBits & ClientSubscriptionFeature::FreeTrial) != 0) - && ((subscriptionBits & ClientSubscriptionFeature::Base) == 0)) - { - // Check cluster free trial user limit - if (cle->m_numFreeTrialPlayers > cle->m_onlineFreeTrialLimit) - { - canLogin = false; - } - // Check cluster free trial character creation - if (!cle->m_freeTrialCanCreateChar) - { - canCreateRegular = false; - canCreateJedi = false; - } + canLogin = false; } } diff --git a/external/3rd/library/udplibrary/UdpLibrary.cpp b/external/3rd/library/udplibrary/UdpLibrary.cpp index 945b3bf4..2971bb9c 100755 --- a/external/3rd/library/udplibrary/UdpLibrary.cpp +++ b/external/3rd/library/udplibrary/UdpLibrary.cpp @@ -1022,7 +1022,7 @@ void UdpManager::ProcessRawPacket(const PacketHistoryEntry *e) { if (e->mBuffer[0] == 0 && e->mBuffer[1] == UdpConnection::cUdpPacketPortAlive) return; // port-alive packets are not supposed to reach the destination machine, but on the odd chance they do, pretend like they never existed - + UdpConnection *con = AddressGetConnection(e->mIp, e->mPort); if (con == nullptr) diff --git a/external/3rd/library/udplibrary/UdpLibrary.hpp b/external/3rd/library/udplibrary/UdpLibrary.hpp index 86534a73..52922dab 100644 --- a/external/3rd/library/udplibrary/UdpLibrary.hpp +++ b/external/3rd/library/udplibrary/UdpLibrary.hpp @@ -1078,7 +1078,7 @@ class UdpConnection : public PriorityQueueMember, public AddressHashTableMember, , cDisconnectReasonNewConnectionAttempt, cDisconnectReasonConnectionRefused , cDisconnectReasonMutualConnectError, cDisconnectReasonConnectingToSelf , cDisconnectReasonReliableOverflow - , cDisconnectReasonCount, cDisconnectReasonDosAttack }; + , cDisconnectReasonDosAttack, cDisconnectReasonCount }; // standard AddRef/Release scheme void AddRef();