Added CIRA timeout

This commit is contained in:
Ylian Saint-Hilaire 2018-05-03 11:09:29 -07:00
parent 08e6a4302e
commit 202f7c7e6a
11 changed files with 49 additions and 34 deletions

View File

@ -24,8 +24,8 @@ module.exports.CreateAmtScanner = function (parent) {
obj.pendingSendTimer = null; obj.pendingSendTimer = null;
obj.mainTimer = null; obj.mainTimer = null;
obj.nextTag = 0; obj.nextTag = 0;
var PeriodicScanTime = 30000; // Interval between scan sweeps const PeriodicScanTime = 30000; // Interval between scan sweeps
var PeriodicScanTimeout = 65000; // After this time, timeout the device. const PeriodicScanTimeout = 65000; // After this time, timeout the device.
// Build a RMCP packet with a given tag field // Build a RMCP packet with a given tag field
obj.buildRmcpPing = function (tag) { obj.buildRmcpPing = function (tag) {

View File

@ -10,16 +10,16 @@ module.exports.CreateAmtScriptEngine = function () {
var o = {}; var o = {};
// Core functions // Core functions
script_functionTable1 = ['nop', 'jump', 'set', 'print', 'dialog', 'getitem', 'substr', 'indexof', 'split', 'join', 'length', 'jsonparse', 'jsonstr', 'add', 'substract', 'parseint', 'wsbatchenum', 'wsput', 'wscreate', 'wsdelete', 'wsexec', 'scriptspeed', 'wssubscribe', 'wsunsubscribe', 'readchar', 'signwithdummyca']; const script_functionTable1 = ['nop', 'jump', 'set', 'print', 'dialog', 'getitem', 'substr', 'indexof', 'split', 'join', 'length', 'jsonparse', 'jsonstr', 'add', 'substract', 'parseint', 'wsbatchenum', 'wsput', 'wscreate', 'wsdelete', 'wsexec', 'scriptspeed', 'wssubscribe', 'wsunsubscribe', 'readchar', 'signwithdummyca'];
// functions of type ARG1 = func(ARG2, ARG3, ARG4, ARG5, ARG6) // functions of type ARG1 = func(ARG2, ARG3, ARG4, ARG5, ARG6)
script_functionTable2 = ['encodeuri', 'decodeuri', 'passwordcheck', 'atob', 'btoa', 'hex2str', 'str2hex', 'random', 'md5', 'maketoarray', 'readshort', 'readshortx', 'readint', 'readsint', 'readintx', 'shorttostr', 'shorttostrx', 'inttostr', 'inttostrx']; const script_functionTable2 = ['encodeuri', 'decodeuri', 'passwordcheck', 'atob', 'btoa', 'hex2str', 'str2hex', 'random', 'md5', 'maketoarray', 'readshort', 'readshortx', 'readint', 'readsint', 'readintx', 'shorttostr', 'shorttostrx', 'inttostr', 'inttostrx'];
// functions of type ARG1 = func(ARG2, ARG3, ARG4, ARG5, ARG6) // functions of type ARG1 = func(ARG2, ARG3, ARG4, ARG5, ARG6)
//script_functionTableX2 = [encodeURI, decodeURI, passwordcheck, window.atob.bind(window), window.btoa.bind(window), hex2rstr, rstr2hex, random, rstr_md5, MakeToArray, ReadShort, ReadShortX, ReadInt, ReadSInt, ReadIntX, ShortToStr, ShortToStrX, IntToStr, IntToStrX]; //script_functionTableX2 = [encodeURI, decodeURI, passwordcheck, window.atob.bind(window), window.btoa.bind(window), hex2rstr, rstr2hex, random, rstr_md5, MakeToArray, ReadShort, ReadShortX, ReadInt, ReadSInt, ReadIntX, ShortToStr, ShortToStrX, IntToStr, IntToStrX];
// Optional functions of type ARG1 = func(ARG2, ARG3, ARG4, ARG5, ARG6) // Optional functions of type ARG1 = func(ARG2, ARG3, ARG4, ARG5, ARG6)
script_functionTable3 = ['pullsystemstatus', 'pulleventlog', 'pullauditlog', 'pullcertificates', 'pullwatchdog', 'pullsystemdefense', 'pullhardware', 'pulluserinfo', 'pullremoteaccess', 'highlightblock', 'disconnect', 'getsidstring', 'getsidbytearray']; const script_functionTable3 = ['pullsystemstatus', 'pulleventlog', 'pullauditlog', 'pullcertificates', 'pullwatchdog', 'pullsystemdefense', 'pullhardware', 'pulluserinfo', 'pullremoteaccess', 'highlightblock', 'disconnect', 'getsidstring', 'getsidbytearray'];
/* /*
// Optional functions of type ARG1 = func(ARG2, ARG3, ARG4, ARG5, ARG6) // Optional functions of type ARG1 = func(ARG2, ARG3, ARG4, ARG5, ARG6)

View File

@ -6,7 +6,7 @@
* @version v0.0.1 * @version v0.0.1
*/ */
var crypto = require('crypto'); const crypto = require('crypto');
// Binary encoding and decoding functions // Binary encoding and decoding functions
module.exports.ReadShort = function(v, p) { return (v.charCodeAt(p) << 8) + v.charCodeAt(p + 1); } module.exports.ReadShort = function(v, p) { return (v.charCodeAt(p) << 8) + v.charCodeAt(p + 1); }

View File

@ -6,8 +6,8 @@
* @version v0.0.3 * @version v0.0.3
*/ */
var crypto = require('crypto'); const crypto = require('crypto');
var common = require('./common.js'); const common = require('./common.js');
var HttpInterceptorAuthentications = {}; var HttpInterceptorAuthentications = {};
var RedirInterceptorAuthentications = {}; var RedirInterceptorAuthentications = {};

View File

@ -27,7 +27,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
obj.agentCoreCheck = 0; obj.agentCoreCheck = 0;
obj.agentInfo; obj.agentInfo;
obj.agentUpdate = null; obj.agentUpdate = null;
var agentUpdateBlockSize = 65520; const agentUpdateBlockSize = 65520;
obj.remoteaddr = obj.ws._socket.remoteAddress; obj.remoteaddr = obj.ws._socket.remoteAddress;
obj.useSHA386 = false; obj.useSHA386 = false;
if (obj.remoteaddr.startsWith('::ffff:')) { obj.remoteaddr = obj.remoteaddr.substring(7); } if (obj.remoteaddr.startsWith('::ffff:')) { obj.remoteaddr = obj.remoteaddr.substring(7); }

View File

@ -17,19 +17,19 @@ module.exports.CreateMeshMain = function (parent) {
const nodemailer = require('nodemailer'); const nodemailer = require('nodemailer');
// Default account email validation mail // Default account email validation mail
var accountCheckSubject = '[[[SERVERNAME]]] - Email Verification'; const accountCheckSubject = '[[[SERVERNAME]]] - Email Verification';
var accountCheckMailHtml = '<div style="font-family:Arial,Helvetica,sans-serif"><table style="background-color:#003366;color:lightgray;width:100%" cellpadding=8><tr><td><b style="font-size:20px;font-family:Arial,Helvetica,sans-serif">[[[SERVERNAME]]] - Verification</b></td></tr></table><p>Hi [[[USERNAME]]], <a href="[[[SERVERURL]]]">[[[SERVERNAME]]]</a> is requesting email verification, click on the following link to complete the process.</p><p style="margin-left:30px"><a href="[[[CALLBACKURL]]]">Click here to verify your e-mail address.</a></p>If you did not initiate this request, please ignore this mail.</div>'; const accountCheckMailHtml = '<div style="font-family:Arial,Helvetica,sans-serif"><table style="background-color:#003366;color:lightgray;width:100%" cellpadding=8><tr><td><b style="font-size:20px;font-family:Arial,Helvetica,sans-serif">[[[SERVERNAME]]] - Verification</b></td></tr></table><p>Hi [[[USERNAME]]], <a href="[[[SERVERURL]]]">[[[SERVERNAME]]]</a> is requesting email verification, click on the following link to complete the process.</p><p style="margin-left:30px"><a href="[[[CALLBACKURL]]]">Click here to verify your e-mail address.</a></p>If you did not initiate this request, please ignore this mail.</div>';
var accountCheckMailText = '[[[SERVERNAME]]] - Verification\r\n\r\nHi [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) is performing an e-mail verification. Nagivate to the following link to complete the process: [[[CALLBACKURL]]]\r\nIf you did not initiate this request, please ignore this mail.\r\n'; const accountCheckMailText = '[[[SERVERNAME]]] - Verification\r\n\r\nHi [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) is performing an e-mail verification. Nagivate to the following link to complete the process: [[[CALLBACKURL]]]\r\nIf you did not initiate this request, please ignore this mail.\r\n';
// Default account reset mail // Default account reset mail
var accountResetSubject = '[[[SERVERNAME]]] - Account Reset'; const accountResetSubject = '[[[SERVERNAME]]] - Account Reset';
var accountResetMailHtml = '<div style="font-family:Arial,Helvetica,sans-serif"><table style="background-color:#003366;color:lightgray;width:100%" cellpadding=8><tr><td><b style="font-size:20px;font-family:Arial,Helvetica,sans-serif">[[[SERVERNAME]]] - Verification</b></td></tr></table><p>Hi [[[USERNAME]]], <a href="[[[SERVERURL]]]">[[[SERVERNAME]]]</a> is requesting an account password reset, click on the following link to complete the process.</p><p style="margin-left:30px"><a href="[[[CALLBACKURL]]]">Click here to reset your account password.</a></p>If you did not initiate this request, please ignore this mail.</div>'; const accountResetMailHtml = '<div style="font-family:Arial,Helvetica,sans-serif"><table style="background-color:#003366;color:lightgray;width:100%" cellpadding=8><tr><td><b style="font-size:20px;font-family:Arial,Helvetica,sans-serif">[[[SERVERNAME]]] - Verification</b></td></tr></table><p>Hi [[[USERNAME]]], <a href="[[[SERVERURL]]]">[[[SERVERNAME]]]</a> is requesting an account password reset, click on the following link to complete the process.</p><p style="margin-left:30px"><a href="[[[CALLBACKURL]]]">Click here to reset your account password.</a></p>If you did not initiate this request, please ignore this mail.</div>';
var accountResetMailText = '[[[SERVERNAME]]] - Account Reset\r\n\r\nHi [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) is requesting an account password reset. Nagivate to the following link to complete the process: [[[CALLBACKURL]]]\r\nIf you did not initiate this request, please ignore this mail.\r\n'; const accountResetMailText = '[[[SERVERNAME]]] - Account Reset\r\n\r\nHi [[[USERNAME]]], [[[SERVERNAME]]] ([[[SERVERURL]]]) is requesting an account password reset. Nagivate to the following link to complete the process: [[[CALLBACKURL]]]\r\nIf you did not initiate this request, please ignore this mail.\r\n';
// Default account invite mail // Default account invite mail
var accountInviteSubject = '[[[SERVERNAME]]] - Agent Installation Invitation'; const accountInviteSubject = '[[[SERVERNAME]]] - Agent Installation Invitation';
var accountInviteMailHtml = '<div style="font-family:Arial,Helvetica,sans-serif"><table style="background-color:#003366;color:lightgray;width:100%" cellpadding=8><tr><td><b style="font-size:20px;font-family:Arial,Helvetica,sans-serif">[[[SERVERNAME]]] - Agent Installation</b></td></tr></table><p>User [[[USERNAME]]] on server <a href="[[[SERVERURL]]]">[[[SERVERNAME]]]</a> is requesting that you install a remote management agent. WARNING: this will allow the requester to <u>take control of your computer</u>. If you wish to do this, click on the following link to download the agent.</p><p style="margin-left:30px"><a href="[[[CALLBACKURL]]]">Click here to download the MeshAgent for Windows.</a></p>If you did not know about this request, please ignore this mail.</div>'; const accountInviteMailHtml = '<div style="font-family:Arial,Helvetica,sans-serif"><table style="background-color:#003366;color:lightgray;width:100%" cellpadding=8><tr><td><b style="font-size:20px;font-family:Arial,Helvetica,sans-serif">[[[SERVERNAME]]] - Agent Installation</b></td></tr></table><p>User [[[USERNAME]]] on server <a href="[[[SERVERURL]]]">[[[SERVERNAME]]]</a> is requesting that you install a remote management agent. WARNING: this will allow the requester to <u>take control of your computer</u>. If you wish to do this, click on the following link to download the agent.</p><p style="margin-left:30px"><a href="[[[CALLBACKURL]]]">Click here to download the MeshAgent for Windows.</a></p>If you did not know about this request, please ignore this mail.</div>';
var accountInviteMailText = '[[[SERVERNAME]]] - Agent Installation Invitation\r\n\r\nUser [[[USERNAME]]] on server [[[SERVERNAME]]] ([[[SERVERURL]]]) is requesting you install a remote management agent. WARNING: This will allow the requester to take control of your computer. If you wish to do this, click on the following link to download the agent: [[[CALLBACKURL]]]\r\nIf you do not know about this request, please ignore this mail.\r\n'; const accountInviteMailText = '[[[SERVERNAME]]] - Agent Installation Invitation\r\n\r\nUser [[[USERNAME]]] on server [[[SERVERNAME]]] ([[[SERVERURL]]]) is requesting you install a remote management agent. WARNING: This will allow the requester to take control of your computer. If you wish to do this, click on the following link to download the agent: [[[CALLBACKURL]]]\r\nIf you do not know about this request, please ignore this mail.\r\n';
function EscapeHtml(x) { if (typeof x == "string") return x.replace(/&/g, '&amp;').replace(/>/g, '&gt;').replace(/</g, '&lt;').replace(/"/g, '&quot;').replace(/'/g, '&apos;'); if (typeof x == "boolean") return x; if (typeof x == "number") return x; } function EscapeHtml(x) { if (typeof x == "string") return x.replace(/&/g, '&amp;').replace(/>/g, '&gt;').replace(/</g, '&lt;').replace(/"/g, '&quot;').replace(/'/g, '&apos;'); if (typeof x == "boolean") return x; if (typeof x == "number") return x; }
function EscapeHtmlBreaks(x) { if (typeof x == "string") return x.replace(/&/g, '&amp;').replace(/>/g, '&gt;').replace(/</g, '&lt;').replace(/"/g, '&quot;').replace(/'/g, '&apos;').replace(/\r/g, '<br />').replace(/\n/g, '').replace(/\t/g, '&nbsp;&nbsp;'); if (typeof x == "boolean") return x; if (typeof x == "number") return x; } function EscapeHtmlBreaks(x) { if (typeof x == "string") return x.replace(/&/g, '&amp;').replace(/>/g, '&gt;').replace(/</g, '&lt;').replace(/"/g, '&quot;').replace(/'/g, '&apos;').replace(/\r/g, '<br />').replace(/\n/g, '').replace(/\t/g, '&nbsp;&nbsp;'); if (typeof x == "boolean") return x; if (typeof x == "number") return x; }

View File

@ -16,9 +16,9 @@ module.exports.CreateMeshScanner = function (parent) {
obj.servers4 = {}; obj.servers4 = {};
obj.servers6 = {}; obj.servers6 = {};
obj.mainTimer = null; obj.mainTimer = null;
var periodicScanTime = (60000 * 20); // Interval between scans, 20 minutes. const periodicScanTime = (60000 * 20); // Interval between scans, 20 minutes.
var membershipIPv4 = '239.255.255.235'; const membershipIPv4 = '239.255.255.235';
var membershipIPv6 = 'FF02:0:0:0:0:0:0:FE'; const membershipIPv6 = 'FF02:0:0:0:0:0:0:FE';
obj.agentCertificateHashHex = parent.certificateOperations.forge.pki.getPublicKeyFingerprint(parent.certificateOperations.forge.pki.certificateFromPem(parent.certificates.agent.cert).publicKey, { md: parent.certificateOperations.forge.md.sha384.create(), encoding: 'hex' }).toUpperCase(); obj.agentCertificateHashHex = parent.certificateOperations.forge.pki.getPublicKeyFingerprint(parent.certificateOperations.forge.pki.certificateFromPem(parent.certificates.agent.cert).publicKey, { md: parent.certificateOperations.forge.md.sha384.create(), encoding: 'hex' }).toUpperCase();
obj.error = 0; obj.error = 0;

View File

@ -14,9 +14,12 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
obj.args = args; obj.args = args;
obj.certificates = certificates; obj.certificates = certificates;
obj.ciraConnections = {}; obj.ciraConnections = {};
var common = require('./common.js'); const common = require('./common.js');
var net = require('net'); const net = require('net');
var tls = require('tls'); const tls = require('tls');
const MAX_IDLE = 90000; // 90 seconds max idle time, higher than the typical KEEP-ALIVE periode of 60 seconds
const CHECK_INTERVAL = 30000; // 30 seconds check interval
if (obj.args.tlsoffload) { if (obj.args.tlsoffload) {
obj.server = net.createServer(onConnection); obj.server = net.createServer(onConnection);
@ -96,7 +99,15 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
} }
socket.setEncoding('binary'); socket.setEncoding('binary');
Debug(1, 'MPS:New CIRA connection'); Debug(1, 'MPS:New CIRA connection');
// Setup the CIRA keep alive timer
socket.lastping = new Date().getTime(); // Get current time in milliseconds from epoch
socket.timer = setInterval(function () {
const now = new Date().getTime();
Debug(3, "MPS:Check interval:" + (socket.lastping && (socket.lastping + MAX_IDLE) < now));
if (socket.lastping && ((socket.lastping + MAX_IDLE) < now)) { Debug(1, "MPS:CIRA timeout, disconnecting."); try { socket.end(); } catch (e) { } }
}, CHECK_INTERVAL);
socket.addListener("data", function (data) { socket.addListener("data", function (data) {
if (args.mpsdebug) { var buf = new Buffer(data, "binary"); console.log('MPS <-- (' + buf.length + '):' + buf.toString('hex')); } // Print out received bytes if (args.mpsdebug) { var buf = new Buffer(data, "binary"); console.log('MPS <-- (' + buf.length + '):' + buf.toString('hex')); } // Print out received bytes
socket.tag.accumulator += data; socket.tag.accumulator += data;
@ -167,6 +178,9 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
} }
try { try {
// Set the last time we received data on the CIRA channel
socket.lastping = new Date().getTime();
// Parse all of the APF data we can // Parse all of the APF data we can
var l = 0; var l = 0;
do { l = ProcessCommand(socket); if (l > 0) { socket.tag.accumulator = socket.tag.accumulator.substring(l); } } while (l > 0); do { l = ProcessCommand(socket); if (l > 0) { socket.tag.accumulator = socket.tag.accumulator.substring(l); } } while (l > 0);
@ -530,6 +544,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
socket.addListener("close", function () { socket.addListener("close", function () {
Debug(1, 'MPS:CIRA connection closed'); Debug(1, 'MPS:CIRA connection closed');
if (socket.timer) { try { clearInterval(socket.timer); } catch (e) { } socket.timer = null; }
try { delete obj.ciraConnections[socket.tag.nodeid]; } catch (e) { } try { delete obj.ciraConnections[socket.tag.nodeid]; } catch (e) { }
obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, 2); obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, 2);
}); });

View File

@ -1,6 +1,6 @@
{ {
"name": "meshcentral", "name": "meshcentral",
"version": "0.1.7-g", "version": "0.1.7-h",
"keywords": [ "keywords": [
"Remote Management", "Remote Management",
"Intel AMT", "Intel AMT",

View File

@ -1,13 +1,13 @@
// check out https://github.com/tj/node-pwd // check out https://github.com/tj/node-pwd
// Module dependencies. // Module dependencies.
var crypto = require('crypto'); const crypto = require('crypto');
// Bytesize. // Bytesize.
var len = 128; const len = 128;
// Iterations. ~300ms // Iterations. ~300ms
var iterations = 12000; const iterations = 12000;
/** /**
* Hashes a password with optional `salt`, otherwise * Hashes a password with optional `salt`, otherwise

View File

@ -15,12 +15,12 @@ module.exports.CreateSwarmServer = function (parent, db, args, certificates) {
obj.certificates = certificates; obj.certificates = certificates;
obj.legacyAgentConnections = {}; obj.legacyAgentConnections = {};
obj.migrationAgents = {}; obj.migrationAgents = {};
var common = require('./common.js'); const common = require('./common.js');
var net = require('net'); const net = require('net');
var tls = require('tls'); const tls = require('tls');
var forge = require('node-forge'); const forge = require('node-forge');
var LegacyMeshProtocol = { const LegacyMeshProtocol = {
NODEPUSH: 1, // Used to send a node block to another peer. NODEPUSH: 1, // Used to send a node block to another peer.
NODEPULL: 2, // Used to send a pull block to another peer. NODEPULL: 2, // Used to send a pull block to another peer.
NODENOTIFY: 3, // Used to indicate the node ID to other peers. NODENOTIFY: 3, // Used to indicate the node ID to other peers.