added ipban support

commands:
/#ipban <nick>
/#ipunban <ip>
This commit is contained in:
Constantin Wenger 2011-08-12 01:13:42 +02:00
parent 371af9c241
commit 5784c14ab7
11 changed files with 271 additions and 1 deletions

@ -127,6 +127,7 @@ set(common_SRCS
test.cpp
sha1.cpp
base64.cpp
ban.cpp
)
# This gives us the icon

@ -40,6 +40,8 @@ std::string privsToString(u64 privs)
os<<"privs,";
if(privs & PRIV_SHOUT)
os<<"shout,";
if(privs & PRIV_BAN)
os<<"ban,";
if(os.tellp())
{
// Drop the trailing comma. (Why on earth can't
@ -70,6 +72,8 @@ u64 stringToPrivs(std::string str)
privs |= PRIV_PRIVS;
else if(s == "shout")
privs |= PRIV_SHOUT;
else if(s == "ban")
privs |= PRIV_BAN;
else
return PRIV_INVALID;
}

@ -38,6 +38,7 @@ const u64 PRIV_SERVER = 16; // Can manage the server (e.g. shutodwn
// ,settings)
const u64 PRIV_SHOUT = 32; // Can broadcast chat messages to all
// players
const u64 PRIV_BAN = 64; // Can ban players
// Default privileges - these can be overriden for new players using the
// config option "default_privs" - however, this value still applies for

118
src/ban.cpp Normal file

