ServerBanned.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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; // Empty File
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                 // Read the mask
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                 // Time
00097                 time_t bantime = 0;
00098                 if (currentNode->getNamedParameter("time", timeNode, false))
00099                 {
00100                         sscanf(timeNode->getContent(), "%u", &bantime);
00101                 }
00102 
00103                 // Type
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                 // Read the ip address
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                 // Add the new entry
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         // Check if the unique id has been banned
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         // Check if the SUI has been banned
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         // Check if the ip address has been banned
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 = &range;
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         // Add ip to list of banned ips
00241         found->ips[newip] = newEntry;
00242 
00243         // Add id to list of banned ids
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         // Add SUI to list of banned SUIs
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                         // Add ip address
00307                         unsigned int ip = (*ipitor).first;
00308                         BannedEntry &entry = (*ipitor).second;
00309                         XMLNode *optionNode = 
00310                                 new XMLNode("ipaddress", NetInterface::getIpName(ip));
00311 
00312                         // Add the mask
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                         // Add to file
00341                         if (entry.type != NotBanned)
00342                         {
00343                                 node.addChild(optionNode);
00344                         }
00345                 }
00346         }
00347         return node.writeToFile(filename);
00348 }
00349 

Generated on Mon Feb 16 15:14:53 2009 for Scorched3D by  doxygen 1.5.3