Fixed multi-tenancy DNS support

This commit is contained in:
Ylian Saint-Hilaire 2018-01-04 12:15:21 -08:00
parent eb363f0cee
commit d455e35658
24 changed files with 167 additions and 110 deletions

Binary file not shown.

Binary file not shown.

View File

@ -1,11 +1,11 @@
/* /*
Copyright 2017 Intel Corporation Copyright 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
@ -16,7 +16,7 @@ limitations under the License.
function createMeshCore(agent) { function createMeshCore(agent) {
var obj = {}; var obj = {};
// MeshAgent JavaScript Core Module. This code is sent to and running on the mesh agent. // MeshAgent JavaScript Core Module. This code is sent to and running on the mesh agent.
obj.meshCoreInfo = "MeshCore v4"; obj.meshCoreInfo = "MeshCore v4";
obj.meshCoreCapabilities = 14; // Capability bitmask: 1 = Desktop, 2 = Terminal, 4 = Files, 8 = Console, 16 = JavaScript obj.meshCoreCapabilities = 14; // Capability bitmask: 1 = Desktop, 2 = Terminal, 4 = Files, 8 = Console, 16 = JavaScript
@ -36,7 +36,7 @@ function createMeshCore(agent) {
var wifiScannerLib = null; var wifiScannerLib = null;
var wifiScanner = null; var wifiScanner = null;
var networkMonitor = null; var networkMonitor = null;
// Try to load up the network monitor // Try to load up the network monitor
try { try {
networkMonitor = require('NetworkMonitor'); networkMonitor = require('NetworkMonitor');
@ -44,7 +44,7 @@ function createMeshCore(agent) {
networkMonitor.on('add', function (addr) { sendNetworkUpdateNagle(); }); networkMonitor.on('add', function (addr) { sendNetworkUpdateNagle(); });
networkMonitor.on('remove', function (addr) { sendNetworkUpdateNagle(); }); networkMonitor.on('remove', function (addr) { sendNetworkUpdateNagle(); });
} catch (e) { networkMonitor = null; } } catch (e) { networkMonitor = null; }
// Try to load up the MEI module // Try to load up the MEI module
try { try {
var amtMeiLib = require('amt_heci'); var amtMeiLib = require('amt_heci');
@ -53,21 +53,21 @@ function createMeshCore(agent) {
amtMei.on('error', function (e) { amtMeiLib = null; amtMei = null; sendPeriodicServerUpdate(); }); amtMei.on('error', function (e) { amtMeiLib = null; amtMei = null; sendPeriodicServerUpdate(); });
amtMei.on('connect', function () { amtMeiConnected = 2; getAmtInfo(); }); amtMei.on('connect', function () { amtMeiConnected = 2; getAmtInfo(); });
} catch (e) { amtMeiLib = null; amtMei = null; amtMeiConnected = -1; } } catch (e) { amtMeiLib = null; amtMei = null; amtMeiConnected = -1; }
// Try to load up the WIFI scanner // Try to load up the WIFI scanner
try { try {
var wifiScannerLib = require('WifiScanner'); var wifiScannerLib = require('WifiScanner');
wifiScanner = new wifiScannerLib(); wifiScanner = new wifiScannerLib();
wifiScanner.on('accessPoint', function (data) { sendConsoleText(JSON.stringify(data)); }); wifiScanner.on('accessPoint', function (data) { sendConsoleText(JSON.stringify(data)); });
} catch (e) { wifiScannerLib = null; wifiScanner = null; } } catch (e) { wifiScannerLib = null; wifiScanner = null; }
// If we are running in Duktape, agent will be null // If we are running in Duktape, agent will be null
if (agent == null) { if (agent == null) {
// Running in native agent, Import libraries // Running in native agent, Import libraries
db = require('SimpleDataStore').Shared(); db = require('SimpleDataStore').Shared();
sha = require('SHA256Stream'); sha = require('SHA256Stream');
mesh = require('MeshAgent'); mesh = require('MeshAgent');
processManager = require('ILibProcessPipe'); childProcess = require('child_process');
if (mesh.hasKVM == 1) { obj.meshCoreCapabilities |= 1; } if (mesh.hasKVM == 1) { obj.meshCoreCapabilities |= 1; }
} else { } else {
// Running in nodejs // Running in nodejs
@ -75,7 +75,7 @@ function createMeshCore(agent) {
obj.meshCoreCapabilities = 8; obj.meshCoreCapabilities = 8;
mesh = agent.getMeshApi(); mesh = agent.getMeshApi();
} }
// Get our location (lat/long) using our public IP address // Get our location (lat/long) using our public IP address
var getIpLocationDataExInProgress = false; var getIpLocationDataExInProgress = false;
var getIpLocationDataExCounts = [0, 0]; var getIpLocationDataExCounts = [0, 0];
@ -91,27 +91,27 @@ function createMeshCore(agent) {
headers: { Host: "ipinfo.io" } headers: { Host: "ipinfo.io" }
}, },
function (resp) { function (resp) {
if (resp.statusCode == 200) { if (resp.statusCode == 200) {
var geoData = ''; var geoData = '';
resp.data = function (geoipdata) { geoData += geoipdata; }; resp.data = function (geoipdata) { geoData += geoipdata; };
resp.end = function () { resp.end = function () {
var location = null; var location = null;
try { try {
if (typeof geoData == 'string') { if (typeof geoData == 'string') {
var result = JSON.parse(geoData); var result = JSON.parse(geoData);
if (result.ip && result.loc) { location = result; } if (result.ip && result.loc) { location = result; }
} }
} catch (e) { } } catch (e) { }
if (func) { getIpLocationDataExCounts[1]++; func(location); } if (func) { getIpLocationDataExCounts[1]++; func(location); }
} }
} else { func(null); } } else { func(null); }
getIpLocationDataExInProgress = false; getIpLocationDataExInProgress = false;
}).end(); }).end();
return true; return true;
} }
catch (e) { return false; } catch (e) { return false; }
} }
// Remove all Gateway MAC addresses for interface list. This is useful because the gateway MAC is not always populated reliably. // Remove all Gateway MAC addresses for interface list. This is useful because the gateway MAC is not always populated reliably.
function clearGatewayMac(str) { function clearGatewayMac(str) {
if (str == null) return null; if (str == null) return null;
@ -119,7 +119,7 @@ function createMeshCore(agent) {
for (var i in x.netif) { if (x.netif[i].gatewaymac) { delete x.netif[i].gatewaymac } } for (var i in x.netif) { if (x.netif[i].gatewaymac) { delete x.netif[i].gatewaymac } }
return JSON.stringify(x); return JSON.stringify(x);
} }
function getIpLocationData(func) { function getIpLocationData(func) {
// Get the location information for the cache if possible // Get the location information for the cache if possible
var publicLocationInfo = db.Get('publicLocationInfo'); var publicLocationInfo = db.Get('publicLocationInfo');
@ -158,7 +158,7 @@ function createMeshCore(agent) {
} }
} }
} }
// Polyfill String.endsWith // Polyfill String.endsWith
if (!String.prototype.endsWith) { if (!String.prototype.endsWith) {
String.prototype.endsWith = function (searchString, position) { String.prototype.endsWith = function (searchString, position) {
@ -169,7 +169,7 @@ function createMeshCore(agent) {
return lastIndex !== -1 && lastIndex === position; return lastIndex !== -1 && lastIndex === position;
}; };
} }
// Polyfill path.join // Polyfill path.join
obj.path = { obj.path = {
join: function () { join: function () {
@ -188,19 +188,19 @@ function createMeshCore(agent) {
return x.join('/'); return x.join('/');
} }
}; };
// Replace a string with a number if the string is an exact number // 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; } function toNumberIfNumber(x) { if ((typeof x == 'string') && (+parseInt(x) === x)) { x = parseInt(x); } return x; }
// Convert decimal to hex // Convert decimal to hex
function char2hex(i) { return (i + 0x100).toString(16).substr(-2).toUpperCase(); } function char2hex(i) { return (i + 0x100).toString(16).substr(-2).toUpperCase(); }
// Convert a raw string to a hex string // 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; } 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 // 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; } 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 // Convert a hex string to a raw string // TODO: Do this using Buffer(), will be MUCH faster
function hex2rstr(d) { function hex2rstr(d) {
if (typeof d != "string" || d.length == 0) return ''; if (typeof d != "string" || d.length == 0) return '';
@ -208,7 +208,7 @@ function createMeshCore(agent) {
while (t = m.shift()) r += String.fromCharCode('0x' + t); while (t = m.shift()) r += String.fromCharCode('0x' + t);
return r return r
} }
// Convert an object to string with all functions // Convert an object to string with all functions
function objToString(x, p, ret) { function objToString(x, p, ret) {
if (ret == undefined) ret = ''; if (ret == undefined) ret = '';
@ -223,17 +223,17 @@ function createMeshCore(agent) {
for (var i in x) { r += (addPad(p + 2, ret) + i + ': ' + objToString(x[i], p + 2, ret) + (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 r + addPad(p, ret) + '}';
} }
// Return p number of spaces // Return p number of spaces
function addPad(p, ret) { var r = ''; for (var i = 0; i < p; i++) { r += ret; } return r; } 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 // Split a string taking into account the quoats. Used for command line parsing
function splitArgs(str) { function splitArgs(str) {
var myArray = [], myRegexp = /[^\s"]+|"([^"]*)"/gi; 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); do { var match = myRegexp.exec(str); if (match != null) { myArray.push(match[1] ? match[1] : match[0]); } } while (match != null);
return myArray; return myArray;
} }
// Parse arguments string array into an object // Parse arguments string array into an object
function parseArgs(argv) { function parseArgs(argv) {
var results = { '_': [] }, current = null; var results = { '_': [] }, current = null;
@ -249,7 +249,7 @@ function createMeshCore(agent) {
if (current != null) { results[current] = true; } if (current != null) { results[current] = true; }
return results; return results;
} }
// Get server target url with a custom path // Get server target url with a custom path
function getServerTargetUrl(path) { function getServerTargetUrl(path) {
var x = mesh.ServerUrl; var x = mesh.ServerUrl;
@ -260,13 +260,13 @@ function createMeshCore(agent) {
if (x == null) return null; if (x == null) return null;
return x.protocol + '//' + x.host + ':' + x.port + '/' + path; return x.protocol + '//' + x.host + ':' + x.port + '/' + path;
} }
// Get server url. If the url starts with "*/..." change it, it not use the url as is. // Get server url. If the url starts with "*/..." change it, it not use the url as is.
function getServerTargetUrlEx(url) { function getServerTargetUrlEx(url) {
if (url.substring(0, 2) == '*/') { return getServerTargetUrl(url.substring(2)); } if (url.substring(0, 2) == '*/') { return getServerTargetUrl(url.substring(2)); }
return url; return url;
} }
// Send a wake-on-lan packet // Send a wake-on-lan packet
function sendWakeOnLan(hexMac) { function sendWakeOnLan(hexMac) {
var count = 0; var count = 0;
@ -275,7 +275,7 @@ function createMeshCore(agent) {
var magic = 'FFFFFFFFFFFF'; var magic = 'FFFFFFFFFFFF';
for (var x = 1; x <= 16; ++x) { magic += hexMac; } for (var x = 1; x <= 16; ++x) { magic += hexMac; }
var magicbin = Buffer.from(magic, 'hex'); var magicbin = Buffer.from(magic, 'hex');
for (var adapter in interfaces) { for (var adapter in interfaces) {
if (interfaces.hasOwnProperty(adapter)) { if (interfaces.hasOwnProperty(adapter)) {
for (var i = 0; i < interfaces[adapter].length; ++i) { for (var i = 0; i < interfaces[adapter].length; ++i) {
@ -293,7 +293,7 @@ function createMeshCore(agent) {
} catch (e) { } } catch (e) { }
return count; return count;
} }
// Handle a mesh agent command // Handle a mesh agent command
function handleServerCommand(data) { function handleServerCommand(data) {
if (typeof data == 'object') { if (typeof data == 'object') {
@ -311,6 +311,7 @@ function createMeshCore(agent) {
var xurl = getServerTargetUrlEx(data.value); var xurl = getServerTargetUrlEx(data.value);
if (xurl != null) { if (xurl != null) {
var woptions = http.parseUri(xurl); var woptions = http.parseUri(xurl);
woptions.rejectUnauthorized = 0;
sendConsoleText(JSON.stringify(woptions)); sendConsoleText(JSON.stringify(woptions));
var tunnel = http.request(woptions); var tunnel = http.request(woptions);
tunnel.upgrade = onTunnelUpgrade; tunnel.upgrade = onTunnelUpgrade;
@ -322,13 +323,14 @@ function createMeshCore(agent) {
tunnel.protocol = 0; tunnel.protocol = 0;
tunnel.tcpaddr = data.tcpaddr; tunnel.tcpaddr = data.tcpaddr;
tunnel.tcpport = data.tcpport; tunnel.tcpport = data.tcpport;
tunnel.end();
sendConsoleText('tunnel.end() called');
// Put the tunnel in the tunnels list // Put the tunnel in the tunnels list
var index = 1; var index = 1;
while (tunnels[index]) { index++; } while (tunnels[index]) { index++; }
tunnel.index = index; tunnel.index = index;
tunnels[index] = tunnel; tunnels[index] = tunnel;
sendConsoleText('New tunnel connection #' + index + ': ' + tunnel.url + ', rights: ' + tunnel.rights, data.sessionid); sendConsoleText('New tunnel connection #' + index + ': ' + tunnel.url + ', rights: ' + tunnel.rights, data.sessionid);
} }
} }
@ -360,7 +362,7 @@ function createMeshCore(agent) {
} }
} }
} }
// Called when a file changed in the file system // Called when a file changed in the file system
/* /*
function onFileWatcher(a, b) { function onFileWatcher(a, b) {
@ -390,7 +392,7 @@ function createMeshCore(agent) {
if (reqpath == '') { reqpath = '/'; } if (reqpath == '') { reqpath = '/'; }
var xpath = obj.path.join(reqpath, '*'); var xpath = obj.path.join(reqpath, '*');
var results = null; var results = null;
try { results = fs.readdirSync(xpath); } catch (e) { } try { results = fs.readdirSync(xpath); } catch (e) { }
if (results != null) { if (results != null) {
for (var i = 0; i < results.length; ++i) { for (var i = 0; i < results.length; ++i) {
@ -410,13 +412,13 @@ function createMeshCore(agent) {
} }
return response; return response;
} }
// Tunnel callback operations // Tunnel callback operations
function onTunnelUpgrade(response, s, head) { function onTunnelUpgrade(response, s, head) {
this.s = s; this.s = s;
s.httprequest = this; s.httprequest = this;
s.end = onTunnelClosed; s.end = onTunnelClosed;
if (this.tcpport != null) { if (this.tcpport != null) {
// This is a TCP relay connection, pause now and try to connect to the target. // This is a TCP relay connection, pause now and try to connect to the target.
s.pause(); s.pause();
@ -430,7 +432,7 @@ function createMeshCore(agent) {
s.data = onTunnelData; s.data = onTunnelData;
} }
} }
// Called when the TCP relay target is connected // Called when the TCP relay target is connected
function onTcpRelayTargetTunnelConnect() { function onTcpRelayTargetTunnelConnect() {
var peerTunnel = tunnels[this.peerindex]; var peerTunnel = tunnels[this.peerindex];
@ -438,17 +440,17 @@ function createMeshCore(agent) {
peerTunnel.s.first = true; peerTunnel.s.first = true;
peerTunnel.s.resume(); peerTunnel.s.resume();
} }
// Called when we get data from the server for a TCP relay (We have to skip the first received 'c' and pipe the rest) // Called when we get data from the server for a TCP relay (We have to skip the first received 'c' and pipe the rest)
function onTcpRelayServerTunnelData(data) { function onTcpRelayServerTunnelData(data) {
if (this.first == true) { this.first = false; this.pipe(this.tcprelay); } // Pipe Server --> Target if (this.first == true) { this.first = false; this.pipe(this.tcprelay); } // Pipe Server --> Target
} }
function onTunnelClosed() { function onTunnelClosed() {
sendConsoleText("Tunnel #" + this.httprequest.index + " closed.", this.httprequest.sessionid); sendConsoleText("Tunnel #" + this.httprequest.index + " closed.", this.httprequest.sessionid);
if (this.httprequest.protocol == 1) { this.httprequest.process.end(); delete this.httprequest.process; } if (this.httprequest.protocol == 1) { this.httprequest.process.end(); delete this.httprequest.process; }
delete tunnels[this.httprequest.index]; delete tunnels[this.httprequest.index];
/* /*
// Close the watcher if required // Close the watcher if required
if (this.httprequest.watcher != undefined) { if (this.httprequest.watcher != undefined) {
@ -466,7 +468,7 @@ function createMeshCore(agent) {
function onTunnelData(data) { function onTunnelData(data) {
//console.log("OnTunnelData"); //console.log("OnTunnelData");
//sendConsoleText('OnTunnelData, ' + data.length + ', ' + typeof data + ', ' + data); //sendConsoleText('OnTunnelData, ' + data.length + ', ' + typeof data + ', ' + data);
// If this is upload data, save it to file // If this is upload data, save it to file
if (this.httprequest.uploadFile) { if (this.httprequest.uploadFile) {
try { fs.writeSync(this.httprequest.uploadFile, data); } catch (e) { this.write(new Buffer(JSON.stringify({ action: 'uploaderror' }))); return; } // Write to the file, if there is a problem, error out. try { fs.writeSync(this.httprequest.uploadFile, data); } catch (e) { this.write(new Buffer(JSON.stringify({ action: 'uploaderror' }))); return; } // Write to the file, if there is a problem, error out.
@ -481,7 +483,7 @@ function createMeshCore(agent) {
if (len > 0) { this.write(buf.slice(0, len)); } else { fs.closeSync(this.httprequest.downloadFile); this.httprequest.downloadFile = undefined; this.end(); } if (len > 0) { this.write(buf.slice(0, len)); } else { fs.closeSync(this.httprequest.downloadFile); this.httprequest.downloadFile = undefined; this.end(); }
return; return;
} }
// Setup remote desktop & terminal without using native pipes // Setup remote desktop & terminal without using native pipes
if ((this.httprequest.desktop) && (obj.useNativePipes == false)) { if ((this.httprequest.desktop) && (obj.useNativePipes == false)) {
if (data.length > 21 && data.toString().startsWith('**********%%%%%%###**')) { if (data.length > 21 && data.toString().startsWith('**********%%%%%%###**')) {
@ -502,7 +504,7 @@ function createMeshCore(agent) {
return; return;
} }
if ((this.httprequest.terminal) && (obj.useNativePipes == false)) { this.httprequest.terminal.write(data); return; } if ((this.httprequest.terminal) && (obj.useNativePipes == false)) { this.httprequest.terminal.write(data); return; }
if (this.httprequest.state == 0) { if (this.httprequest.state == 0) {
// Check if this is a relay connection // Check if this is a relay connection
if (data == 'c') { this.httprequest.state = 1; sendConsoleText("Tunnel #" + this.httprequest.index + " now active", this.httprequest.sessionid); } if (data == 'c') { this.httprequest.state = 1; sendConsoleText("Tunnel #" + this.httprequest.index + " now active", this.httprequest.sessionid); }
@ -516,24 +518,26 @@ function createMeshCore(agent) {
if (obj.useNativePipes == false) { if (obj.useNativePipes == false) {
// Remote Terminal without using native pipes // Remote Terminal without using native pipes
if (process.platform == "win32") { if (process.platform == "win32") {
this.httprequest.terminal = processManager.CreateProcess("%windir%\\system32\\cmd.exe"); this.httprequest.terminal = childProcess.execFile("%windir%\\system32\\cmd.exe");
} else { } else {
this.httprequest.terminal = processManager.CreateProcess("/bin/sh", "sh", ILibProcessPipe_SpawnTypes.TERM); this.httprequest.terminal = childProcess.execFile("/bin/sh", ["sh"], { type: childProcess.SpawnTypes.TERM });
} }
this.httprequest.terminal.tunnel = this; this.httprequest.terminal.tunnel = this;
this.httprequest.terminal.on('data', function (chunk) { this.tunnel.write(chunk); }); this.httprequest.terminal.on('exit', function (ecode, sig) { this.tunnel.end(); });
this.httprequest.terminal.error.data = function (chunk) { this.parent.tunnel.write(chunk); } this.httprequest.terminal.stdout.on('data', function (chunk) { this.parent.tunnel.write(chunk); });
this.httprequest.terminal.stderr.on('data', function (chunk) { this.parent.tunnel.write(chunk); });
} else { } else {
// Remote terminal using native pipes // Remote terminal using native pipes
if (process.platform == "win32") { if (process.platform == "win32") {
this.httprequest.process = processManager.CreateProcess("%windir%\\system32\\cmd.exe"); this.httprequest.process = childProcess.execFile("%windir%\\system32\\cmd.exe");
} else { } else {
this.httprequest.process = processManager.CreateProcess("/bin/sh", "sh", ILibProcessPipe_SpawnTypes.TERM); this.httprequest.process = childProcess.execFile("/bin/sh", ["sh"], { type: childProcess.SpawnTypes.TERM });
} }
this.httprequest.process.tunnel = this; this.httprequest.process.tunnel = this;
this.httprequest.process.error.data = function (chunk) { this.parent.tunnel.write(chunk); } this.httprequest.process.on('exit', function (ecode, sig) { this.tunnel.end(); });
this.httprequest.process.pipe(this, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text. this.httprequest.process.stderr.on('data', function (chunk) { this.parent.tunnel.write(chunk); });
this.pipe(this.httprequest.process, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text. this.httprequest.process.stdout.pipe(this, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
this.pipe(this.httprequest.process.stdin, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
} }
} }
if (this.httprequest.protocol == 2) { if (this.httprequest.protocol == 2) {
@ -604,7 +608,7 @@ function createMeshCore(agent) {
var response = getDirectoryInfo(cmd.path); var response = getDirectoryInfo(cmd.path);
if (cmd.reqid != undefined) { response.reqid = cmd.reqid; } if (cmd.reqid != undefined) { response.reqid = cmd.reqid; }
this.write(new Buffer(JSON.stringify(response))); this.write(new Buffer(JSON.stringify(response)));
/* /*
// Start the directory watcher // Start the directory watcher
if ((cmd.path != '') && (samepath == false)) { if ((cmd.path != '') && (samepath == false)) {
@ -672,17 +676,17 @@ function createMeshCore(agent) {
//sendConsoleText("Got tunnel #" + this.httprequest.index + " data: " + data, this.httprequest.sessionid); //sendConsoleText("Got tunnel #" + this.httprequest.index + " data: " + data, this.httprequest.sessionid);
} }
} }
// Console state // Console state
var consoleWebSockets = {}; var consoleWebSockets = {};
var consoleHttpRequest = null; var consoleHttpRequest = null;
// Console HTTP response // Console HTTP response
function consoleHttpResponse(response) { function consoleHttpResponse(response) {
response.data = function (data) { sendConsoleText(rstr2hex(buf2rstr(data)), this.sessionid); consoleHttpRequest = null; } response.data = function (data) { sendConsoleText(rstr2hex(buf2rstr(data)), this.sessionid); consoleHttpRequest = null; }
response.close = function () { sendConsoleText('httprequest.response.close', this.sessionid); consoleHttpRequest = null; } response.close = function () { sendConsoleText('httprequest.response.close', this.sessionid); consoleHttpRequest = null; }
}; };
// Process a mesh agent console command // Process a mesh agent console command
function processConsoleCommand(cmd, args, rights, sessionid) { function processConsoleCommand(cmd, args, rights, sessionid) {
try { try {
@ -810,12 +814,14 @@ function createMeshCore(agent) {
} else { } else {
var httprequest = null; var httprequest = null;
try { try {
httprequest = http.request(http.parseUri(args['_'][0])); var options = http.parseUri(args['_'][0]);
options.rejectUnauthorized = 0;
httprequest = http.request(options);
} catch (e) { response = 'Invalid HTTP websocket request'; } } catch (e) { response = 'Invalid HTTP websocket request'; }
if (httprequest != null) { if (httprequest != null) {
httprequest.upgrade = onWebSocketUpgrade; httprequest.upgrade = onWebSocketUpgrade;
httprequest.onerror = function (e) { sendConsoleText('ERROR: ' + JSON.stringify(e)); } httprequest.onerror = function (e) { sendConsoleText('ERROR: ' + JSON.stringify(e)); }
var index = 1; var index = 1;
while (consoleWebSockets[index]) { index++; } while (consoleWebSockets[index]) { index++; }
httprequest.sessionid = sessionid; httprequest.sessionid = sessionid;
@ -949,16 +955,16 @@ function createMeshCore(agent) {
} catch (e) { response = 'Command returned an exception error: ' + e; console.log(e); } } catch (e) { response = 'Command returned an exception error: ' + e; console.log(e); }
if (response != null) { sendConsoleText(response, sessionid); } if (response != null) { sendConsoleText(response, sessionid); }
} }
// Send a mesh agent console command // Send a mesh agent console command
function sendConsoleText(text, sessionid) { function sendConsoleText(text, sessionid) {
if (typeof text == 'object') { text = JSON.stringify(text); } if (typeof text == 'object') { text = JSON.stringify(text); }
mesh.SendCommand({ "action": "msg", "type": "console", "value": text, "sessionid": sessionid }); mesh.SendCommand({ "action": "msg", "type": "console", "value": text, "sessionid": sessionid });
} }
// Called before the process exits // Called before the process exits
//process.exit = function (code) { console.log("Exit with code: " + code.toString()); } //process.exit = function (code) { console.log("Exit with code: " + code.toString()); }
// Called when the server connection state changes // Called when the server connection state changes
function handleServerConnection(state) { function handleServerConnection(state) {
meshServerConnectionState = state; meshServerConnectionState = state;
@ -974,7 +980,7 @@ function createMeshCore(agent) {
//if (selfInfoUpdateTimer == null) { selfInfoUpdateTimer = setInterval(sendPeriodicServerUpdate, 60000); } // Should be a long time, like 20 minutes. For now, 1 minute. //if (selfInfoUpdateTimer == null) { selfInfoUpdateTimer = setInterval(sendPeriodicServerUpdate, 60000); } // Should be a long time, like 20 minutes. For now, 1 minute.
} }
} }
// Build a bunch a self information data that will be sent to the server // Build a bunch a self information data that will be sent to the server
// We need to do this periodically and if anything changes, send the update to the server. // We need to do this periodically and if anything changes, send the update to the server.
function buildSelfInfo() { function buildSelfInfo() {
@ -992,20 +998,20 @@ function createMeshCore(agent) {
} }
return JSON.stringify(r); return JSON.stringify(r);
} }
// Update the server with the latest network interface information // Update the server with the latest network interface information
var sendNetworkUpdateNagleTimer = null; var sendNetworkUpdateNagleTimer = null;
function sendNetworkUpdateNagle() { if (sendNetworkUpdateNagleTimer != null) { clearTimeout(sendNetworkUpdateNagleTimer); sendNetworkUpdateNagleTimer = null; } sendNetworkUpdateNagleTimer = setTimeout(sendNetworkUpdate, 5000); } function sendNetworkUpdateNagle() { if (sendNetworkUpdateNagleTimer != null) { clearTimeout(sendNetworkUpdateNagleTimer); sendNetworkUpdateNagleTimer = null; } sendNetworkUpdateNagleTimer = setTimeout(sendNetworkUpdate, 5000); }
function sendNetworkUpdate(force) { function sendNetworkUpdate(force) {
sendNetworkUpdateNagleTimer = null; sendNetworkUpdateNagleTimer = null;
// Update the network interfaces information data // Update the network interfaces information data
var netInfo = mesh.NetInfo; var netInfo = mesh.NetInfo;
netInfo.action = 'netinfo'; netInfo.action = 'netinfo';
var netInfoStr = JSON.stringify(netInfo); var netInfoStr = JSON.stringify(netInfo);
if ((force == true) || (clearGatewayMac(netInfoStr) != clearGatewayMac(lastNetworkInfo))) { mesh.SendCommand(netInfo); lastNetworkInfo = netInfoStr; } if ((force == true) || (clearGatewayMac(netInfoStr) != clearGatewayMac(lastNetworkInfo))) { mesh.SendCommand(netInfo); lastNetworkInfo = netInfoStr; }
} }
// Called periodically to check if we need to send updates to the server // Called periodically to check if we need to send updates to the server
function sendPeriodicServerUpdate(force) { function sendPeriodicServerUpdate(force) {
if ((amtMeiConnected != 1) || (force == true)) { // If we are pending MEI connection, hold off on updating the server on self-info if ((amtMeiConnected != 1) || (force == true)) { // If we are pending MEI connection, hold off on updating the server on self-info
@ -1017,7 +1023,7 @@ function createMeshCore(agent) {
// Update network information // Update network information
sendNetworkUpdateNagle(force); sendNetworkUpdateNagle(force);
} }
// Get Intel AMT information using MEI // Get Intel AMT information using MEI
function getAmtInfo(func) { function getAmtInfo(func) {
if (amtMei == null || amtMeiConnected != 2) { if (func != null) { func(null); } return; } if (amtMei == null || amtMeiConnected != 2) { if (func != null) { func(null); } return; }
@ -1031,13 +1037,13 @@ function createMeshCore(agent) {
//amtMei.getMACAddresses(function (result) { amtMeiTmpState.mac = result; }); //amtMei.getMACAddresses(function (result) { amtMeiTmpState.mac = result; });
amtMei.getDnsSuffix(function (result) { if (result != null) { amtMeiTmpState.dns = result; } amtMeiState = amtMeiTmpState; sendPeriodicServerUpdate(); if (func != null) { func(amtMeiState); } }); amtMei.getDnsSuffix(function (result) { if (result != null) { amtMeiTmpState.dns = result; } amtMeiState = amtMeiTmpState; sendPeriodicServerUpdate(); if (func != null) { func(amtMeiState); } });
} }
// Called on MicroLMS Intel AMT user notification // Called on MicroLMS Intel AMT user notification
function handleAmtNotification(notification) { function handleAmtNotification(notification) {
var amtMessage = notification.messageId; var amtMessage = notification.messageId;
var amtMessageArg = notification.messageArguments; var amtMessageArg = notification.messageArguments;
var notify = null; var notify = null;
switch (amtMessage) { switch (amtMessage) {
case 'iAMT0050': { case 'iAMT0050': {
// Serial over lan // Serial over lan
@ -1063,14 +1069,14 @@ function createMeshCore(agent) {
break; break;
} }
} }
if (notify != null) { if (notify != null) {
var notification = { "action": "msg", "type": "notify", "value": notify, "tag": "general" }; var notification = { "action": "msg", "type": "notify", "value": notify, "tag": "general" };
//mesh.SendCommand(notification); // no sessionid or userid specified, notification will go to the entire mesh //mesh.SendCommand(notification); // no sessionid or userid specified, notification will go to the entire mesh
//console.log("handleAmtNotification", JSON.stringify(notification)); //console.log("handleAmtNotification", JSON.stringify(notification));
} }
} }
// Starting function // Starting function
obj.start = function () { obj.start = function () {
// Setup the mesh agent event handlers // Setup the mesh agent event handlers
@ -1078,14 +1084,14 @@ function createMeshCore(agent) {
mesh.AddConnectHandler(handleServerConnection); mesh.AddConnectHandler(handleServerConnection);
//mesh.lmsNotification = handleAmtNotification; // TODO //mesh.lmsNotification = handleAmtNotification; // TODO
sendPeriodicServerUpdate(true); // TODO: Check if connected before sending sendPeriodicServerUpdate(true); // TODO: Check if connected before sending
// Parse input arguments // Parse input arguments
//var args = parseArgs(process.argv); //var args = parseArgs(process.argv);
//console.log(args); //console.log(args);
//console.log('Stopping.'); //console.log('Stopping.');
//process.exit(); //process.exit();
// Launch LMS // Launch LMS
try { try {
var lme_heci = require('lme_heci'); var lme_heci = require('lme_heci');
@ -1095,16 +1101,16 @@ function createMeshCore(agent) {
amtLms.on('connect', function () { amtLmsState = 2; }); amtLms.on('connect', function () { amtLmsState = 2; });
} catch (e) { amtLmsState = -1; amtLms = null; } } catch (e) { amtLmsState = -1; amtLms = null; }
} }
obj.stop = function () { obj.stop = function () {
mesh.AddCommandHandler(null); mesh.AddCommandHandler(null);
mesh.AddConnectHandler(null); mesh.AddConnectHandler(null);
} }
function onWebSocketClosed() { sendConsoleText("WebSocket #" + this.httprequest.index + " closed.", this.httprequest.sessionid); delete consoleWebSockets[this.httprequest.index]; } function onWebSocketClosed() { sendConsoleText("WebSocket #" + this.httprequest.index + " closed.", this.httprequest.sessionid); delete consoleWebSockets[this.httprequest.index]; }
function onWebSocketData(data) { sendConsoleText("Got WebSocket #" + this.httprequest.index + " data: " + data, this.httprequest.sessionid); } function onWebSocketData(data) { sendConsoleText("Got WebSocket #" + this.httprequest.index + " data: " + data, this.httprequest.sessionid); }
function onWebSocketSendOk() { sendConsoleText("WebSocket #" + this.index + " SendOK.", this.sessionid); } function onWebSocketSendOk() { sendConsoleText("WebSocket #" + this.index + " SendOK.", this.sessionid); }
function onWebSocketUpgrade(response, s, head) { function onWebSocketUpgrade(response, s, head) {
sendConsoleText("WebSocket #" + this.index + " connected.", this.sessionid); sendConsoleText("WebSocket #" + this.index + " connected.", this.sessionid);
this.s = s; this.s = s;
@ -1112,7 +1118,7 @@ function createMeshCore(agent) {
s.end = onWebSocketClosed; s.end = onWebSocketClosed;
s.data = onWebSocketData; s.data = onWebSocketData;
} }
return obj; return obj;
} }

View File

@ -1,5 +1,5 @@
/* /*
Copyright 2017 Intel Corporation Copyright 2018 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@ -1,6 +1,8 @@
/** /**
* @description Meshcentral Intel AMT Event Parser * @description MeshCentral Intel(R) AMT Event Parser
* @author Ylian Saint-Hilaire & Bryan Roe * @author Ylian Saint-Hilaire & Bryan Roe
* @copyright Intel Corporation 2018
* @license Apache-2.0
* @version v0.0.1 * @version v0.0.1
*/ */

View File

@ -1,6 +1,8 @@
/** /**
* @description Meshcentral Intel AMT Local Scanner * @description MeshCentral Intel(R) AMT Local Scanner
* @author Ylian Saint-Hilaire & Joko Sastriawan * @author Ylian Saint-Hilaire & Joko Sastriawan
* @copyright Intel Corporation 2018
* @license Apache-2.0
* @version v0.0.1 * @version v0.0.1
*/ */

View File

@ -1,6 +1,8 @@
/** /**
* @fileoverview Script Compiler / Decompiler / Runner * @fileoverview Script Compiler / Decompiler / Runner
* @author Ylian Saint-Hilaire * @author Ylian Saint-Hilaire
* @copyright Intel Corporation 2018
* @license Apache-2.0
* @version v0.1.0e * @version v0.1.0e
*/ */

View File

@ -1,8 +1,11 @@
/** /**
* @description Certificate generator * @description Certificate generator
* @author Joko Sastriawan / Ylian Saint-Hilaire * @author Joko Sastriawan / Ylian Saint-Hilaire
* @copyright Intel Corporation 2018
* @license Apache-2.0
* @version v0.0.1 * @version v0.0.1
*/ */
module.exports.CertificateOperations = function () { module.exports.CertificateOperations = function () {
var obj = {}; var obj = {};

View File

@ -1,4 +1,11 @@
 /**
* @description MeshCentral Common Library
* @author Ylian Saint-Hilaire
* @copyright Intel Corporation 2018
* @license Apache-2.0
* @version v0.0.1
*/
var crypto = require('crypto'); var crypto = require('crypto');
// Binary encoding and decoding functions // Binary encoding and decoding functions

4
db.js
View File

@ -1,6 +1,8 @@
/** /**
* @description Meshcentral database * @description MeshCentral database module
* @author Ylian Saint-Hilaire * @author Ylian Saint-Hilaire
* @copyright Intel Corporation 2018
* @license Apache-2.0
* @version v0.0.2 * @version v0.0.2
*/ */

View File

@ -1,6 +1,8 @@
/** /**
* @description Intel AMT Interceptor * @description MeshCentral Intel(R) AMT Interceptor
* @author Ylian Saint-Hilaire * @author Ylian Saint-Hilaire
* @copyright Intel Corporation 2018
* @license Apache-2.0
* @version v0.0.3 * @version v0.0.3
*/ */

View File

@ -1,6 +1,8 @@
/** /**
* @description Meshcentral MeshAgent * @description MeshCentral MeshAgent communication module
* @author Ylian Saint-Hilaire & Bryan Roe * @author Ylian Saint-Hilaire & Bryan Roe
* @copyright Intel Corporation 2018
* @license Apache-2.0
* @version v0.0.1 * @version v0.0.1
*/ */

View File

@ -1,6 +1,8 @@
/** /**
* @description Meshcentral * @description MeshCentral main module
* @author Ylian Saint-Hilaire * @author Ylian Saint-Hilaire
* @copyright Intel Corporation 2018
* @license Apache-2.0
* @version v0.0.1 * @version v0.0.1
*/ */

View File

@ -1,6 +1,8 @@
/** /**
* @description Meshcentral MeshMail * @description MeshCentral e-mail server communication modules
* @author Ylian Saint-Hilaire * @author Ylian Saint-Hilaire
* @copyright Intel Corporation 2018
* @license Apache-2.0
* @version v0.0.1 * @version v0.0.1
*/ */
@ -32,7 +34,14 @@ module.exports.CreateMeshMain = function (parent) {
// Perform all e-mail substitution // Perform all e-mail substitution
function mailReplacements(text, domain, username, email, cookie) { function mailReplacements(text, domain, username, email, cookie) {
var url = 'http' + ((obj.parent.args.notls == null) ? 's' : '') + '://' + parent.certificates.CommonName + ':' + obj.parent.args.port + domain.url; var url;
if (domain.dns == null) {
// Default domain or subdomain of the default.
url = 'http' + ((obj.parent.args.notls == null) ? 's' : '') + '://' + parent.certificates.CommonName + ':' + obj.parent.args.port + domain.url;
} else {
// Domain with a DNS name.
url = 'http' + ((obj.parent.args.notls == null) ? 's' : '') + '://' + domain.dns + ':' + obj.parent.args.port + domain.url;
}
if (cookie != null) { text = text.split('[[[CALLBACKURL]]]').join(url + 'checkmail?c=' + cookie) } if (cookie != null) { text = text.split('[[[CALLBACKURL]]]').join(url + 'checkmail?c=' + cookie) }
return text.split('[[[USERNAME]]]').join(username).split('[[[SERVERURL]]]').join(url).split('[[[SERVERNAME]]]').join(domain.title); return text.split('[[[USERNAME]]]').join(username).split('[[[SERVERURL]]]').join(url).split('[[[SERVERNAME]]]').join(domain.title);
} }

View File

@ -1,6 +1,8 @@
/** /**
* @description Meshcentral MeshRelay * @description MeshCentral connection relay module
* @author Ylian Saint-Hilaire * @author Ylian Saint-Hilaire
* @copyright Intel Corporation 2018
* @license Apache-2.0
* @version v0.0.1 * @version v0.0.1
*/ */

View File

@ -1,6 +1,8 @@
/** /**
* @description Meshcentral Mesh Agent Local Scanner * @description MeshCentral Mesh Agent Local Scanner
* @author Ylian Saint-Hilaire * @author Ylian Saint-Hilaire
* @copyright Intel Corporation 2018
* @license Apache-2.0
* @version v0.0.1 * @version v0.0.1
*/ */

View File

@ -1,6 +1,8 @@
/** /**
* @description Meshcentral MeshAgent * @description MeshCentral MeshAgent
* @author Ylian Saint-Hilaire & Bryan Roe * @author Ylian Saint-Hilaire & Bryan Roe
* @copyright Intel Corporation 2018
* @license Apache-2.0
* @version v0.0.1 * @version v0.0.1
*/ */

View File

@ -1,6 +1,8 @@
/** /**
* @description Meshcentral Intel AMT MPS server * @description MeshCentral Intel(R) AMT MPS server
* @author Ylian Saint-Hilaire * @author Ylian Saint-Hilaire
* @copyright Intel Corporation 2018
* @license Apache-2.0
* @version v0.0.1 * @version v0.0.1
*/ */

View File

@ -1,6 +1,8 @@
/** /**
* @description Meshcentral Multi-Server Support * @description MeshCentral Multi-Server Support
* @author Ylian Saint-Hilaire * @author Ylian Saint-Hilaire
* @copyright Intel Corporation 2018
* @license Apache-2.0
* @version v0.0.1 * @version v0.0.1
*/ */

View File

@ -1,6 +1,6 @@
{ {
"name": "meshcentral", "name": "meshcentral",
"version": "0.1.1-r", "version": "0.1.1-u",
"keywords": [ "keywords": [
"Remote Management", "Remote Management",
"Intel AMT", "Intel AMT",

View File

@ -2,6 +2,7 @@ MeshCentral
=========== ===========
For more information, [visit MeshCommander.com/MeshCentral2](http://www.meshcommander.com/meshcentral2). For more information, [visit MeshCommander.com/MeshCentral2](http://www.meshcommander.com/meshcentral2).
Download the [full PDF user's guide](http://info.meshcentral.com/downloads/meshcentral2/MeshCentral2UserGuide.pdf) with more information on installing, configuring and running MeshCentral2. Download the [full PDF user's guide](http://info.meshcentral.com/downloads/meshcentral2/MeshCentral2UserGuide.pdf) with more information on installing, configuring and running MeshCentral2.
This is a full computer management web site. With MeshCentral, you can run your own web server and it to remotely manage and control computers on a local network or anywhere on the internet. Once you get the server started, will create a mesh (a group of computers) and then download and install a mesh agent on each computer you want to manage. A minute later, the new computer will show up on the web site and you can take control of it, etc. MeshCentral includes full web-based remote desktop, terminal and file management capability. This is a full computer management web site. With MeshCentral, you can run your own web server and it to remotely manage and control computers on a local network or anywhere on the internet. Once you get the server started, will create a mesh (a group of computers) and then download and install a mesh agent on each computer you want to manage. A minute later, the new computer will show up on the web site and you can take control of it, etc. MeshCentral includes full web-based remote desktop, terminal and file management capability.

View File

@ -1,6 +1,8 @@
/** /**
* @description Meshcentral web server * @description Meshcentral web server
* @author Ylian Saint-Hilaire * @author Ylian Saint-Hilaire
* @copyright Intel Corporation 2018
* @license Apache-2.0
* @version v0.0.1 * @version v0.0.1
*/ */

View File

@ -1,6 +1,8 @@
/** /**
* @description Meshcentral1 legacy swarm server, used to update agents and get them on MeshCentral2 * @description MeshCentral v1 legacy Swarm Server, used to update agents and get them on MeshCentral2
* @author Ylian Saint-Hilaire * @author Ylian Saint-Hilaire
* @copyright Intel Corporation 2018
* @license Apache-2.0
* @version v0.0.1 * @version v0.0.1
*/ */

View File

@ -1,6 +1,8 @@
/** /**
* @description Meshcentral web server * @description MeshCentral web server
* @author Ylian Saint-Hilaire * @author Ylian Saint-Hilaire
* @copyright Intel Corporation 2018
* @license Apache-2.0
* @version v0.0.1 * @version v0.0.1
*/ */
@ -126,8 +128,8 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
{ {
var dnscount = 0; var dnscount = 0;
obj.tlsSniCredentials = {}; obj.tlsSniCredentials = {};
for (var i in obj.certificates.dns) { if (obj.parent.config.domains[i].dns != null) { obj.dnsDomains[obj.parent.config.domains[i].dns.toLowerCase()] = obj.parent.config.domains[i]; obj.tlsSniCredentials[obj.parent.config.domains[i].dns] = obj.crypto.createCredentials(obj.certificates.dns[i]).context; dnscount++; } } for (var i in obj.certificates.dns) { if (obj.parent.config.domains[i].dns != null) { obj.dnsDomains[obj.parent.config.domains[i].dns.toLowerCase()] = obj.parent.config.domains[i]; obj.tlsSniCredentials[obj.parent.config.domains[i].dns] = obj.tls.createSecureContext(obj.certificates.dns[i]).context; dnscount++; } }
if (dnscount > 0) { obj.tlsSniCredentials[''] = obj.crypto.createCredentials({ cert: obj.certificates.web.cert, key: obj.certificates.web.key, ca: obj.certificates.ca }).context; } else { obj.tlsSniCredentials = null; } if (dnscount > 0) { obj.tlsSniCredentials[''] = obj.tls.createSecureContext({ cert: obj.certificates.web.cert, key: obj.certificates.web.key, ca: obj.certificates.ca }).context; } else { obj.tlsSniCredentials = null; }
} }
function TlsSniCallback(name, cb) { var c = obj.tlsSniCredentials[name]; if (c != null) { cb(null, c); } else { cb(null, obj.tlsSniCredentials['']); } } function TlsSniCallback(name, cb) { var c = obj.tlsSniCredentials[name]; if (c != null) { cb(null, c); } else { cb(null, obj.tlsSniCredentials['']); } }
@ -1535,6 +1537,7 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
obj.app.post('/restoreserver.ashx', handleRestoreRequest); obj.app.post('/restoreserver.ashx', handleRestoreRequest);
if (parent.multiServer != null) { obj.app.ws('/meshserver.ashx', function (ws, req) { parent.multiServer.CreatePeerInServer(parent.multiServer, ws, req); } ); } if (parent.multiServer != null) { obj.app.ws('/meshserver.ashx', function (ws, req) { parent.multiServer.CreatePeerInServer(parent.multiServer, ws, req); } ); }
for (var i in parent.config.domains) { for (var i in parent.config.domains) {
if (parent.config.domains[i].dns != null) { continue; } // This is a subdomain with a DNS name, no added HTTP bindings needed.
var url = parent.config.domains[i].url; var url = parent.config.domains[i].url;
obj.app.get(url, handleRootRequest); obj.app.get(url, handleRootRequest);
obj.app.get(url + 'terms', handleTermsRequest); obj.app.get(url + 'terms', handleTermsRequest);