From feabf3571462c41a88ede2a5846a5aa75b5e8a8f Mon Sep 17 00:00:00 2001 From: calzoneman Date: Wed, 22 Jan 2014 21:12:43 -0600 Subject: [PATCH] Work on SIO and SSL --- lib/io/ioserver.js | 3 - lib/server.js | 77 +--------------------- lib/web/account.js | 12 ++++ lib/web/auth.js | 8 +++ lib/web/webserver.js | 141 +++++++++++++++++++++++++++++------------ templates/channel.jade | 30 ++++----- 6 files changed, 138 insertions(+), 133 deletions(-) diff --git a/lib/io/ioserver.js b/lib/io/ioserver.js index a66dd1b4..06660781 100644 --- a/lib/io/ioserver.js +++ b/lib/io/ioserver.js @@ -27,13 +27,10 @@ function handleAuth(data, accept) { var auth = data.cookie.auth; db.users.verifyAuth(auth, function (err, user) { if (!err) { - console.log('VERIFIED: ' + user.name + ' => ' + user.global_rank); data.user = { name: user.name, global_rank: user.global_rank }; - } else { - console.log('Auth fail: ' + err); } accept(null, true); }); diff --git a/lib/server.js b/lib/server.js index 57f3f3f2..6d6ff253 100644 --- a/lib/server.js +++ b/lib/server.js @@ -83,74 +83,6 @@ var Server = function () { root: path.join(__dirname, "../www") }); }); - /* - self.express.use(express.urlencoded()); - self.express.use(express.json()); - self.express.use(express.cookieParser()); - - // channel route - self.express.get("/r/:channel(*)", function (req, res, next) { - var c = req.params.channel; - if (!$util.isValidChannelName(c)) { - res.redirect("/" + c); - return; - } - - self.logHTTP(req); - res.sendfile("channel.html", { - root: path.join(__dirname, "../www") - }); - }); - - // api route - self.api = require("./api")(self); - - // index - self.express.get("/", function (req, res, next) { - self.logHTTP(req); - res.sendfile("index.html", { - root: path.join(__dirname, "../www") - }); - }); - - // default route - self.express.get("/:thing(*)", function (req, res, next) { - var opts = { - root: path.join(__dirname, "../www"), - maxAge: self.cfg["asset-cache-ttl"] - }; - - res.sendfile(req.params.thing, opts, function (e) { - if (e) { - self.logHTTP(req, e.status); - if (req.params.thing.match(/\.\.|(%25)?%2e(%25)?%2e/)) { - res.send("Don't try that again."); - Logger.syslog.log("WARNING: Attempted path traversal "+ - "from IP " + self.getHTTPIP(req)); - Logger.syslog.log("Path was: " + req.url); - ActionLog.record(self.getHTTPIP(req), "", - "path-traversal", - req.url); - } else if (e.status >= 500) { - Logger.errlog.log(err); - } - res.send(e.status); - } else { - self.logHTTP(req); - } - }); - }); - - // fallback route - self.express.use(function (err, req, res, next) { - self.logHTTP(req, err.status); - if (err.status === 404) { - res.send(404); - } else { - next(err); - } - }); - */ // http/https/sio server init ----------------------------------------- if (Config.get("https.enabled")) { @@ -170,14 +102,7 @@ var Server = function () { self.http = self.express.listen(Config.get("http.port"), Config.get("http.host") || undefined); - /* - self.ioWeb = express().listen(self.cfg["io-port"], self.cfg["io-host"]); - self.io = require("socket.io").listen(self.ioWeb); - self.io.set("log level", 1); - self.io.sockets.on("connection", function (sock) { - self.handleSocketConnection(sock); - }); - */ + require("./io/ioserver").init(self); // background tasks init ---------------------------------------------- diff --git a/lib/web/account.js b/lib/web/account.js index 2d2c803f..5591409c 100644 --- a/lib/web/account.js +++ b/lib/web/account.js @@ -16,6 +16,10 @@ var $util = require('../utilities'); * Handles a GET request for /account/edit */ function handleAccountEditPage(req, res) { + if (webserver.redirectHttps(req, res)) { + return; + } + logRequest(req); var loginName = false; if (req.cookies.auth) { @@ -167,6 +171,10 @@ function handleChangeEmail(req, res) { * Handles a GET request for /account/channels */ function handleAccountChannelPage(req, res) { + if (webserver.redirectHttps(req, res)) { + return; + } + logRequest(req); var loginName = false; if (req.cookies.auth) { @@ -315,6 +323,10 @@ function handleDeleteChannel(req, res) { * Handles a GET request for /account/profile */ function handleAccountProfilePage(req, res) { + if (webserver.redirectHttps(req, res)) { + return; + } + logRequest(req); var loginName = false; diff --git a/lib/web/auth.js b/lib/web/auth.js index 3a12cbe5..cbb0a342 100644 --- a/lib/web/auth.js +++ b/lib/web/auth.js @@ -73,6 +73,10 @@ function handleLogin(req, res) { * Handles a GET request for /login */ function handleLoginPage(req, res) { + if (webserver.redirectHttps(req, res)) { + return; + } + if (req.cookies.auth) { var split = req.cookies.auth.split(":"); if (split.length === 2) { @@ -120,6 +124,10 @@ function handleLogout(req, res) { * Handles a GET request for /register */ function handleRegisterPage(req, res) { + if (webserver.redirectHttps(req, res)) { + return; + } + if (req.cookies.auth) { var split = req.cookies.auth.split(":"); if (split.length === 2) { diff --git a/lib/web/webserver.js b/lib/web/webserver.js index 74858ce4..a72d96d6 100644 --- a/lib/web/webserver.js +++ b/lib/web/webserver.js @@ -4,16 +4,17 @@ * @author Calvin Montgomery */ -var path = require('path'); -var net = require('net'); -var express = require('express'); -var webroot = path.join(__dirname, '..', 'www'); -var sendJade = require('./jade').sendJade; -var Server = require('../server'); -var $util = require('../utilities'); -var Logger = require('../logger'); +var path = require("path"); +var net = require("net"); +var express = require("express"); +var webroot = path.join(__dirname, "..", "www"); +var sendJade = require("./jade").sendJade; +var Server = require("../server"); +var $util = require("../utilities"); +var Logger = require("../logger"); +var Config = require("../config"); -var httplog = new Logger.Logger(path.join(__dirname, '..', '..', 'http.log')); +var httplog = new Logger.Logger(path.join(__dirname, "..", "..", "http.log")); var suspiciousPath = (/admin|adm|\.\.|\/etc\/passwd|\\x5c|%5c|0x5c|setup|install|php|pma|blog|sql|scripts|aspx?|database/ig); /** @@ -21,8 +22,8 @@ var suspiciousPath = (/admin|adm|\.\.|\/etc\/passwd|\\x5c|%5c|0x5c|setup|install */ function isSuspicious(req) { // ZmEu is a penetration script - if (req.header('user-agent') && - req.header('user-agent').toLowerCase() === 'zmeu') { + if (req.header("user-agent") && + req.header("user-agent").toLowerCase() === "zmeu") { return true; } @@ -38,9 +39,9 @@ function isSuspicious(req) { */ function ipForRequest(req) { var ip = req.ip; - if (ip === '127.0.0.1' || ip === '::1') { - var xforward = req.header('x-forwarded-for'); - if (typeof xforward !== 'string' || !net.isIP(xforward)) { + if (ip === "127.0.0.1" || ip === "::1") { + var xforward = req.header("x-forwarded-for"); + if (typeof xforward !== "string" || !net.isIP(xforward)) { return ip; } else { return xforward; @@ -61,34 +62,72 @@ function logRequest(req, status) { ipForRequest(req), req.route.method.toUpperCase(), req.path, - status, - req.header('user-agent') - ].join(' ')); + req.header("user-agent") + ].join(" ")); +} + +/** + * Redirects a request to HTTPS if the server supports it + */ +function redirectHttps(req, res) { + if (!req.secure && Config.get("https.enabled")) { + var ssldomain = Config.get("https.domain"); + var port = Config.get("https.port"); + if (port !== 443) { + ssldomain += ":" + port; + } + res.redirect(ssldomain + req.path); + return true; + } + return false; +} + +/** + * Redirects a request to HTTP if the server supports it + */ +function redirectHttp(req, res) { + if (req.secure) { + var domain = Config.get("http.domain"); + var port = Config.get("http.port"); + if (port !== 80) { + domain += ":" + port; + } + console.log(domain); + res.redirect(domain + req.path); + return true; + } + return false; } /** * Handles a GET request for /r/:channel - serves channel.html */ function handleChannel(req, res) { + if (redirectHttp(req, res)) { + return; + } + if (!$util.isValidChannelName(req.params.channel)) { logRequest(req, 404); res.status(404); - res.send('Invalid channel name "' + req.params.channel + '"'); + res.send("Invalid channel name '" + req.params.channel + "'"); return; } + logRequest(req); + var loginName = false; if (req.cookies.auth) { - loginName = req.cookies.auth.split(':')[0]; + loginName = req.cookies.auth.split(":")[0]; } - var inst = Server.getServer(); - var iourl = ''; - sendJade(res, 'channel', { + + var iourl = ""; + sendJade(res, "channel", { channelName: req.params.channel, - layout: 'hd', loggedIn: loginName !== false, loginName: loginName, - /*ioUrl: 'http://' + inst.config.sio.domain + ':' + inst.config.sio.port*/ + sioSource: Config.get("http.domain") + ":" + Config.get("io.port") + + "/socket.io/socket.io.js" }); } @@ -97,18 +136,37 @@ function handleChannel(req, res) { */ function handleIndex(req, res) { logRequest(req); + var loginName = false; if (req.cookies.auth) { - loginName = req.cookies.auth.split(':')[0]; + loginName = req.cookies.auth.split(":")[0]; } - sendJade(res, 'index', { + sendJade(res, "index", { loggedIn: loginName !== false, loginName: loginName, channels: Server.getServer().packChannelList(true) }); } +/** + * Handles a request for the socket.io information + */ +function handleSocketConfig(req, res) { + logRequest(req); + + res.type("application/javascript"); + + var io_url = Config.get("http.domain") + ":" + Config.get("io.port"); + var web_url = Config.get("http.domain") + ":" + Config.get("http.port"); + var ssl_url = Config.get("https.domain") + ":" + Config.get("https.port"); + res.send("var IO_URL='"+io_url+"',WEB_URL='"+web_url+"',SSL_URL='" + ssl_url + + "',ALLOW_SSL="+Config.get("https.enabled")+";" + + (Config.get("https.enabled") ? + "if(location.protocol=='https:'||USEROPTS.secure_connection){" + + "IO_URL=WEB_URL=SSL_URL;}" : "")); +} + module.exports = { /** * Initializes webserver callbacks @@ -122,33 +180,38 @@ module.exports = { /* Order here is important * Since I placed /r/:channel above *, the function will * not apply to the /r/:channel route. This prevents - * duplicate logging, since /r/:channel's callback does + * duplicate logging, since /r/:channel"s callback does * its own logging */ - app.get('/r/:channel', handleChannel); - app.get('/', handleIndex); - app.all('*', function (req, res, next) { + app.get("/r/:channel", handleChannel); + app.get("/", handleIndex); + app.get("/sioconfig", handleSocketConfig); + app.all("*", function (req, res, next) { if (isSuspicious(req)) { logRequest(req, 403); res.status(403); - if (req.header('user-agent').toLowerCase() === 'zmeu') { - res.send('This server disallows requests from ZmEu.'); + if (req.header("user-agent").toLowerCase() === "zmeu") { + res.send("This server disallows requests from ZmEu."); } else { - res.send('The request ' + req.route.method.toUpperCase() + ' ' + - req.path + ' looks pretty fishy to me. Double check that ' + - 'you typed it correctly.'); + res.send("The request " + req.route.method.toUpperCase() + " " + + req.path + " looks pretty fishy to me. Double check that " + + "you typed it correctly."); } return; } logRequest(req); next(); }); - app.use(express.static('www')); - require('./auth').init(app); - require('./account').init(app); + app.use(express.static("www")); + require("./auth").init(app); + require("./account").init(app); }, logRequest: logRequest, - ipForRequest: ipForRequest + ipForRequest: ipForRequest, + + redirectHttps: redirectHttps, + + redirectHttp: redirectHttp }; diff --git a/templates/channel.jade b/templates/channel.jade index 691cf28f..e82a4e09 100644 --- a/templates/channel.jade +++ b/templates/channel.jade @@ -155,18 +155,18 @@ html(lang="en") ul.nav.nav-tabs li: a(href="#cs-miscoptions", data-toggle="tab") General Settings li: a(href="#cs-adminoptions", data-toggle="tab") Admin Settings - li: a(href="#cs-chanlog", data-toggle="tab", onclick="javascript:socket.emit('readChanLog')") Channel Log - li: a(href="#cs-chatfilters", data-toggle="tab", onclick="javascript:socket.emit('requestChatFilters')") Chat Filters li.dropdown a#cs-edit-dd-toggle(href="#", data-toggle="dropdown") Edit span.caret ul.dropdown-menu - li: a(href="#cs-motdeditor", data-toggle="tab", tabindex="-1") Edit MOTD - li: a(href="#cs-csseditor", data-toggle="tab", tabindex="-1") Edit CSS - li: a(href="#cs-jseditor", data-toggle="tab", tabindex="-1") Edit Javascript - li: a(href="#cs-permedit", data-toggle="tab", tabindex="-1") Edit Permissions - li: a(href="#cs-chanranks", data-toggle="tab", tabindex="-1", onclick="javascript:socket.emit('requestChannelRanks')") Edit moderators + li: a(href="#cs-chatfilters", data-toggle="tab", onclick="javascript:socket.emit('requestChatFilters')") Chat Filters + li: a(href="#cs-motdeditor", data-toggle="tab", tabindex="-1") MOTD + li: a(href="#cs-csseditor", data-toggle="tab", tabindex="-1") CSS + li: a(href="#cs-jseditor", data-toggle="tab", tabindex="-1") Javascript + li: a(href="#cs-permedit", data-toggle="tab", tabindex="-1") Permissions + li: a(href="#cs-chanranks", data-toggle="tab", tabindex="-1", onclick="javascript:socket.emit('requestChannelRanks')") Moderators li: a(href="#cs-banlist", data-toggle="tab", tabindex="-1", onclick="javascript:socket.emit('requestBanlist')") Ban list + li: a(href="#cs-chanlog", data-toggle="tab", onclick="javascript:socket.emit('readChanLog')") Log .modal-body .tab-content include channeloptions @@ -185,17 +185,17 @@ html(lang="en") button.btn.btn-default(type="button", data-dismiss="modal") Close include footer mixin footer() - script(src="/assets/js/iourl.js") - //script(src="#{ioUrl}/socket.io/socket.io.js") - //script(type="text/javascript"). - // var IOSERVER = "#{ioUrl}"; - // var SOCKET = io.connect(IOSERVER); - // $('#channeloptions').modal(); - // $('#channeloptions a[href="#cs-miscoptions"]').tab('show'); + script(src=sioSource) + script(src="/sioconfig") script(src="/assets/js/data.js") script(src="/assets/js/util.js") script(src="/assets/js/player.js") script(src="/assets/js/paginator.js") script(src="/assets/js/ui.js") script(src="/assets/js/callbacks.js") - script(src="https://www.youtube.com/iframe_api") + script(defer, src="https://www.youtube.com/iframe_api") + script(defer, src="//api.dmcdn.net/all.js") + script(defer, src="/assets/js/jwplayer.js") + script(defer, src="/assets/js/sc.js") + script(defer, src="/assets/js/froogaloop.min.js") + script(defer, src="/assets/js/swf.js")