ban.cpp

main 128 lines · 4 KB Raw
Alex Alex Commit Server upload 18/10/2026 23:38
1/**
2 * The Forgotten Server - a free and open-source MMORPG server emulator
3 * Copyright (C) 2019 Mark Samman <mark.samman@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20#include "otpch.h"
21
22#include "ban.h"
23#include "database.h"
24#include "databasetasks.h"
25#include "tools.h"
26
27bool Ban::acceptConnection(uint32_t clientIP)
28{
29 std::lock_guard<std::recursive_mutex> lockClass(lock);
30
31 uint64_t currentTime = OTSYS_TIME();
32
33 auto it = ipConnectMap.find(clientIP);
34 if (it == ipConnectMap.end()) {
35 ipConnectMap.emplace(clientIP, ConnectBlock(currentTime, 0, 1));
36 return true;
37 }
38
39 ConnectBlock& connectBlock = it->second;
40 if (connectBlock.blockTime > currentTime) {
41 connectBlock.blockTime += 250;
42 return false;
43 }
44
45 int64_t timeDiff = currentTime - connectBlock.lastAttempt;
46 connectBlock.lastAttempt = currentTime;
47 if (timeDiff <= 5000) {
48 if (++connectBlock.count > 5) {
49 connectBlock.count = 0;
50 if (timeDiff <= 500) {
51 connectBlock.blockTime = currentTime + 3000;
52 return false;
53 }
54 }
55 } else {
56 connectBlock.count = 1;
57 }
58 return true;
59}
60
61bool IOBan::isAccountBanned(uint32_t accountId, BanInfo& banInfo)
62{
63 Database& db = Database::getInstance();
64
65 std::ostringstream query;
66 query << "SELECT `reason`, `expires_at`, `banned_at`, `banned_by`, (SELECT `name` FROM `players` WHERE `id` = `banned_by`) AS `name` FROM `account_bans` WHERE `account_id` = " << accountId;
67
68 DBResult_ptr result = db.storeQuery(query.str());
69 if (!result) {
70 return false;
71 }
72
73 int64_t expiresAt = result->getNumber<int64_t>("expires_at");
74 if (expiresAt != 0 && time(nullptr) > expiresAt) {
75 // Move the ban to history if it has expired
76 query.str(std::string());
77 query << "INSERT INTO `account_ban_history` (`account_id`, `reason`, `banned_at`, `expired_at`, `banned_by`) VALUES (" << accountId << ',' << db.escapeString(result->getString("reason")) << ',' << result->getNumber<time_t>("banned_at") << ',' << expiresAt << ',' << result->getNumber<uint32_t>("banned_by") << ')';
78 g_databaseTasks.addTask(query.str());
79
80 query.str(std::string());
81 query << "DELETE FROM `account_bans` WHERE `account_id` = " << accountId;
82 g_databaseTasks.addTask(query.str());
83 return false;
84 }
85
86 banInfo.expiresAt = expiresAt;
87 banInfo.reason = result->getString("reason");
88 banInfo.bannedBy = result->getString("name");
89 return true;
90}
91
92bool IOBan::isIpBanned(uint32_t clientIP, BanInfo& banInfo)
93{
94 if (clientIP == 0) {
95 return false;
96 }
97
98 Database& db = Database::getInstance();
99
100 std::ostringstream query;
101 query << "SELECT `reason`, `expires_at`, (SELECT `name` FROM `players` WHERE `id` = `banned_by`) AS `name` FROM `ip_bans` WHERE `ip` = " << clientIP;
102
103 DBResult_ptr result = db.storeQuery(query.str());
104 if (!result) {
105 return false;
106 }
107
108 int64_t expiresAt = result->getNumber<int64_t>("expires_at");
109 if (expiresAt != 0 && time(nullptr) > expiresAt) {
110 query.str(std::string());
111 query << "DELETE FROM `ip_bans` WHERE `ip` = " << clientIP;
112 g_databaseTasks.addTask(query.str());
113 return false;
114 }
115
116 banInfo.expiresAt = expiresAt;
117 banInfo.reason = result->getString("reason");
118 banInfo.bannedBy = result->getString("name");
119 return true;
120}
121
122bool IOBan::isPlayerNamelocked(uint32_t playerId)
123{
124 std::ostringstream query;
125 query << "SELECT 1 FROM `player_namelocks` WHERE `player_id` = " << playerId;
126 return Database::getInstance().storeQuery(query.str()).get() != nullptr;
127}
128
Top