added ipban support
authorConstantin Wenger <constantin.wenger@googlemail.com>
Thu, 11 Aug 2011 23:13:42 +0000 (01:13 +0200)
committerConstantin Wenger <constantin.wenger@googlemail.com>
Fri, 12 Aug 2011 01:37:18 +0000 (03:37 +0200)
commands:
/#ipban <nick>
/#ipunban <ip>

src/CMakeLists.txt
src/auth.cpp
src/auth.h
src/ban.cpp [new file with mode: 0644]
src/ban.h [new file with mode: 0644]
src/game.cpp
src/server.cpp
src/server.h
src/servercommand.cpp
src/socket.cpp
src/socket.h

index 0fceb85e72b967898fe81b22fe878163ac61d687..9c3b0960adbd7a62b0fd28d88dd6a502d409cfef 100644 (file)
@@ -127,6 +127,7 @@ set(common_SRCS
        test.cpp
        sha1.cpp
        base64.cpp
+       ban.cpp
 )
 
 # This gives us the icon
index 5d61243c693e357e279da5d6ee6f06d7160a0960..dc740411b2051109597906195bb65ce6c789ff94 100644 (file)
@@ -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;
        }
index 62dced2a38e0f6b6e481b3cfdaa41c2d7a399eb4..5ea697a6acd1792230ac1e509c31719438e78187 100644 (file)
@@ -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 (file)
index 0000000..0d66e80
--- /dev/null
@@ -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 (file)
index 0000000..38b08b6
--- /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
index 147a1fa07b8680e8ad12ffee4bf83749b6cc7cf3..a3a5f424a376c53b598d2ae6ecd251deaca0a884 100644 (file)
@@ -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;
index 176a13e38f7186dfb78c3af3ad511679810bd0d6..65ea4533043724b869d79f3093afe1719094dbc5 100644 (file)
@@ -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 "
index b10703e707803ee671c5e8ca9cdf4ac93621890a..df2d38e65a220cebd77060cbc9949877644e0c8e 100644 (file)
@@ -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
index 7d6d7bb73e6dbfdf967bead0e39c59e796cb1ff5..87d7cd363c540ffa822554b2a88d2062dffaa8a7 100644 (file)
@@ -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];
index ab3ca62c58d6ee90ee1dc050c92dd7207a9daedd..a7d20404707d977f7ea19f952b797768db7ca8b7 100644 (file)
@@ -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;
index c2b496e9ed3afffd4dde041a56e68766400a61c3..f24947c2785b10341d361514e989f52c12c9c617 100644 (file)
@@ -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;