Added start time to bans and made ban_manager store deleted bans...

...in separate list
This commit is contained in:
Pauli Nieminen 2008-09-03 02:12:32 +00:00
parent 8fdeb979ad
commit 9fd2e4c203
4 changed files with 107 additions and 30 deletions

View file

@ -34,10 +34,11 @@ namespace wesnothd {
std::ostream& operator<<(std::ostream& o, const banned& n)
{
return o << "IP: '" << n.get_ip() <<
"' end_time: '" << n.get_human_end_time() <<
"' reason: '" << n.get_reason() <<
"' issuer: "<< n.get_who_banned() << "\n";
return o << "IP: " << n.get_ip() <<
" reason: '" << n.get_reason() <<
"' end_time: " << n.get_human_end_time() <<
" start_time: " << n.get_human_start_time() <<
" issuer: " << n.get_who_banned();
}
@ -100,6 +101,7 @@ namespace wesnothd {
mask_(0),
ip_text_(),
end_time_(0),
start_time_(0),
reason_(),
who_banned_(who_banned_default_)
@ -116,6 +118,7 @@ namespace wesnothd {
const std::string& group) :
ip_text_(ip),
end_time_(end_time),
start_time_(time(0)),
reason_(reason),
who_banned_(who_banned),
group_(group)
@ -130,6 +133,7 @@ namespace wesnothd {
mask_(0),
ip_text_(),
end_time_(0),
start_time_(0),
reason_(),
who_banned_(who_banned_default_)
{
@ -190,6 +194,8 @@ namespace wesnothd {
if (cfg.has_attribute("end_time"))
end_time_ = lexical_cast_default<time_t>(cfg["end_time"], 0);
if (cfg.has_attribute("start_time"))
start_time_ = lexical_cast_default<time_t>(cfg["start_time"], 0);
reason_ = cfg["reason"];
// only overwrite defaults if exists
@ -208,6 +214,13 @@ namespace wesnothd {
ss << end_time_;
cfg["end_time"] = ss.str();
}
if (start_time_ > 0)
{
std::stringstream ss;
ss << start_time_;
cfg["start_time"] = ss.str();
}
cfg["reason"] = reason_;
if (who_banned_ != who_banned_default_)
{
@ -219,12 +232,15 @@ namespace wesnothd {
}
}
std::string banned::get_human_end_time(const time_t& time)
std::string banned::get_human_start_time() const
{
if (start_time_ == 0)
return "unknown";
return banned::get_human_time(start_time_);
}
std::string banned::get_human_time(const time_t& time)
{
if (time == 0)
{
return "permanent";
}
char buf[30];
struct tm* local;
local = localtime(&time);
@ -235,7 +251,11 @@ namespace wesnothd {
std::string banned::get_human_end_time() const
{
return banned::get_human_end_time(end_time_);
if (end_time_ == 0)
{
return "permanent";
}
return banned::get_human_time(end_time_);
}
bool banned::operator>(const banned& b) const
@ -256,6 +276,7 @@ namespace wesnothd {
config cfg;
scoped_istream ban_file = istream_file(filename_);
read_gz(cfg, *ban_file);
const config::child_list& bans = cfg.get_children("ban");
for (config::child_list::const_iterator itor = bans.begin();
itor != bans.end(); ++itor)
@ -270,6 +291,25 @@ namespace wesnothd {
ERR_SERVER << e.message << " while reading bans\n";
}
}
// load deleted too
if (cfg.child("deleted"))
{
const config& cfg_del = *cfg.child("deleted");
const config::child_list& del_bans = cfg_del.get_children("ban");
for (config::child_list::const_iterator itor = del_bans.begin();
itor != del_bans.end(); ++itor)
{
try {
banned_ptr new_ban(new banned(**itor));
deleted_bans_.push_back(new_ban);
} catch (banned::error& e) {
ERR_SERVER << e.message << " while reading deleted bans\n";
}
}
}
}
void ban_manager::write()
@ -285,6 +325,14 @@ namespace wesnothd {
config& child = cfg.add_child("ban");
(*itor)->write(child);
}
config& deleted = cfg.add_child("deleted");
for (deleted_ban_list::const_iterator itor = deleted_bans_.begin();
itor != deleted_bans_.end(); ++itor)
{
config& child = deleted.add_child("ban");
(*itor)->write(child);
}
scoped_ostream ban_file = ostream_file(filename_);
config_writer writer(*ban_file, true, "");
writer.write(cfg);
@ -407,7 +455,7 @@ namespace wesnothd {
if ((ban = bans_.find(banned::create_dummy(ip))) != bans_.end())
{
// Already exsiting ban for ip. We have to first remove it
LOG_SERVER << "Overwriting ban: " << (*ban)->get_ip() << " reason was: " << (*ban)->get_reason() << "\n";
LOG_SERVER << "Overwriting ban: " << (**ban) << "\n";
bans_.erase(ban);
}
} catch (banned::error& e) {
@ -420,7 +468,7 @@ namespace wesnothd {
bans_.insert(new_ban);
if (end_time != 0)
time_queue_.push(new_ban);
ret << *new_ban << "\n";
ret << *new_ban;
} catch (banned::error& e) {
ERR_SERVER << e.message << " while banning\n";
return e.message;
@ -436,7 +484,7 @@ namespace wesnothd {
ban = bans_.find(banned::create_dummy(ip));
} catch (banned::error& e) {
ERR_SERVER << e.message << "\n";
os << e.message << "\n";
os << e.message;
return;
}
@ -445,10 +493,12 @@ namespace wesnothd {
os << "There is no ban on '" << ip << "'.";
return;
}
// keep ban entry still in memory
os << "Ban on '" << **ban << "' removed.";
deleted_bans_.push_back(*ban);
bans_.erase(ban);
dirty_ = true;
os << "Ban on '" << ip << "' removed.";
}
void ban_manager::unban_group(std::ostringstream& os, const std::string& group)
@ -486,6 +536,27 @@ namespace wesnothd {
write();
}
void ban_manager::list_deleted_bans(std::ostringstream& out) const
{
if (deleted_bans_.empty())
{
out << "No removed bans found.";
return;
}
for (deleted_ban_list::const_iterator i = deleted_bans_.begin();
i != deleted_bans_.end();
++i)
{
if (i != deleted_bans_.begin())
out << "\n";
out << (**i);
}
}
void ban_manager::list_bans(std::ostringstream& out) const
{
if (bans_.empty())
@ -496,13 +567,14 @@ namespace wesnothd {
std::set<std::string> groups;
out << "BAN LIST\n";
for (ban_set::const_iterator i = bans_.begin();
i != bans_.end(); ++i)
{
if ((*i)->get_group().empty())
{
out << (**i) << "\n";
if (i != bans_.begin())
out << "\n";
out << (**i);
} else {
groups.insert((*i)->get_group());
}

View file

@ -18,6 +18,7 @@
#include <set>
#include <map>
#include <list>
#include <queue>
#include <ctime>
@ -56,6 +57,7 @@ namespace wesnothd {
};
typedef std::set<banned_ptr,banned_compare_subnet > ban_set;
typedef std::list<banned_ptr> deleted_ban_list;
typedef std::priority_queue<banned_ptr,std::vector<banned_ptr>, banned_compare> ban_time_queue;
typedef std::map<std::string, size_t> default_ban_times;
@ -65,13 +67,17 @@ namespace wesnothd {
unsigned int mask_;
std::string ip_text_;
time_t end_time_;
time_t start_time_;
std::string reason_;
std::string who_banned_;
std::string group_;
static const std::string who_banned_default_;
typedef std::pair<unsigned int, unsigned int> ip_mask;
ip_mask parse_ip(const std::string&) const;
banned(const std::string& ip);
public:
banned(const std::string& ip, const time_t end_time, const std::string& reason, const std::string& who_banned=who_banned_default_, const std::string& group="");
banned(const config&);
@ -83,7 +89,8 @@ namespace wesnothd {
{ return end_time_; }
std::string get_human_end_time() const;
static std::string get_human_end_time(const time_t&);
std::string get_human_start_time() const;
static std::string get_human_time(const time_t&);
std::string get_reason() const
{ return reason_; }
@ -119,6 +126,7 @@ namespace wesnothd {
{
ban_set bans_;
deleted_ban_list deleted_bans_;
ban_time_queue time_queue_;
default_ban_times ban_times_;
std::string ban_help_;
@ -147,6 +155,7 @@ namespace wesnothd {
void check_ban_times(time_t time_now);
void list_deleted_bans(std::ostringstream& out) const;
void list_bans(std::ostringstream& out) const;
bool is_ip_banned(std::string ip) const;

View file

@ -75,7 +75,8 @@ void metrics::record_sample(const simple_wml::string_span& name,
clock_t parsing_time, clock_t processing_time)
{
std::vector<sample>::iterator isample = std::lower_bound(samples_.begin(), samples_.end(), name,compare_samples_to_stringspan());
if(isample->name != name) {
if(isample == samples_.end()
|| isample->name != name) {
//protect against DoS with memory exhaustion
if(samples_.size() > 30) {
return;

View file

@ -981,7 +981,9 @@ std::string server::process_command(const std::string& query, const std::string&
} else if (command == "ban" || command == "bans" || command == "kban" || command == "kickban" || command == "gban") {
if (parameters == "") {
ban_manager_.list_bans(out);
} else {
} else if (parameters == "deleted") {
ban_manager_.list_deleted_bans(out);
}else {
bool banned_ = false;
const bool kick = (command == "kban" || command == "kickban");
const bool group_ban = command == "gban";
@ -1021,17 +1023,14 @@ std::string server::process_command(const std::string& query, const std::string&
banned_ = true;
std::string err = ban_manager_.ban(target, parsed_time, reason, issuer_name, group);
if (err.empty())
out << "Set ban on '" << target << "' with end time '" << wesnothd::banned::get_human_end_time(parsed_time) << "' with reason: '" << reason << "'.\n";
else
out << err << "\n";
out << err;
if (kick) {
for (wesnothd::player_map::const_iterator pl = players_.begin();
pl != players_.end(); ++pl)
{
if (utils::wildcard_string_match(network::ip_address(pl->first), target)) {
out << "Kicked " << pl->second.name() << ".\n";
out << "\nKicked " << pl->second.name() << ".";
network::queue_disconnect(pl->first);
}
}
@ -1045,14 +1044,10 @@ std::string server::process_command(const std::string& query, const std::string&
const std::string& ip = network::ip_address(pl->first);
if (!is_ip_banned(ip)) {
std::string err = ban_manager_.ban(ip,parsed_time, reason, issuer_name, group);
if (err.empty())
out << "Set ban on '" << ip << "' with end time '" << wesnothd::banned::get_human_end_time(parsed_time) << "' with reason: '"
<< reason << "'.\n";
else
out << err << "\n";
out << err;
}
if (kick) {
out << "Kicked " << pl->second.name() << ".\n";
out << "\nKicked " << pl->second.name() << ".";
network::queue_disconnect(pl->first);
}
}