@ -0,0 +1,118 @@
/*
Minetest-c55
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "ban.h"
#include <fstream>
#include <jmutexautolock.h>
#include <sstream>
#include "strfnd.h"
#include "debug.h"
BanManager::BanManager(const std::string &banfilepath):
m_banfilepath(banfilepath),
m_modified(false)
{
m_mutex.Init();
try{
load();
}
catch(SerializationError &e)
{
dstream<<"WARNING: BanManager: creating "
<<m_banfilepath<<std::endl;
}
}
BanManager::~BanManager()
{
save();
}
void BanManager::load()
{
JMutexAutoLock lock(m_mutex);
dstream<<"BanManager: loading from "<<m_banfilepath<<std::endl;
std::ifstream is(m_banfilepath.c_str(), std::ios::binary);
if(is.good() == false)
{
dstream<<"BanManager: failed loading from "<<m_banfilepath<<std::endl;
throw SerializationError("BanManager::load(): Couldn't open file");
}
for(;;)
{
if(is.eof() || is.good() == false)
break;
std::string ip;
std::getline(is, ip, '\n');
m_ips.insert(ip);
}
m_modified = false;
}
void BanManager::save()
{
JMutexAutoLock lock(m_mutex);
dstream<<"BanManager: saving to "<<m_banfilepath<<std::endl;
std::ofstream os(m_banfilepath.c_str(), std::ios::binary);
if(os.good() == false)
{
dstream<<"BanManager: failed loading from "<<m_banfilepath<<std::endl;
throw SerializationError("BanManager::load(): Couldn't open file");
}
for(std::set<std::string>::iterator
i = m_ips.begin();
i != m_ips.end(); i++)
{
if(*i == "")
continue;
os<<*i<<"\n";
}
m_modified = false;
}
bool BanManager::isIpBanned(std::string ip)
{
JMutexAutoLock lock(m_mutex);
return m_ips.find(ip) != m_ips.end();
}
void BanManager::add(std::string ip)
{
JMutexAutoLock lock(m_mutex);
m_ips.insert(ip);
m_modified = true;
}
void BanManager::remove(std::string ip)
{
JMutexAutoLock lock(m_mutex);
m_ips.erase(m_ips.find(ip));
m_modified = true;
}
bool BanManager::isModified()
{
JMutexAutoLock lock(m_mutex);
return m_modified;
}

49
src/ban.h Normal file

@ -0,0 +1,49 @@
/*
Minetest-c55
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef BAN_HEADER
#define BAN_HEADER
#include <set>
#include <string>
#include <jthread.h>
#include <jmutex.h>
#include "common_irrlicht.h"
#include "exceptions.h"
class BanManager
{
public:
BanManager(const std::string &bannfilepath);
~BanManager();
void load();
void save();
void add(std::string ip);
void remove(std::string ip);
bool isIpBanned(std::string ip);
bool isModified();
private:
JMutex m_mutex;
std::string m_banfilepath;
std::set<std::string> m_ips;
bool m_modified;
};
#endif

@ -1062,6 +1062,14 @@ void the_game(
{
//std::cerr<<"frame"<<std::endl;
if(client.accessDenied())
{
error_message = L"Access denied. Reason: "
+client.accessDeniedReason();
std::cout<<DTIME<<wide_to_narrow(error_message)<<std::endl;
break;
}
if(g_gamecallback->disconnect_requested)
{
g_gamecallback->disconnect_requested = false;

@ -1063,6 +1063,7 @@ Server::Server(
m_env(new ServerMap(mapsavedir), this),
m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, this),
m_authmanager(mapsavedir+"/auth.txt"),
m_banmanager(mapsavedir+"/ipban.txt"),
m_thread(this),
m_emergethread(this),
m_time_counter(0),
@ -1834,6 +1835,10 @@ void Server::AsyncRunStep()
// Auth stuff
if(m_authmanager.isModified())
m_authmanager.save();
//Bann stuff
if(m_banmanager.isModified())
m_banmanager.save();
// Map
JMutexAutoLock lock(m_env_mutex);
@ -1923,6 +1928,14 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
<<peer_id<<" not found"<<std::endl;
return;
}
// drop player if is ip is banned
if(m_banmanager.isIpBanned(peer->address.serializeString())){
SendAccessDenied(m_con, peer_id,
L"Your ip is banned!");
m_con.deletePeer(peer_id, false);
return;
}
u8 peer_ser_ver = getClient(peer->id)->serialization_version;
@ -1959,7 +1972,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
//peer->serialization_version = deployed;
getClient(peer->id)->pending_serialization_version = deployed;
if(deployed == SER_FMT_VER_INVALID)
{
derr_server<<DTIME<<"Server: Cannot negotiate "

@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "map.h"
#include "inventory.h"
#include "auth.h"
#include "ban.h"
/*
Some random functions
@ -455,6 +456,23 @@ public:
g_settings.updateConfigFile(m_configpath.c_str());
}
void setIpBanned(std::string ip)
{
m_banmanager.add(ip);
return;
}
void unsetIpBanned(std::string ip)
{
m_banmanager.remove(ip);
return;
}
con::Peer* getPeerNoEx(u16 peer_id)
{
return m_con.GetPeerNoEx(peer_id);
}
private:
// con::PeerHandler implementation.
@ -566,6 +584,9 @@ private:
// User authentication
AuthManager m_authmanager;
// Bann checking
BanManager m_banmanager;
/*
Threads

@ -183,6 +183,44 @@ void cmd_teleport(std::wostringstream &os,
os<< L"-!- Teleported.";
}
void cmd_ipbanunban(std::wostringstream &os, ServerCommandContext *ctx)
{
if((ctx->privs && PRIV_BAN) == 0)
{
os<<L"-!- You don't have permission to do that";
return;
}
if(ctx->parms.size() != 2)
{
os<<L"-!- Missing parameter";
return;
}
if(ctx->parms[0] == L"ipban")
{
Player *player = ctx->env->getPlayer(wide_to_narrow(ctx->parms[1]).c_str());
if(player == NULL)
{
os<<L"-!- No such Player!";
return;
}
con::Peer *peer = ctx->server->getPeerNoEx(player->peer_id);
if(peer == NULL)
{
dstream<<"peer was not found!"<<std::endl;
}
ctx->server->setIpBanned(peer->address.serializeString());
os<<L"-!- IP: "<<narrow_to_wide(peer->address.serializeString())<<L" was banned!";
}
else
{
ctx->server->unsetIpBanned(wide_to_narrow(ctx->parms[1]));
os<<L"-!- IP: "<<ctx->parms[1]<<L" was unbanned!";
}
}
std::wstring processServerCommand(ServerCommandContext *ctx)
{
@ -204,6 +242,8 @@ std::wstring processServerCommand(ServerCommandContext *ctx)
os<<L" teleport";
if(privs & PRIV_PRIVS)
os<<L" grant revoke";
if(privs & PRIV_BAN)
os<<L" ipban ipunban";
}
else if(ctx->parms[0] == L"status")
{
@ -233,6 +273,10 @@ std::wstring processServerCommand(ServerCommandContext *ctx)
{
cmd_teleport(os, ctx);
}
else if(ctx->parms[0] == L"ipban" || ctx->parms[0] == L"ipunban")
{
cmd_ipbanunban(os, ctx);
}
else
{
os<<L"-!- Invalid command: " + ctx->parms[0];

@ -97,6 +97,16 @@ void Address::Resolve(const char *name)
freeaddrinfo(resolved);
}
std::string Address::serializeString()
{
unsigned int a, b, c, d;
a = (m_address && 0xFF000000)>>24;
b = (m_address && 0x00FF0000)>>16;
c = (m_address && 0x0000FF00)>>8;
d = (m_address && 0x000000FF);
return itos(a)+"."+itos(b)+"."+itos(c)+"."+itos(d);
}
unsigned int Address::getAddress() const
{
return m_address;

@ -97,6 +97,7 @@ public:
void setPort(unsigned short port);
void print(std::ostream *s) const;
void print() const;
std::string serializeString();
private:
unsigned int m_address;
unsigned short m_port;