mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-12-26 07:23:03 +03:00
Added agent time stamping when signing a Windows agent.
This commit is contained in:
parent
de3d47e948
commit
18c11a344c
@ -486,7 +486,7 @@ function createAuthenticodeHandler(path) {
|
||||
fs.closeSync(output);
|
||||
|
||||
// Indicate we are done
|
||||
func(null);
|
||||
func(null, written);
|
||||
});
|
||||
});
|
||||
|
||||
@ -1372,7 +1372,7 @@ function createAuthenticodeHandler(path) {
|
||||
|
||||
// Close the file
|
||||
fs.closeSync(output);
|
||||
func(null);
|
||||
func(null, written);
|
||||
}
|
||||
|
||||
// Save an executable without the signature
|
||||
@ -1635,7 +1635,7 @@ function createAuthenticodeHandler(path) {
|
||||
fs.closeSync(output);
|
||||
|
||||
// Indicate success
|
||||
func(null);
|
||||
func(null, written);
|
||||
}
|
||||
|
||||
function writeExecutableEx(output, p7signature, written, func) {
|
||||
@ -1669,7 +1669,7 @@ function createAuthenticodeHandler(path) {
|
||||
fs.closeSync(output);
|
||||
|
||||
// Indicate success
|
||||
func(null);
|
||||
func(null, written);
|
||||
}
|
||||
|
||||
// Return null if we could not open the file
|
||||
|
@ -101,6 +101,7 @@
|
||||
"agentCoreDump": { "type": "boolean", "default": false, "description": "Automatically activates and transfers any agent crash dump files to the server in meshcentral-data/coredumps." },
|
||||
"agentCoreDumpUsers": { "type": "array", "description": "List of non-administrator users that have access to mesh agent crash dumps." },
|
||||
"agentSignLock": { "type": "boolean", "default": false, "description": "When code signing an agent using authenticode, lock the agent to only allow connection to this server. (This is in testing, the default value will change to true in the future)." },
|
||||
"agentTimeStampServer": { "type": [ "boolean", "string" ], "default": "http://timestamp.comodoca.com/authenticode", "description": "The time stamping server to use when code signing Windows executables. When set to false, the executables are not time stamped." },
|
||||
"ignoreAgentHashCheck": { "type": [ "boolean", "string" ], "default": false, "description": "When true, the agent no longer checked the TLS certificate of the server. This should be used for debugging only. You can also set this to a comma seperated list of IP addresses to ignore, for example: \"192.168.2.100,192.168.1.0/24\"." },
|
||||
"exactPorts": { "type": "boolean", "default": false, "description": "When set to true, MeshCentral will only grab the required TCP listening ports or fail. It will not try to use the next available port of it's busy." },
|
||||
"allowLoginToken": { "type": "boolean", "default": false },
|
||||
|
599
meshcentral.js
599
meshcentral.js
@ -1617,275 +1617,277 @@ function CreateMeshCentralServer(config, args) {
|
||||
|
||||
// Load the list of mesh agents and install scripts
|
||||
if ((obj.args.noagentupdate == 1) || (obj.args.noagentupdate == true)) { for (i in obj.meshAgentsArchitectureNumbers) { obj.meshAgentsArchitectureNumbers[i].update = false; } }
|
||||
obj.updateMeshAgentsTable(obj.config.domains[''], function () {
|
||||
obj.updateMeshAgentInstallScripts();
|
||||
obj.signMeshAgents(obj.config.domains[''], function () {
|
||||
obj.updateMeshAgentsTable(obj.config.domains[''], function () {
|
||||
obj.updateMeshAgentInstallScripts();
|
||||
|
||||
// Setup and start the web server
|
||||
obj.crypto.randomBytes(48, function (err, buf) {
|
||||
// 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; }
|
||||
if (typeof obj.args.sessionkey != 'string') { console.log("ERROR: Multi-server support requires \"SessionKey\" be set in the settings section of config.json, same key for all servers."); process.exit(0); return; }
|
||||
obj.serverId = obj.multiServer.serverid;
|
||||
for (var serverid in obj.config.peers.servers) { obj.peerConnectivityByNode[serverid] = {}; }
|
||||
}
|
||||
// Setup and start the web server
|
||||
obj.crypto.randomBytes(48, function (err, buf) {
|
||||
// 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; }
|
||||
if (typeof obj.args.sessionkey != 'string') { console.log("ERROR: Multi-server support requires \"SessionKey\" be set in the settings section of config.json, same key for all servers."); process.exit(0); return; }
|
||||
obj.serverId = obj.multiServer.serverid;
|
||||
for (var serverid in obj.config.peers.servers) { obj.peerConnectivityByNode[serverid] = {}; }
|
||||
}
|
||||
|
||||
// If the server is set to "nousers", allow only loopback unless IP filter is set
|
||||
if ((obj.args.nousers == true) && (obj.args.userallowedip == null)) { obj.args.userallowedip = "::1,127.0.0.1"; }
|
||||
// If the server is set to "nousers", allow only loopback unless IP filter is set
|
||||
if ((obj.args.nousers == true) && (obj.args.userallowedip == null)) { obj.args.userallowedip = "::1,127.0.0.1"; }
|
||||
|
||||
// Set the session length to 60 minutes if not set and set a random key if needed
|
||||
if ((obj.args.sessiontime != null) && ((typeof obj.args.sessiontime != 'number') || (obj.args.sessiontime < 1))) { delete obj.args.sessiontime; }
|
||||
if (typeof obj.args.sessionkey != 'string') { obj.args.sessionkey = buf.toString('hex').toUpperCase(); }
|
||||
// Set the session length to 60 minutes if not set and set a random key if needed
|
||||
if ((obj.args.sessiontime != null) && ((typeof obj.args.sessiontime != 'number') || (obj.args.sessiontime < 1))) { delete obj.args.sessiontime; }
|
||||
if (typeof obj.args.sessionkey != 'string') { obj.args.sessionkey = buf.toString('hex').toUpperCase(); }
|
||||
|
||||
// Create MQTT Broker to hook into webserver and mpsserver
|
||||
if ((typeof obj.config.settings.mqtt == 'object') && (typeof obj.config.settings.mqtt.auth == 'object') && (typeof obj.config.settings.mqtt.auth.keyid == 'string') && (typeof obj.config.settings.mqtt.auth.key == 'string')) { obj.mqttbroker = require("./mqttbroker.js").CreateMQTTBroker(obj, obj.db, obj.args); }
|
||||
// Create MQTT Broker to hook into webserver and mpsserver
|
||||
if ((typeof obj.config.settings.mqtt == 'object') && (typeof obj.config.settings.mqtt.auth == 'object') && (typeof obj.config.settings.mqtt.auth.keyid == 'string') && (typeof obj.config.settings.mqtt.auth.key == 'string')) { obj.mqttbroker = require("./mqttbroker.js").CreateMQTTBroker(obj, obj.db, obj.args); }
|
||||
|
||||
// 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.StartEx5);
|
||||
if (obj.redirserver != null) { obj.redirserver.hookMainWebServer(obj.certificates); }
|
||||
// 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.StartEx5);
|
||||
if (obj.redirserver != null) { obj.redirserver.hookMainWebServer(obj.certificates); }
|
||||
|
||||
// Update proxy certificates
|
||||
if (obj.supportsProxyCertificatesRequest == true) { obj.updateProxyCertificates(true); }
|
||||
// Update proxy certificates
|
||||
if (obj.supportsProxyCertificatesRequest == true) { obj.updateProxyCertificates(true); }
|
||||
|
||||
// Setup the Intel AMT event handler
|
||||
obj.amtEventHandler = require('./amtevents.js').CreateAmtEventsHandler(obj);
|
||||
// Setup the Intel AMT event handler
|
||||
obj.amtEventHandler = require('./amtevents.js').CreateAmtEventsHandler(obj);
|
||||
|
||||
// Setup the Intel AMT local network scanner
|
||||
if (obj.args.wanonly != true) {
|
||||
if (obj.args.amtscanner != false) { obj.amtScanner = require('./amtscanner.js').CreateAmtScanner(obj).start(); }
|
||||
if (obj.args.meshscanner != false) { obj.meshScanner = require('./meshscanner.js').CreateMeshScanner(obj).start(); }
|
||||
}
|
||||
// Setup the Intel AMT local network scanner
|
||||
if (obj.args.wanonly != true) {
|
||||
if (obj.args.amtscanner != false) { obj.amtScanner = require('./amtscanner.js').CreateAmtScanner(obj).start(); }
|
||||
if (obj.args.meshscanner != false) { obj.meshScanner = require('./meshscanner.js').CreateMeshScanner(obj).start(); }
|
||||
}
|
||||
|
||||
// Setup and start the MPS server
|
||||
obj.mpsserver = require('./mpsserver.js').CreateMpsServer(obj, obj.db, obj.args, obj.certificates);
|
||||
// Setup and start the MPS server
|
||||
obj.mpsserver = require('./mpsserver.js').CreateMpsServer(obj, obj.db, obj.args, obj.certificates);
|
||||
|
||||
// Setup the Intel AMT manager
|
||||
if (obj.args.amtmanager !== false) {
|
||||
obj.amtManager = require('./amtmanager.js').CreateAmtManager(obj);
|
||||
}
|
||||
// Setup the Intel AMT manager
|
||||
if (obj.args.amtmanager !== false) {
|
||||
obj.amtManager = require('./amtmanager.js').CreateAmtManager(obj);
|
||||
}
|
||||
|
||||
// Setup and start the legacy swarm server
|
||||
if ((obj.certificates.swarmserver != null) && (obj.args.swarmport != null) && (obj.args.swarmport !== 0)) {
|
||||
obj.swarmserver = require('./swarmserver.js').CreateSwarmServer(obj, obj.db, obj.args, obj.certificates);
|
||||
}
|
||||
// Setup and start the legacy swarm server
|
||||
if ((obj.certificates.swarmserver != null) && (obj.args.swarmport != null) && (obj.args.swarmport !== 0)) {
|
||||
obj.swarmserver = require('./swarmserver.js').CreateSwarmServer(obj, obj.db, obj.args, obj.certificates);
|
||||
}
|
||||
|
||||
// Setup the main email server
|
||||
if (obj.config.sendgrid != null) {
|
||||
// Sendgrid server
|
||||
obj.mailserver = require('./meshmail.js').CreateMeshMail(obj);
|
||||
obj.mailserver.verify();
|
||||
if (obj.args.lanonly == true) { addServerWarning("SendGrid server has limited use in LAN mode.", 17); }
|
||||
} else if (obj.config.smtp != null) {
|
||||
// SMTP server
|
||||
obj.mailserver = require('./meshmail.js').CreateMeshMail(obj);
|
||||
obj.mailserver.verify();
|
||||
if (obj.args.lanonly == true) { addServerWarning("SMTP server has limited use in LAN mode.", 18); }
|
||||
} else if (obj.config.sendmail != null) {
|
||||
// Sendmail server
|
||||
obj.mailserver = require('./meshmail.js').CreateMeshMail(obj);
|
||||
obj.mailserver.verify();
|
||||
if (obj.args.lanonly == true) { addServerWarning("SMTP server has limited use in LAN mode.", 18); }
|
||||
}
|
||||
|
||||
// Setup the email server for each domain
|
||||
for (i in obj.config.domains) {
|
||||
if (obj.config.domains[i].sendgrid != null) {
|
||||
// Setup the main email server
|
||||
if (obj.config.sendgrid != null) {
|
||||
// Sendgrid server
|
||||
obj.config.domains[i].mailserver = require('./meshmail.js').CreateMeshMail(obj, obj.config.domains[i]);
|
||||
obj.config.domains[i].mailserver.verify();
|
||||
obj.mailserver = require('./meshmail.js').CreateMeshMail(obj);
|
||||
obj.mailserver.verify();
|
||||
if (obj.args.lanonly == true) { addServerWarning("SendGrid server has limited use in LAN mode.", 17); }
|
||||
} else if ((obj.config.domains[i].smtp != null) && (obj.config.domains[i].smtp.host != null) && (obj.config.domains[i].smtp.from != null)) {
|
||||
} else if (obj.config.smtp != null) {
|
||||
// SMTP server
|
||||
obj.config.domains[i].mailserver = require('./meshmail.js').CreateMeshMail(obj, obj.config.domains[i]);
|
||||
obj.config.domains[i].mailserver.verify();
|
||||
obj.mailserver = require('./meshmail.js').CreateMeshMail(obj);
|
||||
obj.mailserver.verify();
|
||||
if (obj.args.lanonly == true) { addServerWarning("SMTP server has limited use in LAN mode.", 18); }
|
||||
} else if (obj.config.domains[i].sendmail != null) {
|
||||
} else if (obj.config.sendmail != null) {
|
||||
// Sendmail server
|
||||
obj.config.domains[i].mailserver = require('./meshmail.js').CreateMeshMail(obj, obj.config.domains[i]);
|
||||
obj.config.domains[i].mailserver.verify();
|
||||
obj.mailserver = require('./meshmail.js').CreateMeshMail(obj);
|
||||
obj.mailserver.verify();
|
||||
if (obj.args.lanonly == true) { addServerWarning("SMTP server has limited use in LAN mode.", 18); }
|
||||
} else {
|
||||
// Setup the parent mail server for this domain
|
||||
if (obj.mailserver != null) { obj.config.domains[i].mailserver = obj.mailserver; }
|
||||
}
|
||||
}
|
||||
|
||||
// Setup SMS gateway
|
||||
if (config.sms != null) {
|
||||
obj.smsserver = require('./meshsms.js').CreateMeshSMS(obj);
|
||||
if ((obj.smsserver != null) && (obj.args.lanonly == true)) { addServerWarning("SMS gateway has limited use in LAN mode.", 19); }
|
||||
}
|
||||
|
||||
// Setup web based push notifications
|
||||
if ((typeof config.settings.webpush == 'object') && (typeof config.settings.webpush.email == 'string')) {
|
||||
obj.webpush = require('web-push');
|
||||
var vapidKeys = null;
|
||||
try { vapidKeys = JSON.parse(obj.fs.readFileSync(obj.path.join(obj.datapath, 'vapid.json')).toString()); } catch (ex) { }
|
||||
if ((vapidKeys == null) || (typeof vapidKeys.publicKey != 'string') || (typeof vapidKeys.privateKey != 'string')) {
|
||||
console.log("Generating web push VAPID keys...");
|
||||
vapidKeys = obj.webpush.generateVAPIDKeys();
|
||||
obj.fs.writeFileSync(obj.path.join(obj.datapath, 'vapid.json'), JSON.stringify(vapidKeys));
|
||||
}
|
||||
obj.webpush.vapidPublicKey = vapidKeys.publicKey;
|
||||
obj.webpush.setVapidDetails('mailto:' + config.settings.webpush.email, vapidKeys.publicKey, vapidKeys.privateKey);
|
||||
if (typeof config.settings.webpush.gcmapi == 'string') { webpush.setGCMAPIKey(config.settings.webpush.gcmapi); }
|
||||
}
|
||||
|
||||
// Setup Firebase
|
||||
if ((config.firebase != null) && (typeof config.firebase.senderid == 'string') && (typeof config.firebase.serverkey == 'string')) {
|
||||
obj.firebase = require('./firebase').CreateFirebase(obj, config.firebase.senderid, config.firebase.serverkey);
|
||||
} else if ((typeof config.firebaserelay == 'object') && (typeof config.firebaserelay.url == 'string')) {
|
||||
// Setup the push messaging relay
|
||||
obj.firebase = require('./firebase').CreateFirebaseRelay(obj, config.firebaserelay.url, config.firebaserelay.key);
|
||||
} else if (obj.config.settings.publicpushnotifications === true) {
|
||||
// Setup the Firebase push messaging relay using https://meshcentral.com, this is the public push notification server.
|
||||
obj.firebase = require('./firebase').CreateFirebaseRelay(obj, 'https://meshcentral.com/firebaserelay.aspx');
|
||||
}
|
||||
|
||||
// Start periodic maintenance
|
||||
obj.maintenanceTimer = setInterval(obj.maintenanceActions, 1000 * 60 * 60); // Run this every hour
|
||||
|
||||
// Dispatch an event that the server is now running
|
||||
obj.DispatchEvent(['*'], obj, { etype: 'server', action: 'started', msg: 'Server started' });
|
||||
|
||||
// Plugin hook. Need to run something at server startup? This is the place.
|
||||
if (obj.pluginHandler) { obj.pluginHandler.callHook('server_startup'); }
|
||||
|
||||
// Setup the login cookie encryption key
|
||||
if ((obj.config) && (obj.config.settings) && (typeof obj.config.settings.logincookieencryptionkey == 'string')) {
|
||||
// We have a string, hash it and use that as a key
|
||||
try { obj.loginCookieEncryptionKey = Buffer.from(obj.config.settings.logincookieencryptionkey, 'hex'); } catch (ex) { }
|
||||
if ((obj.loginCookieEncryptionKey == null) || (obj.loginCookieEncryptionKey.length != 80)) { addServerWarning("Invalid \"LoginCookieEncryptionKey\" in config.json.", 20); obj.loginCookieEncryptionKey = null; }
|
||||
}
|
||||
|
||||
// Login cookie encryption key not set, use one from the database
|
||||
if (obj.loginCookieEncryptionKey == null) {
|
||||
obj.db.Get('LoginCookieEncryptionKey', function (err, docs) {
|
||||
if ((docs != null) && (docs.length > 0) && (docs[0].key != null) && (obj.args.logintokengen == null) && (docs[0].key.length >= 160)) {
|
||||
obj.loginCookieEncryptionKey = Buffer.from(docs[0].key, 'hex');
|
||||
// Setup the email server for each domain
|
||||
for (i in obj.config.domains) {
|
||||
if (obj.config.domains[i].sendgrid != null) {
|
||||
// Sendgrid server
|
||||
obj.config.domains[i].mailserver = require('./meshmail.js').CreateMeshMail(obj, obj.config.domains[i]);
|
||||
obj.config.domains[i].mailserver.verify();
|
||||
if (obj.args.lanonly == true) { addServerWarning("SendGrid server has limited use in LAN mode.", 17); }
|
||||
} else if ((obj.config.domains[i].smtp != null) && (obj.config.domains[i].smtp.host != null) && (obj.config.domains[i].smtp.from != null)) {
|
||||
// SMTP server
|
||||
obj.config.domains[i].mailserver = require('./meshmail.js').CreateMeshMail(obj, obj.config.domains[i]);
|
||||
obj.config.domains[i].mailserver.verify();
|
||||
if (obj.args.lanonly == true) { addServerWarning("SMTP server has limited use in LAN mode.", 18); }
|
||||
} else if (obj.config.domains[i].sendmail != null) {
|
||||
// Sendmail server
|
||||
obj.config.domains[i].mailserver = require('./meshmail.js').CreateMeshMail(obj, obj.config.domains[i]);
|
||||
obj.config.domains[i].mailserver.verify();
|
||||
if (obj.args.lanonly == true) { addServerWarning("SMTP server has limited use in LAN mode.", 18); }
|
||||
} else {
|
||||
obj.loginCookieEncryptionKey = obj.generateCookieKey(); obj.db.Set({ _id: 'LoginCookieEncryptionKey', key: obj.loginCookieEncryptionKey.toString('hex'), time: Date.now() });
|
||||
// Setup the parent mail server for this domain
|
||||
if (obj.mailserver != null) { obj.config.domains[i].mailserver = obj.mailserver; }
|
||||
}
|
||||
}
|
||||
|
||||
// Setup SMS gateway
|
||||
if (config.sms != null) {
|
||||
obj.smsserver = require('./meshsms.js').CreateMeshSMS(obj);
|
||||
if ((obj.smsserver != null) && (obj.args.lanonly == true)) { addServerWarning("SMS gateway has limited use in LAN mode.", 19); }
|
||||
}
|
||||
|
||||
// Setup web based push notifications
|
||||
if ((typeof config.settings.webpush == 'object') && (typeof config.settings.webpush.email == 'string')) {
|
||||
obj.webpush = require('web-push');
|
||||
var vapidKeys = null;
|
||||
try { vapidKeys = JSON.parse(obj.fs.readFileSync(obj.path.join(obj.datapath, 'vapid.json')).toString()); } catch (ex) { }
|
||||
if ((vapidKeys == null) || (typeof vapidKeys.publicKey != 'string') || (typeof vapidKeys.privateKey != 'string')) {
|
||||
console.log("Generating web push VAPID keys...");
|
||||
vapidKeys = obj.webpush.generateVAPIDKeys();
|
||||
obj.fs.writeFileSync(obj.path.join(obj.datapath, 'vapid.json'), JSON.stringify(vapidKeys));
|
||||
}
|
||||
obj.webpush.vapidPublicKey = vapidKeys.publicKey;
|
||||
obj.webpush.setVapidDetails('mailto:' + config.settings.webpush.email, vapidKeys.publicKey, vapidKeys.privateKey);
|
||||
if (typeof config.settings.webpush.gcmapi == 'string') { webpush.setGCMAPIKey(config.settings.webpush.gcmapi); }
|
||||
}
|
||||
|
||||
// Setup Firebase
|
||||
if ((config.firebase != null) && (typeof config.firebase.senderid == 'string') && (typeof config.firebase.serverkey == 'string')) {
|
||||
obj.firebase = require('./firebase').CreateFirebase(obj, config.firebase.senderid, config.firebase.serverkey);
|
||||
} else if ((typeof config.firebaserelay == 'object') && (typeof config.firebaserelay.url == 'string')) {
|
||||
// Setup the push messaging relay
|
||||
obj.firebase = require('./firebase').CreateFirebaseRelay(obj, config.firebaserelay.url, config.firebaserelay.key);
|
||||
} else if (obj.config.settings.publicpushnotifications === true) {
|
||||
// Setup the Firebase push messaging relay using https://meshcentral.com, this is the public push notification server.
|
||||
obj.firebase = require('./firebase').CreateFirebaseRelay(obj, 'https://meshcentral.com/firebaserelay.aspx');
|
||||
}
|
||||
|
||||
// Start periodic maintenance
|
||||
obj.maintenanceTimer = setInterval(obj.maintenanceActions, 1000 * 60 * 60); // Run this every hour
|
||||
|
||||
// Dispatch an event that the server is now running
|
||||
obj.DispatchEvent(['*'], obj, { etype: 'server', action: 'started', msg: 'Server started' });
|
||||
|
||||
// Plugin hook. Need to run something at server startup? This is the place.
|
||||
if (obj.pluginHandler) { obj.pluginHandler.callHook('server_startup'); }
|
||||
|
||||
// Setup the login cookie encryption key
|
||||
if ((obj.config) && (obj.config.settings) && (typeof obj.config.settings.logincookieencryptionkey == 'string')) {
|
||||
// We have a string, hash it and use that as a key
|
||||
try { obj.loginCookieEncryptionKey = Buffer.from(obj.config.settings.logincookieencryptionkey, 'hex'); } catch (ex) { }
|
||||
if ((obj.loginCookieEncryptionKey == null) || (obj.loginCookieEncryptionKey.length != 80)) { addServerWarning("Invalid \"LoginCookieEncryptionKey\" in config.json.", 20); obj.loginCookieEncryptionKey = null; }
|
||||
}
|
||||
|
||||
// Login cookie encryption key not set, use one from the database
|
||||
if (obj.loginCookieEncryptionKey == null) {
|
||||
obj.db.Get('LoginCookieEncryptionKey', function (err, docs) {
|
||||
if ((docs != null) && (docs.length > 0) && (docs[0].key != null) && (obj.args.logintokengen == null) && (docs[0].key.length >= 160)) {
|
||||
obj.loginCookieEncryptionKey = Buffer.from(docs[0].key, 'hex');
|
||||
} else {
|
||||
obj.loginCookieEncryptionKey = obj.generateCookieKey(); obj.db.Set({ _id: 'LoginCookieEncryptionKey', key: obj.loginCookieEncryptionKey.toString('hex'), time: Date.now() });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Load the invitation link encryption key from the database
|
||||
obj.db.Get('InvitationLinkEncryptionKey', function (err, docs) {
|
||||
if ((docs != null) && (docs.length > 0) && (docs[0].key != null) && (docs[0].key.length >= 160)) {
|
||||
obj.invitationLinkEncryptionKey = Buffer.from(docs[0].key, 'hex');
|
||||
} else {
|
||||
obj.invitationLinkEncryptionKey = obj.generateCookieKey(); obj.db.Set({ _id: 'InvitationLinkEncryptionKey', key: obj.invitationLinkEncryptionKey.toString('hex'), time: Date.now() });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Load the invitation link encryption key from the database
|
||||
obj.db.Get('InvitationLinkEncryptionKey', function (err, docs) {
|
||||
if ((docs != null) && (docs.length > 0) && (docs[0].key != null) && (docs[0].key.length >= 160)) {
|
||||
obj.invitationLinkEncryptionKey = Buffer.from(docs[0].key, 'hex');
|
||||
} else {
|
||||
obj.invitationLinkEncryptionKey = obj.generateCookieKey(); obj.db.Set({ _id: 'InvitationLinkEncryptionKey', key: obj.invitationLinkEncryptionKey.toString('hex'), time: Date.now() });
|
||||
// Setup Intel AMT hello server
|
||||
if ((typeof config.settings.amtprovisioningserver == 'object') && (typeof config.settings.amtprovisioningserver.devicegroup == 'string') && (typeof config.settings.amtprovisioningserver.newmebxpassword == 'string') && (typeof config.settings.amtprovisioningserver.trustedfqdn == 'string') && (typeof config.settings.amtprovisioningserver.ip == 'string')) {
|
||||
obj.amtProvisioningServer = require('./amtprovisioningserver').CreateAmtProvisioningServer(obj, config.settings.amtprovisioningserver);
|
||||
}
|
||||
});
|
||||
|
||||
// Setup Intel AMT hello server
|
||||
if ((typeof config.settings.amtprovisioningserver == 'object') && (typeof config.settings.amtprovisioningserver.devicegroup == 'string') && (typeof config.settings.amtprovisioningserver.newmebxpassword == 'string') && (typeof config.settings.amtprovisioningserver.trustedfqdn == 'string') && (typeof config.settings.amtprovisioningserver.ip == 'string')) {
|
||||
obj.amtProvisioningServer = require('./amtprovisioningserver').CreateAmtProvisioningServer(obj, config.settings.amtprovisioningserver);
|
||||
}
|
||||
// Start collecting server stats every 5 minutes
|
||||
obj.trafficStats = obj.webserver.getTrafficStats();
|
||||
setInterval(function () {
|
||||
obj.serverStatsCounter++;
|
||||
var hours = 720; // Start with all events lasting 30 days.
|
||||
if (((obj.serverStatsCounter) % 2) == 1) { hours = 3; } // Half of the event get removed after 3 hours.
|
||||
else if ((Math.floor(obj.serverStatsCounter / 2) % 2) == 1) { hours = 8; } // Another half of the event get removed after 8 hours.
|
||||
else if ((Math.floor(obj.serverStatsCounter / 4) % 2) == 1) { hours = 24; } // Another half of the event get removed after 24 hours.
|
||||
else if ((Math.floor(obj.serverStatsCounter / 8) % 2) == 1) { hours = 48; } // Another half of the event get removed after 48 hours.
|
||||
else if ((Math.floor(obj.serverStatsCounter / 16) % 2) == 1) { hours = 72; } // Another half of the event get removed after 72 hours.
|
||||
const expire = new Date();
|
||||
expire.setTime(expire.getTime() + (60 * 60 * 1000 * hours));
|
||||
|
||||
// Start collecting server stats every 5 minutes
|
||||
obj.trafficStats = obj.webserver.getTrafficStats();
|
||||
setInterval(function () {
|
||||
obj.serverStatsCounter++;
|
||||
var hours = 720; // Start with all events lasting 30 days.
|
||||
if (((obj.serverStatsCounter) % 2) == 1) { hours = 3; } // Half of the event get removed after 3 hours.
|
||||
else if ((Math.floor(obj.serverStatsCounter / 2) % 2) == 1) { hours = 8; } // Another half of the event get removed after 8 hours.
|
||||
else if ((Math.floor(obj.serverStatsCounter / 4) % 2) == 1) { hours = 24; } // Another half of the event get removed after 24 hours.
|
||||
else if ((Math.floor(obj.serverStatsCounter / 8) % 2) == 1) { hours = 48; } // Another half of the event get removed after 48 hours.
|
||||
else if ((Math.floor(obj.serverStatsCounter / 16) % 2) == 1) { hours = 72; } // Another half of the event get removed after 72 hours.
|
||||
const expire = new Date();
|
||||
expire.setTime(expire.getTime() + (60 * 60 * 1000 * hours));
|
||||
// Get traffic data
|
||||
var trafficStats = obj.webserver.getTrafficDelta(obj.trafficStats);
|
||||
obj.trafficStats = trafficStats.current;
|
||||
|
||||
// Get traffic data
|
||||
var trafficStats = obj.webserver.getTrafficDelta(obj.trafficStats);
|
||||
obj.trafficStats = trafficStats.current;
|
||||
var data = {
|
||||
time: new Date(),
|
||||
expire: expire,
|
||||
mem: process.memoryUsage(),
|
||||
conn: {
|
||||
ca: Object.keys(obj.webserver.wsagents).length,
|
||||
cu: Object.keys(obj.webserver.wssessions).length,
|
||||
us: Object.keys(obj.webserver.wssessions2).length,
|
||||
rs: obj.webserver.relaySessionCount
|
||||
},
|
||||
traffic: trafficStats.delta
|
||||
};
|
||||
try { data.cpu = require('os').loadavg(); } catch (ex) { }
|
||||
if (obj.mpsserver != null) {
|
||||
data.conn.am = 0;
|
||||
for (var i in obj.mpsserver.ciraConnections) { data.conn.am += obj.mpsserver.ciraConnections[i].length; }
|
||||
}
|
||||
if (obj.firstStats === true) { delete obj.firstStats; data.first = true; }
|
||||
if (obj.multiServer != null) { data.s = obj.multiServer.serverid; }
|
||||
obj.db.SetServerStats(data); // Save the stats to the database
|
||||
obj.DispatchEvent(['*'], obj, { action: 'servertimelinestats', data: data }); // Event the server stats
|
||||
}, 300000);
|
||||
|
||||
var data = {
|
||||
time: new Date(),
|
||||
expire: expire,
|
||||
mem: process.memoryUsage(),
|
||||
conn: {
|
||||
ca: Object.keys(obj.webserver.wsagents).length,
|
||||
cu: Object.keys(obj.webserver.wssessions).length,
|
||||
us: Object.keys(obj.webserver.wssessions2).length,
|
||||
rs: obj.webserver.relaySessionCount
|
||||
},
|
||||
traffic: trafficStats.delta
|
||||
};
|
||||
try { data.cpu = require('os').loadavg(); } catch (ex) { }
|
||||
if (obj.mpsserver != null) {
|
||||
data.conn.am = 0;
|
||||
for (var i in obj.mpsserver.ciraConnections) { data.conn.am += obj.mpsserver.ciraConnections[i].length; }
|
||||
obj.debug('main', "Server started");
|
||||
if (obj.args.nousers == true) { obj.updateServerState('nousers', '1'); }
|
||||
obj.updateServerState('state', "running");
|
||||
|
||||
// Setup auto-backup defaults
|
||||
if (obj.config.settings.autobackup == null) { obj.config.settings.autobackup = { backupintervalhours: 24, keeplastdaysbackup: 10 }; }
|
||||
else if (obj.config.settings.autobackup === false) { delete obj.config.settings.autobackup; }
|
||||
|
||||
// Check that autobackup path is not within the "meshcentral-data" folder.
|
||||
if ((typeof obj.config.settings.autobackup == 'object') && (typeof obj.config.settings.autobackup.backuppath == 'string') && (obj.path.normalize(obj.config.settings.autobackup.backuppath).startsWith(obj.path.normalize(obj.datapath)))) {
|
||||
addServerWarning("Backup path can't be set within meshcentral-data folder, backup settings ignored.", 21);
|
||||
delete obj.config.settings.autobackup;
|
||||
}
|
||||
if (obj.firstStats === true) { delete obj.firstStats; data.first = true; }
|
||||
if (obj.multiServer != null) { data.s = obj.multiServer.serverid; }
|
||||
obj.db.SetServerStats(data); // Save the stats to the database
|
||||
obj.DispatchEvent(['*'], obj, { action: 'servertimelinestats', data: data }); // Event the server stats
|
||||
}, 300000);
|
||||
|
||||
obj.debug('main', "Server started");
|
||||
if (obj.args.nousers == true) { obj.updateServerState('nousers', '1'); }
|
||||
obj.updateServerState('state', "running");
|
||||
// Load Intel AMT passwords from the "amtactivation.log" file
|
||||
obj.loadAmtActivationLogPasswords(function (amtPasswords) {
|
||||
obj.amtPasswords = amtPasswords;
|
||||
});
|
||||
|
||||
// Setup auto-backup defaults
|
||||
if (obj.config.settings.autobackup == null) { obj.config.settings.autobackup = { backupintervalhours: 24, keeplastdaysbackup: 10 }; }
|
||||
else if (obj.config.settings.autobackup === false) { delete obj.config.settings.autobackup; }
|
||||
|
||||
// Check that autobackup path is not within the "meshcentral-data" folder.
|
||||
if ((typeof obj.config.settings.autobackup == 'object') && (typeof obj.config.settings.autobackup.backuppath == 'string') && (obj.path.normalize(obj.config.settings.autobackup.backuppath).startsWith(obj.path.normalize(obj.datapath)))) {
|
||||
addServerWarning("Backup path can't be set within meshcentral-data folder, backup settings ignored.", 21);
|
||||
delete obj.config.settings.autobackup;
|
||||
}
|
||||
|
||||
// Load Intel AMT passwords from the "amtactivation.log" file
|
||||
obj.loadAmtActivationLogPasswords(function (amtPasswords) {
|
||||
obj.amtPasswords = amtPasswords;
|
||||
});
|
||||
|
||||
// Setup users that can see all device groups
|
||||
if (typeof obj.config.settings.managealldevicegroups == 'string') { obj.config.settings.managealldevicegroups = obj.config.settings.managealldevicegroups.split(','); }
|
||||
else if (Array.isArray(obj.config.settings.managealldevicegroups) == false) { obj.config.settings.managealldevicegroups = []; }
|
||||
for (i in obj.config.domains) {
|
||||
if (Array.isArray(obj.config.domains[i].managealldevicegroups)) {
|
||||
for (var j in obj.config.domains[i].managealldevicegroups) {
|
||||
if (typeof obj.config.domains[i].managealldevicegroups[j] == 'string') {
|
||||
const u = 'user/' + i + '/' + obj.config.domains[i].managealldevicegroups[j];
|
||||
if (obj.config.settings.managealldevicegroups.indexOf(u) == -1) { obj.config.settings.managealldevicegroups.push(u); }
|
||||
// Setup users that can see all device groups
|
||||
if (typeof obj.config.settings.managealldevicegroups == 'string') { obj.config.settings.managealldevicegroups = obj.config.settings.managealldevicegroups.split(','); }
|
||||
else if (Array.isArray(obj.config.settings.managealldevicegroups) == false) { obj.config.settings.managealldevicegroups = []; }
|
||||
for (i in obj.config.domains) {
|
||||
if (Array.isArray(obj.config.domains[i].managealldevicegroups)) {
|
||||
for (var j in obj.config.domains[i].managealldevicegroups) {
|
||||
if (typeof obj.config.domains[i].managealldevicegroups[j] == 'string') {
|
||||
const u = 'user/' + i + '/' + obj.config.domains[i].managealldevicegroups[j];
|
||||
if (obj.config.settings.managealldevicegroups.indexOf(u) == -1) { obj.config.settings.managealldevicegroups.push(u); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
obj.config.settings.managealldevicegroups.sort();
|
||||
obj.config.settings.managealldevicegroups.sort();
|
||||
|
||||
// Start watchdog timer if needed
|
||||
// This is used to monitor if NodeJS is servicing IO correctly or getting held up a lot. Add this line to the settings section of config.json
|
||||
// "watchDog": { "interval": 100, "timeout": 150 }
|
||||
// This will check every 100ms, if the timer is more than 150ms late, it will warn.
|
||||
if ((typeof config.settings.watchdog == 'object') && (typeof config.settings.watchdog.interval == 'number') && (typeof config.settings.watchdog.timeout == 'number') && (config.settings.watchdog.interval >= 50) && (config.settings.watchdog.timeout >= 50)) {
|
||||
obj.watchdogtime = Date.now();
|
||||
obj.watchdogmax = 0;
|
||||
obj.watchdogmaxtime = null;
|
||||
obj.watchdogtable = [];
|
||||
obj.watchdog = setInterval(function () {
|
||||
const now = Date.now(), delta = now - obj.watchdogtime - config.settings.watchdog.interval;
|
||||
if (delta > obj.watchdogmax) { obj.watchdogmax = delta; obj.watchdogmaxtime = new Date().toLocaleString(); }
|
||||
if (delta > config.settings.watchdog.timeout) {
|
||||
const msg = obj.common.format("Watchdog timer timeout, {0}ms.", delta);
|
||||
obj.watchdogtable.push(new Date().toLocaleString() + ', ' + delta + 'ms');
|
||||
while (obj.watchdogtable.length > 10) { obj.watchdogtable.shift(); }
|
||||
obj.debug('main', msg);
|
||||
try {
|
||||
var errlogpath = null;
|
||||
if (typeof obj.args.mesherrorlogpath == 'string') { errlogpath = obj.path.join(obj.args.mesherrorlogpath, 'mesherrors.txt'); } else { errlogpath = obj.getConfigFilePath('mesherrors.txt'); }
|
||||
obj.fs.appendFileSync(errlogpath, new Date().toLocaleString() + ': ' + msg + '\r\n');
|
||||
} catch (ex) { console.log('ERROR: Unable to write to mesherrors.txt.'); }
|
||||
}
|
||||
obj.watchdogtime = now;
|
||||
}, config.settings.watchdog.interval);
|
||||
obj.debug('main', "Started watchdog timer.");
|
||||
}
|
||||
// Start watchdog timer if needed
|
||||
// This is used to monitor if NodeJS is servicing IO correctly or getting held up a lot. Add this line to the settings section of config.json
|
||||
// "watchDog": { "interval": 100, "timeout": 150 }
|
||||
// This will check every 100ms, if the timer is more than 150ms late, it will warn.
|
||||
if ((typeof config.settings.watchdog == 'object') && (typeof config.settings.watchdog.interval == 'number') && (typeof config.settings.watchdog.timeout == 'number') && (config.settings.watchdog.interval >= 50) && (config.settings.watchdog.timeout >= 50)) {
|
||||
obj.watchdogtime = Date.now();
|
||||
obj.watchdogmax = 0;
|
||||
obj.watchdogmaxtime = null;
|
||||
obj.watchdogtable = [];
|
||||
obj.watchdog = setInterval(function () {
|
||||
const now = Date.now(), delta = now - obj.watchdogtime - config.settings.watchdog.interval;
|
||||
if (delta > obj.watchdogmax) { obj.watchdogmax = delta; obj.watchdogmaxtime = new Date().toLocaleString(); }
|
||||
if (delta > config.settings.watchdog.timeout) {
|
||||
const msg = obj.common.format("Watchdog timer timeout, {0}ms.", delta);
|
||||
obj.watchdogtable.push(new Date().toLocaleString() + ', ' + delta + 'ms');
|
||||
while (obj.watchdogtable.length > 10) { obj.watchdogtable.shift(); }
|
||||
obj.debug('main', msg);
|
||||
try {
|
||||
var errlogpath = null;
|
||||
if (typeof obj.args.mesherrorlogpath == 'string') { errlogpath = obj.path.join(obj.args.mesherrorlogpath, 'mesherrors.txt'); } else { errlogpath = obj.getConfigFilePath('mesherrors.txt'); }
|
||||
obj.fs.appendFileSync(errlogpath, new Date().toLocaleString() + ': ' + msg + '\r\n');
|
||||
} catch (ex) { console.log('ERROR: Unable to write to mesherrors.txt.'); }
|
||||
}
|
||||
obj.watchdogtime = now;
|
||||
}, config.settings.watchdog.interval);
|
||||
obj.debug('main', "Started watchdog timer.");
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
@ -2841,24 +2843,29 @@ function CreateMeshCentralServer(config, args) {
|
||||
10006: { id: 10006, localname: 'MeshCentralAssistant.exe', rname: 'MeshCentralAssistant.exe', desc: 'MeshCentral Assistant for Windows', update: false, amt: false, platform: 'win32' } // MeshCentral Assistant
|
||||
};
|
||||
|
||||
// Update the list of available mesh agents
|
||||
obj.updateMeshAgentsTable = function (domain, func) {
|
||||
// Sign windows agents
|
||||
obj.signMeshAgents = function (domain, func) {
|
||||
// Setup the domain is specified
|
||||
var objx = domain, suffix = '';
|
||||
if (domain.id == '') { objx = obj; } else { suffix = '-' + domain.id; objx.meshAgentBinaries = {}; }
|
||||
|
||||
// Check if a custom agent signing certificate is available
|
||||
var agentSignCertInfo = require('./authenticode.js').loadCertificates([ obj.path.join(obj.datapath, 'agentsigningcert.pem') ]);
|
||||
var agentSignCertInfo = require('./authenticode.js').loadCertificates([obj.path.join(obj.datapath, 'agentsigningcert.pem')]);
|
||||
if (agentSignCertInfo == null) { func(); return; } // No code signing certificate, nothing to do.
|
||||
|
||||
// If not using a custom signing cert, get agent code signature certificate ready with the full cert chain
|
||||
if ((agentSignCertInfo == null) && (obj.certificates.codesign != null)) {
|
||||
agentSignCertInfo = {
|
||||
cert: obj.certificateOperations.forge.pki.certificateFromPem(obj.certificates.codesign.cert),
|
||||
key: obj.certificateOperations.forge.pki.privateKeyFromPem(obj.certificates.codesign.key),
|
||||
extraCerts: [obj.certificateOperations.forge.pki.certificateFromPem(obj.certificates.root.cert) ]
|
||||
extraCerts: [obj.certificateOperations.forge.pki.certificateFromPem(obj.certificates.root.cert)]
|
||||
}
|
||||
}
|
||||
|
||||
// Setup the domain is specified
|
||||
var objx = domain, suffix = '';
|
||||
if (domain.id == '') { objx = obj; } else { suffix = '-' + domain.id; objx.meshAgentBinaries = {}; }
|
||||
|
||||
// Generate the agent signature description and URL
|
||||
var serverSignedAgentsPath, signDesc, signUrl;
|
||||
if (agentSignCertInfo != null) {
|
||||
@ -2877,12 +2884,17 @@ function CreateMeshCentralServer(config, args) {
|
||||
if (obj.config.settings.agentsignlock) { signUrl += '?ServerID=' + obj.certificateOperations.getPublicKeyHash(obj.certificates.agent.cert).toUpperCase(); }
|
||||
}
|
||||
|
||||
// Load agent information file. This includes the data & time of the agent.
|
||||
const agentInfo = [];
|
||||
try { agentInfo = JSON.parse(obj.fs.readFileSync(obj.path.join(__dirname, 'agents', 'hashagents.json'), 'utf8')); } catch (ex) { }
|
||||
// Setup the time server
|
||||
var timeStampUrl = 'http://timestamp.comodoca.com/authenticode';
|
||||
if (args.agenttimestampserver === false) { timeStampUrl = null; }
|
||||
else if (typeof args.agenttimestampserver == 'string') { timeStampUrl = args.agenttimestampserver; }
|
||||
|
||||
// Setup the pending operations counter
|
||||
var pendingOperations = 1;
|
||||
|
||||
var archcount = 0;
|
||||
for (var archid in obj.meshAgentsArchitectureNumbers) {
|
||||
if (obj.meshAgentsArchitectureNumbers[archid].codesign !== true) continue;
|
||||
|
||||
var agentpath;
|
||||
if (domain.id == '') {
|
||||
// Load all agents when processing the default domain
|
||||
@ -2895,46 +2907,83 @@ function CreateMeshCentralServer(config, args) {
|
||||
if (obj.fs.existsSync(agentpath)) { delete obj.meshAgentsArchitectureNumbers[archid].codesign; } else { continue; } // If the agent is not present in "meshcentral-data/agents" skip.
|
||||
}
|
||||
|
||||
// Open the original agent with authenticode
|
||||
var signeedagentpath = obj.path.join(serverSignedAgentsPath, obj.meshAgentsArchitectureNumbers[archid].localname);
|
||||
const originalAgent = require('./authenticode.js').createAuthenticodeHandler(agentpath);
|
||||
if (originalAgent != null) {
|
||||
// Check if the agent is already signed correctly
|
||||
const destinationAgent = require('./authenticode.js').createAuthenticodeHandler(signeedagentpath);
|
||||
var destinationAgentOk = (
|
||||
(destinationAgent != null) &&
|
||||
(destinationAgent.fileHashSigned != null) &&
|
||||
(Buffer.compare(destinationAgent.fileHashSigned, destinationAgent.fileHashActual) == 0) &&
|
||||
((Buffer.compare(destinationAgent.fileHashSigned, originalAgent.getHash(destinationAgent.fileHashAlgo))) == 0) &&
|
||||
(destinationAgent.signingAttribs.indexOf(signUrl) >= 0) &&
|
||||
(destinationAgent.signingAttribs.indexOf(signDesc) >= 0)
|
||||
);
|
||||
if (destinationAgent != null) { destinationAgent.close(); }
|
||||
if (destinationAgentOk == false) {
|
||||
// If not signed correctly, sign it. First, create the server signed agent folder if needed
|
||||
try { obj.fs.mkdirSync(serverSignedAgentsPath); } catch (ex) { }
|
||||
const xagentSignedFunc = function agentSignedFunc(err, size) {
|
||||
if (err == null) {
|
||||
// Agent was signed succesfuly
|
||||
console.log(obj.common.format('Code signed agent {0}.', agentSignedFunc.objx.meshAgentsArchitectureNumbers[agentSignedFunc.archid].localname));
|
||||
} else {
|
||||
console.log(obj.common.format('Failed to sign agent {0}: ' + err, agentSignedFunc.objx.meshAgentsArchitectureNumbers[agentSignedFunc.archid].localname));
|
||||
}
|
||||
if (--pendingOperations === 0) { agentSignedFunc.func(); }
|
||||
}
|
||||
pendingOperations++;
|
||||
xagentSignedFunc.func = func;
|
||||
xagentSignedFunc.objx = objx;
|
||||
xagentSignedFunc.archid = archid;
|
||||
xagentSignedFunc.signeedagentpath = signeedagentpath;
|
||||
originalAgent.sign(agentSignCertInfo, { out: signeedagentpath, desc: signDesc, url: signUrl, time: timeStampUrl }, xagentSignedFunc);
|
||||
} else {
|
||||
// Signed agent is already ok, use it.
|
||||
originalAgent.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (--pendingOperations === 0) { func(); }
|
||||
}
|
||||
|
||||
// Update the list of available mesh agents
|
||||
obj.updateMeshAgentsTable = function (domain, func) {
|
||||
// Check if a custom agent signing certificate is available
|
||||
var agentSignCertInfo = require('./authenticode.js').loadCertificates([obj.path.join(obj.datapath, 'agentsigningcert.pem')]);
|
||||
|
||||
// Setup the domain is specified
|
||||
var objx = domain, suffix = '';
|
||||
if (domain.id == '') { objx = obj; } else { suffix = '-' + domain.id; objx.meshAgentBinaries = {}; }
|
||||
|
||||
// Load agent information file. This includes the data & time of the agent.
|
||||
const agentInfo = [];
|
||||
try { agentInfo = JSON.parse(obj.fs.readFileSync(obj.path.join(__dirname, 'agents', 'hashagents.json'), 'utf8')); } catch (ex) { }
|
||||
|
||||
var archcount = 0;
|
||||
for (var archid in obj.meshAgentsArchitectureNumbers) {
|
||||
var agentpath;
|
||||
if (domain.id == '') {
|
||||
// Load all agents when processing the default domain
|
||||
agentpath = obj.path.join(__dirname, 'agents' + suffix, obj.meshAgentsArchitectureNumbers[archid].localname);
|
||||
const agentpath2 = obj.path.join(obj.datapath, 'signedagents' + suffix, obj.meshAgentsArchitectureNumbers[archid].localname);
|
||||
if (obj.fs.existsSync(agentpath2)) { agentpath = agentpath2; } // If the agent is present in "meshcentral-data/signedagents", use that one instead.
|
||||
const agentpath3 = obj.path.join(obj.datapath, 'agents' + suffix, obj.meshAgentsArchitectureNumbers[archid].localname);
|
||||
if (obj.fs.existsSync(agentpath3)) { agentpath = agentpath3; } // If the agent is present in "meshcentral-data/agents", use that one instead.
|
||||
} else {
|
||||
// When processing an extra domain, only load agents that are specific to that domain
|
||||
var agentpath = obj.path.join(obj.datapath, 'agents' + suffix, obj.meshAgentsArchitectureNumbers[archid].localname);
|
||||
if (obj.fs.existsSync(agentpath)) { delete obj.meshAgentsArchitectureNumbers[archid].codesign; } else { continue; } // If the agent is not present in "meshcentral-data/agents" skip.
|
||||
}
|
||||
|
||||
// Fetch agent binary information
|
||||
var stats = null;
|
||||
try { stats = obj.fs.statSync(agentpath); } catch (ex) { }
|
||||
if ((stats == null)) continue; // If this agent does not exist, skip it.
|
||||
|
||||
// Check if we need to sign this agent, if so, check if it's already been signed
|
||||
if ((obj.meshAgentsArchitectureNumbers[archid].codesign === true) && (agentSignCertInfo != null)) {
|
||||
// Open the original agent with authenticode
|
||||
var signeedagentpath = obj.path.join(serverSignedAgentsPath, obj.meshAgentsArchitectureNumbers[archid].localname);
|
||||
const originalAgent = require('./authenticode.js').createAuthenticodeHandler(agentpath);
|
||||
if (originalAgent != null) {
|
||||
// Check if the agent is already signed correctly
|
||||
const destinationAgent = require('./authenticode.js').createAuthenticodeHandler(signeedagentpath);
|
||||
var destinationAgentOk = (
|
||||
(destinationAgent != null) &&
|
||||
(destinationAgent.fileHashSigned != null) &&
|
||||
(Buffer.compare(destinationAgent.fileHashSigned, destinationAgent.fileHashActual) == 0) &&
|
||||
((Buffer.compare(destinationAgent.fileHashSigned, originalAgent.getHash(destinationAgent.fileHashAlgo))) == 0) &&
|
||||
(destinationAgent.signingAttribs.indexOf(signUrl) >= 0) &&
|
||||
(destinationAgent.signingAttribs.indexOf(signDesc) >= 0)
|
||||
);
|
||||
if (destinationAgent != null) { destinationAgent.close(); }
|
||||
if (destinationAgentOk == false) {
|
||||
// If not signed correctly, sign it. First, create the server signed agent folder if needed
|
||||
try { obj.fs.mkdirSync(serverSignedAgentsPath); } catch (ex) { }
|
||||
if (originalAgent.sign(agentSignCertInfo, { out: signeedagentpath, desc: signDesc, url: signUrl }) == true) {
|
||||
// Agent was signed succesfuly
|
||||
agentpath = signeedagentpath;
|
||||
console.log(obj.common.format('Code signed agent {0}.', obj.meshAgentsArchitectureNumbers[archid].localname));
|
||||
} else {
|
||||
console.log(obj.common.format('Failed to sign agent {0}.', obj.meshAgentsArchitectureNumbers[archid].localname));
|
||||
}
|
||||
} else {
|
||||
// Signed agent is already ok, use it.
|
||||
agentpath = signeedagentpath;
|
||||
}
|
||||
originalAgent.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Setup agent information
|
||||
archcount++;
|
||||
objx.meshAgentBinaries[archid] = Object.assign({}, obj.meshAgentsArchitectureNumbers[archid]);
|
||||
|
@ -38,6 +38,7 @@
|
||||
"_agentCoreDump": true,
|
||||
"_agentCoreDumpUsers": "user1,user2",
|
||||
"_agentSignLock": true,
|
||||
"_agentTimeStampServer": "http://timestamp.digicert.com",
|
||||
"_ignoreAgentHashCheck": true,
|
||||
"_exactPorts": true,
|
||||
"_allowLoginToken": true,
|
||||
|
Loading…
Reference in New Issue
Block a user