1 /*****************************************************************************
2 * PokerTH - The open source texas holdem engine *
3 * Copyright (C) 2006-2012 Felix Hammer, Florian Thauer, Lothar May *
4 * *
5 * This program is free software: you can redistribute it and/or modify *
6 * it under the terms of the GNU Affero General Public License as *
7 * published by the Free Software Foundation, either version 3 of the *
8 * License, or (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 Affero General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU Affero General Public License *
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
17 * *
18 * *
19 * Additional permission under GNU AGPL version 3 section 7 *
20 * *
21 * If you modify this program, or any covered work, by linking or *
22 * combining it with the OpenSSL project's OpenSSL library (or a *
23 * modified version of that library), containing parts covered by the *
24 * terms of the OpenSSL or SSLeay licenses, the authors of PokerTH *
25 * (Felix Hammer, Florian Thauer, Lothar May) grant you additional *
26 * permission to convey the resulting work. *
27 * Corresponding Source for a non-source form of such a combination *
28 * shall include the source code for the parts of OpenSSL used as well *
29 * as that of the covered work. *
30 *****************************************************************************/
31
32 #include <net/serverbanmanager.h>
33 #include <algorithm>
34
35 using namespace std;
36
37 #ifdef BOOST_ASIO_HAS_STD_CHRONO
38 using namespace std::chrono;
39 #else
40 using namespace boost::chrono;
41 #endif
42
ServerBanManager(boost::shared_ptr<boost::asio::io_service> ioService)43 ServerBanManager::ServerBanManager(boost::shared_ptr<boost::asio::io_service> ioService)
44 : m_ioService(ioService), m_curBanId(0)
45 {
46 }
47
~ServerBanManager()48 ServerBanManager::~ServerBanManager()
49 {
50 }
51
52 void
SetAdminPlayerIds(const std::list<DB_id> & adminList)53 ServerBanManager::SetAdminPlayerIds(const std::list<DB_id> &adminList)
54 {
55 boost::mutex::scoped_lock lock(m_banMutex);
56 m_adminPlayers.resize(adminList.size());
57 copy(adminList.begin(), adminList.end(), m_adminPlayers.begin());
58 sort(m_adminPlayers.begin(), m_adminPlayers.end());
59 }
60
61 void
BanPlayerName(const std::string & playerName,unsigned durationHours)62 ServerBanManager::BanPlayerName(const std::string &playerName, unsigned durationHours)
63 {
64 boost::mutex::scoped_lock lock(m_banMutex);
65 unsigned banId = GetNextBanId();
66
67 TimedPlayerBan tmpBan;
68 tmpBan.timer = InternalRegisterTimedBan(banId, durationHours);
69 tmpBan.nameStr = playerName;
70 m_banPlayerNameMap[banId] = tmpBan;
71 }
72
73 void
BanPlayerRegex(const string & playerRegex,unsigned durationHours)74 ServerBanManager::BanPlayerRegex(const string &playerRegex, unsigned durationHours)
75 {
76 boost::mutex::scoped_lock lock(m_banMutex);
77 unsigned banId = GetNextBanId();
78
79 TimedPlayerBan tmpBan;
80 tmpBan.timer = InternalRegisterTimedBan(banId, durationHours);
81 tmpBan.nameRegex = boost::regex(playerRegex, boost::regex::extended | boost::regex::icase);
82 m_banPlayerNameMap[banId] = tmpBan;
83 }
84
85 void
BanIPAddress(const string & ipAddress,unsigned durationHours)86 ServerBanManager::BanIPAddress(const string &ipAddress, unsigned durationHours)
87 {
88 boost::mutex::scoped_lock lock(m_banMutex);
89 unsigned banId = GetNextBanId();
90
91 TimedIPBan tmpBan;
92 tmpBan.timer = InternalRegisterTimedBan(banId, durationHours);
93 tmpBan.ipAddress = ipAddress;
94 m_banIPAddressMap[banId] = tmpBan;
95 }
96
97 bool
UnBan(unsigned banId)98 ServerBanManager::UnBan(unsigned banId)
99 {
100 bool retVal = false;
101 boost::mutex::scoped_lock lock(m_banMutex);
102 RegexMap::iterator posNick = m_banPlayerNameMap.find(banId);
103 if (posNick != m_banPlayerNameMap.end()) {
104 if (posNick->second.timer)
105 posNick->second.timer->cancel();
106 m_banPlayerNameMap.erase(posNick);
107 retVal = true;
108 } else {
109 IPAddressMap::iterator posIP = m_banIPAddressMap.find(banId);
110 if (posIP != m_banIPAddressMap.end()) {
111 if (posIP->second.timer)
112 posIP->second.timer->cancel();
113 m_banIPAddressMap.erase(posIP);
114 retVal = true;
115 }
116 }
117 return retVal;
118 }
119
120 void
GetBanList(list<string> & list) const121 ServerBanManager::GetBanList(list<string> &list) const
122 {
123 boost::mutex::scoped_lock lock(m_banMutex);
124 RegexMap::const_iterator i_nick = m_banPlayerNameMap.begin();
125 RegexMap::const_iterator end_nick = m_banPlayerNameMap.end();
126 while (i_nick != end_nick) {
127 ostringstream banText;
128 if ((*i_nick).second.nameStr.empty())
129 banText << (*i_nick).first << ": (nickRegex) - " << (*i_nick).second.nameRegex.str();
130 else
131 banText << (*i_nick).first << ": (nickStr) - " << (*i_nick).second.nameStr;
132
133 if ((*i_nick).second.timer)
134 banText << " duration: " << duration_cast<hours>((*i_nick).second.timer->expires_from_now()).count() << "h";
135 list.push_back(banText.str());
136 ++i_nick;
137 }
138 IPAddressMap::const_iterator i_ip = m_banIPAddressMap.begin();
139 IPAddressMap::const_iterator end_ip = m_banIPAddressMap.end();
140 while (i_ip != end_ip) {
141 ostringstream banText;
142 banText << (*i_ip).first << ": (IP) - " << (*i_ip).second.ipAddress;
143 if ((*i_ip).second.timer)
144 banText << " duration: " << duration_cast<hours>((*i_ip).second.timer->expires_from_now()).count() << "h";
145 list.push_back(banText.str());
146 ++i_ip;
147 }
148 }
149
150 void
ClearBanList()151 ServerBanManager::ClearBanList()
152 {
153 boost::mutex::scoped_lock lock(m_banMutex);
154 m_banPlayerNameMap.clear();
155 m_banIPAddressMap.clear();
156 }
157
158 bool
IsAdminPlayer(DB_id playerId) const159 ServerBanManager::IsAdminPlayer(DB_id playerId) const
160 {
161 bool retVal = false;
162 if (playerId != DB_ID_INVALID) {
163 boost::mutex::scoped_lock lock(m_banMutex);
164
165 if (binary_search(m_adminPlayers.begin(), m_adminPlayers.end(), playerId)) {
166 retVal = true;
167 }
168 }
169 return retVal;
170 }
171
172 bool
IsPlayerBanned(const std::string & name) const173 ServerBanManager::IsPlayerBanned(const std::string &name) const
174 {
175 bool retVal = false;
176 boost::mutex::scoped_lock lock(m_banMutex);
177 RegexMap::const_iterator i = m_banPlayerNameMap.begin();
178 RegexMap::const_iterator end = m_banPlayerNameMap.end();
179 while (i != end) {
180 // Use regex only if name not set.
181 if ((*i).second.nameStr.empty()) {
182 if (regex_match(name, (*i).second.nameRegex)) {
183 retVal = true;
184 break;
185 }
186 } else {
187 if (name == (*i).second.nameStr) {
188 retVal = true;
189 break;
190 }
191 }
192 ++i;
193 }
194
195 return retVal;
196 }
197
198 bool
IsIPAddressBanned(const std::string & ipAddress) const199 ServerBanManager::IsIPAddressBanned(const std::string &ipAddress) const
200 {
201 bool retVal = false;
202 boost::mutex::scoped_lock lock(m_banMutex);
203 IPAddressMap::const_iterator i = m_banIPAddressMap.begin();
204 IPAddressMap::const_iterator end = m_banIPAddressMap.end();
205 while (i != end) {
206 if (ipAddress == (*i).second.ipAddress) {
207 retVal = true;
208 break;
209 }
210 ++i;
211 }
212
213 return retVal;
214 }
215
216 void
InitGameNameBadWordList(const std::list<string> & badWordList)217 ServerBanManager::InitGameNameBadWordList(const std::list<string> &badWordList)
218 {
219 list<string>::const_iterator i = badWordList.begin();
220 list<string>::const_iterator end = badWordList.end();
221 while (i != end) {
222 m_gameNameBadWordFilter.push_back(boost::regex(*i, boost::regex::extended | boost::regex::icase));
223 ++i;
224 }
225 }
226
227 bool
IsBadGameName(const std::string & name) const228 ServerBanManager::IsBadGameName(const std::string &name) const
229 {
230 bool retVal = false;
231 RegexList::const_iterator i = m_gameNameBadWordFilter.begin();
232 RegexList::const_iterator end = m_gameNameBadWordFilter.end();
233 while (i != end) {
234 if (regex_match(name, *i)) {
235 retVal = true;
236 break;
237 }
238 ++i;
239 }
240 return retVal;
241 }
242
243 boost::shared_ptr<boost::asio::steady_timer>
InternalRegisterTimedBan(unsigned timerId,unsigned durationHours)244 ServerBanManager::InternalRegisterTimedBan(unsigned timerId, unsigned durationHours)
245 {
246 boost::shared_ptr<boost::asio::steady_timer> tmpTimer;
247 if (durationHours) {
248 tmpTimer.reset(new boost::asio::steady_timer(*m_ioService));
249 tmpTimer->expires_from_now(
250 hours(durationHours));
251 tmpTimer->async_wait(
252 boost::bind(
253 &ServerBanManager::TimerRemoveBan, shared_from_this(), boost::asio::placeholders::error, timerId, tmpTimer));
254 }
255 return tmpTimer;
256 }
257
258 void
TimerRemoveBan(const boost::system::error_code & ec,unsigned banId,boost::shared_ptr<boost::asio::steady_timer> timer)259 ServerBanManager::TimerRemoveBan(const boost::system::error_code &ec, unsigned banId, boost::shared_ptr<boost::asio::steady_timer> timer)
260 {
261 if (!ec && timer)
262 UnBan(banId);
263 }
264
265 unsigned
GetNextBanId()266 ServerBanManager::GetNextBanId()
267 {
268 m_curBanId++;
269 if (m_curBanId == 0) // 0 is an invalid id.
270 m_curBanId++;
271
272 return m_curBanId;
273 }
274
275