修bug,以及封禁设备码
This commit is contained in:
notify 2023-07-12 20:35:05 +08:00 committed by GitHub
parent e9a81cd185
commit 6097f0b389
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 145 additions and 20 deletions

View File

@ -36,7 +36,7 @@ local function tellRoomToObserver(self, player)
player:doNotify("UpdateDrawPile", #self.draw_pile) player:doNotify("UpdateDrawPile", #self.draw_pile)
player:doNotify("UpdateRoundNum", self:getTag("RoundCount") or 0) player:doNotify("UpdateRoundNum", self:getTag("RoundCount") or 0)
table.insert(self.observers, {observee.id, player}) table.insert(self.observers, {observee.id, player, player:getId()})
end end
local function addObserver(self, id) local function addObserver(self, id)
@ -56,12 +56,10 @@ end
local function removeObserver(self, id) local function removeObserver(self, id)
for _, t in ipairs(self.observers) do for _, t in ipairs(self.observers) do
local __, p = table.unpack(t) local pid = t[3]
if p:getId() == id then if pid == id then
table.removeOne(self.observers, t) table.removeOne(self.observers, t)
self:doBroadcastNotify("RemoveObserver", json.encode{ self:doBroadcastNotify("RemoveObserver", json.encode{ pid })
p:getId(),
})
break break
end end
end end

View File

@ -47,7 +47,7 @@ function ServerPlayer:doNotify(command, jsonData)
local room = self.room local room = self.room
for _, t in ipairs(room.observers) do for _, t in ipairs(room.observers) do
local id, p = table.unpack(t) local id, p = table.unpack(t)
if id == self.id then if id == self.id and room.room:hasObserver(p) then
p:doNotify(command, jsonData) p:doNotify(command, jsonData)
end end
end end

View File

@ -16,6 +16,15 @@ CREATE TABLE IF NOT EXISTS banip (
ip VARCHAR(64) ip VARCHAR(64)
); );
CREATE TABLE IF NOT EXISTS uuidinfo (
id INTEGER PRIMARY KEY,
uuid VARCHAR(32)
);
CREATE TABLE IF NOT EXISTS banuuid (
uuid VARCHAR(32)
);
-- 胜率相关 -- 胜率相关
CREATE TABLE IF NOT EXISTS winRate ( CREATE TABLE IF NOT EXISTS winRate (

View File

@ -4,6 +4,7 @@
#include <qcryptographichash.h> #include <qcryptographichash.h>
#include <qnamespace.h> #include <qnamespace.h>
#include <qregularexpression.h> #include <qregularexpression.h>
#include <QSysInfo>
extern "C" { extern "C" {
int luaopen_fk(lua_State *); int luaopen_fk(lua_State *);
@ -203,6 +204,10 @@ QJsonDocument String2Json(const QString &str) {
return QJsonDocument::fromJson(bytes); return QJsonDocument::fromJson(bytes);
} }
QString GetDeviceUuid() {
return QSysInfo::machineUniqueId();
}
QString Color(const QString &raw, fkShell::TextColor color, QString Color(const QString &raw, fkShell::TextColor color,
fkShell::TextType type) { fkShell::TextType type) {
#ifdef Q_OS_LINUX #ifdef Q_OS_LINUX

View File

@ -20,6 +20,8 @@ QString calcFileMD5();
QByteArray JsonArray2Bytes(const QJsonArray &arr); QByteArray JsonArray2Bytes(const QJsonArray &arr);
QJsonDocument String2Json(const QString &str); QJsonDocument String2Json(const QString &str);
QString GetDeviceUuid();
namespace fkShell { namespace fkShell {
enum TextColor { enum TextColor {
Black, Black,

View File

@ -5,7 +5,12 @@
#include <qjsonarray.h> #include <qjsonarray.h>
#include <qjsondocument.h> #include <qjsondocument.h>
#ifdef FK_SERVER_ONLY
static void *ClientInstance = nullptr;
#else
#include "client.h" #include "client.h"
#endif
#include "client_socket.h" #include "client_socket.h"
#include "roomthread.h" #include "roomthread.h"
#include "server.h" #include "server.h"
@ -268,15 +273,15 @@ void Room::removePlayer(ServerPlayer *player) {
// 原先的跑路机器人会在游戏结束后自动销毁掉 // 原先的跑路机器人会在游戏结束后自动销毁掉
server->addPlayer(runner); server->addPlayer(runner);
// 如果走小道的人不是单机启动玩家 那么直接ban
if (!ClientInstance && !player->isDied()) {
server->temporarilyBan(runner->getId());
}
m_thread->wakeUp(); m_thread->wakeUp();
// 发出信号,让大厅添加这个人 // 发出信号,让大厅添加这个人
emit playerRemoved(runner); emit playerRemoved(runner);
// 如果走小道的人不是单机启动玩家 那么直接ban
if (!ClientInstance && !player->isDied()) {
server->temporarilyBan(runner->getId());
}
} }
// 如果房间空了就把房间标为废弃Server有信号处理函数的 // 如果房间空了就把房间标为废弃Server有信号处理函数的
@ -341,6 +346,8 @@ void Room::removeObserver(ServerPlayer *player) {
QList<ServerPlayer *> Room::getObservers() const { return observers; } QList<ServerPlayer *> Room::getObservers() const { return observers; }
bool Room::hasObserver(ServerPlayer *player) const { return observers.contains(player); }
int Room::getTimeout() const { return timeout; } int Room::getTimeout() const { return timeout; }
void Room::setTimeout(int timeout) { this->timeout = timeout; } void Room::setTimeout(int timeout) { this->timeout = timeout; }

View File

@ -45,6 +45,7 @@ class Room : public QObject {
void addObserver(ServerPlayer *player); void addObserver(ServerPlayer *player);
void removeObserver(ServerPlayer *player); void removeObserver(ServerPlayer *player);
QList<ServerPlayer *> getObservers() const; QList<ServerPlayer *> getObservers() const;
bool hasObserver(ServerPlayer *player) const;
int getTimeout() const; int getTimeout() const;
void setTimeout(int timeout); void setTimeout(int timeout);

View File

@ -273,7 +273,7 @@ void Server::processRequest(const QByteArray &msg) {
doc[2] != "Setup") doc[2] != "Setup")
valid = false; valid = false;
else else
valid = (String2Json(doc[3].toString()).array().size() == 4); valid = (String2Json(doc[3].toString()).array().size() == 5);
} }
if (!valid) { if (!valid) {
@ -313,13 +313,34 @@ void Server::processRequest(const QByteArray &msg) {
return; return;
} }
auto uuid = arr[4].toString();
auto result2 = QJsonArray({1});
if (CheckSqlString(uuid)) {
result2 = SelectFromDatabase(
db, QString("SELECT * FROM banuuid WHERE uuid='%1';").arg(uuid));
}
if (!result2.isEmpty()) {
QJsonArray body;
body << -2;
body << (Router::TYPE_NOTIFICATION | Router::SRC_SERVER |
Router::DEST_CLIENT);
body << "ErrorMsg";
body << "you have been banned!";
client->send(JsonArray2Bytes(body));
qInfo() << "Refused banned UUID:" << uuid;
client->disconnectFromHost();
return;
}
handleNameAndPassword(client, arr[0].toString(), arr[1].toString(), handleNameAndPassword(client, arr[0].toString(), arr[1].toString(),
arr[2].toString()); arr[2].toString(), uuid);
} }
void Server::handleNameAndPassword(ClientSocket *client, const QString &name, void Server::handleNameAndPassword(ClientSocket *client, const QString &name,
const QString &password, const QString &password,
const QString &md5_str) { const QString &md5_str,
const QString &uuid_str) {
auto encryted_pw = QByteArray::fromBase64(password.toLatin1()); auto encryted_pw = QByteArray::fromBase64(password.toLatin1());
unsigned char buf[4096] = {0}; unsigned char buf[4096] = {0};
RSA_private_decrypt(RSA_size(rsa), (const unsigned char *)encryted_pw.data(), RSA_private_decrypt(RSA_size(rsa), (const unsigned char *)encryted_pw.data(),
@ -462,6 +483,9 @@ void Server::handleNameAndPassword(ClientSocket *client, const QString &name,
.arg(obj["id"].toString().toInt()); .arg(obj["id"].toString().toInt());
ExecSQL(db, sql_update); ExecSQL(db, sql_update);
auto uuid_update = QString("REPLACE INTO uuidinfo (id, uuid) VALUES (%1, '%2');").arg(obj["id"].toString().toInt()).arg(uuid_str);
ExecSQL(db, uuid_update);
// create new ServerPlayer and setup // create new ServerPlayer and setup
ServerPlayer *player = new ServerPlayer(lobby()); ServerPlayer *player = new ServerPlayer(lobby());
player->setSocket(client); player->setSocket(client);

View File

@ -86,7 +86,7 @@ private:
void readConfig(); void readConfig();
void handleNameAndPassword(ClientSocket *client, const QString &name, void handleNameAndPassword(ClientSocket *client, const QString &name,
const QString &password, const QString &md5_str); const QString &password, const QString &md5_str, const QString &uuid_str);
void processDatagram(const QByteArray &msg, const QHostAddress &addr, uint port); void processDatagram(const QByteArray &msg, const QHostAddress &addr, uint port);
}; };

View File

@ -29,16 +29,24 @@ void Shell::helpCommand(QStringList &) {
HELP_MSG("%s: List all running rooms.", "lsroom"); HELP_MSG("%s: List all running rooms.", "lsroom");
HELP_MSG("%s: Kick a player by his <id>.", "kick"); HELP_MSG("%s: Kick a player by his <id>.", "kick");
HELP_MSG("%s: Broadcast message.", "msg"); HELP_MSG("%s: Broadcast message.", "msg");
HELP_MSG("%s: Ban 1 or more accounts by their <name>.", "ban"); HELP_MSG("%s: Ban 1 or more accounts, IP, UUID by their <name>.", "ban");
HELP_MSG("%s: Unban 1 or more accounts by their <name>.", "unban"); HELP_MSG("%s: Unban 1 or more accounts by their <name>.", "unban");
HELP_MSG( HELP_MSG(
"%s: Ban 1 or more IP address according to somebody's 'lastLoginIp'. " "%s: Ban 1 or more IP address. "
"At least 1 <name> required.", "At least 1 <name> required.",
"banip"); "banip");
HELP_MSG( HELP_MSG(
"%s: Unban 1 or more IP address according to somebody's 'lastLoginIp'. " "%s: Unban 1 or more IP address. "
"At least 1 <name> required.", "At least 1 <name> required.",
"unbanip"); "unbanip");
HELP_MSG(
"%s: Ban 1 or more UUID. "
"At least 1 <name> required.",
"banuuid");
HELP_MSG(
"%s: Unban 1 or more UUID. "
"At least 1 <name> required.",
"unbanuuid");
qInfo(); qInfo();
qInfo("===== Package commands ====="); qInfo("===== Package commands =====");
HELP_MSG("%s: Install a new package from <url>.", "install"); HELP_MSG("%s: Install a new package from <url>.", "install");
@ -207,6 +215,9 @@ void Shell::banCommand(QStringList &list) {
foreach (auto name, list) { foreach (auto name, list) {
banAccount(db, name, true); banAccount(db, name, true);
} }
banipCommand(list);
banUuidCommand(list);
} }
void Shell::unbanCommand(QStringList &list) { void Shell::unbanCommand(QStringList &list) {
@ -220,7 +231,11 @@ void Shell::unbanCommand(QStringList &list) {
foreach (auto name, list) { foreach (auto name, list) {
banAccount(db, name, false); banAccount(db, name, false);
} }
unbanipCommand(list);
unbanUuidCommand(list);
} }
static void banIPByName(sqlite3 *db, const QString &name, bool banned) { static void banIPByName(sqlite3 *db, const QString &name, bool banned) {
if (!CheckSqlString(name)) if (!CheckSqlString(name))
return; return;
@ -275,6 +290,65 @@ void Shell::unbanipCommand(QStringList &list) {
} }
} }
static void banUuidByName(sqlite3 *db, const QString &name, bool banned) {
if (!CheckSqlString(name))
return;
QString sql_find = QString("SELECT * FROM userinfo \
WHERE name='%1';")
.arg(name);
auto result = SelectFromDatabase(db, sql_find);
if (result.isEmpty())
return;
auto obj = result[0].toObject();
int id = obj["id"].toString().toInt();
auto result2 = SelectFromDatabase(db, QString("SELECT * FROM uuidinfo WHERE id=%1;").arg(id));
if (result2.isEmpty())
return;
auto uuid = result2[0].toObject()["uuid"].toString();
if (banned) {
ExecSQL(db, QString("INSERT INTO banuuid VALUES('%1');").arg(uuid));
auto p = ServerInstance->findPlayer(id);
if (p) {
p->kicked();
}
qInfo("Banned UUID %s.", uuid.toUtf8().constData());
} else {
ExecSQL(db, QString("DELETE FROM banuuid WHERE uuid='%1';").arg(uuid));
qInfo("Unbanned UUID %s.", uuid.toUtf8().constData());
}
}
void Shell::banUuidCommand(QStringList &list) {
if (list.isEmpty()) {
qWarning("The 'banuuid' command needs at least 1 <name>.");
return;
}
auto db = ServerInstance->getDatabase();
foreach (auto name, list) {
banUuidByName(db, name, true);
}
}
void Shell::unbanUuidCommand(QStringList &list) {
if (list.isEmpty()) {
qWarning("The 'unbanuuid' command needs at least 1 <name>.");
return;
}
auto db = ServerInstance->getDatabase();
foreach (auto name, list) {
banUuidByName(db, name, false);
}
}
Shell::Shell() { Shell::Shell() {
setObjectName("Shell"); setObjectName("Shell");
signal(SIGINT, sigintHandler); signal(SIGINT, sigintHandler);
@ -297,6 +371,8 @@ Shell::Shell() {
handlers["unban"] = &Shell::unbanCommand; handlers["unban"] = &Shell::unbanCommand;
handlers["banip"] = &Shell::banipCommand; handlers["banip"] = &Shell::banipCommand;
handlers["unbanip"] = &Shell::unbanipCommand; handlers["unbanip"] = &Shell::unbanipCommand;
handlers["banuuid"] = &Shell::banUuidCommand;
handlers["unbanuuid"] = &Shell::unbanUuidCommand;
} }
handler_map = handlers; handler_map = handlers;
} }

View File

@ -27,8 +27,10 @@ private:
void msgCommand(QStringList &); void msgCommand(QStringList &);
void banCommand(QStringList &); void banCommand(QStringList &);
void banipCommand(QStringList &); void banipCommand(QStringList &);
void banUuidCommand(QStringList &);
void unbanCommand(QStringList &); void unbanCommand(QStringList &);
void unbanipCommand(QStringList &); void unbanipCommand(QStringList &);
void unbanUuidCommand(QStringList &);
}; };
#endif #endif

View File

@ -11,6 +11,7 @@ public:
QList<ServerPlayer *> getPlayers() const; QList<ServerPlayer *> getPlayers() const;
QList<ServerPlayer *> getObservers() const; QList<ServerPlayer *> getObservers() const;
bool hasObserver(ServerPlayer *player) const;
int getTimeout() const; int getTimeout() const;
void checkAbandoned(); void checkAbandoned();

View File

@ -270,7 +270,7 @@ void QmlBackend::replyDelayTest(const QString &screenName,
auto md5 = calcFileMD5(); auto md5 = calcFileMD5();
QJsonArray arr; QJsonArray arr;
arr << screenName << cipher << md5 << FK_VERSION; arr << screenName << cipher << md5 << FK_VERSION << GetDeviceUuid();
ClientInstance->notifyServer("Setup", JsonArray2Bytes(arr)); ClientInstance->notifyServer("Setup", JsonArray2Bytes(arr));
} }