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:
2014-11-24 20:22:30 +00:00
parent 76314aab10
commit c9bf20201b
18 changed files with 368 additions and 136 deletions

View File

@@ -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();