diff --git a/meshagent.js b/meshagent.js index d97c3ee7..9a452e95 100644 --- a/meshagent.js +++ b/meshagent.js @@ -387,13 +387,13 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { // If we did not get an indication that the agent already validated this server, send the server signature. if (obj.useSwarmCert == true) { // Perform the hash signature using older swarm server certificate - parent.parent.certificateOperations.acceleratorPerformSignature(1, msg.substring(2) + obj.nonce, obj, function (obj2, signature) { + parent.parent.certificateOperations.acceleratorPerformSignature(1, msg.substring(2) + obj.nonce, null, function (tag, signature) { // Send back our certificate + signature obj2.sendBinary(common.ShortToStr(2) + common.ShortToStr(parent.swarmCertificateAsn1.length) + parent.swarmCertificateAsn1 + signature); // Command 2, certificate + signature }); } else { // Perform the hash signature using the server agent certificate - parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, obj, function (obj2, signature) { + parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, null, function (tag, signature) { // Send back our certificate + signature obj2.sendBinary(common.ShortToStr(2) + common.ShortToStr(parent.agentCertificateAsn1.length) + parent.agentCertificateAsn1 + signature); // Command 2, certificate + signature }); diff --git a/meshcentral.js b/meshcentral.js index b7903fd0..ccbe61ee 100644 --- a/meshcentral.js +++ b/meshcentral.js @@ -84,6 +84,10 @@ function CreateMeshCentralServer(config, args) { if (obj.fs.existsSync(obj.path.join(__dirname, '../meshcentral-web/public'))) { obj.webPublicPath = obj.path.join(__dirname, '../meshcentral-web/public'); } else { obj.webPublicPath = obj.path.join(__dirname, 'public'); } } + // Look to see if data and/or file path is specified + if (obj.args.datapath) { obj.datapath = obj.args.datapath; } + if (obj.args.filespath) { obj.filespath = obj.args.filespath; } + // Create data and files folders if needed try { obj.fs.mkdirSync(obj.datapath); } catch (e) { } try { obj.fs.mkdirSync(obj.filespath); } catch (e) { } @@ -555,10 +559,6 @@ function CreateMeshCentralServer(config, args) { }, (obj.args.memorytracking * 1000)); } - // Look to see if data and/or file path is specified - if (obj.args.datapath) { obj.datapath = obj.args.datapath; } - if (obj.args.filespath) { obj.filespath = obj.args.filespath; } - // Read environment variables. For a subset of arguments, we allow them to be read from environment variables. var xenv = ['user', 'port', 'mpsport', 'mpsaliasport', 'redirport', 'exactport', 'debug']; for (i in xenv) { if ((obj.args[xenv[i]] == null) && (process.env['mesh' + xenv[i]])) { obj.args[xenv[i]] = obj.common.toNumber(process.env['mesh' + xenv[i]]); } } @@ -798,6 +798,7 @@ function CreateMeshCentralServer(config, args) { // Setup Mesh Multi-Server if needed obj.multiServer = require('./multiserver.js').CreateMultiServer(obj, obj.args); if (obj.multiServer != null) { + if ((obj.db.databaseType != 3) || (obj.db.changeStream != true)) { console.log("ERROR: Multi-server support requires use of MongoDB with ReplicaSet and ChangeStream enabled."); process.exit(0); return; } obj.serverId = obj.multiServer.serverid; for (var serverid in obj.config.peers.servers) { obj.peerConnectivityByNode[serverid] = {}; } } diff --git a/meshuser.js b/meshuser.js index 819babd5..5f854223 100644 --- a/meshuser.js +++ b/meshuser.js @@ -152,7 +152,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if (routing != null) { // Check if we have permission to send a message to that node var rights = user.links[routing.meshid]; - var mesh = parent.meshes[agent.dbMeshKey]; + var mesh = parent.meshes[routing.meshid]; if ((rights != null) && (mesh != null) && ((rights.rights & 8) || (rights.rights & 256))) { // 8 is remote control permission command.fromSessionid = ws.sessionId; // Set the session id, required for responses command.rights = rights.rights; // Add user rights flags to the message diff --git a/multiserver.js b/multiserver.js index fa756037..70b23587 100644 --- a/multiserver.js +++ b/multiserver.js @@ -46,6 +46,7 @@ module.exports.CreateMultiServer = function (parent, args) { obj.peerServerId = null; obj.authenticated = 0; obj.serverCertHash = null; + obj.pendingData = []; // Disconnect from the server and/or stop trying obj.stop = function () { @@ -88,7 +89,7 @@ module.exports.CreateMultiServer = function (parent, args) { if (msg.length < 2) return; if (msg.charCodeAt(0) == 123) { - if (obj.connectionState == 15) { processServerData(msg); } + if ((obj.connectionState & 4) != 0) { processServerData(msg); } else { obj.pendingData.push(msg); } } else { var cmd = obj.common.ReadShort(msg, 0); switch (cmd) { @@ -101,9 +102,9 @@ module.exports.CreateMultiServer = function (parent, args) { obj.servernonce = msg.substring(50); // Perform the hash signature using the server agent certificate - obj.parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, obj, function (obj2, signature) { + obj.parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, null, function (tag, signature) { // Send back our certificate + signature - obj2.ws.send(obj2.common.ShortToStr(2) + obj2.common.ShortToStr(obj2.agentCertificateAsn1.length) + obj2.agentCertificateAsn1 + signature); // Command 2, certificate + signature + obj.ws.send(obj.common.ShortToStr(2) + obj.common.ShortToStr(obj.agentCertificateAsn1.length) + obj.agentCertificateAsn1 + signature); // Command 2, certificate + signature }); break; @@ -131,14 +132,22 @@ module.exports.CreateMultiServer = function (parent, args) { obj.parent.parent.debug(1, 'OutPeer ' + obj.serverid + ': Verified peer connection to ' + obj.url); // Send information about our server to the peer - if (obj.connectionState == 15) { obj.ws.send(JSON.stringify({ action: 'info', serverid: obj.parent.serverid, dbid: obj.parent.parent.db.identifier, key: obj.parent.parent.serverKey.toString('hex'), serverCertHash: obj.parent.parent.webserver.webCertificateHashBase64 })); } + if (obj.connectionState == 15) { + obj.ws.send(JSON.stringify({ action: 'info', serverid: obj.parent.serverid, dbid: obj.parent.parent.db.identifier, key: obj.parent.parent.serverKey.toString('hex'), serverCertHash: obj.parent.parent.webserver.webCertificateHashBase64 })); + for (var i in obj.pendingData) { processServerData(obj.pendingData[i]); } // Process any pending data + obj.pendingData = []; + } //if ((obj.connectionState == 15) && (obj.connectHandler != null)) { obj.connectHandler(1); } break; } case 4: { - // Server confirmed authentication, we are allowed to send commands to the server + // Peer server confirmed authentication, we are allowed to send commands to the server obj.connectionState |= 8; - if (obj.connectionState == 15) { obj.ws.send(JSON.stringify({ action: 'info', serverid: obj.parent.serverid, dbid: obj.parent.parent.db.identifier, key: obj.parent.parent.serverKey.toString('hex'), serverCertHash: obj.parent.parent.webserver.webCertificateHashBase64 })); } + if (obj.connectionState == 15) { + obj.ws.send(JSON.stringify({ action: 'info', serverid: obj.parent.serverid, dbid: obj.parent.parent.db.identifier, key: obj.parent.parent.serverKey.toString('hex'), serverCertHash: obj.parent.parent.webserver.webCertificateHashBase64 })); + for (var i in obj.pendingData) { processServerData(obj.pendingData[i]); } // Process any pending data + obj.pendingData = []; + } //if ((obj.connectionState == 15) && (obj.connectHandler != null)) { obj.connectHandler(1); } break; } @@ -222,6 +231,7 @@ module.exports.CreateMultiServer = function (parent, args) { obj.infoSent = 0; obj.peerServerId = null; obj.serverCertHash = null; + obj.pendingData = []; if (obj.remoteaddr.startsWith('::ffff:')) { obj.remoteaddr = obj.remoteaddr.substring(7); } obj.parent.parent.debug(1, 'InPeer: Connected (' + obj.remoteaddr + ')'); @@ -246,13 +256,10 @@ module.exports.CreateMultiServer = function (parent, args) { if (typeof msg != 'string') { msg = msg.toString('binary'); } if (msg.length < 2) return; - if (obj.authenticated >= 2) { // We are authenticated - if (msg.charCodeAt(0) == 123) { processServerData(msg); } + if (msg.charCodeAt(0) == 123) { if (msg.length < 2) return; - //var cmdid = obj.common.ReadShort(msg, 0); - // Process binary commands (if any). None right now. - } - else if (obj.authenticated < 2) { // We are not authenticated + if (obj.authenticated >= 2) { processServerData(msg); } else { obj.pendingData.push(msg); } + } else if (obj.authenticated < 2) { // We are not authenticated var cmd = obj.common.ReadShort(msg, 0); if (cmd == 1) { // Peer server authentication request @@ -264,9 +271,9 @@ module.exports.CreateMultiServer = function (parent, args) { obj.peernonce = msg.substring(50); // Perform the hash signature using the server agent certificate - obj.parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, obj, function (obj2, signature) { + obj.parent.parent.certificateOperations.acceleratorPerformSignature(0, msg.substring(2) + obj.nonce, null, function (tag, signature) { // Send back our certificate + signature - obj2.send(obj2.common.ShortToStr(2) + obj2.common.ShortToStr(obj2.agentCertificateAsn1.length) + obj2.agentCertificateAsn1 + signature); // Command 2, certificate + signature + obj.send(obj.common.ShortToStr(2) + obj.common.ShortToStr(obj.agentCertificateAsn1.length) + obj.agentCertificateAsn1 + signature); // Command 2, certificate + signature }); // Check the peer server signature if we can @@ -319,6 +326,10 @@ module.exports.CreateMultiServer = function (parent, args) { obj.send(obj.common.ShortToStr(4)); obj.send(JSON.stringify({ action: 'info', serverid: obj.parent.serverid, dbid: obj.parent.parent.db.identifier, key: obj.parent.parent.serverKey.toString('hex'), serverCertHash: obj.parent.parent.webserver.webCertificateHashBase64 })); obj.authenticated = 2; + + // Process any pending data that was received before peer authentication + for (var i in obj.pendingData) { processServerData(obj.pendingData[i]); } + obj.pendingData = null; } // Verify the peer server signature @@ -371,9 +382,10 @@ module.exports.CreateMultiServer = function (parent, args) { // If we have no peering configuration, don't setup this object if (obj.peerConfig == null) { return null; } - obj.serverid = obj.parent.config.peers.serverId; - if (obj.serverid == null) { obj.serverid = require("os").hostname().toLowerCase(); } + obj.serverid = obj.parent.config.peers.serverid; + if (obj.serverid == null) { obj.serverid = require("os").hostname().toLowerCase(); } else { obj.serverid = obj.serverid.toLowerCase(); } if (obj.parent.config.peers.servers[obj.serverid] == null) { console.log("Error: Unable to peer with other servers, \"" + obj.serverid + "\" not present in peer servers list."); return null; } + //console.log('Server peering ID: ' + obj.serverid); // Return the private key of a peer server obj.getServerCookieKey = function (serverid) { diff --git a/package.json b/package.json index 5ef6b3e8..c201e3c0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "meshcentral", - "version": "0.3.9-p", + "version": "0.3.9-r", "keywords": [ "Remote Management", "Intel AMT", diff --git a/redirserver.js b/redirserver.js index d2b2b4e9..8fec5263 100644 --- a/redirserver.js +++ b/redirserver.js @@ -86,8 +86,15 @@ module.exports.CreateRedirServer = function (parent, db, args, func) { obj.app.post(url + "amtevents.ashx", obj.parent.webserver.handleAmtEventRequest); obj.app.get(url + "meshsettings", obj.parent.webserver.handleMeshSettingsRequest); obj.app.get(url + "meshagents", obj.parent.webserver.handleMeshAgentRequest); + + // Server redirects + if (parent.config.domains[i].redirects) { + for (var j in parent.config.domains[i].redirects) { + if (j[0] != '_') { obj.app.get(url + j, obj.parent.webserver.handleDomainRedirect); } + } + } } - }; + } // Setup all HTTP redirection handlers //obj.app.set("etag", false); diff --git a/views/default-min.handlebars b/views/default-min.handlebars index c1559d6c..3d41d6fb 100644 --- a/views/default-min.handlebars +++ b/views/default-min.handlebars @@ -1 +1 @@ - {{{title}}}
{{{title}}}
{{{title2}}}

{{{logoutControl}}}

 

\ No newline at end of file + {{{title}}}
{{{title}}}
{{{title2}}}

{{{logoutControl}}}

 

\ No newline at end of file diff --git a/views/default.handlebars b/views/default.handlebars index def4d805..6483c4d9 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -512,6 +512,8 @@ + + @@ -5056,6 +5058,18 @@ } } else if (ks == 10) { // CTRL-ALT-DEL desktop.m.sendcad(); + } else if (ks == 11) { // WIN-LEFT + if (desktop.contype == 2) { + desktop.m.sendkey([[0xffe7, 1], [0xff51, 1], [0xff51, 0], [0xffe7, 0]]); // Intel AMT: Meta-left down, Left arrow press, Left arrow release, Meta-left release + } else { + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 37], [desktop.m.KeyAction.UP, 37], [desktop.m.KeyAction.EXUP, 0x5B]]); + } + } else if (ks == 12) { // WIN-RIGHT + if (desktop.contype == 2) { + desktop.m.sendkey([[0xffe7, 1], [0xff53, 1], [0xff53, 0], [0xffe7, 0]]); // Intel AMT: Meta-left down, Right arrow press, Right arrow release, Meta-left release + } else { + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 39], [desktop.m.KeyAction.UP, 39], [desktop.m.KeyAction.EXUP, 0x5B]]); + } } } diff --git a/views/error404-mobile.handlebars b/views/error404-mobile.handlebars new file mode 100644 index 00000000..ccd96e4d --- /dev/null +++ b/views/error404-mobile.handlebars @@ -0,0 +1,56 @@ + + + + + + + + + MeshCentral - Terms of use + + + +
+ +
+
+ {{{title}}} +
+
+ {{{title2}}} +
+

{{{logoutControl}}}

+
+
+
+
404
+
This page does not exist
+
Go to main site
+
+
+ +
+ + diff --git a/views/error404.handlebars b/views/error404.handlebars new file mode 100644 index 00000000..5e0cf578 --- /dev/null +++ b/views/error404.handlebars @@ -0,0 +1,133 @@ + + + + + + + + + + + MeshCentral - Terms of use + + +
+ +
+
+ {{{title}}} +
+
+ {{{title2}}} +
+

{{{logoutControl}}}

+
+
+
+
+
+
+ ♦ + +
+
+
+
404
+
This page does not exist
+
Go to main site
+
+ +
+ + + diff --git a/webserver.js b/webserver.js index e4fb19e8..b03eaab8 100644 --- a/webserver.js +++ b/webserver.js @@ -1733,7 +1733,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { } // Handle domain redirection - function handleDomainRedirect(req, res) { + obj.handleDomainRedirect = function(req, res) { const domain = checkUserIpAddress(req, res); if ((domain == null) || (domain.redirects == null)) { res.sendStatus(404); return; } var urlArgs = '', urlName = null, splitUrl = req.originalUrl.split("?"); @@ -3041,7 +3041,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { obj.app.ws(url + 'amtactivate', handleAmtActivateWebSocket); // Server redirects - if (parent.config.domains[i].redirects) { for (var j in parent.config.domains[i].redirects) { if (j[0] != '_') { obj.app.get(url + j, handleDomainRedirect); } } } + if (parent.config.domains[i].redirects) { for (var j in parent.config.domains[i].redirects) { if (j[0] != '_') { obj.app.get(url + j, obj.handleDomainRedirect); } } } // Server picture obj.app.get(url + 'serverpic.ashx', function (req, res) { @@ -3106,6 +3106,12 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Indicates to ExpressJS that the public folder should be used to serve static files. obj.app.use(url, obj.express.static(obj.parent.webPublicPath)); + // Handle 404 error + obj.app.use(function (req, res, next) { + var domain = getDomain(req); + res.status(404).render(obj.path.join(obj.parent.webViewsPath, isMobileBrowser(req) ? 'error404-mobile' : 'error404'), { title: domain.title, title2: domain.title2 }); + }) + // Start regular disconnection list flush every 2 minutes. obj.wsagentsDisconnectionsTimer = setInterval(function () { obj.wsagentsDisconnections = {}; }, 120000); } @@ -3373,7 +3379,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (oldcount == null) { oldcount = 0; } else { delete obj.sessionsCount[userid]; } if (newcount != oldcount) { x = userid.split('/'); - var u = users[userid]; + var u = obj.users[userid]; if (u) { var targets = ['*', 'server-users']; if (u.groups) { for (var i in u.groups) { targets.push('server-users:' + i); } } @@ -3387,7 +3393,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { oldcount = obj.sessionsCount[userid]; if ((oldcount != null) && (oldcount != 0)) { x = userid.split('/'); - var u = users[userid]; + var u = obj.users[userid]; if (u) { var targets = ['*', 'server-users']; if (u.groups) { for (var i in u.groups) { targets.push('server-users:' + i); } } @@ -3412,7 +3418,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // If the count changed, update and event if (newcount != oldcount) { x = userid.split('/'); - var u = users[userid]; + var u = obj.users[userid]; if (u) { var targets = ['*', 'server-users']; if (u.groups) { for (var i in u.groups) { targets.push('server-users:' + i); } }