1
0
Fork 0
mirror of https://github.com/Ylianst/MeshCentral.git synced 2025-03-09 15:40:18 +00:00

Added IP location server rate limit

This commit is contained in:
Ylian Saint-Hilaire 2017-09-05 17:19:28 -07:00
parent 20c836db0d
commit dbaee9b2dc
9 changed files with 496 additions and 74 deletions

BIN
agents/TestSuite.db Normal file

Binary file not shown.

View file

@ -26,6 +26,7 @@ function createMeshCore(agent) {
var lastNetworkInfo = null;
var lastPublicLocationInfo = null;
var selfInfoUpdateTimer = null;
obj.useNativePipes = (process.platform == 'win32');
var http = require('http');
var fs = require('fs');
@ -281,9 +282,9 @@ function createMeshCore(agent) {
}
break;
}
case 'location': {
// Update the location information of this node
getIpLocationData(function (location) { mesh.SendCommand({ "action": "location", "type": "publicip", "value": location }); });
case 'iplocation': {
// Update the IP location information of this node. Only do this when requested by the server since we have a limited amount of time we can call this per day
getIpLocationData(function (location) { mesh.SendCommand({ "action": "iplocation", "type": "publicip", "value": location }); });
break;
}
}
@ -371,10 +372,11 @@ function createMeshCore(agent) {
if (len > 0) { this.write(buf.slice(0, len)); } else { fs.closeSync(this.httprequest.downloadFile); this.httprequest.downloadFile = undefined; this.end(); }
return;
}
// (****) Remote Desktop without using native pipes (TODO: This is in use now because native pipes don't work correctly on Linux)
if (this.httprequest.desktop) { this.httprequest.desktop.kvm.write(data); return; }
// (****) Remote Terminal without using native pipes (TODO: This is in use now because native pipes don't work correctly on Linux)
if (this.httprequest.terminal) { this.httprequest.terminal.write(data); return; }
// Setup remote desktop & terminal without using native pipes
if (useNativePipes == false) {
if (this.httprequest.desktop) { this.httprequest.desktop.kvm.write(data); return; }
if (this.httprequest.terminal) { this.httprequest.terminal.write(data); return; }
}
if (this.httprequest.state == 0) {
// Check if this is a relay connection
@ -386,53 +388,53 @@ function createMeshCore(agent) {
this.httprequest.protocol = parseInt(data);
if (typeof this.httprequest.protocol != 'number') { this.httprequest.protocol = 0; }
if (this.httprequest.protocol == 1) {
// (****) Remote Terminal without using native pipes (TODO: This is in use now because native pipes don't work correctly on Linux)
if (process.platform == "win32") {
this.httprequest.terminal = processManager.CreateProcess("%windir%\\system32\\cmd.exe");
if (useNativePipes == false) {
// Remote Terminal without using native pipes
if (process.platform == "win32") {
this.httprequest.terminal = processManager.CreateProcess("%windir%\\system32\\cmd.exe");
} else {
this.httprequest.terminal = processManager.CreateProcess("/bin/sh", "sh", ILibProcessPipe_SpawnTypes.TERM);
}
this.httprequest.terminal.tunnel = this;
this.httprequest.terminal.on('data', function (chunk) { this.tunnel.write(chunk); });
this.httprequest.terminal.error.data = function (chunk) { this.parent.tunnel.write(chunk); }
} else {
this.httprequest.terminal = processManager.CreateProcess("/bin/sh", "sh", ILibProcessPipe_SpawnTypes.TERM);
// Remote terminal using native pipes
if (process.platform == "win32") {
this.httprequest.process = processManager.CreateProcess("%windir%\\system32\\cmd.exe");
} else {
this.httprequest.process = processManager.CreateProcess("/bin/sh", "sh", ILibProcessPipe_SpawnTypes.TERM);
}
this.httprequest.process.tunnel = this;
this.httprequest.process.error.data = function (chunk) { this.parent.tunnel.write(chunk); }
this.httprequest.process.pipe(this);
this.pipe(this.httprequest.process);
}
this.httprequest.terminal.tunnel = this;
this.httprequest.terminal.on('data', function (chunk) { this.tunnel.write(chunk); });
this.httprequest.terminal.error.data = function (chunk) { this.parent.tunnel.write(chunk); }
/*
// Remote terminal using native pipes
if (process.platform == "win32") {
this.httprequest.process = processManager.CreateProcess("%windir%\\system32\\cmd.exe");
} else {
this.httprequest.process = processManager.CreateProcess("/bin/sh", "sh", ILibProcessPipe_SpawnTypes.TERM);
}
this.httprequest.process.tunnel = this;
this.httprequest.process.error.data = function (chunk) { this.parent.tunnel.write(chunk); }
this.httprequest.process.pipe(this);
this.pipe(this.httprequest.process);
*/
}
if (this.httprequest.protocol == 2) {
// (****) Remote Desktop without using native pipes (TODO: This is in use now because native pipes don't work correctly on Linux)
this.httprequest.desktop = { state: 0, kvm: mesh.getRemoteDesktopStream(), tunnel: this };
this.httprequest.desktop.kvm.tunnel = this;
this.httprequest.desktop.kvm.on('data', function (data) { this.tunnel.write(data); });
this.desktop = this.httprequest.desktop;
this.end = function () { if (--this.desktop.kvm.connectionCount == 0) { this.httprequest.desktop.kvm.end(); } };
if (this.httprequest.desktop.kvm.hasOwnProperty("connectionCount")) { this.httprequest.desktop.kvm.connectionCount++; } else { this.httprequest.desktop.kvm.connectionCount = 1; }
/*
// Remote desktop using native pipes
this.httprequest.desktop = { state: 0, kvm: mesh.getRemoteDesktopStream(), tunnel: this };
this.httprequest.desktop.kvm.parent = this.httprequest.desktop;
this.desktop = this.httprequest.desktop;
this.end = function () {
--this.desktop.kvm.connectionCount;
this.unpipe(this.httprequest.desktop.kvm);
this.httprequest.desktop.kvm.unpipe(this);
if (this.desktop.kvm.connectionCount == 0) { this.httprequest.desktop.kvm.end(); }
};
if (this.httprequest.desktop.kvm.hasOwnProperty("connectionCount")) { this.httprequest.desktop.kvm.connectionCount++; } else { this.httprequest.desktop.kvm.connectionCount = 1; }
this.pipe(this.httprequest.desktop.kvm);
this.httprequest.desktop.kvm.pipe(this);
*/
if (useNativePipes == false) {
// Remote Desktop without using native pipes
this.httprequest.desktop = { state: 0, kvm: mesh.getRemoteDesktopStream(), tunnel: this };
this.httprequest.desktop.kvm.tunnel = this;
this.httprequest.desktop.kvm.on('data', function (data) { this.tunnel.write(data); });
this.desktop = this.httprequest.desktop;
this.end = function () { if (--this.desktop.kvm.connectionCount == 0) { this.httprequest.desktop.kvm.end(); } };
if (this.httprequest.desktop.kvm.hasOwnProperty("connectionCount")) { this.httprequest.desktop.kvm.connectionCount++; } else { this.httprequest.desktop.kvm.connectionCount = 1; }
} else {
// Remote desktop using native pipes
this.httprequest.desktop = { state: 0, kvm: mesh.getRemoteDesktopStream(), tunnel: this };
this.httprequest.desktop.kvm.parent = this.httprequest.desktop;
this.desktop = this.httprequest.desktop;
this.end = function () {
--this.desktop.kvm.connectionCount;
this.unpipe(this.httprequest.desktop.kvm);
this.httprequest.desktop.kvm.unpipe(this);
if (this.desktop.kvm.connectionCount == 0) { this.httprequest.desktop.kvm.end(); }
};
if (this.httprequest.desktop.kvm.hasOwnProperty("connectionCount")) { this.httprequest.desktop.kvm.connectionCount++; } else { this.httprequest.desktop.kvm.connectionCount = 1; }
this.pipe(this.httprequest.desktop.kvm);
this.httprequest.desktop.kvm.pipe(this);
}
}
else if (this.httprequest.protocol == 5) {
// Setup files
@ -569,7 +571,7 @@ function createMeshCore(agent) {
break;
}
case 'info': { // Return information about the agent and agent core module
response = 'Current Core: ' + obj.meshCoreInfo + '.\r\nAgent Time: ' + Date() + '.\r\nUser Rights: 0x' + rights.toString(16) + '.\r\nPlatform Info: ' + process.platform + '.\r\Capabilities: ' + obj.meshCoreCapabilities + '.';
response = 'Current Core: ' + obj.meshCoreInfo + '.\r\nAgent Time: ' + Date() + '.\r\nUser Rights: 0x' + rights.toString(16) + '.\r\nPlatform Info: ' + process.platform + '.\r\nCapabilities: ' + obj.meshCoreCapabilities + '.\r\nNative Pipes: ' + obj.useNativePipes + '.';
break;
}
case 'selfinfo': { // Return self information block
@ -763,14 +765,6 @@ function createMeshCore(agent) {
sendConsoleText(args['_'].join(' '));
break;
}
case 'location': { // Get location information about this computer
if (args['_'][0] == 'force') {
getIpLocationDataEx(function (location) { sendConsoleText('IpLocation: ' + getIpLocationDataExCounts[0] + ' querie(s), ' + getIpLocationDataExCounts[1] + ' response(s), inProgress: ' + getIpLocationDataExInProgress + "\r\nPublic IP location data:\r\n" + objToString(location, 0, '.'), sessionid); }, args['_'][0]);
} else {
getIpLocationData(function (location) { sendConsoleText('IpLocation: ' + getIpLocationDataExCounts[0] + ' querie(s), ' + getIpLocationDataExCounts[1] + ' response(s), inProgress: ' + getIpLocationDataExInProgress + "\r\nPublic IP location data:\r\n" + objToString(location, 0, '.'), sessionid); }, args['_'][0]);
}
break;
}
case 'power': { // Execute a power action on this computer
if (mesh.ExecPowerState == undefined) {
response = 'Power command not supported on this agent.';
@ -844,12 +838,6 @@ function createMeshCore(agent) {
netInfo.action = 'netinfo';
var netInfoStr = JSON.stringify(netInfo);
if ((force == true) || (clearGatewayMac(netInfoStr) != clearGatewayMac(lastNetworkInfo))) { mesh.SendCommand(netInfo); lastNetworkInfo = netInfoStr; }
// Update public IP location information, location caching will be used
getIpLocationData(function (location) {
var locationStr = JSON.stringify(location);
if ((force == true) || (locationStr != lastPublicLocationInfo)) { mesh.SendCommand({ "action": "location", "type": "publicip", "value": location }); lastPublicLocationInfo = locationStr; }
});
}
// Called on MicroLMS Intel AMT user notification

157
agents/testsuite.js Normal file
View file

@ -0,0 +1,157 @@
/*
Copyright 2017 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Polyfill String.endsWith
if (!String.prototype.endsWith) {
String.prototype.endsWith = function (searchString, position) {
var subjectString = this.toString();
if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) { position = subjectString.length; }
position -= searchString.length;
var lastIndex = subjectString.lastIndexOf(searchString, position);
return lastIndex !== -1 && lastIndex === position;
};
}
// Replace a string with a number if the string is an exact number
function toNumberIfNumber(x) { if ((typeof x == 'string') && (+parseInt(x) == x)) { x = parseInt(x); } return x; }
// Convert decimal to hex
function char2hex(i) { return (i + 0x100).toString(16).substr(-2).toUpperCase(); }
// Convert a raw string to a hex string
function rstr2hex(input) { var r = '', i; for (i = 0; i < input.length; i++) { r += char2hex(input.charCodeAt(i)); } return r; }
// Convert a buffer into a string
function buf2rstr(buf) { var r = ''; for (var i = 0; i < buf.length; i++) { r += String.fromCharCode(buf[i]); } return r; }
// Convert a hex string to a raw string // TODO: Do this using Buffer(), will be MUCH faster
function hex2rstr(d) {
if (typeof d != "string" || d.length == 0) return '';
var r = '', m = ('' + d).match(/../g), t;
while (t = m.shift()) r += String.fromCharCode('0x' + t);
return r
}
// Convert an object to string with all functions
function objToString(x, p, ret) {
if (ret == undefined) ret = '';
if (p == undefined) p = 0;
if (x == null) { return '[null]'; }
if (p > 8) { return '[...]'; }
if (x == undefined) { return '[undefined]'; }
if (typeof x == 'string') { if (p == 0) return x; return '"' + x + '"'; }
if (typeof x == 'buffer') { return '[buffer]'; }
if (typeof x != 'object') { return x; }
var r = '{' + (ret ? '\r\n' : ' ');
for (var i in x) { r += (addPad(p + 2, ret) + i + ': ' + objToString(x[i], p + 2, ret) + (ret ? '\r\n' : ' ')); }
return r + addPad(p, ret) + '}';
}
// Return p number of spaces
function addPad(p, ret) { var r = ''; for (var i = 0; i < p; i++) { r += ret; } return r; }
// Split a string taking into account the quoats. Used for command line parsing
function splitArgs(str) {
var myArray = [], myRegexp = /[^\s"]+|"([^"]*)"/gi;
do { var match = myRegexp.exec(str); if (match != null) { myArray.push(match[1] ? match[1] : match[0]); } } while (match != null);
return myArray;
}
// Parse arguments string array into an object
function parseArgs(argv) {
var results = { '_': [] }, current = null;
for (var i = 1, len = argv.length; i < len; i++) {
var x = argv[i];
if (x.length > 2 && x[0] == '-' && x[1] == '-') {
if (current != null) { results[current] = true; }
current = x.substring(2);
} else {
if (current != null) { results[current] = toNumberIfNumber(x); current = null; } else { results['_'].push(toNumberIfNumber(x)); }
}
}
if (current != null) { results[current] = true; }
return results;
}
// Parge a URL string into an options object
function parseUrl(url) {
var x = url.split('/');
if (x.length < 4) return null;
var y = x[2].split(':');
var options = {};
var options = { protocol: x[0], hostname: y[0], path: '/' + x.splice(3).join('/') };
if (y.length == 1) { options.port = ((x[0] == 'https:') || (x[0] == 'wss:')) ? 443 : 80; } else { options.port = parseInt(y[1]); }
if (isNaN(options.port) == true) return null;
return options;
}
//console.log(objToString(db2, 2, ' '));
{
// TODO: Fix this to use the event emitor
// TODO: Add SHA256 sync
console.log('--- Test 1: SHA256 hashing ---');
var sha256 = require('SHA256Stream');
sha256.hashString = function (x) { if (x == '81B637D8FCD2C6DA6359E6963113A1170DE795E4B725B84D1E0B4CFD9EC58CE9') { console.log('Test 1 - OK: ' + x); } else { console.log('Test 1 - FAIL: ' + x); } };
sha256.write('bob');
sha256.end();
}
{
// FAIL!!!!!!!!!
var sha256x = require('SHA256Stream');
sha256x.hashString = function (x) { if (x == '81B637D8FCD2C6DA6359E6963113A1170DE795E4B725B84D1E0B4CFD9EC58CE9') { console.log('Test 1 - OK: ' + x); } else { console.log('Test 1 - FAIL: ' + x); } };
sha256x.write('bob');
sha256x.end();
}
/*
{
console.log('--- Test 2: Database ---');
var db = require('SimpleDataStore').Create('TestSuite.db');
var sha256 = require('SHA256Stream');
// Write a pile of hashes to the DB
sha256.hashString = function (x) { db.Put(x.substring(0, 16), x.substring(16)); console.log('ADD: ' + x.substring(0, 16) + ': ' + x.substring(16)); };
for (var i = 0; i < 10; i++) { console.log(i); sha256.write('A' + i); sha256.end(); }
// Compact plenty of times
for (var i = 0; i < 10; i++) { console.log(i); db.Compact(); }
// Check all the hashes
sha256.hashString = function (x) {
var r = db.Get(x.substring(0, 16));
console.log('GET: ' + x.substring(0, 16) + ': ' + r);
if (r != x.substring(16)) { console.log('FAILED ' + x.substring(0, 16) + ': ' + x.substring(16) + ' != ' + r); }
//db.Put(x.substring(0, 16), '');
};
for (var i = 0; i < 10; i++) { console.log(i); sha256.write('A' + i); sha256.end(); }
console.log('Test 2 - Completed.');
}
*/
{
console.log('--- Test 3: Files ---');
var r, fs = require('fs');
//console.log(objToString(fs, 2, ' '));
r = fs.mkdirSync('TestSuite-123');
r = fs.renameSync('TestSuite-123', 'TestSuite-1234');
console.log(r);
r = fs.unlinkSync('TestSuite-1234');
}
console.log('--- Tests Completed ---');
process.exit(2);