From cc0fadb7cdcc0d4f1f63926ae88abf96aa3bfff1 Mon Sep 17 00:00:00 2001 From: baldo Date: Mon, 23 May 2016 22:36:27 +0200 Subject: [PATCH] Lookup node via monitoring token only --- .../controllers/confirmMonitoringCtrl.js | 2 +- .../controllers/disableMonitoringCtrl.js | 2 +- app/scripts/services/monitoringService.js | 12 +-- bin/fix_key_file_names.py | 7 +- server/resources/monitoringResource.js | 15 +--- server/router.js | 4 +- server/services/monitoringService.js | 8 +- server/services/nodeService.js | 75 +++++++++++++------ server/utils/urlBuilder.js | 8 +- 9 files changed, 78 insertions(+), 55 deletions(-) diff --git a/app/scripts/controllers/confirmMonitoringCtrl.js b/app/scripts/controllers/confirmMonitoringCtrl.js index f900e72..86d2d7b 100644 --- a/app/scripts/controllers/confirmMonitoringCtrl.js +++ b/app/scripts/controllers/confirmMonitoringCtrl.js @@ -12,7 +12,7 @@ angular.module('ffffng') $scope.monitoringInfo = {}; $scope.monitoringStatus = 'loading'; - MonitoringService.confirm($routeParams['mac'], $routeParams['token']) + MonitoringService.confirm($routeParams['token']) .then( function (response) { // success diff --git a/app/scripts/controllers/disableMonitoringCtrl.js b/app/scripts/controllers/disableMonitoringCtrl.js index b6e205f..c39ee28 100644 --- a/app/scripts/controllers/disableMonitoringCtrl.js +++ b/app/scripts/controllers/disableMonitoringCtrl.js @@ -12,7 +12,7 @@ angular.module('ffffng') $scope.monitoringInfo = {}; $scope.monitoringStatus = 'loading'; - MonitoringService.disable($routeParams['mac'], $routeParams['token']) + MonitoringService.disable($routeParams['token']) .then( function (response) { // success diff --git a/app/scripts/services/monitoringService.js b/app/scripts/services/monitoringService.js index 302f3e1..f67768d 100644 --- a/app/scripts/services/monitoringService.js +++ b/app/scripts/services/monitoringService.js @@ -3,18 +3,18 @@ angular.module('ffffng') .service('MonitoringService', function ($http, $q) { return { - 'confirm': function (mac, token) { - if (!mac || !token) { + 'confirm': function (token) { + if (!token) { return $q.reject({}); } - return $http.put('/api/monitoring/confirm/' + mac + '?token=' + token); + return $http.put('/api/monitoring/confirm/' + token); }, - 'disable': function (mac, token) { - if (!mac || !token) { + 'disable': function (token) { + if (!token) { return $q.reject({}); } - return $http.put('/api/monitoring/disable/' + mac + '?token=' + token); + return $http.put('/api/monitoring/disable/' + token); } }; }); diff --git a/bin/fix_key_file_names.py b/bin/fix_key_file_names.py index 5bd07ec..c15bada 100755 --- a/bin/fix_key_file_names.py +++ b/bin/fix_key_file_names.py @@ -26,7 +26,7 @@ def normalizeMac(mac): def toFilename(peer): filename = '' - for field in ['name', 'mac', 'vpn', 'token']: + for field in ['name', 'mac', 'vpn', 'token', 'monitoring-token']: if peer.has_key(field): filename = filename + peer[field] filename = filename + '@' @@ -48,12 +48,17 @@ for filename in os.listdir(peersDir): parts = line.split() if len(parts) > 0: + for i in range(0, 3 - len(parts)): + parts.append('') + if parts[1] == 'Knotenname:': peer['name'] = parts[2].lower() elif parts[1] == 'MAC:': peer['mac'] = normalizeMac(parts[2]) elif parts[1] == 'Token:': peer['token'] = parts[2].lower() + elif parts[1] == 'Monitoring-Token:': + peer['monitoring-token'] = parts[2].lower() elif parts[0] == 'key': peer['vpn'] = parts[1].split('"')[1].lower() diff --git a/server/resources/monitoringResource.js b/server/resources/monitoringResource.js index 5a90c24..4a975bf 100644 --- a/server/resources/monitoringResource.js +++ b/server/resources/monitoringResource.js @@ -9,24 +9,18 @@ angular.module('ffffng').factory('MonitoringResource', function ( Resources, ErrorTypes ) { - var isValidMac = Validator.forConstraint(Constraints.node.mac); var isValidToken = Validator.forConstraint(Constraints.token); return { confirm: function (req, res) { var data = Resources.getData(req); - var mac = Strings.normalizeMac(data.mac); - if (!isValidMac(mac)) { - return Resources.error(res, {data: 'Invalid MAC.', type: ErrorTypes.badRequest}); - } - var token = Strings.normalizeString(data.token); if (!isValidToken(token)) { return Resources.error(res, {data: 'Invalid token.', type: ErrorTypes.badRequest}); } - return MonitoringService.confirm(mac, token, function (err, node) { + return MonitoringService.confirm(token, function (err, node) { if (err) { return Resources.error(res, err); } @@ -43,17 +37,12 @@ angular.module('ffffng').factory('MonitoringResource', function ( disable: function (req, res) { var data = Resources.getData(req); - var mac = Strings.normalizeMac(data.mac); - if (!isValidMac(mac)) { - return Resources.error(res, {data: 'Invalid MAC.', type: ErrorTypes.badRequest}); - } - var token = Strings.normalizeString(data.token); if (!isValidToken(token)) { return Resources.error(res, {data: 'Invalid token.', type: ErrorTypes.badRequest}); } - return MonitoringService.disable(mac, token, function (err, node) { + return MonitoringService.disable(token, function (err, node) { if (err) { return Resources.error(res, err); } diff --git a/server/router.js b/server/router.js index a3a05e8..3824651 100644 --- a/server/router.js +++ b/server/router.js @@ -8,8 +8,8 @@ angular.module('ffffng').factory('Router', function (app, NodeResource, Monitori app.delete('/api/node/:token', NodeResource.delete); app.get('/api/node/:token', NodeResource.get); - app.put('/api/monitoring/confirm/:mac', MonitoringResource.confirm); - app.put('/api/monitoring/disable/:mac', MonitoringResource.disable); + app.put('/api/monitoring/confirm/:token', MonitoringResource.confirm); + app.put('/api/monitoring/disable/:token', MonitoringResource.disable); } }; }); diff --git a/server/services/monitoringService.js b/server/services/monitoringService.js index 9221ca4..3cd8010 100644 --- a/server/services/monitoringService.js +++ b/server/services/monitoringService.js @@ -3,8 +3,8 @@ angular.module('ffffng') .service('MonitoringService', function (NodeService, ErrorTypes) { return { - confirm: function (mac, token, callback) { - NodeService.getNodeDataByMac(mac, function (err, node, nodeSecrets) { + confirm: function (token, callback) { + NodeService.getNodeDataByMonitoringToken(token, function (err, node, nodeSecrets) { if (err) { return callback(err); } @@ -27,8 +27,8 @@ angular.module('ffffng') }); }, - disable: function (mac, token, callback) { - NodeService.getNodeDataByMac(mac, function (err, node, nodeSecrets) { + disable: function (token, callback) { + NodeService.getNodeDataByMonitoringToken(token, function (err, node, nodeSecrets) { if (err) { return callback(err); } diff --git a/server/services/nodeService.js b/server/services/nodeService.js index bb1beb3..09493e5 100644 --- a/server/services/nodeService.js +++ b/server/services/nodeService.js @@ -23,48 +23,77 @@ angular.module('ffffng') monitoringToken: '# Monitoring-Token: ' }; + var filenameParts = ['hostname', 'mac', 'key', 'token', 'monitoringToken']; + function generateToken() { return crypto.randomBytes(8).toString('hex'); } - function findNodeFiles(pattern) { + function findNodeFiles(filter) { + var pattern = _.join( + _.map(filenameParts, function (field) { + return filter.hasOwnProperty(field) ? filter[field] : '*'; + }), + '@' + ); + return glob.sync(config.server.peersPath + '/' + pattern.toLowerCase()); } - function isDuplicate(pattern, token) { - var files = findNodeFiles(pattern); + function parseNodeFilename(filename) { + var parts = _.split(filename, '@', filenameParts.length); + var parsed = {}; + _.each(_.zip(filenameParts, parts), function (part) { + parsed[part[0]] = part[1]; + }); + return parsed; + } + + function isDuplicate(filter, token) { + var files = findNodeFiles(filter); if (files.length === 0) { return false; } - if (files.length > 1 || !token) { + if (files.length > 1 || !token /* node is being created*/) { return true; } - var file = files[0]; - return file.substring(file.length - token.length, file.length) !== token; + return parseNodeFilename(files[0]).token !== token; } - function checkNoDuplicates(token, node) { - if (isDuplicate(node.hostname + '@*@*@*', token)) { + function checkNoDuplicates(token, node, nodeSecrets) { + if (isDuplicate({ hostname: node.hostname }, token)) { return {data: {msg: 'Already exists.', field: 'hostname'}, type: ErrorTypes.conflict}; } if (node.key) { - if (isDuplicate('*@*@' + node.key + '@*', token)) { + if (isDuplicate({ key: node.key }, token)) { return {data: {msg: 'Already exists.', field: 'key'}, type: ErrorTypes.conflict}; } } - if (isDuplicate('*@' + node.mac + '@*@*', token)) { + if (isDuplicate({ mac: node.mac }, token)) { return {data: {msg: 'Already exists.', field: 'mac'}, type: ErrorTypes.conflict}; } + + if (nodeSecrets.monitoringToken && isDuplicate({ monitoringToken: nodeSecrets.monitoringToken }, token)) { + return {data: {msg: 'Already exists.', field: 'monitoringToken'}, type: ErrorTypes.conflict}; + } + return null; } function writeNodeFile(isUpdate, token, node, nodeSecrets, callback) { var filename = - config.server.peersPath + '/' + (node.hostname + '@' + node.mac + '@' + (node.key || '') + '@' + token).toLowerCase(); + config.server.peersPath + '/' + + ( + node.hostname + '@' + + node.mac + '@' + + (node.key || '') + '@' + + token + '@' + + nodeSecrets.monitoringToken + ).toLowerCase(); var data = ''; _.each(linePrefixes, function (prefix, key) { @@ -102,12 +131,12 @@ angular.module('ffffng') var error; if (isUpdate) { - var files = findNodeFiles('*@*@*@' + token); + var files = findNodeFiles({ token: token }); if (files.length !== 1) { return callback({data: 'Node not found.', type: ErrorTypes.notFound}); } - error = checkNoDuplicates(token, node); + error = checkNoDuplicates(token, node, nodeSecrets); if (error) { return callback(error); } @@ -121,7 +150,7 @@ angular.module('ffffng') return callback({data: 'Could not remove old node data.', type: ErrorTypes.internalError}); } } else { - error = checkNoDuplicates(null, node); + error = checkNoDuplicates(null, node, nodeSecrets); if (error) { return callback(error); } @@ -139,7 +168,7 @@ angular.module('ffffng') } function deleteNodeFile(token, callback) { - var files = findNodeFiles('*@*@*@' + token); + var files = findNodeFiles({ token: token }); if (files.length !== 1) { return callback({data: 'Node not found.', type: ErrorTypes.notFound}); } @@ -195,8 +224,8 @@ angular.module('ffffng') callback(null, node, nodeSecrets); } - function getNodeDataByFilePattern(pattern, callback) { - var files = findNodeFiles(pattern); + function getNodeDataByFilePattern(filter, callback) { + var files = findNodeFiles(filter); if (files.length !== 1) { return callback({data: 'Node not found.', type: ErrorTypes.notFound}); @@ -207,8 +236,8 @@ angular.module('ffffng') } function sendMonitoringConfirmationMail(node, nodeSecrets, callback) { - var confirmUrl = UrlBuilder.monitoringConfirmUrl(node, nodeSecrets); - var disableUrl = UrlBuilder.monitoringDisableUrl(node, nodeSecrets); + var confirmUrl = UrlBuilder.monitoringConfirmUrl(nodeSecrets); + var disableUrl = UrlBuilder.monitoringDisableUrl(nodeSecrets); MailService.enqueue( config.server.email.from, @@ -220,7 +249,7 @@ angular.module('ffffng') disableUrl: disableUrl }, function (err) { - if (err) { + if (err) {checkNoDuplicates console.error(err); return callback({data: 'Internal error.', type: ErrorTypes.internalError}); } @@ -323,11 +352,11 @@ angular.module('ffffng') }, getNodeDataByToken: function (token, callback) { - return getNodeDataByFilePattern('*@*@*@' + token, callback); + return getNodeDataByFilePattern({ token: token }, callback); }, - getNodeDataByMac: function (mac, callback) { - return getNodeDataByFilePattern('*@' + mac + '@*@*', callback); + getNodeDataByMonitoringToken: function (monitoringToken, callback) { + return getNodeDataByFilePattern({ monitoringToken: monitoringToken }, callback); } }; }); diff --git a/server/utils/urlBuilder.js b/server/utils/urlBuilder.js index 1385caf..b63ab3c 100644 --- a/server/utils/urlBuilder.js +++ b/server/utils/urlBuilder.js @@ -29,11 +29,11 @@ angular.module('ffffng').factory('UrlBuilder', function (_, config) { return formUrl('update'); }, - monitoringConfirmUrl: function (node, nodeSecrets) { - return formUrl('monitoring/confirm', { mac: node.mac, token: nodeSecrets.monitoringToken }); + monitoringConfirmUrl: function (nodeSecrets) { + return formUrl('monitoring/confirm', { token: nodeSecrets.monitoringToken }); }, - monitoringDisableUrl: function (node, nodeSecrets) { - return formUrl('monitoring/disable', { mac: node.mac, token: nodeSecrets.monitoringToken }); + monitoringDisableUrl: function (nodeSecrets) { + return formUrl('monitoring/disable', { token: nodeSecrets.monitoringToken }); } }; });