Skip to content

Commit

Permalink
changed verifyOrigin to verifyClient and added info indicating connec…
Browse files Browse the repository at this point in the history
…tion ssl status
  • Loading branch information
einaros committed Jan 31, 2012
1 parent a96c7fc commit 1686e63
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 13 deletions.
13 changes: 9 additions & 4 deletions lib/WebSocketServer.js
Expand Up @@ -11,6 +11,7 @@ var util = require('util')
, url = require('url') , url = require('url')
, Options = require('options') , Options = require('options')
, WebSocket = require('./WebSocket') , WebSocket = require('./WebSocket')
, tls = require('tls')
, url = require('url'); , url = require('url');


/** /**
Expand All @@ -22,7 +23,7 @@ function WebSocketServer(options, callback) {
host: '127.0.0.1', host: '127.0.0.1',
port: null, port: null,
server: null, server: null,
verifyOrigin: null, verifyClient: null,
path: null, path: null,
noServer: false noServer: false
}).merge(options); }).merge(options);
Expand Down Expand Up @@ -147,12 +148,16 @@ WebSocketServer.prototype.handleUpgrade = function(req, socket, upgradeHead) {
return; return;
} }


// verify origin // verify client
var origin = version < 13 ? var origin = version < 13 ?
req.headers['sec-websocket-origin'] : req.headers['sec-websocket-origin'] :
req.headers['origin']; req.headers['origin'];
if (typeof this.options.verifyOrigin == 'function') { if (typeof this.options.verifyClient == 'function') {
if (!this.options.verifyOrigin(origin)) { var info = {
origin: origin,
secure: typeof req.connection.encrypted !== 'undefined'
};
if (!this.options.verifyClient(info)) {
abortConnection(socket, 401, 'Unauthorized'); abortConnection(socket, 401, 'Unauthorized');
return; return;
} }
Expand Down
114 changes: 105 additions & 9 deletions test/WebSocketServer.test.js
@@ -1,4 +1,5 @@
var http = require('http') var http = require('http')
, https = require('https')
, WebSocket = require('../') , WebSocket = require('../')
, WebSocketServer = WebSocket.Server , WebSocketServer = WebSocket.Server
, fs = require('fs') , fs = require('fs')
Expand Down Expand Up @@ -199,6 +200,9 @@ describe('WebSocketServer', function() {
done(); done();
}); });
}); });
wss.on('connection', function(ws) {
done(new Error('connection must not be established'));
});
wss.on('error', function() {}); wss.on('error', function() {});
}); });


Expand All @@ -221,6 +225,9 @@ describe('WebSocketServer', function() {
done(); done();
}); });
}); });
wss.on('connection', function(ws) {
done(new Error('connection must not be established'));
});
wss.on('error', function() {}); wss.on('error', function() {});
}); });


Expand All @@ -244,12 +251,14 @@ describe('WebSocketServer', function() {
done(); done();
}); });
}); });
wss.on('connection', function(ws) {
done(new Error('connection must not be established'));
});
wss.on('error', function() {}); wss.on('error', function() {});
}); });


it('does not accept connections with invalid sec-websocket-origin (8)', function(done) { it('client can be denied', function(done) {
var wss = new WebSocketServer({port: ++port, verifyOrigin: function(o) { var wss = new WebSocketServer({port: ++port, verifyClient: function(o) {
o.should.eql('http://foobar.com');
return false; return false;
}}, function() { }}, function() {
var options = { var options = {
Expand All @@ -267,17 +276,21 @@ describe('WebSocketServer', function() {
req.end(); req.end();
req.on('response', function(res) { req.on('response', function(res) {
res.statusCode.should.eql(401); res.statusCode.should.eql(401);
wss.close(); process.nextTick(function() {
done(); wss.close();
done();
});
}); });
}); });
wss.on('connection', function(ws) {
done(new Error('connection must not be established'));
});
wss.on('error', function() {}); wss.on('error', function() {});
}); });


it('does not accept connections with invalid origin', function(done) { it('client can be accepted', function(done) {
var wss = new WebSocketServer({port: ++port, verifyOrigin: function(o) { var wss = new WebSocketServer({port: ++port, verifyClient: function(o) {
o.should.eql('http://foobar.com'); return true;
return false;
}}, function() { }}, function() {
var options = { var options = {
port: port, port: port,
Expand All @@ -294,12 +307,95 @@ describe('WebSocketServer', function() {
req.end(); req.end();
req.on('response', function(res) { req.on('response', function(res) {
res.statusCode.should.eql(401); res.statusCode.should.eql(401);
});
});
wss.on('connection', function(ws) {
ws.terminate();
wss.close();
done();
});
wss.on('error', function() {});
});

it('verifyClient gets client origin', function(done) {
var wss = new WebSocketServer({port: ++port, verifyClient: function(info) {
info.origin.should.eql('http://foobarbaz.com');
return false;
}}, function() {
var options = {
port: port,
host: '127.0.0.1',
headers: {
'Connection': 'Upgrade',
'Upgrade': 'websocket',
'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==',
'Sec-WebSocket-Version': 13,
'Origin': 'http://foobarbaz.com'
}
};
var req = http.request(options);
req.end();
req.on('response', function(res) {
wss.close(); wss.close();
done(); done();
}); });
}); });
wss.on('error', function() {}); wss.on('error', function() {});
}); });

it('verifyClient has secure:true for ssl connections', function(done) {
var options = {
key: fs.readFileSync('test/fixtures/key.pem'),
cert: fs.readFileSync('test/fixtures/certificate.pem')
};
var app = https.createServer(options, function (req, res) {
res.writeHead(200);
res.end();
});
var success = false;
var wss = new WebSocketServer({
server: app,
verifyClient: function(info) {
success = info.secure === true;
return true;
}
});
app.listen(++port, function() {
var ws = new WebSocket('wss://localhost:' + port);
});
wss.on('connection', function(ws) {
app.close();
ws.terminate();
wss.close();
success.should.be.ok;
done();
});
});

it('verifyClient has secure:false for non-ssl connections', function(done) {
var app = http.createServer(function (req, res) {
res.writeHead(200);
res.end();
});
var success = false;
var wss = new WebSocketServer({
server: app,
verifyClient: function(info) {
success = info.secure === false;
return true;
}
});
app.listen(++port, function() {
var ws = new WebSocket('ws://localhost:' + port);
});
wss.on('connection', function(ws) {
app.close();
ws.terminate();
wss.close();
success.should.be.ok;
done();
});
});
}); });


it('can send data', function(done) { it('can send data', function(done) {
Expand Down

0 comments on commit 1686e63

Please sign in to comment.