00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <server/ServerBanned.h>
00022 #include <server/ScorchedServer.h>
00023 #include <common/OptionsScorched.h>
00024 #include <common/Defines.h>
00025 #include <common/Logger.h>
00026 #include <net/NetInterface.h>
00027 #include <XML/XMLFile.h>
00028 #include <limits.h>
00029
00030 ServerBanned::ServerBanned() : lastReadTime_(0)
00031 {
00032 }
00033
00034 ServerBanned::~ServerBanned()
00035 {
00036 }
00037
00038 bool ServerBanned::load(bool force)
00039 {
00040 std::string filename =
00041 S3D::getSettingsFile(S3D::formatStringBuffer("banned-%i.xml",
00042 ScorchedServer::instance()->getOptionsGame().getPortNo()));
00043 if (!S3D::fileExists(filename)) return true;
00044
00045 time_t fileTime = S3D::fileModTime(filename);
00046 if (!force && fileTime == lastReadTime_) return true;
00047
00048 XMLFile file;
00049 if (!file.readFile(filename))
00050 {
00051 Logger::log(S3D::formatStringBuffer("Failed to parse banned file \"%s\"\n%s",
00052 filename.c_str(), file.getParserError()));
00053 return false;
00054 }
00055
00056 Logger::log(S3D::formatStringBuffer("Refreshing banned list %s", filename.c_str()));
00057 lastReadTime_ = fileTime;
00058 bannedIps_.clear();
00059 bannedIds_.clear();
00060 bannedSUIs_.clear();
00061 if (!file.getRootNode()) return true;
00062
00063 std::list<XMLNode *>::iterator childrenItor;
00064 std::list<XMLNode *> &children = file.getRootNode()->getChildren();
00065 for (childrenItor = children.begin();
00066 childrenItor != children.end();
00067 childrenItor++)
00068 {
00069 XMLNode *currentNode = (*childrenItor);
00070 XMLNode *maskNode = 0, *timeNode = 0, *typeNode = 0;
00071
00072
00073 unsigned int m = UINT_MAX;
00074 if (currentNode->getNamedParameter("mask", maskNode, false))
00075 {
00076 unsigned int mask[4];
00077 if (sscanf(maskNode->getContent(), "%u.%u.%u.%u",
00078 &mask[3], &mask[2], &mask[1], &mask[0]) != 4)
00079 {
00080 S3D::dialogMessage("ServerBanned",
00081 S3D::formatStringBuffer("Failed to parse mask %s",
00082 maskNode->getContent()));
00083 return false;
00084 }
00085 m = mask[3] << 24 | mask[2] << 16 | mask[1] << 8 | mask[0];
00086 }
00087
00088 LangString name;
00089 std::string adminname, uniqueid, reason, SUI;
00090 currentNode->getNamedParameter("name", name, false);
00091 currentNode->getNamedParameter("adminname", adminname, false);
00092 currentNode->getNamedParameter("reason", reason, false);
00093 currentNode->getNamedParameter("id", uniqueid, false);
00094 currentNode->getNamedParameter("SUI", SUI, false);
00095
00096
00097 time_t bantime = 0;
00098 if (currentNode->getNamedParameter("time", timeNode, false))
00099 {
00100 sscanf(timeNode->getContent(), "%u", &bantime);
00101 }
00102
00103
00104 BannedType type = Banned;
00105 if (currentNode->getNamedParameter("type", typeNode, false))
00106 {
00107 if (0 == strcmp("banned", typeNode->getContent())) type = Banned;
00108 else if (0 == strcmp("muted", typeNode->getContent())) type = Muted;
00109 else if (0 == strcmp("flagged", typeNode->getContent())) type = Flagged;
00110 else
00111 {
00112 S3D::dialogMessage("ServerBanned",
00113 S3D::formatStringBuffer("Failed to parse banned type %s",
00114 typeNode->getContent()));
00115 return false;
00116 }
00117 }
00118
00119
00120 unsigned int address[4];
00121 if (sscanf(currentNode->getContent(), "%u.%u.%u.%u",
00122 &address[3], &address[2], &address[1], &address[0]) != 4)
00123 {
00124 S3D::dialogMessage("ServerBanned",
00125 S3D::formatStringBuffer("Failed to parse ip address %s",
00126 currentNode->getContent()));
00127 return false;
00128 }
00129
00130 unsigned int ip = 0;
00131 ip = address[3] << 24 | address[2] << 16 | address[1] << 8 | address[0];
00132
00133
00134 addBannedEntry(ip, m, name, uniqueid.c_str(), SUI.c_str(),
00135 (unsigned int) bantime, type,
00136 adminname.c_str(), reason.c_str());
00137 }
00138 return true;
00139 }
00140
00141 std::list<ServerBanned::BannedRange> &ServerBanned::getBannedIps()
00142 {
00143 load();
00144 return bannedIps_;
00145 }
00146
00147 ServerBanned::BannedType ServerBanned::getBanned(
00148 const char *unqiueid, const char *SUI)
00149 {
00150 load();
00151
00152
00153 std::map<std::string, BannedEntry>::iterator findItor =
00154 bannedIds_.find(unqiueid);
00155 if (findItor != bannedIds_.end())
00156 {
00157 BannedEntry &entry = (*findItor).second;
00158 return entry.type;
00159 }
00160
00161
00162 std::map<std::string, BannedEntry>::iterator findItor2 =
00163 bannedSUIs_.find(SUI);
00164 if (findItor2 != bannedSUIs_.end())
00165 {
00166 BannedEntry &entry = (*findItor2).second;
00167 return entry.type;
00168 }
00169 return NotBanned;
00170 }
00171
00172 ServerBanned::BannedType ServerBanned::getBanned(
00173 unsigned int ip)
00174 {
00175 load();
00176
00177
00178 std::list<BannedRange>::iterator itor;
00179 for (itor = bannedIps_.begin();
00180 itor != bannedIps_.end();
00181 itor++)
00182 {
00183 BannedRange &range = *itor;
00184 unsigned int newip = range.mask & ip;
00185 std::map<unsigned int, BannedEntry>::iterator findItor =
00186 range.ips.find(newip);
00187 if (findItor != range.ips.end())
00188 {
00189 BannedEntry &entry = (*findItor).second;
00190 return entry.type;
00191 }
00192 }
00193 return NotBanned;
00194 }
00195
00196 void ServerBanned::addBanned(unsigned int ip, const LangString &name,
00197 const char *uniqueId, const char *SUI, BannedType type,
00198 const char *adminname, const char *reason)
00199 {
00200 unsigned int t = (unsigned int) time(0);
00201 addBannedEntry(ip, UINT_MAX, name, uniqueId, SUI, t, type, adminname, reason);
00202 save();
00203 }
00204
00205 void ServerBanned::addBannedEntry(unsigned int ip, unsigned int mask,
00206 const LangString &name, const char *uniqueId, const char *SUid, unsigned int bantime, BannedType type,
00207 const char *adminname, const char *reason)
00208 {
00209 unsigned int newip = mask & ip;
00210 BannedEntry newEntry;
00211 newEntry.name = name;
00212 newEntry.bantime = bantime;
00213 newEntry.type = type;
00214 newEntry.uniqueid = uniqueId;
00215 newEntry.SUI = SUid;
00216 newEntry.adminname = adminname;
00217 newEntry.reason = reason;
00218
00219 BannedRange *found = 0;
00220 std::list<BannedRange>::iterator itor;
00221 for (itor = bannedIps_.begin();
00222 itor != bannedIps_.end();
00223 itor++)
00224 {
00225 BannedRange &range = *itor;
00226 if (range.mask == mask)
00227 {
00228 found = ⦥
00229 break;
00230 }
00231 }
00232 if (!found)
00233 {
00234 BannedRange range;
00235 range.mask = mask;
00236 bannedIps_.push_back(range);
00237 found = &bannedIps_.back();
00238 }
00239
00240
00241 found->ips[newip] = newEntry;
00242
00243
00244 if (uniqueId[0])
00245 {
00246 std::map<std::string, BannedEntry>::iterator findItor =
00247 bannedIds_.find(uniqueId);
00248 if (findItor == bannedIds_.end())
00249 {
00250 bannedIds_[uniqueId] = newEntry;
00251 }
00252 }
00253
00254
00255 if (SUid[0])
00256 {
00257 std::map<std::string, BannedEntry>::iterator findItor2 =
00258 bannedSUIs_.find(SUid);
00259 if (findItor2 == bannedSUIs_.end())
00260 {
00261 bannedSUIs_[SUid] = newEntry;
00262 }
00263 }
00264 }
00265
00266 const char *ServerBanned::getBannedTypeStr(BannedType type)
00267 {
00268 const char *str = "error";
00269 switch (type)
00270 {
00271 case Muted:
00272 str = "muted";
00273 break;
00274 case Banned:
00275 str = "banned";
00276 break;
00277 case NotBanned:
00278 str = "notbanned";
00279 break;
00280 case Flagged:
00281 str = "flagged";
00282 break;
00283 }
00284 return str;
00285 }
00286
00287 bool ServerBanned::save()
00288 {
00289 std::string filename =
00290 S3D::getSettingsFile(S3D::formatStringBuffer("banned-%i.xml",
00291 ScorchedServer::instance()->getOptionsGame().getPortNo()));
00292
00293 XMLNode node("bannednodes");
00294 std::list<BannedRange>::iterator itor;
00295 for (itor = bannedIps_.begin();
00296 itor != bannedIps_.end();
00297 itor++)
00298 {
00299 BannedRange &range = *itor;
00300 unsigned int m = range.mask;
00301 std::map<unsigned int, BannedEntry>::iterator ipitor;
00302 for (ipitor = range.ips.begin();
00303 ipitor != range.ips.end();
00304 ipitor++)
00305 {
00306
00307 unsigned int ip = (*ipitor).first;
00308 BannedEntry &entry = (*ipitor).second;
00309 XMLNode *optionNode =
00310 new XMLNode("ipaddress", NetInterface::getIpName(ip));
00311
00312
00313 if (m != UINT_MAX)
00314 {
00315 optionNode->addParameter(new XMLNode("mask", NetInterface::getIpName(m),
00316 XMLNode::XMLParameterType));
00317 }
00318 optionNode->addParameter(new XMLNode("name",
00319 entry.name,
00320 XMLNode::XMLParameterType));
00321 optionNode->addParameter(new XMLNode("time",
00322 S3D::formatStringBuffer("%u", (unsigned int) entry.bantime),
00323 XMLNode::XMLParameterType));
00324 optionNode->addParameter(new XMLNode("type",
00325 getBannedTypeStr(entry.type),
00326 XMLNode::XMLParameterType));
00327 optionNode->addParameter(new XMLNode("id",
00328 entry.uniqueid,
00329 XMLNode::XMLParameterType));
00330 optionNode->addParameter(new XMLNode("SUI",
00331 entry.SUI,
00332 XMLNode::XMLParameterType));
00333 optionNode->addParameter(new XMLNode("adminname",
00334 entry.adminname,
00335 XMLNode::XMLParameterType));
00336 optionNode->addParameter(new XMLNode("reason",
00337 entry.reason,
00338 XMLNode::XMLParameterType));
00339
00340
00341 if (entry.type != NotBanned)
00342 {
00343 node.addChild(optionNode);
00344 }
00345 }
00346 }
00347 return node.writeToFile(filename);
00348 }
00349