From 3ff34f50d1bebb01985bf9bab19e51e03a9ade0e Mon Sep 17 00:00:00 2001 From: Peter 'Pita' Martischka Date: Tue, 16 Aug 2011 15:53:09 +0100 Subject: [PATCH] added a security control at socketiorouter, pad security is now fully enforced --- node/handler/SocketIORouter.js | 84 ++++++++++++++++++++++++++++------ node/server.js | 3 +- static/timeslider.html | 9 ++++ 3 files changed, 82 insertions(+), 14 deletions(-) diff --git a/node/handler/SocketIORouter.js b/node/handler/SocketIORouter.js index 08448f7c..2d8f4f44 100644 --- a/node/handler/SocketIORouter.js +++ b/node/handler/SocketIORouter.js @@ -21,6 +21,7 @@ var log4js = require('log4js'); var messageLogger = log4js.getLogger("message"); +var securityManager = require("../db/SecurityManager"); /** * Saves all components @@ -53,11 +54,13 @@ exports.setSocketIO = function(_socket) socket.sockets.on('connection', function(client) { + var clientAuthorized = false; + //wrap the original send function to log the messages client._send = client.send; client.send = function(message) { - messageLogger.info("to " + client.id + ": " + JSON.stringify(message)); + messageLogger.info("to " + client.id + ": " + stringifyWithoutPassword(message)); client._send(message); } @@ -67,34 +70,72 @@ exports.setSocketIO = function(_socket) components[i].handleConnect(client); } - client.on('message', function(message) + //try to handle the message of this client + function handleMessage(message) { - if(message.protocolVersion && message.protocolVersion != 2) - { - messageLogger.warn("Protocolversion header is not correct:" + JSON.stringify(message)); - return; - } - - //route this message to the correct component, if possible if(message.component && components[message.component]) { - messageLogger.info("from " + client.id + ": " + JSON.stringify(message)); - //check if component is registered in the components array if(components[message.component]) { + messageLogger.info("from " + client.id + ": " + stringifyWithoutPassword(message)); components[message.component].handleMessage(client, message); } } else { - messageLogger.error("Can't route the message:" + JSON.stringify(message)); + messageLogger.error("Can't route the message:" + stringifyWithoutPassword(message)); + } + } + + client.on('message', function(message) + { + if(message.protocolVersion && message.protocolVersion != 2) + { + messageLogger.warn("Protocolversion header is not correct:" + stringifyWithoutPassword(message)); + return; + } + + //client is authorized, everything ok + if(clientAuthorized) + { + handleMessage(message); + } + //try to authorize the client + else + { + //this message has everything to try an authorization + if(message.padId !== undefined && message.sessionID !== undefined && message.token !== undefined && message.password !== undefined) + { + securityManager.checkAccess (message.padId, message.sessionID, message.token, message.password, function(err, statusObject) + { + if(err) throw err; + + //access was granted, mark the client as authorized and handle the message + if(statusObject.accessStatus == "grant") + { + clientAuthorized = true; + handleMessage(message); + } + //no access, send the client a message that tell him why + else + { + messageLogger.warn("Authentication try failed:" + stringifyWithoutPassword(message)); + client.json.send({accessStatus: statusObject.accessStatus}); + } + }); + } + //drop message + else + { + messageLogger.warn("Droped message cause of bad permissions:" + stringifyWithoutPassword(message)); + } } }); client.on('disconnect', function() { - //tell all components about this disconnect + //tell all components about this disconnect for(var i in components) { components[i].handleDisconnect(client); @@ -102,3 +143,20 @@ exports.setSocketIO = function(_socket) }); }); } + +//returns a stringified representation of a message, removes the password +//this ensures there are no passwords in the log +function stringifyWithoutPassword(message) +{ + var newMessage = {}; + + for(var i in message) + { + if(i == "password" && message[i] != null) + newMessage["password"] = "xxx"; + else + newMessage[i]=message[i]; + } + + return JSON.stringify(newMessage); +} diff --git a/node/server.js b/node/server.js index 028d5c2f..fa7796d5 100644 --- a/node/server.js +++ b/node/server.js @@ -26,7 +26,6 @@ var log4js = require('log4js'); var socketio = require('socket.io'); var fs = require('fs'); var settings = require('./utils/Settings'); -var socketIORouter = require("./handler/SocketIORouter"); var db = require('./db/DB'); var async = require('async'); var express = require('express'); @@ -40,6 +39,7 @@ var exporthtml; var readOnlyManager; var padManager; var securityManager; +var socketIORouter; //try to get the git version var version = ""; @@ -80,6 +80,7 @@ async.waterfall([ apiHandler = require('./handler/APIHandler'); padManager = require('./db/PadManager'); securityManager = require('./db/SecurityManager'); + socketIORouter = require("./handler/SocketIORouter"); //install logging var httpLogger = log4js.getLogger("http"); diff --git a/static/timeslider.html b/static/timeslider.html index 110b6d12..5282972d 100644 --- a/static/timeslider.html +++ b/static/timeslider.html @@ -105,17 +105,26 @@ { changesetLoader.handleSocketResponse(message); } + else if(message.accessStatus) + { + $("body").html("

You have no permission to access this pad

") + } }); }); //sends a message over the socket function sendSocketMsg(type, data) { + var sessionID = readCookie("sessionID"); + var password = readCookie("password"); + var msg = { "component" : "timeslider", "type": type, "data": data, "padId": padId, "token": token, + "sessionID": sessionID, + "password": password, "protocolVersion": 2}; socket.json.send(msg);