1. Updated AgentMessage infrastructure 2. Updated to be compatible with older agents, displaying agentmessage advising to update, if important components are missing

1. Updated AgentMessage infrastructure 2. Updated to be compatible with older agents, displaying agentmessage advising to update, if important components are missing

Bryan Roe committed Jun 8, 2021 at 00:11 UTC 73f426bc24c29f4258c441a1df5891c3d2d1df8c
1 file changed +117 -38
agents/meshcore.js
+117 -38
@@ -46,9 +46,11 @@ var MESHRIGHT_CHATNOTIFY = 16384;
46 var MESHRIGHT_UNINSTALL = 32768;
47 var MESHRIGHT_NODESKTOP = 65536;
48
49 -if (require('MeshAgent').ARCHID == null) {
49 +if (require('MeshAgent').ARCHID == null)
50 +{
51 var id = null;
51 - switch (process.platform) {
52 + switch (process.platform)
53 + {
54 case 'win32':
55 id = require('_GenericMarshal').PointerSize == 4 ? 3 : 4;
56 break;
@@ -56,21 +58,22 @@ if (require('MeshAgent').ARCHID == null) {
58 id = require('_GenericMarshal').PointerSize == 4 ? 31 : 30;
59 break;
60 case 'darwin':
59 - try {
61 + try
62 + {
63 id = require('os').arch() == 'x64' ? 16 : 29;
64 }
62 - catch (xx) {
65 + catch (xx)
66 + {
67 id = 16;
68 }
69 break;
70 }
71 if (id != null) { Object.defineProperty(require('MeshAgent'), 'ARCHID', { value: id }); }
72 }
69 -
73 var obj = {};
74 var agentFileHttpRequests = {}; // Currently active agent HTTPS GET requests from the server.
75 var agentFileHttpPendingRequests = []; // Pending HTTPS GET requests from the server.
73 -var debugConsole = (_MSH().debugConsole == 1);
76 +var debugConsole = (global._MSH && (_MSH().debugConsole == 1));
77
78 if (process.platform == 'win32' && require('user-sessions').isRoot()) {
79 // Check the Agent Uninstall MetaData for correctness, as the installer may have written an incorrect value
@@ -277,8 +280,16 @@ obj.DAIPC.on('connection', function (c) {
280 });
281
282 // Send current sessions to registered apps
280 -function broadcastSessionsToRegisteredApps(x) {
283 +function broadcastSessionsToRegisteredApps(x)
284 +{
285 + var p = {}, i;
286 + for (i = 0; i < sendAgentMessage.messages.length; ++i)
287 + {
288 + p[i] = sendAgentMessage.messages[i];
289 + }
290 + tunnelUserCount.msg = p;
291 broadcastToRegisteredApps({ cmd: 'sessions', sessions: tunnelUserCount });
292 + tunnelUserCount.msg = {};
293 }
294
295 // Send this object to all registered local applications
@@ -838,7 +849,8 @@ function handleServerCommand(data) {
849
850 // Perform manual server TLS certificate checking based on the certificate hash given by the server.
851 woptions.rejectUnauthorized = 0;
841 - woptions.checkServerIdentity = function checkServerIdentity(certs) {
852 + woptions.checkServerIdentity = function checkServerIdentity(certs)
853 + {
854 /*
855 try { sendConsoleText("certs[0].digest: " + certs[0].digest); } catch (ex) { sendConsoleText(ex); }
856 try { sendConsoleText("certs[0].fingerprint: " + certs[0].fingerprint); } catch (ex) { sendConsoleText(ex); }
@@ -847,8 +859,15 @@ function handleServerCommand(data) {
859 */
860
861 // If the tunnel certificate matches the control channel certificate, accept the connection
850 - try { if (require('MeshAgent').ServerInfo.ControlChannelCertificate.digest == certs[0].digest) return; } catch (ex) { }
851 - try { if (require('MeshAgent').ServerInfo.ControlChannelCertificate.fingerprint == certs[0].fingerprint) return; } catch (ex) { }
862 + var noErrors = true;
863 + try { if (require('MeshAgent').ServerInfo.ControlChannelCertificate.digest == certs[0].digest) return; } catch (ex) { noErrors = false; }
864 + try { if (require('MeshAgent').ServerInfo.ControlChannelCertificate.fingerprint == certs[0].fingerprint) return; } catch (ex) { noErrors = false; }
865 + if (certs[0].digest == null || noErrors == true)
866 + {
867 + sendAgentMessage("This agent is using insecure tunnels, consider updating.", 3, 119, true);
868 + return;
869 + }
870 +
871 // Check that the certificate is the one expected by the server, fail if not.
872 if ((checkServerIdentity.servertlshash != null) && (checkServerIdentity.servertlshash.toLowerCase() != certs[0].digest.split(':').join('').toLowerCase())) { throw new Error('BadCert') }
873 }
@@ -2942,31 +2961,32 @@ function processConsoleCommand(cmd, args, rights, sessionid) {
2961 break;
2962 }
2963 case 'agentmsg': {
2945 - if (args['_'].length == 0) {
2964 + if (args['_'].length == 0)
2965 + {
2966 response = "Proper usage:\r\n agentmsg add \"[message]\" [iconIndex]\r\n agentmsg remove [index]\r\n agentmsg list"; // Display usage
2947 - } else {
2948 - if ((args['_'][0] == 'add') && (args['_'].length > 1)) {
2949 - var msgIndex = 1, iconIndex = 0;
2950 - while (tunnelUserCount.msg[msgIndex] != null) { msgIndex++; }
2967 + } else
2968 + {
2969 + if ((args['_'][0] == 'add') && (args['_'].length > 1))
2970 + {
2971 + var msgID, iconIndex = 0;
2972 if (args['_'].length >= 3) { try { iconIndex = parseInt(args['_'][2]); } catch (e) { } }
2973 if (typeof iconIndex != 'number') { iconIndex = 0; }
2953 - tunnelUserCount.msg[msgIndex] = { msg: args['_'][1], icon: iconIndex };
2954 - response = 'Agent message ' + msgIndex + ' added.';
2955 - } else if ((args['_'][0] == 'remove') && (args['_'].length > 1)) {
2956 - var msgIndex = 0;
2957 - try { msgIndex = parseInt(args['_'][1]); } catch (x) { }
2958 - if (tunnelUserCount.msg[msgIndex] == null) { response = "Message not found."; } else { delete tunnelUserCount.msg[msgIndex]; response = "Message removed."; }
2959 - } else if (args['_'][0] == 'list') {
2960 - response = JSON.stringify(tunnelUserCount.msg, null, 2);
2974 + msgID = sendAgentMessage(args['_'][1], iconIndex);
2975 + response = 'Agent message: ' + msgID + ' added.';
2976 + } else if ((args['_'][0] == 'remove') && (args['_'].length > 1))
2977 + {
2978 + var r = removeAgentMessage(args['_'][1]);
2979 + response = 'Message ' + (r ? 'removed' : 'NOT FOUND');
2980 + } else if (args['_'][0] == 'list')
2981 + {
2982 + response = JSON.stringify(sendAgentMessage(), null, 2);
2983 }
2962 - try { mesh.SendCommand({ action: 'sessions', type: 'msg', value: tunnelUserCount.msg }); } catch (x) { }
2984 broadcastSessionsToRegisteredApps();
2985 }
2986 break;
2987 }
2988 case 'clearagentmsg': {
2968 - tunnelUserCount.msg = {};
2969 - try { mesh.SendCommand({ action: 'sessions', type: 'msg', value: tunnelUserCount.msg }); } catch (x) { }
2989 + removeAgentMessage();
2990 broadcastSessionsToRegisteredApps();
2991 break;
2992 }
@@ -3985,14 +4005,58 @@ function sendConsoleText(text, sessionid) {
4005 if (sessionid != 'pipe') { require('MeshAgent').SendCommand({ action: 'msg', type: 'console', value: text, sessionid: sessionid }); }
4006 }
4007
4008 +function removeAgentMessage(msgid)
4009 +{
4010 + var ret = false;
4011 + if (msgid == null)
4012 + {
4013 + // Delete all messages
4014 + sendAgentMessage.messages = [];
4015 + ret = true;
4016 + }
4017 + else
4018 + {
4019 + var i = sendAgentMessage.messages.findIndex(function (v) { return (v.id == msgid); });
4020 + if (i >= 0)
4021 + {
4022 + sendAgentMessage.messages.splice(i, 1);
4023 + ret = true;
4024 + }
4025 + }
4026 + if (ret) { sendAgentMessage(); }
4027 + return (ret);
4028 +}
4029 +
4030 // Send a mesh agent message to server, placing a bubble/badge on the agent device
3989 -function sendAgentMessage(msg, icon) {
3990 - if (sendAgentMessage.messages == null) {
3991 - sendAgentMessage.messages = {};
3992 - sendAgentMessage.nextid = 1;
4031 +function sendAgentMessage(msg, icon, serverid, first)
4032 +{
4033 + if (sendAgentMessage.messages == null)
4034 + {
4035 + sendAgentMessage.messages = [];
4036 + }
4037 +
4038 + if (arguments.length > 0)
4039 + {
4040 + if (first == null || (serverid && first && sendAgentMessage.messages.findIndex(function (v) { return (v.msgid == serverid); }) < 0))
4041 + {
4042 + sendAgentMessage.messages.push({ msg: msg, icon: icon, msgid: serverid });
4043 + sendAgentMessage.messages.peek().id = sendAgentMessage.messages.peek()._hashCode();
4044 + }
4045 + }
4046 +
4047 + var p = {}, i;
4048 + for (i = 0; i < sendAgentMessage.messages.length; ++i)
4049 + {
4050 + p[i] = sendAgentMessage.messages[i];
4051 + }
4052 + try
4053 + {
4054 + require('MeshAgent').SendCommand({ action: 'sessions', type: 'msg', value: p });
4055 + }
4056 + catch(ex)
4057 + {
4058 }
3994 - sendAgentMessage.messages[sendAgentMessage.nextid++] = { msg: msg, icon: icon };
3995 - require('MeshAgent').SendCommand({ action: 'sessions', type: 'msg', value: sendAgentMessage.messages });
4059 + return (arguments.length > 0 ? sendAgentMessage.messages.peek().id : sendAgentMessage.messages);
4060 }
4061 function getOpenDescriptors() {
4062 switch (process.platform) {
@@ -4390,14 +4454,27 @@ function agentUpdate_Start(updateurl, updateoptions) {
4454 //process.exit = function (code) { console.log("Exit with code: " + code.toString()); }
4455
4456 // Called when the server connection state changes
4393 -function handleServerConnection(state) {
4457 +function handleServerConnection(state)
4458 +{
4459 meshServerConnectionState = state;
4395 - if (meshServerConnectionState == 0) {
4460 + if (meshServerConnectionState == 0)
4461 + {
4462 // Server disconnected
4463 if (selfInfoUpdateTimer != null) { clearInterval(selfInfoUpdateTimer); selfInfoUpdateTimer = null; }
4464 lastSelfInfo = null;
4399 - } else {
4465 + } else
4466 + {
4467 // Server connected, send mesh core information
4468 + if (require('MeshAgent').ServerInfo == null || require('MeshAgent').ServerInfo.ControlChannelCertificate == null)
4469 + {
4470 + // Outdated Agent, will have insecure tunnels
4471 + sendAgentMessage("This agent has an outdated certificate validation mechanism, consider updating.", 3, 118);
4472 + }
4473 + else if (global._MSH == null)
4474 + {
4475 + sendAgentMessage("This agent is outdated, consider updating.", 3, 120);
4476 + }
4477 +
4478 var oldNodeId = db.Get('OldNodeId');
4479 if (oldNodeId != null) { mesh.SendCommand({ action: 'mc1migration', oldnodeid: oldNodeId }); }
4480
@@ -4407,14 +4484,16 @@ function handleServerConnection(state) {
4484 // Update the server on with basic info, logged in users and more advanced stuff, like Intel ME and Network Settings
4485 meInfoStr = null;
4486 sendPeriodicServerUpdate(null, true);
4410 - if (selfInfoUpdateTimer == null) {
4487 + if (selfInfoUpdateTimer == null)
4488 + {
4489 selfInfoUpdateTimer = setInterval(sendPeriodicServerUpdate, 1200000); // 20 minutes
4490 selfInfoUpdateTimer.metadata = 'meshcore (InfoUpdate Timer)';
4491 }
4492
4493 // Send any state messages
4416 - if (Object.keys(tunnelUserCount.msg).length > 0) {
4417 - try { mesh.SendCommand({ action: 'sessions', type: 'msg', value: tunnelUserCount.msg }); } catch (e) { }
4494 + if (Object.keys(tunnelUserCount.msg).length > 0)
4495 + {
4496 + sendAgentMessage();
4497 broadcastSessionsToRegisteredApps();
4498 }
4499