📄 warsessionmanager.cpp
字号:
#include "StdAfx.h"#include "WarSessionManager.h" // class implemented#ifndef WAR_SESSION_MANAGER_PLUGINS_H# include "WarSessionManagerPlugins.h"#endif#ifndef WAR_AUTO_LOCK_H# include "WarAutoLock.h"#endif#ifndef WAR_LOG_H# include "WarLog.h"#endif#ifndef WAR_TIMER_H# include "WarTimer.h"#endif#define AUTO_LOCK WarAutoLock MyLock(mLock);using namespace std;#define RemoveExpieredEntries(containerT, var)\{\ for(containerT::iterator P = var.begin()\ ; P != var.end()\ ;)\ {\ if (P->second.IsTimeOut())\ {\ containerT::iterator PP = P;\ bool is_first = (P == var.begin());\ if (!is_first)\ --P;\ var.erase(PP);\ if (is_first)\ P = var.begin();\ else\ ++P;\ }\ else\ ++P;\ }\}/////////////////////////////// PUBLIC /////////////////////////////////////////============================= LIFECYCLE ====================================WarSessionManager::WarSessionManager(): WarPluginSupport<WarSessionManager>("WarSessionManager"), WarPluginModule("WarSessionManager"),mShortTimeHistorySeconds(60 * 5), // 5 minutes defaultmNumConnectsBeforeFlood(1000), // Max 1000 connections within 5 minutes from one hostmNumClientConnections(0){ assert(NULL == mpManager); mpManager = this; // Register what classes we have interest in NotifyOnClassInstance("WarSvrEngine"); NotifyOnClassInstance("WarSvrProtocol"); // Set up the timer to run each 15 seconds WarTime first_run; first_run.Reset(1000 * 15); mTimerPtr = new timer_class_t(this, first_run, WarTimerEvent::TIMER_LOOP_RELATIVE, 1000 * 15); WarTimer::GetTimer().AddEvent((WarPtrWrapper<class WarTimerEvent>&)mTimerPtr); }// WarSessionManagerWarSessionManager::~WarSessionManager(){ if (mpManager == this) mpManager = NULL;}// ~WarSessionManager//============================= OPERATORS ====================================//============================= OPERATIONS ===================================void WarSessionManager::ShitlistIp(const WarIpShitlisted& badIp){ AUTO_LOCK; shitlist_t::iterator P = mIpShitlist.find(badIp.GetIpAddr().s_addr); if (P != mIpShitlist.end()) mIpShitlist.erase(P); // We will renew the shitlisting mIpShitlist.insert(shitlist_t::value_type( badIp.GetIpAddr().s_addr, badIp)); badIp.LogWhy();}//============================= CALLBACK ===================================void WarSessionManager::OnClassInstance( WarPluginBaseSupport *pClassInstance, const NotificationE notificationType) throw(WarException) // Should not throw{ switch(notificationType) { case NOTIFY_CREATED: if (*pClassInstance == "WarSvrEngine") { pClassInstance->AddPlugin( WarSvrEngine::PLUGIN_EVENT_ON_ACCEPT, new WarSessionManager_WarSvrEngine_OnAccept(this)); } else if (*pClassInstance == "WarSvrProtocol") { pClassInstance->AddPlugin( WarSvrProtocol::PLUGIN_ON_CLIENT_CONNECT, new WarSessionManager_WarSvrProtocol_OnClientConnect(this)); pClassInstance->AddPlugin( WarSvrProtocol::PLUGIN_ON_LOGIN_POST_AUTH, new WarSessionManager_WarSvrProtocol_OnLoginPostAuth(this)); pClassInstance->AddPlugin( WarSvrProtocol::PLUGIN_ON_LOGOUT, new WarSessionManager_WarSvrProtocol_OnLogout(this)); } break; default: ; // No action }}// Incomming client connection. // At this time we don't know what service the// user is connecting to - so we can't do any// real validiation.void WarSessionManager::OnAccept(const WarError& status, war_socket_t newSocket, const WarNetAddress& remoteAddress, const WarNetAddress& localAddress, WarSvrEngineSocket *pListenSck) throw (WarException){ if (status) return; // Error, - ignore // Check host against shitlist WarIpShitlisted shitlist_copy; if (IsShitlisted(remoteAddress.GetInAddr(), &shitlist_copy)) {is_shitlisted: WarLog debug_log(WARLOG_DEBUG, "WarSessionManager::OnAccept()"); if (debug_log) { debug_log << "Rejecting access from " << remoteAddress.Explain() << ". The IP address is shitlisted from " << shitlist_copy.GetCreatedTime().FormatLT() << " and until " << shitlist_copy.GetExpireTime().FormatLT() << " due to " << shitlist_copy.Explain() << war_endl; } WarThrow(WarError(WAR_ERR_SECURITY_VIOLATION), NULL); } // Check for flood int num_connects = 0; { const int this_addr = remoteAddress.GetInAddr().s_addr; AUTO_LOCK; // Add this entry WarTime until; until.Reset(mShortTimeHistorySeconds * 1000); mShortTermHistory.insert(connect_history_t(this_addr, until)); num_connects = mShortTermHistory.count(this_addr); } if (num_connects > mNumConnectsBeforeFlood) { ShitlistIp(shitlist_copy = WarIpShitlisted( WarIpShitlisted::REASON_FLOOD, remoteAddress.GetInAddr())); goto is_shitlisted; }}/* Incomming client connection. * The sockets are set up, and we have a pointer to the * server protocol in use. * We can now take the final decision wether to accept this * connection or not. */void WarSessionManager::OnClientConnect(WarSvrProtocol *pSvrProtocol) throw (WarException){ // Check the IP access list for this protocol. if (!pSvrProtocol->IsAllowed( pSvrProtocol->GetRemoteAddress().GetInAddr())) { WarLog inout_log(WARLOG_INOUT, "WarSessionManager::OnClientConnect()"); inout_log << "Rejecting connection from " << pSvrProtocol->GetRemoteAddress().Explain() << ". The IP address is denied in the IP access list." << war_endl; WarThrow(WarError(WAR_ERR_IP_IS_DENIED), NULL); }}/* A client have tried to authenticate. The result of the * authication attempts is in loginResult. Our primary concern is * brute-force password attacks. */void WarSessionManager::OnPostLogin( const std::string& userName, WarSvrProtocol *pSvrProtocol, war_authdata_ptr_t& userDataPtr, int& numFailedLoginAttepmts, WarSvrEnums::WarLoginResultE& loginResult) throw (WarException){ switch(loginResult) { case LF_OK: { string native_site_name = pSvrProtocol->GetNativeSiteName(); host_sessions_map_t::iterator hlP; site_sessions_map_t::iterator slP; AUTO_LOCK; // Create a session object. war_client_session_ptr_t session_ptr = new WarClientSession( native_site_name, userName, pSvrProtocol->GetRemoteAddress(), pSvrProtocol->GetSeqNumber()); // Check total number of logged-in users const int max_total_logins = pSvrProtocol->GetIntOption("svr_MAXTOTALCONN"); if (max_total_logins <= mNumClientConnections) { WarLog auth_log(WARLOG_INOUT, "WarSessionManager::OnPostLogin()"); auth_log << "The connection from " << *session_ptr << " is rejected because we have reached the " "limit of " << max_total_logins << " concurrent users. This limit can be " "altered by changing the svr_MAXTOTALCONN option." << war_endl; loginResult = LF_TOO_MANY_CONNECTIONS_TOTAL; } // Check total logins for this site int max_site_logins = pSvrProtocol->GetIntOption("svr_MAXSITECONN"); int num_logins = 0; slP = mSiteLogins.find( native_site_name); if (slP != mSiteLogins.end()) num_logins = slP->second; if ((0 < max_site_logins) && (num_logins >= max_site_logins)) { WarLog auth_log(WARLOG_INOUT, "WarSessionManager::OnPostLogin()"); auth_log << "The connection from " << *session_ptr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -