mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-04-27 07:48:01 -07:00
improved banning and deck hashing
This commit is contained in:
parent
9fe8f6fc03
commit
632e9bbff3
22 changed files with 211 additions and 92 deletions
|
|
@ -50,10 +50,6 @@ Servatrice::Servatrice(QSettings *_settings, 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();
|
||||
|
||||
serverId = settings->value("server/id", 0).toInt();
|
||||
|
|
@ -171,13 +167,6 @@ bool Servatrice::execSqlQuery(QSqlQuery &query)
|
|||
|
||||
AuthenticationResult Servatrice::checkUserPassword(Server_ProtocolHandler *handler, const QString &user, const QString &password)
|
||||
{
|
||||
serverMutex.lock();
|
||||
QHostAddress address = static_cast<ServerSocketInterface *>(handler)->getPeerAddress();
|
||||
for (int i = 0; i < addressBanList.size(); ++i)
|
||||
if (address == addressBanList[i].first)
|
||||
return PasswordWrong;
|
||||
serverMutex.unlock();
|
||||
|
||||
QMutexLocker locker(&dbMutex);
|
||||
const QString method = settings->value("authentication/method").toString();
|
||||
if (method == "none")
|
||||
|
|
@ -185,8 +174,23 @@ AuthenticationResult Servatrice::checkUserPassword(Server_ProtocolHandler *handl
|
|||
else if (method == "sql") {
|
||||
checkSql();
|
||||
|
||||
QSqlQuery ipBanQuery;
|
||||
ipBanQuery.prepare("select time_to_sec(timediff(now(), date_add(b.time_from, interval b.minutes minute))) < 0, b.minutes <=> 0 from " + dbPrefix + "_bans b where b.time_from = (select max(c.time_from) from " + dbPrefix + "_bans c where c.ip_address = :address) and b.ip_address = :address2");
|
||||
ipBanQuery.bindValue(":address", static_cast<ServerSocketInterface *>(handler)->getPeerAddress().toString());
|
||||
ipBanQuery.bindValue(":address2", static_cast<ServerSocketInterface *>(handler)->getPeerAddress().toString());
|
||||
if (!execSqlQuery(ipBanQuery)) {
|
||||
qDebug("Login denied: SQL error");
|
||||
return PasswordWrong;
|
||||
}
|
||||
|
||||
if (ipBanQuery.next())
|
||||
if (ipBanQuery.value(0).toInt() || ipBanQuery.value(1).toInt()) {
|
||||
qDebug("Login denied: banned by address");
|
||||
return PasswordWrong;
|
||||
}
|
||||
|
||||
QSqlQuery query;
|
||||
query.prepare("select a.password_sha512, time_to_sec(timediff(now(), date_add(b.time_from, interval b.minutes minute))) < 0, b.minutes <=> 0 from " + dbPrefix + "_users a left join " + dbPrefix + "_bans b on b.id_user = a.id and b.time_from = (select max(c.time_from) from " + dbPrefix + "_bans c where c.id_user = a.id) where a.name = :name and a.active = 1");
|
||||
query.prepare("select a.password_sha512, time_to_sec(timediff(now(), date_add(b.time_from, interval b.minutes minute))) < 0, b.minutes <=> 0 from " + dbPrefix + "_users a left join " + dbPrefix + "_bans b on b.user_name = a.name and b.time_from = (select max(c.time_from) from " + dbPrefix + "_bans c where c.user_name = a.name) where a.name = :name and a.active = 1");
|
||||
query.bindValue(":name", user);
|
||||
if (!execSqlQuery(query)) {
|
||||
qDebug("Login denied: SQL error");
|
||||
|
|
@ -195,7 +199,7 @@ AuthenticationResult Servatrice::checkUserPassword(Server_ProtocolHandler *handl
|
|||
|
||||
if (query.next()) {
|
||||
if (query.value(1).toInt() || query.value(2).toInt()) {
|
||||
qDebug("Login denied: banned");
|
||||
qDebug("Login denied: banned by name");
|
||||
return PasswordWrong;
|
||||
}
|
||||
if (query.value(0).toString() == PasswordHasher::computeHash(password, query.value(0).toString().left(16))) {
|
||||
|
|
@ -257,6 +261,7 @@ ServerInfo_User *Servatrice::evalUserQueryResult(const QSqlQuery &query, bool co
|
|||
return new ServerInfo_User(
|
||||
name,
|
||||
userLevel,
|
||||
QString(),
|
||||
realName,
|
||||
gender,
|
||||
country,
|
||||
|
|
@ -341,16 +346,6 @@ QMap<QString, ServerInfo_User *> Servatrice::getIgnoreList(const QString &name)
|
|||
return result;
|
||||
}
|
||||
|
||||
void Servatrice::updateBanTimer()
|
||||
{
|
||||
QMutexLocker locker(&serverMutex);
|
||||
for (int i = 0; i < addressBanList.size(); )
|
||||
if (--(addressBanList[i].second) <= 0)
|
||||
addressBanList.removeAt(i);
|
||||
else
|
||||
++i;
|
||||
}
|
||||
|
||||
void Servatrice::updateLoginMessage()
|
||||
{
|
||||
QMutexLocker locker(&dbMutex);
|
||||
|
|
@ -424,4 +419,4 @@ void Servatrice::shutdownTimeout()
|
|||
deleteLater();
|
||||
}
|
||||
|
||||
const QString Servatrice::versionString = "Servatrice 0.20111004";
|
||||
const QString Servatrice::versionString = "Servatrice 0.20111101";
|
||||
|
|
|
|||
|
|
@ -49,7 +49,6 @@ class Servatrice : public Server
|
|||
Q_OBJECT
|
||||
private slots:
|
||||
void statusUpdate();
|
||||
void updateBanTimer();
|
||||
void shutdownTimeout();
|
||||
public:
|
||||
QMutex dbMutex;
|
||||
|
|
@ -75,13 +74,12 @@ public:
|
|||
int getUsersWithAddress(const QHostAddress &address) const;
|
||||
QMap<QString, ServerInfo_User *> getBuddyList(const QString &name);
|
||||
QMap<QString, ServerInfo_User *> getIgnoreList(const QString &name);
|
||||
void addAddressBan(const QHostAddress &address, int minutes) { addressBanList.append(QPair<QHostAddress, int>(address, minutes)); }
|
||||
void scheduleShutdown(const QString &reason, int minutes);
|
||||
protected:
|
||||
bool userExists(const QString &user);
|
||||
AuthenticationResult checkUserPassword(Server_ProtocolHandler *handler, const QString &user, const QString &password);
|
||||
private:
|
||||
QTimer *pingClock, *statusUpdateClock, *banTimeoutClock;
|
||||
QTimer *pingClock, *statusUpdateClock;
|
||||
QTcpServer *tcpServer;
|
||||
QString loginMessage;
|
||||
QString dbPrefix;
|
||||
|
|
@ -89,7 +87,6 @@ private:
|
|||
int serverId;
|
||||
bool threaded;
|
||||
int uptime;
|
||||
QList<QPair<QHostAddress, int> > addressBanList;
|
||||
int maxGameInactivityTime, maxPlayerInactivityTime;
|
||||
int maxUsersPerAddress, messageCountingInterval, maxMessageCountPerInterval, maxMessageSizePerInterval, maxGamesPerUser;
|
||||
ServerInfo_User *evalUserQueryResult(const QSqlQuery &query, bool complete);
|
||||
|
|
|
|||
|
|
@ -464,50 +464,43 @@ ResponseCode ServerSocketInterface::cmdDeckDownload(Command_DeckDownload *cmd, C
|
|||
// MODERATOR FUNCTIONS.
|
||||
// May be called by admins and moderators. Permission is checked by the calling function.
|
||||
|
||||
ResponseCode ServerSocketInterface::cmdUpdateServerMessage(Command_UpdateServerMessage * /*cmd*/, CommandContainer * /*cont*/)
|
||||
ResponseCode ServerSocketInterface::cmdBanFromServer(Command_BanFromServer *cmd, CommandContainer * /*cont*/)
|
||||
{
|
||||
servatrice->updateLoginMessage();
|
||||
QString userName = cmd->getUserName();
|
||||
QString address = cmd->getAddress();
|
||||
int minutes = cmd->getMinutes();
|
||||
|
||||
servatrice->dbMutex.lock();
|
||||
QSqlQuery query;
|
||||
query.prepare("insert into " + servatrice->getDbPrefix() + "_bans (user_name, ip_address, id_admin, time_from, minutes, reason) values(:user_name, :ip_address, :id_admin, NOW(), :minutes, :reason)");
|
||||
query.bindValue(":user_name", userName);
|
||||
query.bindValue(":ip_address", address);
|
||||
query.bindValue(":id_admin", getUserIdInDB(userInfo->getName()));
|
||||
query.bindValue(":minutes", minutes);
|
||||
query.bindValue(":reason", cmd->getReason() + "\n");
|
||||
servatrice->execSqlQuery(query);
|
||||
servatrice->dbMutex.unlock();
|
||||
|
||||
ServerSocketInterface *user = static_cast<ServerSocketInterface *>(server->getUsers().value(userName));
|
||||
if (user) {
|
||||
user->sendProtocolItem(new Event_ConnectionClosed("banned"));
|
||||
user->deleteLater();
|
||||
}
|
||||
|
||||
return RespOk;
|
||||
}
|
||||
|
||||
// ADMIN FUNCTIONS.
|
||||
// Permission is checked by the calling function.
|
||||
|
||||
ResponseCode ServerSocketInterface::cmdUpdateServerMessage(Command_UpdateServerMessage * /*cmd*/, CommandContainer * /*cont*/)
|
||||
{
|
||||
servatrice->updateLoginMessage();
|
||||
return RespOk;
|
||||
}
|
||||
|
||||
ResponseCode ServerSocketInterface::cmdShutdownServer(Command_ShutdownServer *cmd, CommandContainer * /*cont*/)
|
||||
{
|
||||
servatrice->scheduleShutdown(cmd->getReason(), cmd->getMinutes());
|
||||
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.
|
||||
QMutexLocker locker(&servatrice->dbMutex);
|
||||
QSqlQuery query;
|
||||
query.prepare("insert into " + servatrice->getDbPrefix() + "_bans (id_user, id_admin, time_from, minutes, reason) values(:id_user, :id_admin, NOW(), :minutes, :reason)");
|
||||
query.bindValue(":id_user", getUserIdInDB(userName));
|
||||
query.bindValue(":id_admin", getUserIdInDB(userInfo->getName()));
|
||||
query.bindValue(":minutes", minutes);
|
||||
query.bindValue(":reason", cmd->getReason() + "\n");
|
||||
servatrice->execSqlQuery(query);
|
||||
} 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ public:
|
|||
ServerSocketInterface(Servatrice *_server, QTcpSocket *_socket, QObject *parent = 0);
|
||||
~ServerSocketInterface();
|
||||
QHostAddress getPeerAddress() const { return socket->peerAddress(); }
|
||||
QString getAddress() const { return socket->peerAddress().toString(); }
|
||||
|
||||
void sendProtocolItem(ProtocolItem *item, bool deleteItem = true);
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue