From b3526b5ee282728e6a438ddd79d5222d23554252 Mon Sep 17 00:00:00 2001 From: calzoneman Date: Sun, 18 Aug 2013 17:58:16 -0500 Subject: [PATCH] Revisit some banning issues --- channel.js | 62 +++++++++++++++++------------------- database.js | 89 ++++++++++++++++++++++++++++++++++++++++++++-------- utilities.js | 10 ++++++ 3 files changed, 115 insertions(+), 46 deletions(-) diff --git a/channel.js b/channel.js index 1d53a34b..2639c6fc 100644 --- a/channel.js +++ b/channel.js @@ -20,6 +20,7 @@ var ChatCommand = require("./chatcommand.js"); var Filter = require("./filter.js").Filter; var Playlist = require("./playlist"); var sanitize = require("validator").sanitize; +var $util = require("./utilities"); var Channel = function(name, Server) { var self = this; @@ -307,8 +308,11 @@ Channel.prototype.readLog = function (filterIp, callback) { rs.on("end", function () { if(filterIp) { buffer = buffer.replace( - /(\d{1,3}\.){2}(\d{1,3})\.(\d{1,3})/g, - "x.x.$2.$3" + /\d+\.\d+\.(\d+\.\d+)/, + "x.x.$1" + ).replace( + /\d+\.\d+\.(\d+)/, + "x.x.$1.*" ); } @@ -456,10 +460,9 @@ Channel.prototype.saveRank = function (user, callback) { Channel.prototype.getIPRank = function (ip, callback) { var self = this; - var names = []; - var next = function (names) { - self.server.db.getChannelRank(self.name, names, - function (err, res) { + self.server.db.listAliases(ip, function (err, names) { + self.server.db.listChannelUserRanks(self.name, names, + function (err, res) { if(err) { callback(err, null); return; @@ -467,30 +470,23 @@ Channel.prototype.getIPRank = function (ip, callback) { var rank = 0; for(var i in res) { - rank = (res[i].rank > rank) ? res[i].rank : rank; + rank = (res[i] > rank) ? res[i] : rank; } - callback(null, rank); - }); - }; - if(ip in self.ip_alias) { - names = self.ip_alias[ip]; - next(names); - } else if(ip.match(/^(\d+)\.(\d+)\.(\d+)$/)) { - // Range - for(var ip2 in self.ip_alias) { - if(ip2.indexOf(ip) == 0) { - for(var i in self.ip_aliases[ip2]) - names.push(self.ip_aliases[ip2][i]); - } - } - next(names); - } else { - self.server.db.listAliases(ip, function (err, names) { - self.ip_alias[ip] = names; - next(names); + self.server.db.listGlobalRanks(names, function (err, res) { + if(err) { + callback(err, null); + return; + } + + for(var i in res) { + rank = (res[i] > rank) ? res[i] : rank; + } + + callback(null, rank); + }); }); - } + }); } Channel.prototype.cacheMedia = function(media) { @@ -516,7 +512,7 @@ Channel.prototype.tryNameBan = function(actor, name) { self.getRank(name, function (err, rank) { if(err) { actor.socket.emit("errorMsg", { - msg: "Internal error" + msg: "Internal error " + err }); return; } @@ -577,7 +573,7 @@ Channel.prototype.tryIPBan = function(actor, name, range) { self.server.db.listIPsForName(name, function (err, ips) { if(err) { actor.socket.emit("errorMsg", { - msg: "Internal error" + msg: "Internal error: " + err }); return; } @@ -594,8 +590,8 @@ Channel.prototype.tryIPBan = function(actor, name, range) { if(rank >= actor.rank) { actor.socket.emit("errorMsg", { - msg: "You don't have permission to ban IP: x.x." + - ip.replace(/\d+\.\d+\.(\d+\.\d+)/, "$1") + msg: "You don't have permission to ban IP: " + + $util.maskIP(ip) }); return; } @@ -807,7 +803,7 @@ Channel.prototype.sendBanlist = function(user) { var ip_hidden = this.hideIP(ip); var disp = ip; if(user.rank < Rank.Siteadmin) { - disp = "x.x." + ip.replace(/\d+\.\d+\.(\d+\.\d+)/, "$1"); + disp = $util.maskIP(ip); } ents.push({ ip_displayed: disp, @@ -1032,7 +1028,7 @@ Channel.prototype.broadcastBanlist = function() { var name = this.ipbans[ip][0]; var ip_hidden = this.hideIP(ip); ents.push({ - ip_displayed: "x.x." + ip.replace(/\d+\.\d+\.(\d+\.\d+)/, "$1"), + ip_displayed: $util.maskIP(ip), ip_hidden: ip_hidden, name: name, aliases: this.ip_alias[ip] || [], diff --git a/database.js b/database.js index 74af84c0..c965d4e4 100644 --- a/database.js +++ b/database.js @@ -468,7 +468,35 @@ Database.prototype.dropChannel = function (name, callback) { }); }; -Database.prototype.getChannelRank = function (channame, names, callback) { +Database.prototype.getChannelRank = function (channame, name, callback) { + var self = this; + if(typeof callback !== "function") + return; + + if(!$util.isValidChannelName(channame)) { + callback("Invalid channel name", null); + return; + } + + var query = "SELECT name, rank FROM `chan_" + channame + "_ranks`" + + "WHERE name=?"; + + self.query(query, [name], function (err, res) { + if(err) { + Logger.errlog.log("! Failed to lookup " + channame + " ranks"); + callback(err, null); + return; + } + + if(res.length == 0) + callback(null, 0); + else + callback(null, res[0].rank); + }); +}; + +Database.prototype.listChannelUserRanks = function (channame, names, + callback) { var self = this; if(typeof callback !== "function") return; @@ -493,20 +521,12 @@ Database.prototype.getChannelRank = function (channame, names, callback) { self.query(query, names, function (err, res) { if(err) { Logger.errlog.log("! Failed to lookup " + channame + " ranks"); - if(names.length == 1) - callback(err, 0); - else - callback(err, []); + callback(err, null); return; } - if(names.length == 1) { - if(res.length == 0) - callback(null, 0); - else - callback(null, res[0].rank); - return; - } + for(var i in res) + res[i] = res[i].rank; callback(null, res); }); @@ -898,6 +918,7 @@ Database.prototype.getGlobalRank = function (name, callback) { return; var query = "SELECT global_rank FROM registrations WHERE uname=?"; + self.query(query, [name], function (err, res) { if(err) { callback(err, null); @@ -913,6 +934,40 @@ Database.prototype.getGlobalRank = function (name, callback) { }); }; +Database.prototype.listGlobalRanks = function (names, callback) { + var self = this; + if(typeof callback !== "function") + return; + + if(typeof names === "string") + names = [names]; + + // Build the query template (?, ?, ?, ?, ...) + var nlist = []; + for(var i in names) + nlist.push("?"); + nlist = "(" + nlist.join(",") + ")"; + + var query = "SELECT global_rank FROM registrations WHERE uname IN " + + nlist; + self.query(query, names, function (err, res) { + if(err) { + callback(err, null); + return; + } + + if(res.length == 0) { + callback("User does not exist", null); + return; + } + + for(var i in res) + res[i] = res[i].global_rank; + + callback(null, res); + }); +}; + /* END REGION */ /* REGION users */ @@ -1224,7 +1279,15 @@ Database.prototype.listAliases = function (ip, callback) { if(typeof callback !== "function") return; - var query = "SELECT name FROM aliases WHERE ip=?"; + var query = "SELECT name FROM aliases WHERE ip"; + // Range + if(ip.match(/^\d+\.\d+\.\d+$/)) { + query += " LIKE ?"; + ip += ".%"; + } else { + query += "=?"; + } + self.query(query, [ip], function (err, res) { var names = null; if(!err) { diff --git a/utilities.js b/utilities.js index 42d04df5..0e401cb4 100644 --- a/utilities.js +++ b/utilities.js @@ -15,5 +15,15 @@ module.exports = { salt.push(chars[parseInt(Math.random()*chars.length)]); } return salt.join(''); + }, + + maskIP: function (ip) { + if(ip.match(/^\d+\.\d+\.\d+\.\d+$/)) { + // standard 32 bit IP + return ip.replace(/\d+\.\d+\.(\d+\.\d+)/, "x.x.$1"); + } else if(ip.match(/^\d+\.\d+\.\d+/)) { + // /24 range + return ip.replace(/\d+\.\d+\.(\d+)/, "x.x.$1.*"); + } } };