added: possibility to ban if a session cookie is incorrect (when we are using encoded cookies)
added: possibility to ban if a client tries to hijack the session cookie added: possibility to ban if a client did not send a session cookie renamed: ezc functions: login_cannot_login -> ipban_is_login_allowed_from_this_ip (and the return value was changed) login_when_available_login -> ipban_current_ip_expires_time added: config options: // after how many broken encoded cookie we should ban the current IP // default: 2 (value in the range <0 - 65535>) size_t broken_encoded_cookie_treshold; // after how many incorrect session identifiers (or session indices) we should ban the current IP // do not set this value too low, as people connecting from the same IP address (from behind a NAT) // would be banned if they have an old session cookie remembered in the browser // default: 128 (value in the range <0 - 65535>) size_t session_hijacking_treshold; // after how many times a client will be banned if it did not send a session cookie // default: 1000 (value in the range <0 - 65535>) size_t no_session_cookie_treshold; git-svn-id: svn://ttmath.org/publicrep/winix/trunk@995 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
@@ -127,6 +127,9 @@ bool SessionManager::EncodeSessionId(long id, unsigned int index, std::wstring &
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* IMPROVE ME we need a better algorithm
|
||||
*/
|
||||
long SessionManager::CreateSessionId()
|
||||
{
|
||||
long id;
|
||||
@@ -179,6 +182,7 @@ SessionContainer::Iterator i = session_tab.End();
|
||||
|
||||
if( i != session_tab.End() )
|
||||
{
|
||||
is_session_set = true;
|
||||
session = &(*i);
|
||||
session->new_session = true;
|
||||
session->SetTimesTo(cur->request->start_time);
|
||||
@@ -190,7 +194,7 @@ SessionContainer::Iterator i = session_tab.End();
|
||||
else
|
||||
{
|
||||
// there is a problem with generating a new session id
|
||||
log << log1 << "SM: cannot create a session id (temporary used: with id 0)" << logend;
|
||||
log << log1 << "SM: cannot create a session id" << logend;
|
||||
SetTemporarySession();
|
||||
}
|
||||
}
|
||||
@@ -198,14 +202,18 @@ SessionContainer::Iterator i = session_tab.End();
|
||||
|
||||
void SessionManager::SetTemporarySession()
|
||||
{
|
||||
is_session_set = true;
|
||||
|
||||
session = &temporary_session;
|
||||
session->Clear(false);
|
||||
session->SetTimesTo(cur->request->start_time);
|
||||
session->new_session = false; // temporary session was initialized at the beginning
|
||||
|
||||
log << log2 << "SM: using temporary session" << logend;
|
||||
}
|
||||
|
||||
|
||||
unsigned int SessionManager::SetSessionCalcDifference(Session & ses, unsigned int index)
|
||||
unsigned int SessionManager::CalculateIndexDifference(Session & ses, unsigned int index)
|
||||
{
|
||||
unsigned int difference;
|
||||
|
||||
@@ -233,15 +241,103 @@ void SessionManager::SetSessionPutLogInfo(Session & ses, bool has_index, unsigne
|
||||
|
||||
|
||||
|
||||
bool SessionManager::SetSessionFromCookie(long id, bool has_index, unsigned int index)
|
||||
void SessionManager::IncrementBanLevel(IPBan * ip_ban)
|
||||
{
|
||||
unsigned int difference = 0;
|
||||
ip_ban->SetFlag(WINIX_IPBAN_FLAG_ACTIVE);
|
||||
|
||||
SessionContainer::Iterator s = session_tab.FindById(id);
|
||||
ip_ban->IncrementBanLevel(cur->request->start_time + (time_t)config->ban_level_1_delay,
|
||||
cur->request->start_time + (time_t)config->ban_level_2_delay,
|
||||
cur->request->start_time + (time_t)config->ban_level_3_delay);
|
||||
|
||||
PT::Date date(ip_ban->expires);
|
||||
log << log2 << "SM: this IP address has been banned to: " << date << " UTC" << logend;
|
||||
}
|
||||
|
||||
|
||||
void SessionManager::SetFirstExpirationTime(IPBan * ip_ban)
|
||||
{
|
||||
time_t expiry = cur->request->start_time + (time_t)config->ban_level_1_delay;
|
||||
|
||||
if( ip_ban->expires < expiry )
|
||||
ip_ban->expires = expiry;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SessionManager::BrokenCookieCheckBan()
|
||||
{
|
||||
if( !current_ip_ban )
|
||||
current_ip_ban = &AddIPToBanList(cur->request->ip, cur->request->start_time);
|
||||
|
||||
if( current_ip_ban->broken_encoded_cookie_events < config->broken_encoded_cookie_treshold )
|
||||
{
|
||||
current_ip_ban->broken_encoded_cookie_events += 1;
|
||||
SetFirstExpirationTime(current_ip_ban);
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log2 << "SM: too many incorrect encoded cookies were sent from this IP" << logend;
|
||||
IncrementBanLevel(current_ip_ban);
|
||||
SetTemporarySession();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SessionManager::IncorrectSessionCheckBan()
|
||||
{
|
||||
if( !current_ip_ban )
|
||||
current_ip_ban = &AddIPToBanList(cur->request->ip, cur->request->start_time);
|
||||
|
||||
if( current_ip_ban->session_hijacking_events < config->session_hijacking_treshold )
|
||||
{
|
||||
current_ip_ban->session_hijacking_events += 1;
|
||||
SetFirstExpirationTime(current_ip_ban);
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log2 << "SM: too many incorrect sessions identifiers were sent from this IP" << logend;
|
||||
IncrementBanLevel(current_ip_ban);
|
||||
SetTemporarySession();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SessionManager::NoSessionCookieCheckBan()
|
||||
{
|
||||
if( !current_ip_ban )
|
||||
current_ip_ban = &AddIPToBanList(cur->request->ip, cur->request->start_time);
|
||||
|
||||
if( current_ip_ban->no_session_cookie_events < config->no_session_cookie_treshold )
|
||||
{
|
||||
current_ip_ban->no_session_cookie_events += 1;
|
||||
SetFirstExpirationTime(current_ip_ban);
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log2 << "SM: too many times you have not sent a session cookie" << logend;
|
||||
IncrementBanLevel(current_ip_ban);
|
||||
SetTemporarySession();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool SessionManager::IsSessionCorrect(long id, bool has_index, unsigned int index,
|
||||
const SessionContainer::Iterator & s, unsigned int & difference)
|
||||
{
|
||||
difference = 0;
|
||||
|
||||
if( id == 0 )
|
||||
{
|
||||
log << log3 << "SM: id 0 is reserved for the temporary session" << logend;
|
||||
IncorrectSessionCheckBan();
|
||||
return false;
|
||||
}
|
||||
|
||||
if( s == session_tab.End() )
|
||||
{
|
||||
log << log3 << "SM: there is no a session with id: " << id << logend;
|
||||
IncorrectSessionCheckBan();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -253,34 +349,51 @@ unsigned int difference = 0;
|
||||
|
||||
if( has_index )
|
||||
{
|
||||
difference = SetSessionCalcDifference(*s, index);
|
||||
difference = CalculateIndexDifference(*s, index);
|
||||
|
||||
if( (size_t)difference > config->session_allow_index_difference )
|
||||
{
|
||||
log << log2 << "SM: an incorrect session index for session: " << id
|
||||
<< ", index difference: " << (size_t)difference << logend;
|
||||
|
||||
IncorrectSessionCheckBan();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// that session is in the table
|
||||
session = &(*s);
|
||||
session->new_session = false;
|
||||
session->last_time = cur->request->start_time;
|
||||
session->last_date = cur->request->start_date;
|
||||
return true;
|
||||
}
|
||||
|
||||
if( session->id_index_changed + config->session_index_time_increment < cur->request->start_time )
|
||||
|
||||
bool SessionManager::SetSessionFromCookie(long id, bool has_index, unsigned int index)
|
||||
{
|
||||
unsigned int difference;
|
||||
bool is_session_correct;
|
||||
|
||||
SessionContainer::Iterator s = session_tab.FindById(id);
|
||||
is_session_correct = IsSessionCorrect(id, has_index, index, s, difference);
|
||||
|
||||
if( is_session_correct )
|
||||
{
|
||||
session->id_index += 1;
|
||||
session->id_index_changed = cur->request->start_time;
|
||||
is_session_set = true;
|
||||
session = &(*s);
|
||||
session->new_session = false;
|
||||
session->last_time = cur->request->start_time;
|
||||
session->last_date = cur->request->start_date;
|
||||
|
||||
if( session->id_index_changed + config->session_index_time_increment < cur->request->start_time )
|
||||
{
|
||||
session->id_index += 1;
|
||||
session->id_index_changed = cur->request->start_time;
|
||||
}
|
||||
|
||||
if( cur->request->method == Request::get )
|
||||
session->last_time_get = cur->request->start_time;
|
||||
|
||||
SetSessionPutLogInfo(*session, has_index, difference);
|
||||
}
|
||||
|
||||
if( cur->request->method == Request::get )
|
||||
session->last_time_get = cur->request->start_time;
|
||||
|
||||
SetSessionPutLogInfo(*session, has_index, difference);
|
||||
|
||||
return true;
|
||||
return is_session_correct;
|
||||
}
|
||||
|
||||
|
||||
@@ -296,6 +409,7 @@ bool SessionManager::SetSessionFromCookie(const std::wstring & cookie)
|
||||
if( !session_id_manager.DecodeToken(cookie, id, index) )
|
||||
{
|
||||
log << log2 << "SM: an incorrect cookie string was sent" << logend;
|
||||
BrokenCookieCheckBan();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -309,45 +423,52 @@ bool SessionManager::SetSessionFromCookie(const std::wstring & cookie)
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SessionManager::SetSession()
|
||||
bool SessionManager::IsIPBanned()
|
||||
{
|
||||
current_ip_ban = ban_tab.FindIP(cur->request->ip);
|
||||
|
||||
if( current_ip_ban && current_ip_ban->IsIPBanned() )
|
||||
if( current_ip_ban )
|
||||
{
|
||||
if( current_ip_ban->expires != 0 && cur->request->start_time >= current_ip_ban->expires )
|
||||
{
|
||||
log << log2 << "SM: removing a ban from this IP and resetting events counter" << logend;
|
||||
current_ip_ban->ClearAfterRemovingBan();
|
||||
log << log2 << "SM: resetting events counters for this IP" << logend;
|
||||
current_ip_ban->ResetEventsCounters();
|
||||
}
|
||||
else
|
||||
if( current_ip_ban->IsIPBanned() )
|
||||
{
|
||||
PT::Date date = current_ip_ban->expires;
|
||||
log << log2 << "SM: this ip is bannned to: " << date << logend;
|
||||
SetTemporarySession();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void SessionManager::SetSession()
|
||||
{
|
||||
is_session_set = false;
|
||||
|
||||
if( !IsIPBanned() )
|
||||
{
|
||||
CookieTab::iterator i = cur->request->cookie_tab.find(config->http_session_id_name);
|
||||
|
||||
if( i != cur->request->cookie_tab.end() )
|
||||
{
|
||||
if( !SetSessionFromCookie(i->second) )
|
||||
cur->request->cookie_tab.erase(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
log << log2 << "SM: this ip is bannned, using a temporary session" << logend;
|
||||
SetTemporarySession();
|
||||
session->ip_ban = current_ip_ban;
|
||||
return;
|
||||
NoSessionCookieCheckBan();
|
||||
}
|
||||
}
|
||||
|
||||
CookieTab::iterator i = cur->request->cookie_tab.find(config->http_session_id_name);
|
||||
|
||||
if( i == cur->request->cookie_tab.end() )
|
||||
{
|
||||
if( !is_session_set )
|
||||
CreateSession();
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !SetSessionFromCookie(i->second) )
|
||||
{
|
||||
// there is no such a session
|
||||
// deleting the old cookie
|
||||
cur->request->cookie_tab.erase(i);
|
||||
|
||||
// and creating a new one
|
||||
CreateSession();
|
||||
}
|
||||
}
|
||||
|
||||
session->ip_ban = current_ip_ban;
|
||||
}
|
||||
@@ -578,6 +699,15 @@ IPBan & SessionManager::AddIPToBanList(int ip)
|
||||
}
|
||||
|
||||
|
||||
IPBan & SessionManager::AddIPToBanList(int ip, time_t cur_time)
|
||||
{
|
||||
IPBan & ban = ban_tab.AddIP(ip);
|
||||
ban.last_used = cur_time;
|
||||
|
||||
return ban;
|
||||
}
|
||||
|
||||
|
||||
size_t SessionManager::BanListSize()
|
||||
{
|
||||
return ban_tab.Size();
|
||||
|
Reference in New Issue
Block a user