diff --git a/NEWS.md b/NEWS.md index 07a77aa8..849cf000 100644 --- a/NEWS.md +++ b/NEWS.md @@ -7,6 +7,7 @@ Enhancements: - Upgrade windshaft to 0.19.2, see node_modules/windshaft/NEWS - Clarify obscure "ECONNREFUSED" error message (#171) - Change some http status responses to be more appropriate to the case + - Forbid using map signatures of foreign users (#173) 1.8.3 -- 2014-02-27 ------------------- diff --git a/lib/cartodb/server_options.js b/lib/cartodb/server_options.js index f32d0835..a153cb8a 100644 --- a/lib/cartodb/server_options.js +++ b/lib/cartodb/server_options.js @@ -718,6 +718,12 @@ module.exports = function(){ if ( tksplit.length > 1 ) { req.params.signer = tksplit.shift(); if ( ! req.params.signer ) req.params.signer = user; + else if ( req.params.signer != user ) { + var err = new Error('Cannot use map signature of user "' + req.params.signer + '" on database of user "' + user + '"') + err.http_status = 403; + callback(err); + return; + } if ( tksplit.length > 1 ) { var template_hash = tksplit.shift(); // unused } diff --git a/test/acceptance/templates.js b/test/acceptance/templates.js index b411836f..a93f5700 100644 --- a/test/acceptance/templates.js +++ b/test/acceptance/templates.js @@ -865,7 +865,7 @@ suite('template_api', function() { "Missing 'error' from response body: " + res.body); assert.ok(parsed.error.match(/permission denied/i), 'Unexpected error for unauthorized instance ' - + '(expected /permission denied): ' + parsed.error); + + '(expected /permission denied/): ' + parsed.error); var get_request = { url: '/tiles/layergroup/' + layergroupid + '/0/0/0.png?auth_token=valid1', method: 'GET', @@ -884,6 +884,33 @@ suite('template_api', function() { assert.equal(res.headers['content-type'], "image/png"); return null; }, + // See https://github.com/CartoDB/Windshaft-cartodb/issues/172 + function fetchTileForeignSignature(err, res) { + if ( err ) throw err; + var foreignsigned = layergroupid.replace(/[^@]*@/, 'foreign@'); + var get_request = { + url: '/tiles/layergroup/' + foreignsigned + '/0/0/0.png?auth_token=valid1', + method: 'GET', + headers: {host: 'localhost' }, + encoding: 'binary' + } + var next = this; + assert.response(server, get_request, {}, + function(res) { next(null, res); }); + }, + function checkForeignSignerError(err, res) { + if ( err ) throw err; + assert.equal(res.statusCode, 403, + 'Unexpected error for authorized instance: ' + + res.statusCode + ' -- ' + res.body); + var parsed = JSON.parse(res.body); + assert.ok(parsed.hasOwnProperty('error'), + "Missing 'error' from response body: " + res.body); + assert.ok(parsed.error.match(/cannot use/i), + 'Unexpected error for unauthorized instance ' + + '(expected /cannot use/): ' + parsed.error); + return null; + }, function deleteTemplate(err) { if ( err ) throw err;