Deserialise session store using ruby child process

This commit is contained in:
Chris Blanchard 2015-09-15 14:25:00 +01:00
parent 6e00b38707
commit 9583ca688b
3 changed files with 59 additions and 34 deletions

View file

@ -22,6 +22,14 @@ var assignRandomUser = (socket, next) => {
}); });
}; };
var handleFailedAuth = (socket, next) => {
if (process.env.RANDOM_USER) {
return assignRandomUser(socket, next);
} else {
return next(new Error("Authentication Failed"));
}
};
module.exports = io => { module.exports = io => {
var rootNamespace = io.of('/') var rootNamespace = io.of('/')
@ -29,28 +37,28 @@ module.exports = io => {
io.use((socket, next) => { io.use((socket, next) => {
let cookies = parseCookies(socket); let cookies = parseCookies(socket);
let session; if (!cookies) {
if (cookies) { return handleFailedAuth(socket, next);
session = EnslClient.decodeSession(cookies[config.session_store_name]);
} }
if (!session || typeof session.user !== 'number') { let session = cookies[config.session_store_name];
if (process.env.RANDOM_USER) {
return assignRandomUser(socket, next); if (!session) {
} else { return handleFailedAuth(socket, next);
return next(new Error("Authentication Failed"));
}
} }
User.find(session.user, (error, user) => { EnslClient.decodeSession(session, function (error, userId) {
if (error) { if (error) return handleFailedAuth(socket, next);
winston.error(error); User.find(userId, (error, user) => {
return next(new Error("Authentication failed")); if (error) {
} winston.error(error);
socket._user = user; return next(new Error("Authentication failed"));
if (socket._user.bans.gather) return next(new Error("Gather Banned")); }
winston.info("Logged in:", user.username, user.id); socket._user = user;
return next(); if (socket._user.bans.gather) return next(new Error("Gather Banned"));
winston.info("Logged in:", user.username, user.id);
return next();
});
}); });
}); });

View file

@ -4,7 +4,6 @@ var path = require("path");
var crypto = require("crypto"); var crypto = require("crypto");
var request = require("request"); var request = require("request");
var logger = require("winston"); var logger = require("winston");
var Marshal = require("marsha");
var querystring = require('querystring'); var querystring = require('querystring');
var config = require(path.join(__dirname, "../../config/config")); var config = require(path.join(__dirname, "../../config/config"));
const SECRET_TOKEN = config.secret_token; const SECRET_TOKEN = config.secret_token;
@ -79,31 +78,36 @@ EnslClient.parseCookies = (socket) => {
return cookies; return cookies;
}; };
EnslClient.decodeSession = sessionCookie => { EnslClient.decodeSession = (sessionCookie, callback) => {
if (typeof sessionCookie !== 'string') return null; if (typeof sessionCookie !== 'string') {
return callback(new Error("Invalid cookie"), null);
}
var session = sessionCookie.split("--"); var session = sessionCookie.split("--");
if (session.length !== 2) return null; if (session.length !== 2) {
return callback(new Error("Invalid cookie: No signature provided"), null);
}
// Separate text and signature // Separate text and signature
var text = querystring.unescape(session[0]); var text = querystring.unescape(session[0]);
var signature = session[1]; var signature = session[1];
// Verify signature // Verify signature
if (crypto.createHmac("sha1", SECRET_TOKEN).update(text).digest('hex') !== signature) return null; if (crypto.createHmac("sha1", SECRET_TOKEN).update(text).digest('hex') !== signature) {
return callback(new Error("Invalid cookie signature"), null);
childProcess('ruby -e "puts \'Hello World!\'"', function (err, stdout, stderr) {
console.log(stdout);
});
var parsedSession;
try {
parsedSession = Marshal.load(text, 'base64');
} catch (e) {
logger.error(e);
} }
return parsedSession || null; var cb = callback;
childProcess("ruby unmarshal.rb " + text, {
cwd: path.join(__dirname, "../../scripts")
}, function (err, stdout, stderr) {
var userId = parseInt(stdout, 10);
if (isNaN(userId)) {
return callback(new Error("Invalid cookie: User ID not found"), null);
} else {
return callback(null, userId);
}
});
}; };
module.exports = EnslClient; module.exports = EnslClient;

13
scripts/unmarshal.rb Normal file
View file

@ -0,0 +1,13 @@
# Reads in raw Rails 3 session store, returns user id
require 'base64'
session_store = ARGV[0]
deserialised_store = Marshal.load(Base64.decode64(session_store))
user_id = deserialised_store['user']
STDOUT.write user_id
exit 0