Added server support for agent update using meshcore.

Ylian Saint-Hilaire committed Jan 14, 2021 at 16:17 UTC 2f5482e230b1c558b7da12767b8761841576fc7d
2 files changed +36 -11
agents/recoverycore.js
+1 -1
@@ -88,7 +88,7 @@ function getServerTargetUrlEx(url) {
88
89 require('MeshAgent').on('Connected', function () {
90 require('os').name().then(function (v) {
91 - sendConsoleText("Mesh Agent Receovery Console, OS: " + v);
91 + //sendConsoleText("Mesh Agent Receovery Console, OS: " + v);
92 require('MeshAgent').SendCommand(meshCoreObj);
93 });
94 });
meshagent.js
+35 -10
@@ -167,7 +167,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
167 // If we have a core, use it.
168 if (corename != null) {
169 const meshcorehash = parent.parent.defaultMeshCoresHash[corename];
170 - if (agentMeshCoreHash != meshcorehash) {
170 + if ((agentMeshCoreHash != meshcorehash) || (obj.agentCoreUpdate === true)) {
171 if ((obj.agentCoreCheck < 5) || (obj.agentCoreCheck == 1001)) {
172 if (meshcorehash == null) {
173 // Clear the core
@@ -187,7 +187,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
187 obj.agentCoreUpdatePending = true;
188 parent.parent.taskLimiter.launch(function (argument, taskid, taskLimiterQueue) {
189 if (obj.authenticated == 2) {
190 - // Send the updated code.
190 + // Send the updated core.
191 delete obj.agentCoreUpdatePending;
192 obj.sendBinary(common.ShortToStr(10) + common.ShortToStr(0) + argument.hash + argument.core, function () { parent.parent.taskLimiter.completed(taskid); }); // MeshCommand_CoreModule, start core update
193 parent.agentStats.updatingCoreCount++;
@@ -234,7 +234,15 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
234 else if (cmdid == 12) { // MeshCommand_AgentHash
235 if ((msg.length == 52) && (obj.agentExeInfo != null) && (obj.agentExeInfo.update == true)) {
236 const agenthash = msg.substring(4);
237 - if (compareAgentBinaryHash(obj.agentExeInfo, agenthash)) {
237 + const agentUpdateMethod = compareAgentBinaryHash(obj.agentExeInfo, agenthash)
238 + if (agentUpdateMethod === 2) { // Use meshcore agent update system
239 + // Send the recovery core to the agent, if the agent is capable of running one
240 + if (((obj.agentInfo.capabilities & 16) != 0) && (parent.parent.meshAgentsArchitectureNumbers[obj.agentInfo.agentId].core != null)) {
241 + obj.agentCoreCheck = 1001;
242 + obj.agentCoreUpdate = true;
243 + obj.sendBinary(common.ShortToStr(11) + common.ShortToStr(0)); // Command 11, ask for mesh core hash.
244 + }
245 + } else if (agentUpdateMethod === 1) { // Use native agent update system
246 // Mesh agent update required, do it using task limiter so not to flood the network. Medium priority task.
247 parent.parent.taskLimiter.launch(function (argument, taskid, taskLimiterQueue) {
248 if (obj.authenticated != 2) { parent.parent.taskLimiter.completed(taskid); return; } // If agent disconnection, complete and exit now.
@@ -518,7 +526,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
526 if ((msg.substring(2, 34) == parent.swarmCertificateHash256) || (msg.substring(2, 50) == parent.swarmCertificateHash384)) { obj.useSwarmCert = true; }
527 } else if (cmd == 30) {
528 // Agent Commit Date. This is future proofing. Can be used to change server behavior depending on the date range of the agent.
521 - //console.log('Connected Agent Commit Date: ' + msg.substring(2));
529 + //console.log('Connected Agent Commit Date: ' + msg.substring(2) + ", " + Date.parse(msg.substring(2)));
530 }
531 }
532 });
@@ -1140,8 +1148,21 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
1148 }
1149 case 'coreinfo':
1150 {
1143 - // Sent by the agent to update agent information
1144 - ChangeAgentCoreInfo(command);
1151 + if ((obj.agentCoreUpdate === true) && (obj.agentExeInfo != null)) {
1152 + // Agent update. The recovery core was loaded in the agent, send a command to update the agent
1153 + var cmd = { action: 'agentUpdate', url: obj.agentExeInfo.url, hash: obj.agentExeInfo.hashhex };
1154 + // Add server TLS cert hash
1155 + if (parent.parent.args.ignoreagenthashcheck !== true) {
1156 + const tlsCertHash = parent.webCertificateFullHashs[domain.id];
1157 + if (tlsCertHash != null) { cmd.servertlshash = Buffer.from(tlsCertHash, 'binary').toString('hex'); }
1158 + }
1159 + // Send the agent update command
1160 + obj.send(JSON.stringify(cmd));
1161 + delete obj.agentCoreUpdate;
1162 + } else {
1163 + // Sent by the agent to update agent information
1164 + ChangeAgentCoreInfo(command);
1165 + }
1166 break;
1167 }
1168 case 'smbios':
@@ -1669,15 +1690,19 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
1690 }
1691
1692 // Check if we need to update this agent, return true if agent binary update required.
1693 + // Return 0 is no update needed, 1 update using native system, 2 update using meshcore system
1694 function compareAgentBinaryHash(agentExeInfo, agentHash) {
1695 // If we are testing the agent update system, always return true
1674 - if (args.agentupdatetest === true) return true;
1696 + if ((args.agentupdatetest === true) || (args.agentupdatetest === 1)) return 1;
1697 + if (args.agentupdatetest === 2) return 2;
1698 // If the hash matches or is null, no update required.
1676 - if ((agentExeInfo.hash == agentHash) || (agentHash == '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0')) return false;
1699 + if ((agentExeInfo.hash == agentHash) || (agentHash == '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0')) return 0;
1700 // If this is a macOS x86 or ARM agent type and it matched the universal binary, no update required.
1678 - if (((agentExeInfo.id == 16) || (agentExeInfo.id == 29)) && (parent.parent.meshAgentBinaries[10005].hash == agentHash)) return false;
1701 + if (((agentExeInfo.id == 16) || (agentExeInfo.id == 29)) && (parent.parent.meshAgentBinaries[10005].hash == agentHash)) return 0;
1702 +
1703 // No match, update the agent.
1680 - return true;
1704 + if ((agentExeInfo.id == 3) && (agentExeInfo.id == 4)) return 2; // For Windows agents, use the meshcore update technique.
1705 + return 1; // For all other agents, use the native update technique.
1706 }
1707
1708 // Request that the core dump file on this agent be uploaded to the server