From: Daniel R. <dtr...@us...> - 2005-11-23 01:35:11
|
Update of /cvsroot/bzflag/bzflag/src/bzfs In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv7697/src/bzfs Modified Files: AccessControlList.cxx AccessControlList.h BanCommands.cxx CmdLineOptions.cxx GameKeeper.cxx GameKeeper.h ListServerConnection.cxx Permissions.cxx Permissions.h bzfs.cxx commands.cxx Log Message: merge changes from 2.0.5. v2_0branch tagged as merge-2_0-2_1-5. Index: AccessControlList.cxx =================================================================== RCS file: /cvsroot/bzflag/bzflag/src/bzfs/AccessControlList.cxx,v retrieving revision 2.15 retrieving revision 2.16 diff -w -u -r2.15 -r2.16 --- AccessControlList.cxx 16 Oct 2005 19:31:06 -0000 2.15 +++ AccessControlList.cxx 23 Nov 2005 01:34:58 -0000 2.16 @@ -17,6 +17,7 @@ /* system interface headers */ #include <time.h> +#include <ctype.h> #include <fstream> #include <vector> #include <string> @@ -27,6 +28,7 @@ /* common interface headers */ #include "global.h" +#include "bzglob.h" #include "network.h" #include "Address.h" #include "TimeKeeper.h" @@ -35,7 +37,10 @@ // bzfs specific headers #include "bzfs.h" -void AccessControlList::ban(in_addr &ipAddr, const char *bannedBy, int period, const char *reason, bool fromMaster) { + +void AccessControlList::ban(in_addr &ipAddr, const char *bannedBy, int period, + const char *reason, bool fromMaster) +{ BanInfo toban(ipAddr, bannedBy, period,fromMaster); if (reason) toban.reason = reason; banList_t::iterator oldit = std::find(banList.begin(), banList.end(), toban); @@ -45,11 +50,17 @@ banList.push_back(toban); } -bool AccessControlList::ban(std::string &ipList, const char *bannedBy, int period, const char *reason, bool fromMaster) { + +bool AccessControlList::ban(std::string &ipList, const char *bannedBy, int period, + const char *reason, bool fromMaster) +{ return ban(ipList.c_str(), bannedBy, period, reason,fromMaster); } -bool AccessControlList::ban(const char *ipList, const char *bannedBy, int period, const char *reason, bool fromMaster) { + +bool AccessControlList::ban(const char *ipList, const char *bannedBy, int period, + const char *reason, bool fromMaster) +{ char *buf = strdup(ipList); char *pStart = buf; char *pSep; @@ -73,17 +84,37 @@ return added; } -void AccessControlList::hostBan(std::string hostpat, const char *bannedBy, int period, const char *reason, bool fromMaster) { + +void AccessControlList::hostBan(std::string hostpat, const char *bannedBy, int period, + const char *reason, bool fromMaster) +{ HostBanInfo toban(hostpat, bannedBy, period,fromMaster); if (reason) toban.reason = reason; hostBanList_t::iterator oldit = std::find(hostBanList.begin(), hostBanList.end(), toban); - if (oldit != hostBanList.end()) + if (oldit != hostBanList.end()) { *oldit = toban; - else + } else { hostBanList.push_back(toban); } +} -bool AccessControlList::unban(in_addr &ipAddr) { + +void AccessControlList::idBan(std::string idpat, const char *bannedBy, int period, + const char *reason, bool fromMaster) +{ + IdBanInfo toban(idpat, bannedBy, period, fromMaster); + if (reason) toban.reason = reason; + idBanList_t::iterator oldit = std::find(idBanList.begin(), idBanList.end(), toban); + if (oldit != idBanList.end()) { + *oldit = toban; + } else { + idBanList.push_back(toban); + } +} + + +bool AccessControlList::unban(in_addr &ipAddr) +{ banList_t::iterator it = std::remove(banList.begin(), banList.end(), BanInfo(ipAddr)); if (it != banList.end()) { banList.erase(it, banList.end()); @@ -92,11 +123,15 @@ return false; } -bool AccessControlList::unban(std::string &ipList) { + +bool AccessControlList::unban(std::string &ipList) +{ return unban(ipList.c_str()); } -bool AccessControlList::unban(const char *ipList) { + +bool AccessControlList::unban(const char *ipList) +{ char *buf = strdup(ipList); char *pStart = buf; char *pSep; @@ -116,7 +151,9 @@ return success; } -bool AccessControlList::hostUnban(std::string hostpat) { + +bool AccessControlList::hostUnban(std::string hostpat) +{ hostBanList_t::iterator it = std::remove(hostBanList.begin(), hostBanList.end(), HostBanInfo(hostpat)); if (it != hostBanList.end()) { hostBanList.erase(it, hostBanList.end()); @@ -125,7 +162,20 @@ return false; } -bool AccessControlList::validate(const in_addr &ipAddr, BanInfo *info) { + +bool AccessControlList::idUnban(std::string idpat) +{ + idBanList_t::iterator it = std::remove(idBanList.begin(), idBanList.end(), IdBanInfo(idpat)); + if (it != idBanList.end()) { + idBanList.erase(it, idBanList.end()); + return true; + } + return false; +} + + +bool AccessControlList::validate(const in_addr &ipAddr, BanInfo *info) +{ expire(); for (banList_t::iterator it = banList.begin(); it != banList.end(); ++it) { @@ -147,6 +197,7 @@ return true; } + bool AccessControlList::does_match(const char *targ, int targlen, const char *pat, int patlen) { if (!targlen) @@ -173,7 +224,9 @@ return false; } -bool AccessControlList::hostValidate(const char *hostname, HostBanInfo *info) { + +bool AccessControlList::hostValidate(const char *hostname, HostBanInfo *info) +{ expire(); for (hostBanList_t::iterator it = hostBanList.begin(); it != hostBanList.end(); ++it) { @@ -187,12 +240,47 @@ return true; } -void AccessControlList::sendBan(PlayerId id, const BanInfo &baninfo) + +bool AccessControlList::idValidate(const char *id, IdBanInfo *info) +{ + expire(); + if (strlen(id) == 0) { + return true; + } + for (idBanList_t::iterator it = idBanList.begin(); it != idBanList.end(); ++it) { + if (strcmp(id, it->idpat.c_str()) == 0) { + if (info) + *info = *it; + return false; + } + } + + return true; +} + + +static std::string makeGlobPattern(const char* str) { - in_addr mask = baninfo.addr; + if (str == NULL) { + return "*"; + } + while ((*str != '\0') && isspace(*str)) str++; + if (*str == '\0') { + return "*"; + } + std::string pattern = str; + pattern = TextUtils::toupper(pattern); + if (pattern.find('*') == std::string::npos) { + pattern = "*" + pattern + "*"; + } + printf ("PATTERN = \"%s\"\n", pattern.c_str()); + return pattern; +} - std::ostringstream os; +static std::string getBanMaskString(in_addr mask) +{ + std::ostringstream os; os << (ntohl(mask.s_addr) >> 24) << '.'; if ((ntohl(mask.s_addr) & 0x00ffffff) == 0x00ffffff) { os << "*.*.*"; @@ -208,10 +296,20 @@ os << (ntohl(mask.s_addr) & 0xff); } } + return os.str(); +} + + +void AccessControlList::sendBan(PlayerId id, const BanInfo &baninfo) +{ + std::ostringstream os; + os << getBanMaskString(baninfo.addr); + // print duration when < 1 year double duration = baninfo.banEnd - TimeKeeper::getCurrent(); if (duration < 365.0f * 24 * 3600) - os << std::setiosflags(std::ios::fixed) << std::setprecision(1) << " (" << duration/60 << " minutes)"; + os << std::setiosflags(std::ios::fixed) << std::setprecision(1) + << " (" << duration/60 << " minutes)"; if( baninfo.fromMaster ) os << " (m)"; if (baninfo.bannedBy.length()) @@ -226,48 +324,117 @@ } } -void AccessControlList::sendBans(PlayerId id) + +void AccessControlList::sendBans(PlayerId id, const char* pattern) { expire(); - sendMessage(ServerPlayer, id, "IP Ban List"); sendMessage(ServerPlayer, id, "-----------"); - for (banList_t::iterator it = banList.begin(); it != banList.end(); ++it) + + const std::string glob = makeGlobPattern(pattern); + + for (banList_t::iterator it = banList.begin(); it != banList.end(); ++it) { + const BanInfo& bi = *it; + if (!glob_match(glob, getBanMaskString(bi.addr)) && + !glob_match(glob, TextUtils::toupper(bi.reason)) && + !glob_match(glob, TextUtils::toupper(bi.bannedBy))) { + continue; + } sendBan(id, *it); } +} -void AccessControlList::sendHostBans(PlayerId id) + +void AccessControlList::sendHostBans(PlayerId id, const char* pattern) { - char banlistmessage[MessageLen]; expire(); - sendMessage(ServerPlayer, id, "Host Ban List"); sendMessage(ServerPlayer, id, "-------------"); + + const std::string glob = makeGlobPattern(pattern); + + char banlistmessage[MessageLen]; for (hostBanList_t::iterator it = hostBanList.begin(); it != hostBanList.end(); ++it) { + + const HostBanInfo& bi = *it; + if (!glob_match(glob, TextUtils::toupper(bi.hostpat)) && + !glob_match(glob, TextUtils::toupper(bi.reason)) && + !glob_match(glob, TextUtils::toupper(bi.bannedBy))) { + continue; + } + + char *pMsg = banlistmessage; + sprintf(pMsg, "%s", bi.hostpat.c_str()); + + // print duration when < 1 year + double duration = bi.banEnd - TimeKeeper::getCurrent(); + if (duration < 365.0f * 24 * 3600) + sprintf(pMsg + strlen(pMsg)," (%.1f minutes)", duration / 60); + if (bi.bannedBy.length()) + sprintf(pMsg + strlen(pMsg), " banned by: %s", bi.bannedBy.c_str()); + if (bi.fromMaster) + sprintf(pMsg + strlen(pMsg), "(m)"); + + sendMessage(ServerPlayer, id, banlistmessage); + + // add reason, if any + if (bi.reason.size()) { + pMsg = banlistmessage; + sprintf(pMsg, " reason: %s", bi.reason.c_str()); + sendMessage(ServerPlayer, id, banlistmessage); + } + } +} + + +void AccessControlList::sendIdBans(PlayerId id, const char* pattern) +{ + expire(); + sendMessage(ServerPlayer, id, "BZID Ban List"); + sendMessage(ServerPlayer, id, "-------------"); + + const std::string glob = makeGlobPattern(pattern); + + char banlistmessage[MessageLen]; + for (idBanList_t::iterator it = idBanList.begin(); it != idBanList.end(); ++it) { + + const IdBanInfo& bi = *it; + if (!glob_match(glob, TextUtils::toupper(bi.idpat)) && + !glob_match(glob, TextUtils::toupper(bi.reason)) && + !glob_match(glob, TextUtils::toupper(bi.bannedBy))) { + continue; + } + char *pMsg = banlistmessage; - sprintf(pMsg, "%s", it->hostpat.c_str()); + bool useQuotes = (bi.idpat.find_first_of(" \t") != std::string::npos); + if (useQuotes) { + sprintf(pMsg, "\"%s\"", bi.idpat.c_str()); + } else { + sprintf(pMsg, "%s", bi.idpat.c_str()); + } // print duration when < 1 year - double duration = it->banEnd - TimeKeeper::getCurrent(); + double duration = bi.banEnd - TimeKeeper::getCurrent(); if (duration < 365.0f * 24 * 3600) sprintf(pMsg + strlen(pMsg)," (%.1f minutes)", duration / 60); - if (it->bannedBy.length()) - sprintf(pMsg + strlen(pMsg), " banned by: %s", it->bannedBy.c_str()); - if (it->fromMaster) + if (bi.bannedBy.length()) + sprintf(pMsg + strlen(pMsg), " banned by: %s", bi.bannedBy.c_str()); + if (bi.fromMaster) sprintf(pMsg + strlen(pMsg), "(m)"); sendMessage(ServerPlayer, id, banlistmessage); // add reason, if any - if (it->reason.size()) { + if (bi.reason.size()) { pMsg = banlistmessage; - sprintf(pMsg, " reason: %s", it->reason.c_str()); + sprintf(pMsg, " reason: %s", bi.reason.c_str()); sendMessage(ServerPlayer, id, banlistmessage); } } } + bool AccessControlList::load() { if (banFile.size() == 0) @@ -283,54 +450,140 @@ banList.clear(); // try to read ban entries - std::string ipAddress, hostpat, bannedBy, reason, tmp; + std::string ipAddress, hostpat, bzId, bannedBy, reason, tmp; long banEnd; is>>std::ws; while (!is.eof()) { is>>ipAddress; - if (ipAddress == "host:") + if (ipAddress == "host:") { is>>hostpat; + } else if (ipAddress == "bzid:") { + is.ignore(1); + std::getline(is, bzId); + } is>>tmp; - if (tmp != "end:") + if (tmp != "end:") { + DEBUG3("Banfile: bad 'end:' line\n"); return false; + } is>>banEnd; if (banEnd != 0) { // banEnd is absolute time - get delay from now, in minute // ban command use minute as ban time banEnd -= long(time(NULL)); banEnd /= 60; - if (banEnd == 0) - banEnd = -1; + if (banEnd == 0) banEnd = -1; } is>>tmp; - if (tmp != "banner:") + if (tmp != "banner:") { + DEBUG3("Banfile: bad 'banner:' line\n"); return false; + } is.ignore(1); std::getline(is, bannedBy); is>>tmp; - if (tmp != "reason:") + if (tmp != "reason:") { + DEBUG3("Banfile: bad 'reason:' line\n"); return false; + } is.ignore(1); std::getline(is, reason); is>>std::ws; - if (banEnd < 0) - continue; + if (banEnd < 0) continue; if (ipAddress == "host:") { hostBan(hostpat, (bannedBy.size() ? bannedBy.c_str(): NULL), banEnd, (reason.size() > 0 ? reason.c_str() : NULL)); + } else if (ipAddress == "bzid:") { + idBan(bzId, (bannedBy.size() ? bannedBy.c_str(): NULL), banEnd, + (reason.size() > 0 ? reason.c_str() : NULL)); } else { std::string::size_type n; while ((n = ipAddress.find('*')) != std::string::npos) { ipAddress.replace(n, 1, "255"); } if (!ban(ipAddress, (bannedBy.size() ? bannedBy.c_str(): NULL), banEnd, - (reason.size() > 0 ? reason.c_str() : NULL))) + (reason.size() > 0 ? reason.c_str() : NULL))) { + DEBUG3("Banfile: bad ban\n"); return false; } } + } return true; } + +int AccessControlList::merge(const std::string& banData) { + if (!banData.size()) { + return 0; + } + int bansAdded = 0; + std::stringstream is(banData,std::stringstream::in); + + // try to read ban entries + std::string ipAddress, hostpat, bzId, bannedBy, reason, tmp; + long banEnd; + is>>std::ws; + while (!is.eof()) { + is >> ipAddress; + if (ipAddress == "host:") { + is >> hostpat; + } else if (ipAddress == "bzid:") { + is.ignore(1); + std::getline(is, bzId); + } + is >> tmp; + if (tmp != "end:") { + DEBUG3("Banfile: bad 'end:' line\n"); + return bansAdded; + } + is >> banEnd; + if (banEnd != 0) { + banEnd -= long(time(NULL)); + banEnd /= 60; + if (banEnd == 0) + banEnd = -1; + } + is >> tmp; + if (tmp != "banner:") { + DEBUG3("Banfile: bad 'banner:' line\n"); + return bansAdded; + } + is.ignore(1); + std::getline(is, bannedBy); + is >> tmp; + if (tmp != "reason:") { + DEBUG3("Banfile: bad 'reason:' line\n"); + return bansAdded; + } + is.ignore(1); + std::getline(is, reason); + is >> std::ws; + if (banEnd < 0) + continue; + if (ipAddress == "host:") { + hostBan(hostpat, (bannedBy.size() ? bannedBy.c_str(): NULL), banEnd, + (reason.size() > 0 ? reason.c_str() : NULL),true); + bansAdded++; + } else if (ipAddress == "bzid:") { + idBan(bzId, (bannedBy.size() ? bannedBy.c_str(): NULL), banEnd, + (reason.size() > 0 ? reason.c_str() : NULL)); + } else { + std::string::size_type n; + while ((n = ipAddress.find('*')) != std::string::npos) { + ipAddress.replace(n, 1, "255"); + } + if (!ban(ipAddress, (bannedBy.size() ? bannedBy.c_str(): NULL), banEnd, + (reason.size() > 0 ? reason.c_str() : NULL),true)) { + DEBUG3("Banfile: bad ban\n"); + return bansAdded; + } + bansAdded++; + } + } + return bansAdded; +} + + void AccessControlList::save() { if (banFile.size() == 0) return; @@ -370,6 +623,7 @@ } os<<"banner: "<<it->bannedBy<<'\n'; os<<"reason: "<<it->reason<<'\n'; + os << '\n'; } } for (hostBanList_t::const_iterator ith = hostBanList.begin(); ith != hostBanList.end(); ++ith) { @@ -386,65 +640,27 @@ } os<<"banner: "<<ith->bannedBy<<'\n'; os<<"reason: "<<ith->reason<<'\n'; + os << '\n'; } -} - -int AccessControlList::merge(const std::string& banData) { - if (!banData.size()) { - return 0; - } - int bansAdded = 0; - std::stringstream is(banData,std::stringstream::in); + for (idBanList_t::const_iterator iti = idBanList.begin(); iti != idBanList.end(); ++iti) { + // print bzid + os << "bzid: " << iti->idpat << '\n'; - // try to read ban entries - std::string ipAddress, hostpat, bannedBy, reason, tmp; - long banEnd; - is>>std::ws; - while (!is.eof()) { - is>>ipAddress; - if (ipAddress == "host:") - is>>hostpat; - is>>tmp; - if (tmp != "end:") - return bansAdded; - is>>banEnd; - if (banEnd != 0) { - banEnd -= long(time(NULL)); - banEnd /= 60; - if (banEnd == 0) - banEnd = -1; - } - is>>tmp; - if (tmp != "banner:") - return bansAdded; - is.ignore(1); - std::getline(is, bannedBy); - is>>tmp; - if (tmp != "reason:") - return bansAdded; - is.ignore(1); - std::getline(is, reason); - is>>std::ws; - if (banEnd < 0) - continue; - if (ipAddress == "host:") { - hostBan(hostpat, (bannedBy.size() ? bannedBy.c_str(): NULL), banEnd, - (reason.size() > 0 ? reason.c_str() : NULL),true); - bansAdded++; + // print ban end, banner, and reason + if (iti->banEnd.getSeconds() == + TimeKeeper::getSunExplodeTime().getSeconds()) { + os << "end: 0" << '\n'; } else { - std::string::size_type n; - while ((n = ipAddress.find('*')) != std::string::npos) { - ipAddress.replace(n, 1, "255"); - } - if (!ban(ipAddress, (bannedBy.size() ? bannedBy.c_str(): NULL), banEnd, - (reason.size() > 0 ? reason.c_str() : NULL),true)) - return bansAdded; - bansAdded++; + os << "end: " << (long(iti->banEnd.getSeconds() + time(NULL) - + TimeKeeper::getCurrent().getSeconds())) << '\n'; } + os << "banner: " << iti->bannedBy << '\n'; + os << "reason: " << iti->reason << '\n'; + os << '\n'; } - return bansAdded; } + void AccessControlList::purgeMasters(void) { // remove any bans from the master server banList_t::iterator bItr = banList.begin(); @@ -454,7 +670,6 @@ else bItr++; } - hostBanList_t::iterator hItr = hostBanList.begin(); while (hItr != hostBanList.end()) { if (hItr->fromMaster) @@ -462,25 +677,49 @@ else hItr++; } + idBanList_t::iterator iItr = idBanList.begin(); + while (iItr != idBanList.end()) { + if (iItr->fromMaster) { + iItr = idBanList.erase(iItr); + } else { + iItr++; + } + } } -std::vector<std::pair<std::string, std::string> > AccessControlList::listMasterBans(void) const { +std::vector<std::pair<std::string, std::string> > AccessControlList::listMasterBans(void) const +{ std::vector<std::pair<std::string, std::string> >bans; std::string explain; - for (banList_t::const_iterator bItr = banList.begin(); bItr != banList.end(); bItr++) { + banList_t::const_iterator bItr; + for (bItr = banList.begin(); bItr != banList.end(); bItr++) { if (bItr->fromMaster) { - explain = TextUtils::format("%s (banned by %s)", bItr->reason.c_str(), bItr->bannedBy.c_str()); - const std::pair<std::string, std::string> baninfo = std::make_pair(std::string(inet_ntoa(bItr->addr)), explain); + explain = TextUtils::format("%s (banned by %s)", + bItr->reason.c_str(), bItr->bannedBy.c_str()); + const std::pair<std::string, std::string> + baninfo = std::make_pair(std::string(inet_ntoa(bItr->addr)), explain); bans.push_back(baninfo); } } - - for (hostBanList_t::const_iterator hItr = hostBanList.begin(); hItr != hostBanList.end(); hItr++) { + hostBanList_t::const_iterator hItr; + for (hItr = hostBanList.begin(); hItr != hostBanList.end(); hItr++) { if (hItr->fromMaster) { - explain = TextUtils::format("%s (banned by %s)", hItr->reason.c_str(), hItr->bannedBy.c_str()); - const std::pair<std::string, std::string> baninfo = std::make_pair(hItr->hostpat, explain); + explain = TextUtils::format("%s (banned by %s)", + hItr->reason.c_str(), hItr->bannedBy.c_str()); + const std::pair<std::string, std::string> + baninfo = std::make_pair(hItr->hostpat, explain); + bans.push_back(baninfo); + } + } + idBanList_t::const_iterator iItr; + for (iItr = idBanList.begin(); iItr != idBanList.end(); iItr++) { + if (iItr->fromMaster) { + explain = TextUtils::format("%s (banned by %s)", + iItr->reason.c_str(), iItr->bannedBy.c_str()); + const std::pair<std::string, std::string> + baninfo = std::make_pair(iItr->idpat, explain); bans.push_back(baninfo); } } @@ -513,11 +752,15 @@ b[3] = atoi(ip); mask.s_addr= htonl(((unsigned int)b[0] << 24) | - ((unsigned int)b[1] << 16) | ((unsigned int)b[2] << 8) | (unsigned int)b[3]); + ((unsigned int)b[1] << 16) | + ((unsigned int)b[2] << 8) | + (unsigned int)b[3]); return true; } -void AccessControlList::expire() { + +void AccessControlList::expire() +{ TimeKeeper now = TimeKeeper::getCurrent(); for (banList_t::iterator it = banList.begin(); it != banList.end();) { if (it->banEnd <= now) { @@ -533,7 +776,15 @@ ++ith; } } + for (idBanList_t::iterator iti = idBanList.begin(); iti != idBanList.end();) { + if (iti->banEnd <= now) { + iti = idBanList.erase(iti); + } else { + ++iti; + } } +} + // Local Variables: *** // mode:C++ *** Index: AccessControlList.h =================================================================== RCS file: /cvsroot/bzflag/bzflag/src/bzfs/AccessControlList.h,v retrieving revision 2.5 retrieving revision 2.6 diff -w -u -r2.5 -r2.6 --- AccessControlList.h 6 Oct 2005 13:12:25 -0000 2.5 +++ AccessControlList.h 23 Nov 2005 01:34:58 -0000 2.6 @@ -96,6 +96,46 @@ bool fromMaster; // where the ban came from, local or master list. }; + +/** This struct contains information about an idban - the databaseid pattern + that was banned, the time the ban will expire, the callsign of the player + who performed the ban, and the reason. It also has operators defined for + checking if two bans are equal. */ +struct IdBanInfo +{ + /** This constructor creates a new IdBanInfo with the id pattern + @c idpat, the ban performer @c bannedBy, and the expiration time + @c period minutes from now. */ + IdBanInfo(std::string _idpat, const char *_bannedBy = NULL, + int period = 0, bool isFromMaster = false ) { + idpat = _idpat; + if (_bannedBy) + bannedBy = _bannedBy; + if (period == 0) { + banEnd = TimeKeeper::getSunExplodeTime(); + } else { + banEnd = TimeKeeper::getCurrent(); + banEnd += period * 60.0f; + } + fromMaster = isFromMaster; + } + /** IdBanInfos with same id pattern are identical. */ + bool operator==(const IdBanInfo &rhs) const { + return idpat == rhs.idpat; + } + /** Only IdBanInfos with same id pattern are identical. */ + bool operator!=(const IdBanInfo& rhs) const { + return idpat != rhs.idpat; + } + + std::string idpat; + TimeKeeper banEnd; + std::string bannedBy; + std::string reason; + bool fromMaster; // where the ban came from, local or master list. +}; + + /* FIXME the AccessControlList assumes that 255 is a wildcard. it "should" * include a cidr mask with each address. it's still useful as is, though * see wildcard conversion occurs in convert(). @@ -112,22 +152,32 @@ /** This function will add a ban for the address @c ipAddr with the given parameters. If that address already is banned the old ban will be replaced. */ - void ban(in_addr &ipAddr, const char *bannedBy, int period = 0, const char *reason=NULL, bool fromMaster = false); + void ban(in_addr &ipAddr, const char *bannedBy, int period = 0, + const char *reason=NULL, bool fromMaster = false); /** This function takes a list of addresses as a string and tries to ban them using the given parameters. The string should be comma separated, like this: "1.2.3.4,5.6.7.8,9.10.11.12". */ - bool ban(std::string &ipList, const char *bannedBy=NULL, int period = 0, const char *reason=NULL, bool fromMaster = false); + bool ban(std::string &ipList, const char *bannedBy=NULL, int period = 0, + const char *reason=NULL, bool fromMaster = false); /** This function takes a list of addresses as a <code>const char*</code> and tries to ban them using the given parameters. The string should be comma separated, like this: "1.2.3.4,5.6.7.8,9.10.11.12". */ - bool ban(const char *ipList, const char *bannedBy=NULL, int period = 0, const char *reason=NULL, bool fromMaster = false); + bool ban(const char *ipList, const char *bannedBy=NULL, int period = 0, + const char *reason=NULL, bool fromMaster = false); /** This function adds a hostban for the host pattern @c hostpat with the given parameters. If the host pattern already is banned the old ban will be replaced. */ - void hostBan(std::string hostpat, const char *bannedBy, int period = 0, const char *reason = NULL, bool fromMaster = false); + void hostBan(std::string hostpat, const char *bannedBy, int period = 0, + const char *reason = NULL, bool fromMaster = false); + + /** This function adds an idban for the id pattern @c idpat with the + given parameters. If the idban pattern already is banned the old ban will + be replaced. */ + void idBan(std::string hostpat, const char *bannedBy, int period = 0, + const char *reason = NULL, bool fromMaster = false); /** This function removes any ban for the address @c ipAddr. @returns @c true if there was a ban for that address, @c false if there @@ -151,6 +201,11 @@ otherwise. */ bool hostUnban(std::string hostpat); + /** This function removes any ban for the database id @c idpat. + @returns @c true if there was a ban for the database id, @c false + otherwise. */ + bool idUnban(std::string idpat); + /** This function checks if an address is "valid" or not. Valid in this case means that it has not been banned. @returns @c true if the address is valid, @c false if not. */ @@ -165,14 +220,22 @@ @returns @c true if the hostname is valid, @c false if it isn't. */ bool hostValidate(const char *hostname, HostBanInfo *info = NULL); + /** This function checks that an id is "valid". In this case valid means + "not banned". + @returns @c true if the id is valid, @c false if it isn't. */ + bool idValidate(const char *idname, IdBanInfo *info = NULL); + /** This function sends a textual list of the given IP ban to a player. */ void sendBan(PlayerId id, const BanInfo&); /** This function sends a textual list of all IP bans to a player. */ - void sendBans(PlayerId id); + void sendBans(PlayerId id, const char* pattern); /** This function sends a textual list of all host bans to a player. */ - void sendHostBans(PlayerId id); + void sendHostBans(PlayerId id, const char* pattern); + + /** This function sends a textual list of all id bans to a player. */ + void sendIdBans(PlayerId id, const char* pattern); /** This function tells this object where to save the banlist, and where to load it from. */ @@ -212,6 +275,9 @@ typedef std::vector<HostBanInfo> hostBanList_t; hostBanList_t hostBanList; + typedef std::vector<IdBanInfo> idBanList_t; + idBanList_t idBanList; + std::string banFile; }; Index: BanCommands.cxx =================================================================== RCS file: /cvsroot/bzflag/bzflag/src/bzfs/BanCommands.cxx,v retrieving revision 2.23 retrieving revision 2.24 diff -w -u -r2.23 -r2.24 --- BanCommands.cxx 24 Oct 2005 17:24:59 -0000 2.23 +++ BanCommands.cxx 23 Nov 2005 01:34:58 -0000 2.24 @@ -15,8 +15,10 @@ // system headers #include <ctype.h> +#include <string.h> // common implementation headers +#include "TextUtils.h" #include "WorldEventManager.h" // local implementation headers @@ -24,6 +26,7 @@ #include "MasterBanList.h" #include "bzfs.h" + class KickCommand : ServerCommand { public: KickCommand(); @@ -64,6 +67,14 @@ GameKeeper::Player *playerData); }; +class IdBanListCommand : ServerCommand { +public: + IdBanListCommand(); + + virtual bool operator() (const char *commandLine, + GameKeeper::Player *playerData); +}; + class BanCommand : ServerCommand { public: BanCommand(); @@ -80,6 +91,14 @@ GameKeeper::Player *playerData); }; +class IdBanCommand : ServerCommand { +public: + IdBanCommand(); + + virtual bool operator() (const char *commandLine, + GameKeeper::Player *playerData); +}; + class UnbanCommand : ServerCommand { public: UnbanCommand(); @@ -96,6 +115,14 @@ GameKeeper::Player *playerData); }; +class IdUnbanCommand : ServerCommand { +public: + IdUnbanCommand(); + + virtual bool operator() (const char *commandLine, + GameKeeper::Player *playerData); +}; + class MuteCommand : ServerCommand { public: MuteCommand(); @@ -122,13 +149,16 @@ static KickCommand kickCommand; static KillCommand killCommand; -static BanListCommand banListCommand; static CheckIPCommand checkIPCommand; -static HostbanListCommand hostbanListCommand; static BanCommand banCommand; -static HostbanCommand hostbanCommand; static UnbanCommand unbanCommand; +static BanListCommand banListCommand; +static HostbanCommand hostbanCommand; static HostUnbanCommand hostUnbanCommand; +static HostbanListCommand hostbanListCommand; +static IdBanCommand idBanCommand; +static IdUnbanCommand idUnbanCommand; +static IdBanListCommand idBanListCommand; static MuteCommand muteCommand; static UnmuteCommand unmuteCommand; static MasterBanCommand masterBanCommand; @@ -138,19 +168,25 @@ KillCommand::KillCommand() : ServerCommand("/kill", "<#slot|PlayerName|\"Player Name\"> [reason] - kill a player") {} BanListCommand::BanListCommand() : ServerCommand("/banlist", - "- List all of the IPs currently banned from this server") {} + "[pattern] - List the IPs currently banned from this server") {} CheckIPCommand::CheckIPCommand() : ServerCommand("/checkip", "<ip> - check if IP is banned and print corresponding ban info") {} -HostbanListCommand::HostbanListCommand() : ServerCommand("/hostbanlist", - "- List all of the host patterns currently banned from this server") {} BanCommand::BanCommand() : ServerCommand("/ban", "<#slot|PlayerName|\"Player Name\"|ip> <duration> <reason> - ban a player, ip or ip range off the server") {} +UnbanCommand::UnbanCommand() : ServerCommand("/unban", + "<ip> - remove a ip pattern from the ban list") {} HostbanCommand::HostbanCommand() : ServerCommand("/hostban", "<host pattern> [duration] [reason] - ban using host pattern off the server") {} -UnbanCommand::UnbanCommand() : ServerCommand("/unban", - "[ip] - remove a ip pattern from the ban list") {} HostUnbanCommand::HostUnbanCommand() : ServerCommand("/hostunban", "<host pattern> - remove a host pattern from the host ban list") {} +HostbanListCommand::HostbanListCommand() : ServerCommand("/hostbanlist", + "[pattern] - List the host patterns currently banned from this server") {} +IdBanCommand::IdBanCommand() : ServerCommand("/idban", + "<#slot|+id|PlayerName|\"Player Name\"> <duration> <reason> - ban using BZID") {} +IdUnbanCommand::IdUnbanCommand() : ServerCommand("/idunban", + "<id> - remove a BZID from the ban list") {} +IdBanListCommand::IdBanListCommand(): ServerCommand("/idbanlist", + "[pattern] - List the BZIDs currently banned from this server") {} MuteCommand::MuteCommand() : ServerCommand("/mute", "<#slot|PlayerName|\"Player Name\"> - remove the ability for a player to communicate with other players") {} UnmuteCommand::UnmuteCommand() : ServerCommand("/unmute", @@ -402,19 +438,6 @@ return true; } -bool BanListCommand::operator() (const char *, - GameKeeper::Player *playerData) -{ - int t = playerData->getIndex(); - if (!playerData->accessInfo.hasPerm(PlayerAccessInfo::banlist)) { - sendMessage(ServerPlayer, t, - "You do not have permission to run the banlist command"); - return true; - } - clOptions->acl.sendBans(t); - return true; -} - bool CheckIPCommand::operator() (const char *message, GameKeeper::Player *playerData) @@ -449,7 +472,35 @@ } -bool HostbanListCommand::operator() (const char *, +bool BanListCommand::operator() (const char* message, + GameKeeper::Player* playerData) +{ + int t = playerData->getIndex(); + if (!playerData->accessInfo.hasPerm(PlayerAccessInfo::banlist)) { + sendMessage(ServerPlayer, t, + "You do not have permission to run the banlist command"); + return true; + } + clOptions->acl.sendBans(t, message + commandName.size()); + return true; +} + + +bool HostbanListCommand::operator() (const char* message, + GameKeeper::Player* playerData) +{ + int t = playerData->getIndex(); + if (!playerData->accessInfo.hasPerm(PlayerAccessInfo::banlist)) { + sendMessage(ServerPlayer, t, + "You do not have permission to run the banlist command"); + return true; + } + clOptions->acl.sendHostBans(t, message + commandName.size()); + return true; +} + + +bool IdBanListCommand::operator() (const char* message, GameKeeper::Player *playerData) { int t = playerData->getIndex(); @@ -458,7 +509,65 @@ "You do not have permission to run the banlist command"); return true; } - clOptions->acl.sendHostBans(t); + clOptions->acl.sendIdBans(t, message + commandName.size()); + return true; +} + + +static void addNamePrefix(std::string& reason, const std::string& name) +{ + // add the name prefix if the name isn't already contained + if (strstr(reason.c_str(), name.c_str()) == NULL) { + reason = "(" + name + ") " + reason; + } + return; +} + + +static bool doBanKick(GameKeeper::Player *victim, + GameKeeper::Player *banner, + const char* reason) +{ + if ((victim == NULL) || (banner == NULL)) { + return true; // proceed with the ban + } + + char buffer[MessageLen]; + const int victimID = victim->getIndex(); + const int bannerID = banner->getIndex(); + + // operators can override antiperms, except for other operators + if (victim->accessInfo.isOperator() || + !banner->accessInfo.isOperator()) { + // make sure this player isn't protected + if (victim->accessInfo.hasPerm(PlayerAccessInfo::antiban)) { + snprintf(buffer, MessageLen, + "%s is protected from being banned (skipped).", + victim->player.getCallSign()); + sendMessage(ServerPlayer, bannerID, buffer); + return false; // do not use the ban + } + } + + // send a notice to the victim + snprintf(buffer, MessageLen, + "You were banned from this server by %s", + banner->player.getCallSign()); + sendMessage(ServerPlayer, victimID, buffer); + if (strlen(reason) > 0) { + snprintf(buffer, MessageLen, "Reason given: %s", reason); + sendMessage(ServerPlayer, victimID, buffer); + } + + // send a notice to the admins + snprintf(buffer, MessageLen, "%s banned by %s, reason: %s", + victim->player.getCallSign(), banner->player.getCallSign(), + reason); + sendMessage(ServerPlayer, AdminPlayers, buffer); + + // you're outta here + removePlayer(victimID, "/ban"); + return true; } @@ -477,7 +586,7 @@ std::string msg = message; std::vector<std::string> argv = TextUtils::tokenize(msg, " \t", 4, true); - if (argv.size() < 4) { + if (argv.size() != 4) { sendMessage(ServerPlayer, t, "Syntax: /ban <#slot | PlayerName | \"Player Name\" | ip> " "<duration> <reason>"); @@ -498,31 +607,29 @@ } std::string ip = argv[1]; - std::string reason; - int durationInt = clOptions->banTime; int victim = GameKeeper::Player::getPlayerIDByName(argv[1]); - char kickmessage[MessageLen]; - + GameKeeper::Player* victimPlayer = NULL; if (victim >= 0) { // valid slot or callsign - GameKeeper::Player *playerBannedData - = GameKeeper::Player::getPlayerByIndex(victim); - if (playerBannedData) { - if (playerBannedData->accessInfo.hasPerm(PlayerAccessInfo::antiban)){ - snprintf(kickmessage, MessageLen, + victimPlayer = GameKeeper::Player::getPlayerByIndex(victim); + if (victimPlayer) { + if (victimPlayer->accessInfo.hasPerm(PlayerAccessInfo::antiban)){ + char buffer[MessageLen]; + snprintf(buffer, MessageLen, "%s is protected from being banned (skipped).", - playerBannedData->player.getCallSign()); - sendMessage(ServerPlayer, t, kickmessage); + victimPlayer->player.getCallSign()); + sendMessage(ServerPlayer, t, buffer); return true; } - ip = playerBannedData->netHandler->getTargetIP(); + ip = victimPlayer->netHandler->getTargetIP(); } } - int specifiedDuration = 0; - // check the ban duration + // setup the ban duration + int durationInt = clOptions->banTime; + int specifiedDuration; if (!TextUtils::parseDuration(argv[2].c_str(), specifiedDuration)) { sendMessage(ServerPlayer, t, "Error: invalid ban duration"); sendMessage(ServerPlayer, t, @@ -530,8 +637,7 @@ "1w2d1m"); return true; } - - if (specifiedDuration >= 0) + if (specifiedDuration >= 0) { if ((durationInt > 0) && ((specifiedDuration > durationInt) || (specifiedDuration <= 0)) && !playerData->accessInfo.hasPerm(PlayerAccessInfo::ban)) { @@ -540,9 +646,14 @@ } else { durationInt = specifiedDuration; } - { + } + // set the ban reason + std::string reason; reason = argv[3]; + if (victimPlayer) { + addNamePrefix(reason, victimPlayer->player.getCallSign()); + } // call any plugin events registered for /ban bz_BanEventData banEvent; @@ -551,9 +662,9 @@ banEvent.reason = reason.c_str(); banEvent.duration = durationInt; // if we know for sure who is to be banned, submit it - if (victim >= 0) + if (victim >= 0) { banEvent.banneeID = victim; - + } worldEventManager.callEvents(bz_eBanEvent,&banEvent); // a plugin might have changed bannerID @@ -563,65 +674,50 @@ return true; } + // handle the case of a single intended victim + if (victimPlayer) { + if (!doBanKick(victimPlayer, playerData, banEvent.reason.c_str())) { + return true; // could not ban, bail + } + // add a bzId ban if we can + const std::string& bzid = victimPlayer->getBzIdentifier(); + if (bzid.size() > 0) { + clOptions->acl.load(); + clOptions->acl.idBan(bzid, playerData->player.getCallSign(), + banEvent.duration, banEvent.reason.c_str()); + clOptions->acl.save(); + sendMessage(ServerPlayer, t, "Pattern added to the BZID banlist"); + } + } // reload the banlist in case anyone else has added clOptions->acl.load(); + // add the ban, and kick any that it applies to if (clOptions->acl.ban(banEvent.ipAddress.c_str(), - playerData->player.getCallSign(), banEvent.duration, + playerData->player.getCallSign(), + banEvent.duration, banEvent.reason.c_str())) { clOptions->acl.save(); - sendMessage(ServerPlayer, t, "IP pattern added to banlist"); + sendMessage(ServerPlayer, t, "Pattern added to the IP banlist"); - GameKeeper::Player *otherPlayer; for (int i = 0; i < curMaxPlayers; i++) { - otherPlayer = GameKeeper::Player::getPlayerByIndex(i); - if (otherPlayer && !clOptions->acl.validate - (otherPlayer->netHandler->getIPAddress())) { - - // operators can override antiperms - if (!playerData->accessInfo.isOperator()) { - // make sure this player isn't protected - GameKeeper::Player *p = GameKeeper::Player::getPlayerByIndex(i); - if ((p != NULL) - && (p->accessInfo.hasPerm(PlayerAccessInfo::antiban))) { - snprintf(kickmessage, MessageLen, - "%s is protected from being banned (skipped).", - p->player.getCallSign()); - sendMessage(ServerPlayer, t, kickmessage); - continue; - } - } - - snprintf(kickmessage, MessageLen, - "You were banned from this server by %s", - playerData->player.getCallSign()); - sendMessage(ServerPlayer, i, kickmessage); - if (reason.length() > 0) { - snprintf(kickmessage, MessageLen, "Reason given: %s", - banEvent.reason.c_str()); - sendMessage(ServerPlayer, i, kickmessage); - } - if (otherPlayer) { - snprintf(kickmessage, MessageLen, - "%s banned by %s, reason: %s", - otherPlayer->player.getCallSign(), - playerData->player.getCallSign(), - banEvent.reason.c_str()); - sendMessage(ServerPlayer, AdminPlayers, kickmessage); - } - removePlayer(i, "/ban"); + GameKeeper::Player *tmpVictim = GameKeeper::Player::getPlayerByIndex(i); + if (tmpVictim && + !clOptions->acl.validate(tmpVictim->netHandler->getIPAddress())) { + // ignore the return code + doBanKick(tmpVictim, playerData, banEvent.reason.c_str()); } } } else { - char errormessage[MessageLen]; - snprintf(errormessage, MessageLen, + char buffer[MessageLen]; + snprintf(buffer, MessageLen, "Malformed address or invalid Player/Slot: %s", argv[1].c_str()); - sendMessage(ServerPlayer, t, errormessage); - } + sendMessage(ServerPlayer, t, buffer); } + return true; } @@ -646,15 +742,16 @@ sendMessage(ServerPlayer, t, " Please keep in mind that reason is displayed to the " "user."); - } else { + return true; + } + std::string hostpat = argv[1]; - std::string reason; - int durationInt = clOptions->banTime; // set the ban time + int durationInt = clOptions->banTime; if (argv.size() >= 3) { int specifiedDuration; - // check the ban duration + // setup the ban duration if (!TextUtils::parseDuration(argv[2].c_str(), specifiedDuration)) { sendMessage(ServerPlayer, t, "Error: invalid ban duration"); sendMessage(ServerPlayer, t, @@ -674,6 +771,7 @@ } // set the ban reason + std::string reason; if (argv.size() == 4) { reason = argv[3]; } @@ -694,6 +792,9 @@ return true; } + // reload the banlist in case anyone else has added + clOptions->acl.load(); + clOptions->acl.hostBan(hostBanEvent.hostPattern.c_str(), playerData->player.getCallSign(), hostBanEvent.duration, @@ -702,8 +803,125 @@ GameKeeper::Player::setAllNeedHostbanChecked(true); - sendMessage(ServerPlayer, t, "Host pattern added to banlist"); + sendMessage(ServerPlayer, t, "Pattern added to the HOSTNAME banlist"); + + return true; +} + + +bool IdBanCommand::operator() (const char* message, + GameKeeper::Player* playerData) +{ + int t = playerData->getIndex(); + if (!playerData->accessInfo.hasPerm(PlayerAccessInfo::ban) && + !playerData->accessInfo.hasPerm(PlayerAccessInfo::shortBan)) { + sendMessage(ServerPlayer, t, + "You do not have permission to run the ban command"); + return true; + } + + std::string msg = message; + std::vector<std::string> argv = TextUtils::tokenize(msg, " \t", 4, true); + + if (argv.size() != 4) { + sendMessage(ServerPlayer, t, + "Syntax: /idban <#slot|+id|PlayerName|\"Player Name\"> <duration> <reason>"); + sendMessage(ServerPlayer, t, + " Please keep in mind that reason is displayed to the user."); + return true; + } + + // get the ban pattern or victim + std::string idpat = argv[1]; + int victim = -1; + GameKeeper::Player *victimPlayer = NULL; + if (idpat[0] == '+') { + idpat = idpat.c_str() + 1; // strip the '+' for a raw id pattern + if (idpat.size() <= 0) { + sendMessage(ServerPlayer, t, "Error: invalid id pattern"); + return true; + } + // check for a player that matches + for (int i = 0; i < curMaxPlayers; i++) { + GameKeeper::Player *tmpPlayer = GameKeeper::Player::getPlayerByIndex(i); + if ((tmpPlayer != NULL) && (tmpPlayer->getBzIdentifier().size() > 0)) { + const std::string& bzId = tmpPlayer->getBzIdentifier(); + if (idpat == bzId) { + victim = i; + victimPlayer = tmpPlayer; + break; + } + } + } + } + else { + // looking for a specific player + victim = GameKeeper::Player::getPlayerIDByName(idpat); + victimPlayer = GameKeeper::Player::getPlayerByIndex(victim); + if ((victim < 0) || (victimPlayer == NULL)) { + char buffer[MessageLen]; + snprintf(buffer, MessageLen, "could not find player (%s)", idpat.c_str()); + sendMessage(ServerPlayer, t, buffer); + return true; + } + // found the player, check for a BZID + const std::string& bzId = victimPlayer->getBzIdentifier(); + if (bzId.size() <= 0) { + char buffer[MessageLen]; + snprintf(buffer, MessageLen, "no BZID for player (%s)", idpat.c_str()); + sendMessage(ServerPlayer, t, buffer); + return true; + } + idpat = bzId; // success + } + + // setup the ban duration + int durationInt = clOptions->banTime; + int specifiedDuration; + if (!TextUtils::parseDuration(argv[2].c_str(), specifiedDuration)) { + sendMessage(ServerPlayer, t, "Error: invalid ban duration"); + sendMessage(ServerPlayer, t, + "Duration examples: 30m 1h 1d 1w and mixing: 1w2d4h " + "1w2d1m"); + return true; + } + if (specifiedDuration >= 0) { + if ((durationInt > 0) && + ((specifiedDuration > durationInt) || (specifiedDuration <= 0)) && + !playerData->accessInfo.hasPerm(PlayerAccessInfo::ban)) { + sendMessage (ServerPlayer, t, "You only have SHORTBAN privileges," + " using default ban time"); + } else { + durationInt = specifiedDuration; + } + } + + // set the ban reason + std::string reason = argv[3]; + if (victimPlayer) { + addNamePrefix(reason, victimPlayer->player.getCallSign()); + } + + // remove the victim if we have one + if (victimPlayer) { + if (!doBanKick(victimPlayer, playerData, reason.c_str())) { + return true; // could not ban, bail } + } + + // + // FIXME: add to the plugin system + // + + // reload the banlist in case anyone else has added + clOptions->acl.load(); + + clOptions->acl.idBan(idpat, playerData->player.getCallSign(), + durationInt, reason.c_str()); + clOptions->acl.save(); + + sendMessage(ServerPlayer, t, "Pattern added to the BZID banlist"); + return true; } @@ -727,13 +945,14 @@ return true; } + bool HostUnbanCommand::operator() (const char *message, GameKeeper::Player *playerData) { int t = playerData->getIndex(); if (!playerData->accessInfo.hasPerm(PlayerAccessInfo::unban)) { sendMessage(ServerPlayer, t, - "You do not have permission to run the unban command"); + "You do not have permission to run the /hostunban command"); return true; } @@ -746,6 +965,27 @@ return true; } + +bool IdUnbanCommand::operator() (const char *message, + GameKeeper::Player *playerData) +{ + int t = playerData->getIndex(); + if (!playerData->accessInfo.hasPerm(PlayerAccessInfo::unban)) { + sendMessage(ServerPlayer, t, + "You do not have permission to run the /idunban command"); + return true; + } + + if (clOptions->acl.idUnban(message + 9)) { + sendMessage(ServerPlayer, t, "Removed id from the ban list"); + clOptions->acl.save(); + } else { + sendMessage(ServerPlayer, t, "No pattern removed"); + } + return true; +} + + /** /masterban command * * /masterban flush # remove all master ban entries from this server Index: CmdLineOptions.cxx =================================================================== RCS file: /cvsroot/bzflag/bzflag/src/bzfs/CmdLineOptions.cxx,v retrieving revision 2.40 retrieving revision 2.41 diff -w -u -r2.40 -r2.41 --- CmdLineOptions.cxx 13 Nov 2005 02:49:49 -0000 2.40 +++ CmdLineOptions.cxx 23 Nov 2005 01:34:58 -0000 2.41 @@ -72,7 +72,6 @@ "[-filterCallsigns] " "[-filterChat] " "[-filterSimple] " -"[-forcegfx] " "[-g] " "[-gndtex <texture name>] " "[-groupdb <group file>] " @@ -113,6 +112,8 @@ "[-reportfile <filename>] " "[-reportpipe <filename>] " "[-requireudp] " +"[-reqgfx] " +"[-reqreg] " "[+s <flag-count>] " "[-s <flag-count>] " "[-sa] " @@ -165,7 +166,6 @@ "\t-filterCallsigns: filter callsigns to disallow inappropriate user names\n" "\t-filterChat: filter chat messages\n" "\t-filterSimple: perform simple exact matches with the bad word list\n" -"\t-forcegfx: required that the clients use advanced graphics mode\n" "\t-g: serve one game and then exit\n" "\t-gndtex: specify ground texture\n" "\t-groupdb: file to read for group permissions\n" @@ -206,6 +206,8 @@ "\t-reportfile <filename>: the file to store reports in\n" "\t-reportpipe <filename>: the program to pipe reports through\n" "\t-requireudp: require clients to use udp\n" +"\t-reqgfx: required that the clients use advanced graphics mode\n" +"\t-reqreg: required that the clients are registered to spawn and talk" "\t+s: always have <num> super flags (default=16)\n" "\t-s: allow up to <num> super flags (default=16)\n" "\t-sa: insert antidote superflags\n" @@ -688,8 +690,6 @@ options.filterChat = true; } else if (strcmp(argv[i], "-filterSimple") == 0) { options.filterSimple = true; - } else if (strcmp(argv[i], "-forcegfx") == 0) { - options.gameStyle |= int(RequireGraphics); } else if (strcmp(argv[i], "-g") == 0) { options.oneGameOnly = true; } else if (strcmp(argv[i], "-gndtex") == 0) { @@ -934,6 +934,10 @@ } else if (strcmp(argv[i], "-reportpipe") == 0) { checkArgc(1, i, argc, argv[i]); options.reportPipe = argv[i]; + } else if (strcmp(argv[i], "-reqgfx") == 0) { + options.gameStyle |= int(RequireGraphics); + } else if (strcmp(argv[i], "-reqreg") == 0) { + options.gameStyle |= int(RequireRegistration); } else if (strcmp(argv[i], "-requireudp") == 0) { std::cerr << "require UDP clients!" << std::endl; options.requireUDP = true; Index: GameKeeper.cxx =================================================================== RCS file: /cvsroot/bzflag/bzflag/src/bzfs/GameKeeper.cxx,v retrieving revision 2.32 retrieving revision 2.33 diff -w -u -r2.32 -r2.33 --- GameKeeper.cxx 13 Nov 2005 02:48:31 -0000 2.32 +++ GameKeeper.cxx 23 Nov 2005 01:34:58 -0000 2.33 @@ -63,6 +63,7 @@ refCount = 1; #endif _LSAState = start; + bzIdentifier = ""; } GameKeeper::Player::~Player() Index: GameKeeper.h =================================================================== RCS file: /cvsroot/bzflag/bzflag/src/bzfs/GameKeeper.h,v retrieving revision 2.23 retrieving revision 2.24 diff -w -u -r2.23 -r2.24 --- GameKeeper.h 13 Nov 2005 02:49:50 -0000 2.23 +++ GameKeeper.h 23 Nov 2005 01:34:58 -0000 2.24 @@ -109,6 +109,9 @@ void getPlayerState(float pos[3], float &azimuth); void setPlayerState(PlayerState state, float timestamp); + void setBzIdentifier(const std::string& id); + const std::string& getBzIdentifier() const; + // When is the player's next GameTime? const TimeKeeper& getNextGameTime() const; void updateNextGameTime(); @@ -126,7 +129,7 @@ required, requesting, checking, - timed, + timedOut, failed, verified, done @@ -150,12 +153,15 @@ FlagHistory flagHistory; // Score Score score; + // Authentication Authentication authentication; + private: static Player *playerList[PlayerSlot]; int playerIndex; bool closed; tcpCallback clientCallback; + std::string bzIdentifier; #if defined(USE_THREADS) pthread_t thread; static pthread_mutex_t mutex; @@ -164,11 +170,10 @@ bool needThisHostbanChecked; // In case you want recheck all condition on all players static bool allNeedHostbanChecked; - static int maxShots; std::vector<ShotInfo> shotsInfo; - }; + class Flag { }; }; @@ -230,11 +235,24 @@ return (allNeedHostbanChecked || needThisHostbanChecked); } + +inline void GameKeeper::Player::setBzIdentifier(const std::string& id) +{ + bzIdentifier = id; +} + +inline const std::string& GameKeeper::Player::getBzIdentifier() const +{ + return bzIdentifier; +} + + inline const TimeKeeper& GameKeeper::Player::getNextGameTime() const { return gameTimeNext; } + #endif // Local Variables: *** Index: ListServerConnection.cxx =================================================================== RCS file: /cvsroot/bzflag/bzflag/src/bzfs/ListServerConnection.cxx,v retrieving revision 2.49 retrieving revision 2.50 diff -w -u -r2.49 -r2.50 --- ListServerConnection.cxx 29 Oct 2005 16:31:43 -0000 2.49 +++ ListServerConnection.cxx 23 Nov 2005 01:34:58 -0000 2.50 @@ -107,6 +107,7 @@ static char *tokGoodIdentifier = "TOKGOOD: "; static char *tokBadIdentifier = "TOKBAD: "; static char *unknownPlayer = "UNK: "; + static char *bzIdentifier = "BZID: "; // walks entire reply including HTTP headers while (*base) { // find next newline @@ -124,6 +125,7 @@ bool verified = false; // this is a reply to an authentication request ? bool authReply = false; + char *callsign; if (strncmp(base, tokGoodIdentifier, strlen(tokGoodIdentifier)) == 0) { callsign = base + strlen(tokGoodIdentifier); @@ -137,7 +139,72 @@ } else if (!strncmp(base, unknownPlayer, strlen(unknownPlayer))) { callsign = base + strlen(unknownPlayer); authReply = true; + } else if (!strncmp(base, bzIdentifier, strlen(bzIdentifier))) { + std::string line = base; + std::vector<std::string> args = TextUtils::tokenize(line, " \t", 3, true); + if (args.size() < 3) { + DEBUG3("Bad BZID string: %s\n", line.c_str()); + } else { + const std::string& bzId = args[1]; + const std::string& nick = args[2]; + DEBUG4("Got BZID: \"%s\" || \"%s\"\n", bzId.c_str(), nick.c_str()); + for (int i = 0; i < curMaxPlayers; i++) { + GameKeeper::Player* gkp = GameKeeper::Player::getPlayerByIndex(i); + if ((gkp != NULL) && + (strcasecmp(gkp->player.getCallSign(), nick.c_str()) == 0)) { + gkp->setBzIdentifier(bzId); + DEBUG3("Set player (%s [%i]) bzId to (%s)\n", + nick.c_str(), i, bzId.c_str()); + break; + } + } + } + } +/* + char* start = base + strlen(bzIdentifier); + // skip leading white + while ((*start != '\0') && isspace(*start)) start++; + const bool useQuotes = (*start == '"'); + if (useQuotes) start++; // ditch the '"' + char* end = start; + // skip until the end of the id + if (useQuotes) { + while ((*end != '\0') && (*end != '"')) end++; + } else { + while ((*end != '\0') && !isspace(*end)) end++; + } + if ((*end != '\0') && (useQuotes && (*end != '"'))) { + if (useQuotes) { + callsign = end + 1; + end--; // ditch the '"' + } else { + callsign = end; } + // skip leading white + while ((*callsign != '\0') && isspace(*callsign)) callsign++; + if (*callsign != '\0') { + bzId = start; + bzId = bzId.substr(end - start); + if ((bzId.size() > 0) && (strlen(callsign) > 0)) { + bzIdInfo = true; + } + } + } + } + + if (bzIdInfo == true) { + DEBUG3("Got BZID: %s", base); + for (int i = 0; i < curMaxPlayers; i++) { + GameKeeper::Player* gkp = GameKeeper::Player::getPlayerByIndex(i); + if ((gkp != NULL) && + (strcasecmp(gkp->player.getCallSign(), callsign) == 0)) { + gkp->setBzIdentifier(bzId); + DEBUG3("Set player (%s [%i]) bzId to (%s)\n", callsign, i, bzId.c_str()); + break; + } + } + } +*/ if (authReply) { DEBUG3("Got: %s", base); char *group; @@ -208,11 +275,13 @@ } } else { playerData->_LSAState = GameKeeper::Player::notRequired; + if (!playerData->player.isBot()) { sendMessage(ServerPlayer, playerIndex, "This callsign is not registered."); sendMessage(ServerPlayer, playerIndex, "You can register it at http://my.bzflag.org/bb/"); } + } playerData->player.clearToken(); } } @@ -227,7 +296,7 @@ continue; if (playerData->_LSAState != GameKeeper::Player::checking) continue; - playerData->_LSAState = GameKeeper::Player::timed; + playerData->_LSAState = GameKeeper::Player::timedOut; } if (nextMessageType != ListServerLink::NONE) { // There was a pending request arrived after we write: Index: Permissions.cxx =================================================================== RCS file: /cvsroot/bzflag/bzflag/src/bzfs/Permissions.cxx,v retrieving revision 2.33 retrieving revision 2.34 diff -w -u -r2.33 -r2.34 --- Permissions.cxx 20 Oct 2005 13:54:43 -0000 2.33 +++ Permissions.cxx 23 Nov 2005 01:34:58 -0000 2.34 @@ -362,6 +362,7 @@ case PlayerAccessInfo::date: return "date"; case PlayerAccessInfo::endGame: return "endGame"; case PlayerAccessInfo::flagHistory: return "flagHistory"; + case PlayerAccessInfo::flagMaster: return "flagMaster"; case PlayerAccessInfo::flagMod: return "flagMod"; case PlayerAccessInfo::hideAdmin: return "hideAdmin"; case PlayerAccessInfo::idleStats: return "idleStats"; @@ -426,6 +427,7 @@ if (name == "DATE") return PlayerAccessInfo::date; if (name == "ENDGAME") return PlayerAccessInfo::endGame; if (name == "FLAGHISTORY") return PlayerAccessInfo::flagHistory; + if (name == "FLAGMASTER") return PlayerAccessInfo::flagMaster; if (name == "FLAGMOD") return PlayerAccessInfo::flagMod; if (name == "HIDEADMIN") return PlayerAccessInfo::hideAdmin; if (name == "IDLESTATS") return PlayerAccessInfo::idleStats; Index: Permissions.h =================================================================== RCS file: /cvsroot/bzflag/bzflag/src/bzfs/Permissions.h,v retrieving revision 2.19 retrieving revision 2.20 diff -w -u -r2.19 -r2.20 --- Permissions.h 20 Oct 2005 05:08:01 -0000 2.19 +++ Permissions.h 23 Nov 2005 01:34:58 -0000 2.20 @@ -59,6 +59,7 @@ date, endGame, flagHistory, + flagMaster, flagMod, hideAdmin, idleStats, Index: bzfs.cxx =================================================================== RCS file: /cvsroot/bzflag/bzflag/src/bzfs/bzfs.cxx,v retrieving revision 2.216 retrieving revision 2.217 diff -w -u -r2.216 -r2.217 --- bzfs.cxx 20 Nov 2005 22:59:49 -0000 2.216 +++ bzfs.cxx 23 Nov 2005 01:34:58 -0000 2.217 @@ -1423,7 +1423,7 @@ return; } - if (!resultEnter) + if (!resultEnter) { // Find the user already logged on and kick it. The new player // has been globally authenticated. for (int i = 0; i < curMaxPlayers; i++) { @@ -1444,6 +1444,7 @@ break; } } + } if (clOptions->filterCallsigns) { int filterIndex = 0; @@ -1454,12 +1455,13 @@ } } - // check against ban lists - playerData->setNeedThisHostbanChecked(true); - bool playerIsAntiBanned = playerData->accessInfo.hasPerm(PlayerAccessInfo::antiban); + const bool playerIsAntiBanned = + playerData->accessInfo.hasPerm(PlayerAccessInfo::antiban); + + // check against the ip ban list in_addr playerIP = playerData->netHandler->getIPAddress(); BanInfo info(playerIP); - if (!clOptions->acl.validate(playerIP,&info) && !playerIsAntiBanned) { + if (!playerIsAntiBanned && !clOptions->acl.validate(playerIP,&info)) { std::string rejectionMessage; rejectionMessage = BanRefusalString; @@ -1483,8 +1485,38 @@ return; } - // see if any watchers don't want this guy + // check against the id ban list + const std::string& bzid = playerData->getBzIdentifier(); + IdBanInfo idInfo(""); + if (!playerIsAntiBanned && !clOptions->acl.idValidate(bzid.c_str(), &idInfo)) { + std::string rejectionMessage; + + rejectionMessage = BanRefusalString; + ... [truncated message content] |