Sunday, August 8, 2010

Faye Extensions 101: Disabling Wildcard Subscriptions

‹prev | My Chain | next›

I continue my exploration of faye tonight with a little extension work. Last night, I found that it is possible for a client to subscribe to all channels ("/**") and see whatever communication takes place. I would like to assure myself that it is possible to have private communications channels.

I believe that the extension examples on the faye site should be sufficient for locking things down as I would like. I could run through those examples here, and I would learn much by doing so. But I think I might learn a bit more by trying to roll my own.

To that effect, I am going to attempt to prevent subscription requests that include wildcards. Following along from the faye documentation, I create a test node.js server:
#!/usr/bin/env node

var faye = require('faye'),
server = new faye.NodeAdapter({mount: '/faye'}),
puts = require('sys').puts;

server.listen(8000);
Before running, I will try walking with a server extension that refuses all subscriptions, not just those to wildcard channels. I define my extension to work on incoming connections only, on subscription requests only, and deny access by setting an error message (which is how faye signals errors):
var no_connection = {
incoming: function(message, callback) {
// Let non-subscribe messages through
if (message.channel !== '/meta/subscribe')
return callback(message);

puts("Not allowing: " + message.subscription);
message.error = 'No subscriptions allowed';

// Call the server back now we're done
callback(message);
}
};

server.addExtension(no_connection);
If my understanding is correct, I should not be able to subscribe to any channels on the server now. Putting this to the test, I start the server up:
cstrom@whitefall:~/tmp$ ./app.js 
Then I hop into a node-repl session to subscribe to the two channels (neither should work):
node> var faye = require("faye");
node> var client = new faye.Client('http://localhost:8000/faye');
node> var wc = client.subscribe('/**', function(message) {puts("[**]: " + message)});
node> var foo_bar = client.subscribe('/foo/bar', function(message) {puts("[foo/bar]: " + message)});
Hrm. I kinda expected to get an error back. In the backend output, I do see:
cstrom@whitefall:~/tmp$ ./app.js
Not allowing: /**
Not allowing: /foo/bar
So I suppose blocking is working. I try publishing messages from another node-repl session:
node> var faye = require('faye');
node> var client = new faye.Client('http://localhost:8000/faye');
node> client.publish("/foo/bar", "test 01");
And I see no messages from my subscriptions. OK so far, so good.

Up next, I try my slightly more sophisticated extension that blocks wildcard subscriptions:
var no_wildcards = {
incoming: function(message, callback) {
// Let non-subscribe messages through
if (message.channel !== '/meta/subscribe')
return callback(message);

// Get subscribed channel and auth token
var subscription = message.subscription;

// if subscription contains something other than alphanumeric or /
if ( /[^/\w]/.test(message.subscription) ) {
puts("Not allowing: " + message.subscription);
message.error = 'Wildcard subscriptions not allowed';
}

// Call the server back now we're done
callback(message);
}
};

server.addExtension(no_wildcards);
I set up my same subscriptions. This time only the wildcard subscription is reported as blocked by the backend:
cstrom@whitefall:~/tmp$ ./app.js
Not allowing: /**
And, when I publish a message to the "/foo/bar" channel, I see only the non-wildcard subscription respond:
node> [foo/bar]: test 02
I am still somewhat surprised that subscription failure was not more obvious. I will investigate that some more tomorrow.


Day #189

No comments:

Post a Comment