diff options
-rw-r--r-- | src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/auth.cpp | 4 | ||||
-rw-r--r-- | src/auth.h | 1 | ||||
-rw-r--r-- | src/ban.cpp | 118 | ||||
-rw-r--r-- | src/ban.h | 49 | ||||
-rw-r--r-- | src/game.cpp | 8 | ||||
-rw-r--r-- | src/server.cpp | 15 | ||||
-rw-r--r-- | src/server.h | 21 | ||||
-rw-r--r-- | src/servercommand.cpp | 44 | ||||
-rw-r--r-- | src/socket.cpp | 10 | ||||
-rw-r--r-- | src/socket.h | 1 |
11 files changed, 271 insertions, 1 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0fceb85e7..9c3b0960a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -127,6 +127,7 @@ set(common_SRCS test.cpp sha1.cpp base64.cpp + ban.cpp ) # This gives us the icon diff --git a/src/auth.cpp b/src/auth.cpp index 5d61243c6..dc740411b 100644 --- a/src/auth.cpp +++ b/src/auth.cpp @@ -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; } diff --git a/src/auth.h b/src/auth.h index 62dced2a3..5ea697a6a 100644 --- a/src/auth.h +++ b/src/auth.h @@ -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 diff --git a/src/ban.cpp b/src/ban.cpp new file mode 100644 index 000000000..0d66e8041 --- /dev/null +++ b/src/ban.cpp @@ -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; +} + diff --git a/src/ban.h b/src/ban.h new file mode 100644 index 000000000..38b08b604 --- /dev/null +++ b/src/ban.h @@ -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 diff --git a/src/game.cpp b/src/game.cpp index 147a1fa07..a3a5f424a 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -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; diff --git a/src/server.cpp b/src/server.cpp index 176a13e38..65ea45330 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -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 " diff --git a/src/server.h b/src/server.h index b10703e70..df2d38e65 100644 --- a/src/server.h +++ b/src/server.h @@ -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 diff --git a/src/servercommand.cpp b/src/servercommand.cpp index 7d6d7bb73..87d7cd363 100644 --- a/src/servercommand.cpp +++ b/src/servercommand.cpp @@ -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]; diff --git a/src/socket.cpp b/src/socket.cpp index ab3ca62c5..a7d204047 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -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; diff --git a/src/socket.h b/src/socket.h index c2b496e9e..f24947c27 100644 --- a/src/socket.h +++ b/src/socket.h @@ -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; |