Made MQTT optional.
This commit is contained in:
parent
8abb6ef910
commit
7bba856984
|
@ -116,6 +116,7 @@
|
||||||
<Compile Include="meshrelay.js" />
|
<Compile Include="meshrelay.js" />
|
||||||
<Compile Include="meshuser.js" />
|
<Compile Include="meshuser.js" />
|
||||||
<Compile Include="mpsserver.js" />
|
<Compile Include="mpsserver.js" />
|
||||||
|
<Compile Include="mqttbroker.js" />
|
||||||
<Compile Include="public\scripts\agent-redir-rtc-0.1.0.js" />
|
<Compile Include="public\scripts\agent-redir-rtc-0.1.0.js" />
|
||||||
<Compile Include="swarmserver.js" />
|
<Compile Include="swarmserver.js" />
|
||||||
<Compile Include="multiserver.js" />
|
<Compile Include="multiserver.js" />
|
||||||
|
|
|
@ -824,8 +824,9 @@ function CreateMeshCentralServer(config, args) {
|
||||||
|
|
||||||
// Create APF server to hook into webserver
|
// Create APF server to hook into webserver
|
||||||
obj.apfserver = require('./apfserver.js').CreateApfServer(obj, obj.db, obj.args);
|
obj.apfserver = require('./apfserver.js').CreateApfServer(obj, obj.db, obj.args);
|
||||||
|
|
||||||
// Create MQTT Broker to hook into webserver and mpsserver
|
// Create MQTT Broker to hook into webserver and mpsserver
|
||||||
obj.mqttbroker = require("./mqttbroker.js").CreateMQTTBroker(obj,obj.db,obj.args);
|
if (obj.config.mqtt != null) { obj.mqttbroker = require("./mqttbroker.js").CreateMQTTBroker(obj, obj.db, obj.args); }
|
||||||
|
|
||||||
// Start the web server and if needed, the redirection web server.
|
// Start the web server and if needed, the redirection web server.
|
||||||
obj.webserver = require('./webserver.js').CreateWebServer(obj, obj.db, obj.args, obj.certificates);
|
obj.webserver = require('./webserver.js').CreateWebServer(obj, obj.db, obj.args, obj.certificates);
|
||||||
|
@ -1828,6 +1829,7 @@ function mainStart() {
|
||||||
if (require('os').platform() == 'win32') { modules.push('node-windows'); if (sspi == true) { modules.push('node-sspi'); } } // Add Windows modules
|
if (require('os').platform() == 'win32') { modules.push('node-windows'); if (sspi == true) { modules.push('node-sspi'); } } // Add Windows modules
|
||||||
if (ldap == true) { modules.push('ldapauth-fork'); }
|
if (ldap == true) { modules.push('ldapauth-fork'); }
|
||||||
if (config.letsencrypt != null) { modules.push('greenlock'); modules.push('le-store-certbot'); modules.push('le-challenge-fs'); modules.push('le-acme-core'); } // Add Greenlock Modules
|
if (config.letsencrypt != null) { modules.push('greenlock'); modules.push('le-store-certbot'); modules.push('le-challenge-fs'); modules.push('le-acme-core'); } // Add Greenlock Modules
|
||||||
|
if (config.mqtt != null) { modules.push('mqtt'); modules.push('aedes'); } // Add MQTT Modules
|
||||||
if (config.settings.mongodb != null) { modules.push('mongodb'); } // Add MongoDB, official driver.
|
if (config.settings.mongodb != null) { modules.push('mongodb'); } // Add MongoDB, official driver.
|
||||||
else if (config.settings.xmongodb != null) { modules.push('mongojs'); } // Add MongoJS, old driver.
|
else if (config.settings.xmongodb != null) { modules.push('mongojs'); } // Add MongoJS, old driver.
|
||||||
if (config.smtp != null) { modules.push('nodemailer'); } // Add SMTP support
|
if (config.smtp != null) { modules.push('nodemailer'); } // Add SMTP support
|
||||||
|
|
66
mpsserver.js
66
mpsserver.js
|
@ -155,11 +155,11 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
||||||
disconnectCommandCount: disconnectCommandCount,
|
disconnectCommandCount: disconnectCommandCount,
|
||||||
socketClosedCount: socketClosedCount,
|
socketClosedCount: socketClosedCount,
|
||||||
socketErrorCount: socketErrorCount,
|
socketErrorCount: socketErrorCount,
|
||||||
maxDomainDevicesReached : maxDomainDevicesReached
|
maxDomainDevicesReached: maxDomainDevicesReached
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// required for TLS piping to MQTT broker
|
// Required for TLS piping to MQTT broker
|
||||||
function SerialTunnel(options) {
|
function SerialTunnel(options) {
|
||||||
var obj = new require('stream').Duplex(options);
|
var obj = new require('stream').Duplex(options);
|
||||||
obj.forwardwrite = null;
|
obj.forwardwrite = null;
|
||||||
|
@ -167,12 +167,13 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
||||||
obj._write = function (chunk, encoding, callback) { if (obj.forwardwrite != null) { obj.forwardwrite(chunk); } else { console.err("Failed to fwd _write."); } if (callback) callback(); }; // Pass data written to forward
|
obj._write = function (chunk, encoding, callback) { if (obj.forwardwrite != null) { obj.forwardwrite(chunk); } else { console.err("Failed to fwd _write."); } if (callback) callback(); }; // Pass data written to forward
|
||||||
obj._read = function (size) { }; // Push nothing, anything to read should be pushed from updateBuffer()
|
obj._read = function (size) { }; // Push nothing, anything to read should be pushed from updateBuffer()
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return's the length of an MQTT packet
|
||||||
function getMQTTPacketLength(chunk) {
|
function getMQTTPacketLength(chunk) {
|
||||||
var packet_len = 0;
|
var packet_len = 0;
|
||||||
if (chunk.readUInt8(0)==16) {
|
if (chunk.readUInt8(0) == 16) {
|
||||||
if (chunk.readUInt8(1) < 128 ) {
|
if (chunk.readUInt8(1) < 128) {
|
||||||
packet_len += chunk.readUInt8(1) + 2;
|
packet_len += chunk.readUInt8(1) + 2;
|
||||||
} else {
|
} else {
|
||||||
// continuation bit, get real value and do next
|
// continuation bit, get real value and do next
|
||||||
|
@ -188,15 +189,16 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
||||||
if (chunk.readUInt8(4) < 128) {
|
if (chunk.readUInt8(4) < 128) {
|
||||||
packet_len += 1 + chunk.readUInt8(4) * 128 * 128 * 128;
|
packet_len += 1 + chunk.readUInt8(4) * 128 * 128 * 128;
|
||||||
} else {
|
} else {
|
||||||
packet_len += 1 + (chunk.readUInt8(4) & 0x7F) * 128* 128 * 128;
|
packet_len += 1 + (chunk.readUInt8(4) & 0x7F) * 128 * 128 * 128;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return packet_len;
|
return packet_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Called when a new TLS/TCP connection is accepted
|
||||||
function onConnection(socket) {
|
function onConnection(socket) {
|
||||||
connectionCount++;
|
connectionCount++;
|
||||||
if (obj.args.mpstlsoffload) {
|
if (obj.args.mpstlsoffload) {
|
||||||
|
@ -220,31 +222,33 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
||||||
if (socket.tag.accumulator.length < 3) return;
|
if (socket.tag.accumulator.length < 3) return;
|
||||||
//if (!socket.tag.clientCert.subject) { console.log("MPS Connection, no client cert: " + socket.remoteAddress); socket.write('HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\nMeshCentral2 MPS server.\r\nNo client certificate given.'); socket.end(); return; }
|
//if (!socket.tag.clientCert.subject) { console.log("MPS Connection, no client cert: " + socket.remoteAddress); socket.write('HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\nMeshCentral2 MPS server.\r\nNo client certificate given.'); socket.end(); return; }
|
||||||
if (socket.tag.accumulator.substring(0, 3) == "GET") { if (args.mpsdebug) { console.log("MPS Connection, HTTP GET detected: " + socket.remoteAddress); } socket.write("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n<!DOCTYPE html><html><head><meta charset=\"UTF-8\"></head><body>MeshCentral2 MPS server.<br />Intel® AMT computers should connect here.</body></html>"); socket.end(); return; }
|
if (socket.tag.accumulator.substring(0, 3) == "GET") { if (args.mpsdebug) { console.log("MPS Connection, HTTP GET detected: " + socket.remoteAddress); } socket.write("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n<!DOCTYPE html><html><head><meta charset=\"UTF-8\"></head><body>MeshCentral2 MPS server.<br />Intel® AMT computers should connect here.</body></html>"); socket.end(); return; }
|
||||||
|
|
||||||
var chunk = Buffer.from(socket.tag.accumulator,"binary");
|
// If the MQTT broker is active, look for inbound MQTT connections
|
||||||
var packet_len = 0;
|
if (parent.mqttbroker != null) {
|
||||||
if (chunk.readUInt8(0)==16) {
|
var chunk = Buffer.from(socket.tag.accumulator, "binary");
|
||||||
packet_len = getMQTTPacketLength(chunk);
|
var packet_len = 0;
|
||||||
}
|
if (chunk.readUInt8(0) == 16) { packet_len = getMQTTPacketLength(chunk); }
|
||||||
|
if (chunk.readUInt8(0) == 16 && (socket.tag.accumulator.length < packet_len)) return; // Minimum MQTT detection
|
||||||
if (chunk.readUInt8(0)==16 && (socket.tag.accumulator.length < packet_len )) return;// minimum MQTT detection
|
|
||||||
|
// check if it is MQTT, need more initial packet to probe
|
||||||
// check if it is MQTT, need more initial packet to probe
|
if (chunk.readUInt8(0) == 16 && ((chunk.slice(4, 8).toString() === "MQTT") || (chunk.slice(5, 9).toString() === "MQTT")
|
||||||
if (chunk.readUInt8(0) == 16 && ((chunk.slice(4, 8).toString() === "MQTT") || (chunk.slice(5, 9).toString() === "MQTT")
|
|| (chunk.slice(6, 10).toString() === "MQTT") || (chunk.slice(7, 11).toString() === "MQTT"))) {
|
||||||
|| (chunk.slice(6, 10).toString() === "MQTT") || (chunk.slice(7, 11).toString() === "MQTT"))) {
|
parent.debug("mps", "MQTT connection detected.");
|
||||||
parent.debug("mps", "MQTT connection detected.");
|
socket.removeAllListeners("data");
|
||||||
socket.removeAllListeners("data");
|
socket.removeAllListeners("close");
|
||||||
socket.removeAllListeners("close");
|
socket.setNoDelay(true);
|
||||||
socket.setNoDelay(true);
|
socket.serialtunnel = SerialTunnel();
|
||||||
socket.serialtunnel = SerialTunnel();
|
socket.on('data', function (b) { socket.serialtunnel.updateBuffer(Buffer.from(b, 'binary')) });
|
||||||
socket.on('data', function(b) { socket.serialtunnel.updateBuffer(Buffer.from(b,'binary'))});
|
socket.serialtunnel.forwardwrite = function (b) { socket.write(b, "binary") }
|
||||||
socket.serialtunnel.forwardwrite = function(b) { socket.write(b,"binary")}
|
socket.on("close", function () { socket.serialtunnel.emit('end'); });
|
||||||
socket.on("close", function() { socket.serialtunnel.emit('end');});
|
|
||||||
//pass socket wrapper to mqtt broker
|
// Pass socket wrapper to the MQTT broker
|
||||||
parent.mqttbroker.handle(socket.serialtunnel);
|
parent.mqttbroker.handle(socket.serialtunnel);
|
||||||
socket.unshift(socket.tag.accumulator);
|
socket.unshift(socket.tag.accumulator);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
socket.tag.first = false;
|
socket.tag.first = false;
|
||||||
|
|
||||||
// Setup this node with certificate authentication
|
// Setup this node with certificate authentication
|
||||||
|
|
|
@ -6,49 +6,46 @@
|
||||||
* @version v0.0.1
|
* @version v0.0.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
module.exports.CreateMQTTBroker = function (parent, db, args) {
|
module.exports.CreateMQTTBroker = function (parent, db, args) {
|
||||||
|
|
||||||
// internal objects container
|
// Internal objects container
|
||||||
var obj = {}
|
var obj = {}
|
||||||
obj.parent = parent;
|
obj.parent = parent;
|
||||||
obj.db = db;
|
obj.db = db;
|
||||||
obj.args = args;
|
obj.args = args;
|
||||||
|
|
||||||
obj.aedes = require("aedes")();
|
obj.aedes = require("aedes")();
|
||||||
|
|
||||||
|
|
||||||
// argument parsing -- tbd
|
// argument parsing -- tbd
|
||||||
|
|
||||||
// event handling and filtering
|
// event handling and filtering
|
||||||
// authentication filter
|
// authentication filter
|
||||||
obj.aedes.authenticate = function (client, username, password, callback) {
|
obj.aedes.authenticate = function (client, username, password, callback) {
|
||||||
// accept all user
|
|
||||||
// TODO: add authentication handler
|
// TODO: add authentication handler
|
||||||
obj.parent.debug("mqtt","Authentication with "+username+":"+password);
|
obj.parent.debug("mqtt", "Authentication with " + username + ":" + password);
|
||||||
callback(null, true);
|
callback(null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if a client can publish a packet
|
// check if a client can publish a packet
|
||||||
obj.aedes.authorizePublish = function (client, packet, callback) {
|
obj.aedes.authorizePublish = function (client, packet, callback) {
|
||||||
//TODO: add authorized publish control
|
// TODO: add authorized publish control
|
||||||
obj.parent.debug("mqtt","AuthorizePublish");
|
obj.parent.debug("mqtt", "AuthorizePublish");
|
||||||
callback(null);
|
callback(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if a client can publish a packet
|
// Check if a client can publish a packet
|
||||||
obj.aedes.authorizeSubscribe = function (client, sub, callback) {
|
obj.aedes.authorizeSubscribe = function (client, sub, callback) {
|
||||||
//TODO: add subscription control here
|
// TODO: add subscription control here
|
||||||
obj.parent.debug("mqtt","AuthorizeSubscribe");
|
obj.parent.debug("mqtt", "AuthorizeSubscribe");
|
||||||
callback(null, sub);
|
callback(null, sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if a client can publish a packet
|
// Check if a client can publish a packet
|
||||||
obj.aedes.authorizeForward = function (client, packet) {
|
obj.aedes.authorizeForward = function (client, packet) {
|
||||||
//TODO: add forwarding control
|
// TODO: add forwarding control
|
||||||
obj.parent.debug("mqtt","AuthorizeForward");
|
obj.parent.debug("mqtt", "AuthorizeForward");
|
||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
obj.handle = obj.aedes.handle;
|
|
||||||
return obj;
|
obj.handle = obj.aedes.handle;
|
||||||
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "meshcentral",
|
"name": "meshcentral",
|
||||||
"version": "0.4.1-r",
|
"version": "0.4.1-s",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"Remote Management",
|
"Remote Management",
|
||||||
"Intel AMT",
|
"Intel AMT",
|
||||||
|
@ -27,7 +27,6 @@
|
||||||
"sample-config.json"
|
"sample-config.json"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"aedes": "^0.39.0",
|
|
||||||
"archiver": "^3.0.0",
|
"archiver": "^3.0.0",
|
||||||
"body-parser": "^1.19.0",
|
"body-parser": "^1.19.0",
|
||||||
"cbor": "4.1.5",
|
"cbor": "4.1.5",
|
||||||
|
@ -40,11 +39,9 @@
|
||||||
"ipcheck": "^0.1.0",
|
"ipcheck": "^0.1.0",
|
||||||
"meshcentral": "*",
|
"meshcentral": "*",
|
||||||
"minimist": "^1.2.0",
|
"minimist": "^1.2.0",
|
||||||
"mqtt": "^3.0.0",
|
|
||||||
"multiparty": "^4.2.1",
|
"multiparty": "^4.2.1",
|
||||||
"nedb": "^1.8.0",
|
"nedb": "^1.8.0",
|
||||||
"node-forge": "^0.8.4",
|
"node-forge": "^0.8.4",
|
||||||
"otplib": "^11.0.1",
|
|
||||||
"ws": "^6.2.1",
|
"ws": "^6.2.1",
|
||||||
"xmldom": "^0.1.27",
|
"xmldom": "^0.1.27",
|
||||||
"yauzl": "^2.10.0"
|
"yauzl": "^2.10.0"
|
||||||
|
|
File diff suppressed because one or more lines are too long
55
webserver.js
55
webserver.js
|
@ -42,7 +42,7 @@ if (!String.prototype.endsWith) { String.prototype.endsWith = function (searchSt
|
||||||
|
|
||||||
// Construct a HTTP server object
|
// Construct a HTTP server object
|
||||||
module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
var obj = {}, i = 0;
|
var obj = {}, i = 0;
|
||||||
|
|
||||||
// Modules
|
// Modules
|
||||||
obj.fs = require('fs');
|
obj.fs = require('fs');
|
||||||
|
@ -208,7 +208,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
// Fetch all meshes from the database, keep this in memory
|
// Fetch all meshes from the database, keep this in memory
|
||||||
obj.db.GetAllType('mesh', function (err, docs) {
|
obj.db.GetAllType('mesh', function (err, docs) {
|
||||||
obj.common.unEscapeAllLinksFieldName(docs);
|
obj.common.unEscapeAllLinksFieldName(docs);
|
||||||
for (var i in docs) {obj.meshes[docs[i]._id] = docs[i]; } // Get all meshes, including deleted ones.
|
for (var i in docs) { obj.meshes[docs[i]._id] = docs[i]; } // Get all meshes, including deleted ones.
|
||||||
|
|
||||||
// We loaded the users and mesh state, start the server
|
// We loaded the users and mesh state, start the server
|
||||||
serverStart();
|
serverStart();
|
||||||
|
@ -451,7 +451,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
|
|
||||||
if (ip) { for (var i = 0; i < ipList.length; i++) { if (require('ipcheck').match(ip, ipList[i])) { if (closeIfThis === true) { try { req.close(); } catch (e) { } } return true; } } }
|
if (ip) { for (var i = 0; i < ipList.length; i++) { if (require('ipcheck').match(ip, ipList[i])) { if (closeIfThis === true) { try { req.close(); } catch (e) { } } return true; } } }
|
||||||
if (closeIfThis === false) { try { req.close(); } catch (e) { } }
|
if (closeIfThis === false) { try { req.close(); } catch (e) { } }
|
||||||
}
|
}
|
||||||
} catch (e) { console.log(e); } // Should never happen
|
} catch (e) { console.log(e); } // Should never happen
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -646,7 +646,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
checkUserOneTimePassword(req, domain, user, req.body.token, req.body.hwtoken, function (result) {
|
checkUserOneTimePassword(req, domain, user, req.body.token, req.body.hwtoken, function (result) {
|
||||||
if (result == false) {
|
if (result == false) {
|
||||||
var randomWaitTime = 0;
|
var randomWaitTime = 0;
|
||||||
|
|
||||||
// 2-step auth is required, but the token is not present or not valid.
|
// 2-step auth is required, but the token is not present or not valid.
|
||||||
if ((req.body.token != null) || (req.body.hwtoken != null)) {
|
if ((req.body.token != null) || (req.body.hwtoken != null)) {
|
||||||
randomWaitTime = 2000 + (obj.crypto.randomBytes(2).readUInt16BE(0) % 4095); // This is a fail, wait a random time. 2 to 6 seconds.
|
randomWaitTime = 2000 + (obj.crypto.randomBytes(2).readUInt16BE(0) % 4095); // This is a fail, wait a random time. 2 to 6 seconds.
|
||||||
|
@ -1251,7 +1251,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check a user's password
|
// Check a user's password
|
||||||
obj.checkUserPassword = function(domain, user, password, func) {
|
obj.checkUserPassword = function (domain, user, password, func) {
|
||||||
// Check the old password
|
// Check the old password
|
||||||
if (user.passtype != null) {
|
if (user.passtype != null) {
|
||||||
// IIS default clear or weak password hashing (SHA-1)
|
// IIS default clear or weak password hashing (SHA-1)
|
||||||
|
@ -1259,7 +1259,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
if (err) { parent.debug('web', 'checkUserPassword: SHA-1 fail.'); return func(false); }
|
if (err) { parent.debug('web', 'checkUserPassword: SHA-1 fail.'); return func(false); }
|
||||||
if (hash == user.hash) {
|
if (hash == user.hash) {
|
||||||
if ((user.siteadmin) && (user.siteadmin != 0xFFFFFFFF) && (user.siteadmin & 32) != 0) { parent.debug('web', 'checkUserPassword: SHA-1 locked.'); return func(false); } // Account is locked
|
if ((user.siteadmin) && (user.siteadmin != 0xFFFFFFFF) && (user.siteadmin & 32) != 0) { parent.debug('web', 'checkUserPassword: SHA-1 locked.'); return func(false); } // Account is locked
|
||||||
parent.debug('web', 'checkUserPassword: SHA-1 ok.');
|
parent.debug('web', 'checkUserPassword: SHA-1 ok.');
|
||||||
return func(true); // Allow password change
|
return func(true); // Allow password change
|
||||||
}
|
}
|
||||||
func(false);
|
func(false);
|
||||||
|
@ -1270,7 +1270,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
if (err) { parent.debug('web', 'checkUserPassword: pbkdf2 SHA384 fail.'); return func(false); }
|
if (err) { parent.debug('web', 'checkUserPassword: pbkdf2 SHA384 fail.'); return func(false); }
|
||||||
if (hash == user.hash) {
|
if (hash == user.hash) {
|
||||||
if ((user.siteadmin) && (user.siteadmin != 0xFFFFFFFF) && (user.siteadmin & 32) != 0) { parent.debug('web', 'checkUserPassword: pbkdf2 SHA384 locked.'); return func(false); } // Account is locked
|
if ((user.siteadmin) && (user.siteadmin != 0xFFFFFFFF) && (user.siteadmin & 32) != 0) { parent.debug('web', 'checkUserPassword: pbkdf2 SHA384 locked.'); return func(false); } // Account is locked
|
||||||
parent.debug('web', 'checkUserPassword: pbkdf2 SHA384 ok.');
|
parent.debug('web', 'checkUserPassword: pbkdf2 SHA384 ok.');
|
||||||
return func(true); // Allow password change
|
return func(true); // Allow password change
|
||||||
}
|
}
|
||||||
func(false);
|
func(false);
|
||||||
|
@ -1728,7 +1728,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the CIRA configuration script
|
// Return the CIRA configuration script
|
||||||
obj.getCiraCleanupScript = function(func) {
|
obj.getCiraCleanupScript = function (func) {
|
||||||
obj.fs.readFile(obj.parent.path.join(obj.parent.webPublicPath, 'scripts/cira_cleanup.mescript'), 'utf8', function (err, data) {
|
obj.fs.readFile(obj.parent.path.join(obj.parent.webPublicPath, 'scripts/cira_cleanup.mescript'), 'utf8', function (err, data) {
|
||||||
if (err != null) { func(null); return; }
|
if (err != null) { func(null); return; }
|
||||||
func(Buffer.from(data));
|
func(Buffer.from(data));
|
||||||
|
@ -1904,7 +1904,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle domain redirection
|
// Handle domain redirection
|
||||||
obj.handleDomainRedirect = function(req, res) {
|
obj.handleDomainRedirect = function (req, res) {
|
||||||
const domain = checkUserIpAddress(req, res);
|
const domain = checkUserIpAddress(req, res);
|
||||||
if ((domain == null) || (domain.redirects == null)) { res.sendStatus(404); return; }
|
if ((domain == null) || (domain.redirects == null)) { res.sendStatus(404); return; }
|
||||||
var urlArgs = '', urlName = null, splitUrl = req.originalUrl.split("?");
|
var urlArgs = '', urlName = null, splitUrl = req.originalUrl.split("?");
|
||||||
|
@ -2116,7 +2116,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
function handleRelayWebSocket(ws, req, domain, user, cookie) {
|
function handleRelayWebSocket(ws, req, domain, user, cookie) {
|
||||||
if (!(req.query.host)) { console.log('ERR: No host target specified'); try { ws.close(); } catch (e) { } return; } // Disconnect websocket
|
if (!(req.query.host)) { console.log('ERR: No host target specified'); try { ws.close(); } catch (e) { } return; } // Disconnect websocket
|
||||||
parent.debug('web', 'Websocket relay connected from ' + user.name + ' for ' + req.query.host + '.');
|
parent.debug('web', 'Websocket relay connected from ' + user.name + ' for ' + req.query.host + '.');
|
||||||
|
|
||||||
try { ws._socket.setKeepAlive(true, 240000); } catch (ex) { } // Set TCP keep alive
|
try { ws._socket.setKeepAlive(true, 240000); } catch (ex) { } // Set TCP keep alive
|
||||||
|
|
||||||
// Fetch information about the target
|
// Fetch information about the target
|
||||||
|
@ -2308,7 +2308,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
data = Buffer.from(data, 'binary');
|
data = Buffer.from(data, 'binary');
|
||||||
recordingEntry(ws.logfile.fd, 2, 0, data, function () { try { ws.send(data); } catch (e) { } }); // TODO: Add TLS support
|
recordingEntry(ws.logfile.fd, 2, 0, data, function () { try { ws.send(data); } catch (e) { } }); // TODO: Add TLS support
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ws.forwardclient.onSendOk = function (ciraconn) {
|
ws.forwardclient.onSendOk = function (ciraconn) {
|
||||||
|
@ -2468,7 +2468,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
const mesh = obj.meshes[ws.meshid];
|
const mesh = obj.meshes[ws.meshid];
|
||||||
if (mesh == null) { delete ws.meshid; ws.send(JSON.stringify({ errorText: 'Invalid device group' })); ws.close(); return; }
|
if (mesh == null) { delete ws.meshid; ws.send(JSON.stringify({ errorText: 'Invalid device group' })); ws.close(); return; }
|
||||||
if (mesh.mtype != 1) { ws.send(JSON.stringify({ errorText: 'Invalid device group type' })); ws.close(); return; }
|
if (mesh.mtype != 1) { ws.send(JSON.stringify({ errorText: 'Invalid device group type' })); ws.close(); return; }
|
||||||
|
|
||||||
// Fetch the remote IP:Port for logging
|
// Fetch the remote IP:Port for logging
|
||||||
ws.remoteaddr = cleanRemoteAddr(req.ip);
|
ws.remoteaddr = cleanRemoteAddr(req.ip);
|
||||||
ws.remoteaddrport = ws.remoteaddr + ':' + ws._socket.remotePort;
|
ws.remoteaddrport = ws.remoteaddr + ':' + ws._socket.remotePort;
|
||||||
|
@ -2526,7 +2526,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
if ((activationMode == 4) && (cmd.modes.indexOf(2) == -1)) { ws.send(JSON.stringify({ messageText: 'ACM not allowed on this machine, activating in CCM instead...' })); activationMode = 2; } // We want to do ACM, but mode is not allowed. Change to CCM.
|
if ((activationMode == 4) && (cmd.modes.indexOf(2) == -1)) { ws.send(JSON.stringify({ messageText: 'ACM not allowed on this machine, activating in CCM instead...' })); activationMode = 2; } // We want to do ACM, but mode is not allowed. Change to CCM.
|
||||||
|
|
||||||
// If we want to do CCM, but mode is not allowed. Error out.
|
// If we want to do CCM, but mode is not allowed. Error out.
|
||||||
if ((activationMode == 2) && (cmd.modes.indexOf(1) == -1)) { ws.send(JSON.stringify({ errorText: 'CCM is not an allowed activation mode' })); ws.close(); return; }
|
if ((activationMode == 2) && (cmd.modes.indexOf(1) == -1)) { ws.send(JSON.stringify({ errorText: 'CCM is not an allowed activation mode' })); ws.close(); return; }
|
||||||
|
|
||||||
// Get the Intel AMT admin password, randomize if needed.
|
// Get the Intel AMT admin password, randomize if needed.
|
||||||
var amtpassword = ((mesh.amt.password == '') ? getRandomAmtPassword() : mesh.amt.password);
|
var amtpassword = ((mesh.amt.password == '') ? getRandomAmtPassword() : mesh.amt.password);
|
||||||
|
@ -2992,7 +2992,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get the web server hostname. This may change if using a domain with a DNS name.
|
// Get the web server hostname. This may change if using a domain with a DNS name.
|
||||||
obj.getWebServerName = function(domain) {
|
obj.getWebServerName = function (domain) {
|
||||||
if (domain.dns != null) return domain.dns;
|
if (domain.dns != null) return domain.dns;
|
||||||
return obj.certificates.CommonName;
|
return obj.certificates.CommonName;
|
||||||
}
|
}
|
||||||
|
@ -3152,7 +3152,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
// Get the list of power events and send them
|
// Get the list of power events and send them
|
||||||
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'text/csv', 'Content-Disposition': 'attachment; filename="powerevents.csv"' });
|
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'text/csv', 'Content-Disposition': 'attachment; filename="powerevents.csv"' });
|
||||||
obj.db.getPowerTimeline(node._id, function (err, docs) {
|
obj.db.getPowerTimeline(node._id, function (err, docs) {
|
||||||
var xevents = [ 'Time, State, Previous State' ], prevState = 0;
|
var xevents = ['Time, State, Previous State'], prevState = 0;
|
||||||
for (var i in docs) {
|
for (var i in docs) {
|
||||||
if (docs[i].power != prevState) {
|
if (docs[i].power != prevState) {
|
||||||
prevState = docs[i].power;
|
prevState = docs[i].power;
|
||||||
|
@ -3220,7 +3220,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
"Referrer-Policy": "no-referrer",
|
"Referrer-Policy": "no-referrer",
|
||||||
"X-XSS-Protection": "1; mode=block",
|
"X-XSS-Protection": "1; mode=block",
|
||||||
"X-Content-Type-Options": "nosniff",
|
"X-Content-Type-Options": "nosniff",
|
||||||
"Content-Security-Policy": "default-src 'none'; script-src 'self' 'unsafe-inline'; connect-src 'self' ws" + ((args.notls !== true)?'s':'') + "://" + req.headers.host + "; img-src 'self' data:; style-src 'self' 'unsafe-inline'; frame-src 'self'; media-src 'self'"
|
"Content-Security-Policy": "default-src 'none'; script-src 'self' 'unsafe-inline'; connect-src 'self' ws" + ((args.notls !== true) ? 's' : '') + "://" + req.headers.host + "; img-src 'self' data:; style-src 'self' 'unsafe-inline'; frame-src 'self'; media-src 'self'"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3277,7 +3277,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
obj.app.post(url + 'uploadmeshcorefile.ashx', handleUploadMeshCoreFile);
|
obj.app.post(url + 'uploadmeshcorefile.ashx', handleUploadMeshCoreFile);
|
||||||
obj.app.get(url + 'userfiles/*', handleDownloadUserFiles);
|
obj.app.get(url + 'userfiles/*', handleDownloadUserFiles);
|
||||||
obj.app.ws(url + 'echo.ashx', handleEchoWebSocket);
|
obj.app.ws(url + 'echo.ashx', handleEchoWebSocket);
|
||||||
obj.app.ws(url+'apf.ashx', function (ws, req) { obj.parent.apfserver.onConnection(ws);})
|
obj.app.ws(url + 'apf.ashx', function (ws, req) { obj.parent.apfserver.onConnection(ws); })
|
||||||
obj.app.ws(url + 'meshrelay.ashx', function (ws, req) { PerformWSSessionAuth(ws, req, true, function (ws1, req1, domain, user, cookie) { obj.meshRelayHandler.CreateMeshRelay(obj, ws1, req1, domain, user, cookie); }); });
|
obj.app.ws(url + 'meshrelay.ashx', function (ws, req) { PerformWSSessionAuth(ws, req, true, function (ws1, req1, domain, user, cookie) { obj.meshRelayHandler.CreateMeshRelay(obj, ws1, req1, domain, user, cookie); }); });
|
||||||
obj.app.get(url + 'webrelay.ashx', function (req, res) { res.send('Websocket connection expected'); });
|
obj.app.get(url + 'webrelay.ashx', function (req, res) { res.send('Websocket connection expected'); });
|
||||||
obj.app.get(url + 'health.ashx', function (req, res) { res.send('ok'); }); // TODO: Perform more server checking.
|
obj.app.get(url + 'health.ashx', function (req, res) { res.send('ok'); }); // TODO: Perform more server checking.
|
||||||
|
@ -3323,15 +3323,16 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
try { obj.meshAgentHandler.CreateMeshAgent(obj, obj.db, ws, req, obj.args, domain); } catch (e) { console.log(e); }
|
try { obj.meshAgentHandler.CreateMeshAgent(obj, obj.db, ws, req, obj.args, domain); } catch (e) { console.log(e); }
|
||||||
});
|
});
|
||||||
|
|
||||||
// MQTT broker over websocket
|
// Setup MQTT broker over websocket
|
||||||
obj.app.ws(url+'mqtt.ashx', function (ws, req) {
|
if (obj.parent.mqttbroker != null) {
|
||||||
var ser = SerialTunnel();
|
obj.app.ws(url + 'mqtt.ashx', function (ws, req) {
|
||||||
ws.on('message', function(b) { ser.updateBuffer(Buffer.from(b,'binary'))});
|
var ser = SerialTunnel();
|
||||||
ser.forwardwrite = function(b) { ws.send(b,"binary")}
|
ws.on('message', function (b) { ser.updateBuffer(Buffer.from(b, 'binary')) });
|
||||||
ws.on("close", function() { ser.emit('end');});
|
ser.forwardwrite = function (b) { ws.send(b, "binary") }
|
||||||
//pass socket wrapper to mqtt broker
|
ws.on("close", function () { ser.emit('end'); });
|
||||||
obj.parent.mqttbroker.handle(ser);
|
obj.parent.mqttbroker.handle(ser); // Pass socket wrapper to MQTT broker
|
||||||
})
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Memory Tracking
|
// Memory Tracking
|
||||||
if (typeof obj.args.memorytracking == 'number') {
|
if (typeof obj.args.memorytracking == 'number') {
|
||||||
|
@ -3384,7 +3385,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||||
res.status(404).render(getRenderPage('error404', req), { title: domain.title, title2: domain.title2 });
|
res.status(404).render(getRenderPage('error404', req), { title: domain.title, title2: domain.title2 });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start server on a free port
|
// Start server on a free port
|
||||||
CheckListenPort(obj.args.port, StartWebServer);
|
CheckListenPort(obj.args.port, StartWebServer);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue