user banning

This commit is contained in:
Max-Wilhelm Bruker 2011-03-03 01:16:13 +01:00
parent 6145d6d524
commit 57f9e2c3b4
27 changed files with 220 additions and 37 deletions

View file

@ -33,6 +33,10 @@ Servatrice::Servatrice(QObject *parent)
connect(pingClock, SIGNAL(timeout()), this, SIGNAL(pingClockTimeout()));
pingClock->start(1000);
banTimeoutClock = new QTimer(this);
connect(banTimeoutClock, SIGNAL(timeout()), this, SLOT(updateBanTimer()));
banTimeoutClock->start(60000);
ProtocolItem::initializeHash();
settings = new QSettings("servatrice.ini", QSettings::IniFormat, this);
@ -85,6 +89,7 @@ Servatrice::Servatrice(QObject *parent)
maxGameInactivityTime = settings->value("game/max_game_inactivity_time").toInt();
maxPlayerInactivityTime = settings->value("game/max_player_inactivity_time").toInt();
maxUsersPerAddress = settings->value("security/max_users_per_address").toInt();
messageCountingInterval = settings->value("security/message_counting_interval").toInt();
maxMessageCountPerInterval = settings->value("security/max_message_count_per_interval").toInt();
maxMessageSizePerInterval = settings->value("security/max_message_size_per_interval").toInt();
@ -232,6 +237,15 @@ ServerInfo_User *Servatrice::getUserData(const QString &name)
return new ServerInfo_User(name, ServerInfo_User::IsUser);
}
int Servatrice::getUsersWithAddress(const QHostAddress &address) const
{
int result = 0;
for (int i = 0; i < clients.size(); ++i)
if (static_cast<ServerSocketInterface *>(clients[i])->getPeerAddress() == address)
++result;
return result;
}
QMap<QString, ServerInfo_User *> Servatrice::getBuddyList(const QString &name)
{
QMap<QString, ServerInfo_User *> result;
@ -276,6 +290,32 @@ QMap<QString, ServerInfo_User *> Servatrice::getIgnoreList(const QString &name)
return result;
}
bool Servatrice::getUserBanned(Server_ProtocolHandler *client, const QString &userName) const
{
QHostAddress address = static_cast<ServerSocketInterface *>(client)->getPeerAddress();
for (int i = 0; i < addressBanList.size(); ++i)
if (address == addressBanList[i].first)
return true;
for (int i = 0; i < nameBanList.size(); ++i)
if (userName == nameBanList[i].first)
return true;
return false;
}
void Servatrice::updateBanTimer()
{
for (int i = 0; i < addressBanList.size(); )
if (--(addressBanList[i].second) <= 0)
addressBanList.removeAt(i);
else
++i;
for (int i = 0; i < nameBanList.size(); )
if (--(nameBanList[i].second) <= 0)
nameBanList.removeAt(i);
else
++i;
}
void Servatrice::updateLoginMessage()
{
checkSql();
@ -308,4 +348,4 @@ void Servatrice::statusUpdate()
execSqlQuery(query);
}
const QString Servatrice::versionString = "Servatrice 0.20110215";
const QString Servatrice::versionString = "Servatrice 0.20110303";

View file

@ -34,6 +34,7 @@ class Servatrice : public Server
private slots:
void newConnection();
void statusUpdate();
void updateBanTimer();
public:
static const QString versionString;
Servatrice(QObject *parent = 0);
@ -45,27 +46,33 @@ public:
bool getGameShouldPing() const { return true; }
int getMaxGameInactivityTime() const { return maxGameInactivityTime; }
int getMaxPlayerInactivityTime() const { return maxPlayerInactivityTime; }
int getMaxUsersPerAddress() const { return maxUsersPerAddress; }
int getMessageCountingInterval() const { return messageCountingInterval; }
int getMaxMessageCountPerInterval() const { return maxMessageCountPerInterval; }
int getMaxMessageSizePerInterval() const { return maxMessageSizePerInterval; }
QString getDbPrefix() const { return dbPrefix; }
void updateLoginMessage();
ServerInfo_User *getUserData(const QString &name);
int getUsersWithAddress(const QHostAddress &address) const;
QMap<QString, ServerInfo_User *> getBuddyList(const QString &name);
QMap<QString, ServerInfo_User *> getIgnoreList(const QString &name);
bool getUserBanned(Server_ProtocolHandler *client, const QString &userName) const;
void addAddressBan(const QHostAddress &address, int minutes) { addressBanList.append(QPair<QHostAddress, int>(address, minutes)); }
void addNameBan(const QString &name, int minutes) { nameBanList.append(QPair<QString, int>(name, minutes)); }
protected:
bool userExists(const QString &user);
AuthenticationResult checkUserPassword(const QString &user, const QString &password);
QMap<QString, ServerInfo_User *> getBuddyList(const QString &name);
QMap<QString, ServerInfo_User *> getIgnoreList(const QString &name);
private:
QTimer *pingClock, *statusUpdateClock;
QTimer *pingClock, *statusUpdateClock, *banTimeoutClock;
QTcpServer *tcpServer;
QString loginMessage;
QString dbPrefix;
QSettings *settings;
int uptime;
int maxGameInactivityTime;
int maxPlayerInactivityTime;
int messageCountingInterval, maxMessageCountPerInterval, maxMessageSizePerInterval;
QList<QPair<QHostAddress, int> > addressBanList;
QList<QPair<QString, int> > nameBanList;
int maxGameInactivityTime, maxPlayerInactivityTime;
int maxUsersPerAddress, messageCountingInterval, maxMessageCountPerInterval, maxMessageSizePerInterval;
ServerInfo_User *evalUserQueryResult(const QSqlQuery &query, bool complete);
};

