Skip to content

Commit 67b4eb9

Browse files
committed
Making ID generation securely random
1 parent fe6dd87 commit 67b4eb9

File tree

2 files changed

+92
-6
lines changed

2 files changed

+92
-6
lines changed

lib/manager.js

+12-6
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
var fs = require('fs')
1212
, url = require('url')
1313
, tty = require('tty')
14+
, crypto = require('crypto')
1415
, util = require('./util')
1516
, store = require('./store')
1617
, client = require('socket.io-client')
@@ -139,6 +140,8 @@ function Manager (server, options) {
139140
self.emit('connection', conn);
140141
});
141142

143+
this.sequenceNumber = Date.now() | 0;
144+
142145
this.log.info('socket.io started');
143146
};
144147

@@ -702,9 +705,12 @@ Manager.prototype.handleClient = function (data, req) {
702705
* @api private
703706
*/
704707

705-
Manager.prototype.generateId = function () {
706-
return Math.abs(Math.random() * Math.random() * Date.now() | 0).toString()
707-
+ Math.abs(Math.random() * Math.random() * Date.now() | 0).toString();
708+
Manager.prototype.generateId = function (data) {
709+
var rand = new Buffer(15); // multiple of 3 for base64
710+
this.sequenceNumber = (this.sequenceNumber + 1) | 0;
711+
rand.writeInt32BE(this.sequenceNumber, 11);
712+
crypto.randomBytes(12).copy(rand);
713+
return rand.toString('base64').replace(/\//g, '_').replace(/\+/g, '-');
708714
};
709715

710716
/**
@@ -752,7 +758,7 @@ Manager.prototype.handleHandshake = function (data, req, res) {
752758
if (err) return error(err);
753759

754760
if (authorized) {
755-
var id = self.generateId()
761+
var id = self.generateId(newData || handshakeData)
756762
, hs = [
757763
id
758764
, self.enabled('heartbeats') ? self.get('heartbeat timeout') || '' : ''
@@ -872,9 +878,9 @@ Manager.prototype.authorize = function (data, fn) {
872878
if (this.get('authorization')) {
873879
var self = this;
874880

875-
this.get('authorization').call(this, data, function (err, authorized) {
881+
this.get('authorization').call(this, data, function (err, authorized, newData) {
876882
self.log.debug('client ' + authorized ? 'authorized' : 'unauthorized');
877-
fn(err, authorized);
883+
fn(err, authorized, newData);
878884
});
879885
} else {
880886
this.log.debug('client authorized');

test/manager.test.js

+80
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,86 @@ module.exports = {
220220
});
221221
},
222222

223+
'test authorization gets handshake data': function (done) {
224+
var port = ++ports
225+
, io = sio.listen(port)
226+
, cl = client(port);
227+
228+
io.configure(function () {
229+
function auth (data, fn) {
230+
data.query.should.have.foo;
231+
data.query.foo.should.eql('bar');
232+
fn(null, false);
233+
};
234+
235+
io.set('authorization', auth);
236+
});
237+
238+
cl.get('/socket.io/{protocol}/?foo=bar', function (res, data) {
239+
res.statusCode.should.eql(403);
240+
data.should.match(/handshake unauthorized/);
241+
242+
cl.end();
243+
io.server.close();
244+
done();
245+
});
246+
},
247+
248+
'test that authorization can view handshake data': function (done) {
249+
var port = ++ports
250+
, io = sio.listen(port)
251+
, cl = client(port);
252+
253+
io.configure(function () {
254+
function auth (data, fn) {
255+
data.query.should.have.foo;
256+
data.query.foo.should.eql('bar');
257+
fn(null, true);
258+
};
259+
260+
io.set('authorization', auth);
261+
});
262+
263+
cl.get('/socket.io/{protocol}/?foo=bar', function (res, data) {
264+
res.statusCode.should.eql(200);
265+
266+
cl.end();
267+
io.server.close();
268+
done();
269+
});
270+
},
271+
272+
'test that authorization can change handshake data': function (done) {
273+
var port = ++ports
274+
, io = sio.listen(port)
275+
, cl = client(port);
276+
277+
io.configure(function () {
278+
function auth (data, fn) {
279+
var replacement = { baz: 'qu' };
280+
for (i in data) {
281+
if (data.hasOwnProperty(i)) {
282+
replacement[i] = data[i];
283+
}
284+
}
285+
fn(null, true, replacement);
286+
};
287+
288+
io.set('authorization', auth);
289+
});
290+
291+
cl.get('/socket.io/{protocol}/', function (res, data) {
292+
var id = data.split(':', 2)[0];
293+
res.statusCode.should.eql(200);
294+
io.handshaken[id].should.have.baz;
295+
io.handshaken[id].baz.should.eql('qu');
296+
297+
cl.end();
298+
io.server.close();
299+
done();
300+
});
301+
},
302+
223303
'test a handshake error': function (done) {
224304
var port = ++ports
225305
, io = sio.listen(port)

0 commit comments

Comments
 (0)