View file

@ -21,6 +21,7 @@
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
#include <QtSql>
#include <QHostAddress>
#include <QDebug>
#include "serversocketinterface.h"
#include "servatrice.h"
@ -45,13 +46,19 @@ ServerSocketInterface::ServerSocketInterface(Servatrice *_server, QTcpSocket *_s
xmlWriter->writeStartElement("cockatrice_server_stream");
xmlWriter->writeAttribute("version", QString::number(ProtocolItem::protocolVersion));
sendProtocolItem(new Event_ServerMessage(Servatrice::versionString));
int maxUsers = _server->getMaxUsersPerAddress();
if ((maxUsers > 0) && (_server->getUsersWithAddress(socket->peerAddress()) >= maxUsers)) {
sendProtocolItem(new Event_ConnectionClosed("too_many_connections"));
deleteLater();
} else
sendProtocolItem(new Event_ServerMessage(Servatrice::versionString));
}
ServerSocketInterface::~ServerSocketInterface()
{
qDebug("ServerSocketInterface destructor");
socket->flush();
delete xmlWriter;
delete xmlReader;
delete socket;
@ -424,3 +431,35 @@ ResponseCode ServerSocketInterface::cmdUpdateServerMessage(Command_UpdateServerM
servatrice->updateLoginMessage();
return RespOk;
}
ResponseCode ServerSocketInterface::cmdBanFromServer(Command_BanFromServer *cmd, CommandContainer *cont)
{
QString userName = cmd->getUserName();
if (!server->getUsers().contains(userName))
return RespNameNotFound;
int minutes = cmd->getMinutes();
ServerSocketInterface *user = static_cast<ServerSocketInterface *>(server->getUsers().value(userName));
if (user->getUserInfo()->getUserLevel() & ServerInfo_User::IsRegistered) {
// Registered users can be banned by name.
if (minutes == 0) {
QSqlQuery query;
query.prepare("update " + servatrice->getDbPrefix() + "_users set banned=1 where name = :name");
query.bindValue(":name", userName);
servatrice->execSqlQuery(query);
} else
servatrice->addNameBan(userName, minutes);
} else {
// Unregistered users must be banned by IP address.
// Indefinite address bans are not reasonable -> default to 30 minutes.
if (minutes == 0)
minutes = 30;
servatrice->addAddressBan(user->getPeerAddress(), minutes);
}
user->sendProtocolItem(new Event_ConnectionClosed("banned"));
user->deleteLater();
return RespOk;
}

View file

@ -21,6 +21,7 @@
#define SERVERSOCKETINTERFACE_H
#include <QTcpSocket>
#include <QHostAddress>
#include "server_protocolhandler.h"
class QTcpSocket;
@ -59,9 +60,11 @@ private:
DeckList *getDeckFromDatabase(int deckId);
ResponseCode cmdDeckDownload(Command_DeckDownload *cmd, CommandContainer *cont);
ResponseCode cmdUpdateServerMessage(Command_UpdateServerMessage *cmd, CommandContainer *cont);
ResponseCode cmdBanFromServer(Command_BanFromServer *cmd, CommandContainer *cont);
public:
ServerSocketInterface(Servatrice *_server, QTcpSocket *_socket, QObject *parent = 0);
~ServerSocketInterface();
QHostAddress getPeerAddress() const { return socket->peerAddress(); }
void sendProtocolItem(ProtocolItem *item, bool deleteItem = true);
};