Added agent time stamping when signing a Windows agent.
Ylian Saint-Hilaire committed
Jun 18, 2022 at 00:07 UTC
18c11a344c69c3c3ec00450d9f755c6ce2dd0a19
4 files changed
+325
-274
authenticode.js
+4
-4
@@ -486,7 +486,7 @@ function createAuthenticodeHandler(path) {
486
fs.closeSync(output);
487
488
// Indicate we are done
489
- func(null);
489
+ func(null, written);
490
});
491
});
492
@@ -1372,7 +1372,7 @@ function createAuthenticodeHandler(path) {
1372
1373
// Close the file
1374
fs.closeSync(output);
1375
- func(null);
1375
+ func(null, written);
1376
}
1377
1378
// Save an executable without the signature
@@ -1635,7 +1635,7 @@ function createAuthenticodeHandler(path) {
1635
fs.closeSync(output);
1636
1637
// Indicate success
1638
- func(null);
1638
+ func(null, written);
1639
}
1640
1641
function writeExecutableEx(output, p7signature, written, func) {
@@ -1669,7 +1669,7 @@ function createAuthenticodeHandler(path) {
1669
fs.closeSync(output);
1670
1671
// Indicate success
1672
- func(null);
1672
+ func(null, written);
1673
}
1674
1675
// Return null if we could not open the file
meshcentral-config-schema.json
+1
@@ -101,6 +101,7 @@
101
"agentCoreDump": { "type": "boolean", "default": false, "description": "Automatically activates and transfers any agent crash dump files to the server in meshcentral-data/coredumps." },
102
"agentCoreDumpUsers": { "type": "array", "description": "List of non-administrator users that have access to mesh agent crash dumps." },
103
"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)." },
104
+ "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." },
105
"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\"." },
106
"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." },
107
"allowLoginToken": { "type": "boolean", "default": false },
meshcentral.js
+319
-270
@@ -1617,275 +1617,277 @@ function CreateMeshCentralServer(config, args) {
1617
1618
// Load the list of mesh agents and install scripts
1619
if ((obj.args.noagentupdate == 1) || (obj.args.noagentupdate == true)) { for (i in obj.meshAgentsArchitectureNumbers) { obj.meshAgentsArchitectureNumbers[i].update = false; } }
1620
- obj.updateMeshAgentsTable(obj.config.domains[''], function () {
1621
- obj.updateMeshAgentInstallScripts();
1622
-
1623
- // Setup and start the web server
1624
- obj.crypto.randomBytes(48, function (err, buf) {
1625
- // Setup Mesh Multi-Server if needed
1626
- obj.multiServer = require('./multiserver.js').CreateMultiServer(obj, obj.args);
1627
- if (obj.multiServer != null) {
1628
- 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; }
1629
- 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; }
1630
- obj.serverId = obj.multiServer.serverid;
1631
- for (var serverid in obj.config.peers.servers) { obj.peerConnectivityByNode[serverid] = {}; }
1632
- }
1633
-
1634
- // If the server is set to "nousers", allow only loopback unless IP filter is set
1635
- if ((obj.args.nousers == true) && (obj.args.userallowedip == null)) { obj.args.userallowedip = "::1,127.0.0.1"; }
1620
+ obj.signMeshAgents(obj.config.domains[''], function () {
1621
+ obj.updateMeshAgentsTable(obj.config.domains[''], function () {
1622
+ obj.updateMeshAgentInstallScripts();
1623
+
1624
+ // Setup and start the web server
1625
+ obj.crypto.randomBytes(48, function (err, buf) {
1626
+ // Setup Mesh Multi-Server if needed
1627
+ obj.multiServer = require('./multiserver.js').CreateMultiServer(obj, obj.args);
1628
+ if (obj.multiServer != null) {
1629
+ 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; }
1630
+ 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; }
1631
+ obj.serverId = obj.multiServer.serverid;
1632
+ for (var serverid in obj.config.peers.servers) { obj.peerConnectivityByNode[serverid] = {}; }
1633
+ }
1634
1637
- // Set the session length to 60 minutes if not set and set a random key if needed
1638
- if ((obj.args.sessiontime != null) && ((typeof obj.args.sessiontime != 'number') || (obj.args.sessiontime < 1))) { delete obj.args.sessiontime; }
1639
- if (typeof obj.args.sessionkey != 'string') { obj.args.sessionkey = buf.toString('hex').toUpperCase(); }
1635
+ // If the server is set to "nousers", allow only loopback unless IP filter is set
1636
+ if ((obj.args.nousers == true) && (obj.args.userallowedip == null)) { obj.args.userallowedip = "::1,127.0.0.1"; }
1637
1641
- // Create MQTT Broker to hook into webserver and mpsserver
1642
- 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); }
1638
+ // Set the session length to 60 minutes if not set and set a random key if needed
1639
+ if ((obj.args.sessiontime != null) && ((typeof obj.args.sessiontime != 'number') || (obj.args.sessiontime < 1))) { delete obj.args.sessiontime; }
1640
+ if (typeof obj.args.sessionkey != 'string') { obj.args.sessionkey = buf.toString('hex').toUpperCase(); }
1641
1644
- // Start the web server and if needed, the redirection web server.
1645
- obj.webserver = require('./webserver.js').CreateWebServer(obj, obj.db, obj.args, obj.certificates, obj.StartEx5);
1646
- if (obj.redirserver != null) { obj.redirserver.hookMainWebServer(obj.certificates); }
1642
+ // Create MQTT Broker to hook into webserver and mpsserver
1643
+ 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); }
1644
1648
- // Update proxy certificates
1649
- if (obj.supportsProxyCertificatesRequest == true) { obj.updateProxyCertificates(true); }
1645
+ // Start the web server and if needed, the redirection web server.
1646
+ obj.webserver = require('./webserver.js').CreateWebServer(obj, obj.db, obj.args, obj.certificates, obj.StartEx5);
1647
+ if (obj.redirserver != null) { obj.redirserver.hookMainWebServer(obj.certificates); }
1648
1651
- // Setup the Intel AMT event handler
1652
- obj.amtEventHandler = require('./amtevents.js').CreateAmtEventsHandler(obj);
1649
+ // Update proxy certificates
1650
+ if (obj.supportsProxyCertificatesRequest == true) { obj.updateProxyCertificates(true); }
1651
1654
- // Setup the Intel AMT local network scanner
1655
- if (obj.args.wanonly != true) {
1656
- if (obj.args.amtscanner != false) { obj.amtScanner = require('./amtscanner.js').CreateAmtScanner(obj).start(); }
1657
- if (obj.args.meshscanner != false) { obj.meshScanner = require('./meshscanner.js').CreateMeshScanner(obj).start(); }
1658
- }
1652
+ // Setup the Intel AMT event handler
1653
+ obj.amtEventHandler = require('./amtevents.js').CreateAmtEventsHandler(obj);
1654
1660
- // Setup and start the MPS server
1661
- obj.mpsserver = require('./mpsserver.js').CreateMpsServer(obj, obj.db, obj.args, obj.certificates);
1655
+ // Setup the Intel AMT local network scanner
1656
+ if (obj.args.wanonly != true) {
1657
+ if (obj.args.amtscanner != false) { obj.amtScanner = require('./amtscanner.js').CreateAmtScanner(obj).start(); }
1658
+ if (obj.args.meshscanner != false) { obj.meshScanner = require('./meshscanner.js').CreateMeshScanner(obj).start(); }
1659
+ }
1660
1663
- // Setup the Intel AMT manager
1664
- if (obj.args.amtmanager !== false) {
1665
- obj.amtManager = require('./amtmanager.js').CreateAmtManager(obj);
1666
- }
1661
+ // Setup and start the MPS server
1662
+ obj.mpsserver = require('./mpsserver.js').CreateMpsServer(obj, obj.db, obj.args, obj.certificates);
1663
1668
- // Setup and start the legacy swarm server
1669
- if ((obj.certificates.swarmserver != null) && (obj.args.swarmport != null) && (obj.args.swarmport !== 0)) {
1670
- obj.swarmserver = require('./swarmserver.js').CreateSwarmServer(obj, obj.db, obj.args, obj.certificates);
1671
- }
1664
+ // Setup the Intel AMT manager
1665
+ if (obj.args.amtmanager !== false) {
1666
+ obj.amtManager = require('./amtmanager.js').CreateAmtManager(obj);
1667
+ }
1668
1673
- // Setup the main email server
1674
- if (obj.config.sendgrid != null) {
1675
- // Sendgrid server
1676
- obj.mailserver = require('./meshmail.js').CreateMeshMail(obj);
1677
- obj.mailserver.verify();
1678
- if (obj.args.lanonly == true) { addServerWarning("SendGrid server has limited use in LAN mode.", 17); }
1679
- } else if (obj.config.smtp != null) {
1680
- // SMTP server
1681
- obj.mailserver = require('./meshmail.js').CreateMeshMail(obj);
1682
- obj.mailserver.verify();
1683
- if (obj.args.lanonly == true) { addServerWarning("SMTP server has limited use in LAN mode.", 18); }
1684
- } else if (obj.config.sendmail != null) {
1685
- // Sendmail server
1686
- obj.mailserver = require('./meshmail.js').CreateMeshMail(obj);
1687
- obj.mailserver.verify();
1688
- if (obj.args.lanonly == true) { addServerWarning("SMTP server has limited use in LAN mode.", 18); }
1689
- }
1669
+ // Setup and start the legacy swarm server
1670
+ if ((obj.certificates.swarmserver != null) && (obj.args.swarmport != null) && (obj.args.swarmport !== 0)) {
1671
+ obj.swarmserver = require('./swarmserver.js').CreateSwarmServer(obj, obj.db, obj.args, obj.certificates);
1672
+ }
1673
1691
- // Setup the email server for each domain
1692
- for (i in obj.config.domains) {
1693
- if (obj.config.domains[i].sendgrid != null) {
1674
+ // Setup the main email server
1675
+ if (obj.config.sendgrid != null) {
1676
// Sendgrid server
1695
- obj.config.domains[i].mailserver = require('./meshmail.js').CreateMeshMail(obj, obj.config.domains[i]);
1696
- obj.config.domains[i].mailserver.verify();
1677
+ obj.mailserver = require('./meshmail.js').CreateMeshMail(obj);
1678
+ obj.mailserver.verify();
1679
if (obj.args.lanonly == true) { addServerWarning("SendGrid server has limited use in LAN mode.", 17); }
1698
- } else if ((obj.config.domains[i].smtp != null) && (obj.config.domains[i].smtp.host != null) && (obj.config.domains[i].smtp.from != null)) {
1680
+ } else if (obj.config.smtp != null) {
1681
// SMTP server
1700
- obj.config.domains[i].mailserver = require('./meshmail.js').CreateMeshMail(obj, obj.config.domains[i]);
1701
- obj.config.domains[i].mailserver.verify();
1682
+ obj.mailserver = require('./meshmail.js').CreateMeshMail(obj);
1683
+ obj.mailserver.verify();
1684
if (obj.args.lanonly == true) { addServerWarning("SMTP server has limited use in LAN mode.", 18); }
1703
- } else if (obj.config.domains[i].sendmail != null) {
1685
+ } else if (obj.config.sendmail != null) {
1686
// Sendmail server
1705
- obj.config.domains[i].mailserver = require('./meshmail.js').CreateMeshMail(obj, obj.config.domains[i]);
1706
- obj.config.domains[i].mailserver.verify();
1687
+ obj.mailserver = require('./meshmail.js').CreateMeshMail(obj);
1688
+ obj.mailserver.verify();
1689
if (obj.args.lanonly == true) { addServerWarning("SMTP server has limited use in LAN mode.", 18); }
1708
- } else {
1709
- // Setup the parent mail server for this domain
1710
- if (obj.mailserver != null) { obj.config.domains[i].mailserver = obj.mailserver; }
1690
}
1712
- }
1691
1714
- // Setup SMS gateway
1715
- if (config.sms != null) {
1716
- obj.smsserver = require('./meshsms.js').CreateMeshSMS(obj);
1717
- if ((obj.smsserver != null) && (obj.args.lanonly == true)) { addServerWarning("SMS gateway has limited use in LAN mode.", 19); }
1718
- }
1692
+ // Setup the email server for each domain
1693
+ for (i in obj.config.domains) {
1694
+ if (obj.config.domains[i].sendgrid != null) {
1695
+ // Sendgrid server
1696
+ obj.config.domains[i].mailserver = require('./meshmail.js').CreateMeshMail(obj, obj.config.domains[i]);
1697
+ obj.config.domains[i].mailserver.verify();
1698
+ if (obj.args.lanonly == true) { addServerWarning("SendGrid server has limited use in LAN mode.", 17); }
1699
+ } else if ((obj.config.domains[i].smtp != null) && (obj.config.domains[i].smtp.host != null) && (obj.config.domains[i].smtp.from != null)) {
1700
+ // SMTP server
1701
+ obj.config.domains[i].mailserver = require('./meshmail.js').CreateMeshMail(obj, obj.config.domains[i]);
1702
+ obj.config.domains[i].mailserver.verify();
1703
+ if (obj.args.lanonly == true) { addServerWarning("SMTP server has limited use in LAN mode.", 18); }
1704
+ } else if (obj.config.domains[i].sendmail != null) {
1705
+ // Sendmail server
1706
+ obj.config.domains[i].mailserver = require('./meshmail.js').CreateMeshMail(obj, obj.config.domains[i]);
1707
+ obj.config.domains[i].mailserver.verify();
1708
+ if (obj.args.lanonly == true) { addServerWarning("SMTP server has limited use in LAN mode.", 18); }
1709
+ } else {
1710
+ // Setup the parent mail server for this domain
1711
+ if (obj.mailserver != null) { obj.config.domains[i].mailserver = obj.mailserver; }
1712
+ }
1713
+ }
1714
1720
- // Setup web based push notifications
1721
- if ((typeof config.settings.webpush == 'object') && (typeof config.settings.webpush.email == 'string')) {
1722
- obj.webpush = require('web-push');
1723
- var vapidKeys = null;
1724
- try { vapidKeys = JSON.parse(obj.fs.readFileSync(obj.path.join(obj.datapath, 'vapid.json')).toString()); } catch (ex) { }
1725
- if ((vapidKeys == null) || (typeof vapidKeys.publicKey != 'string') || (typeof vapidKeys.privateKey != 'string')) {
1726
- console.log("Generating web push VAPID keys...");
1727
- vapidKeys = obj.webpush.generateVAPIDKeys();
1728
- obj.fs.writeFileSync(obj.path.join(obj.datapath, 'vapid.json'), JSON.stringify(vapidKeys));
1715
+ // Setup SMS gateway
1716
+ if (config.sms != null) {
1717
+ obj.smsserver = require('./meshsms.js').CreateMeshSMS(obj);
1718
+ if ((obj.smsserver != null) && (obj.args.lanonly == true)) { addServerWarning("SMS gateway has limited use in LAN mode.", 19); }
1719
}
1730
- obj.webpush.vapidPublicKey = vapidKeys.publicKey;
1731
- obj.webpush.setVapidDetails('mailto:' + config.settings.webpush.email, vapidKeys.publicKey, vapidKeys.privateKey);
1732
- if (typeof config.settings.webpush.gcmapi == 'string') { webpush.setGCMAPIKey(config.settings.webpush.gcmapi); }
1733
- }
1720
1735
- // Setup Firebase
1736
- if ((config.firebase != null) && (typeof config.firebase.senderid == 'string') && (typeof config.firebase.serverkey == 'string')) {
1737
- obj.firebase = require('./firebase').CreateFirebase(obj, config.firebase.senderid, config.firebase.serverkey);
1738
- } else if ((typeof config.firebaserelay == 'object') && (typeof config.firebaserelay.url == 'string')) {
1739
- // Setup the push messaging relay
1740
- obj.firebase = require('./firebase').CreateFirebaseRelay(obj, config.firebaserelay.url, config.firebaserelay.key);
1741
- } else if (obj.config.settings.publicpushnotifications === true) {
1742
- // Setup the Firebase push messaging relay using https://meshcentral.com, this is the public push notification server.
1743
- obj.firebase = require('./firebase').CreateFirebaseRelay(obj, 'https://meshcentral.com/firebaserelay.aspx');
1744
- }
1721
+ // Setup web based push notifications
1722
+ if ((typeof config.settings.webpush == 'object') && (typeof config.settings.webpush.email == 'string')) {
1723
+ obj.webpush = require('web-push');
1724
+ var vapidKeys = null;
1725
+ try { vapidKeys = JSON.parse(obj.fs.readFileSync(obj.path.join(obj.datapath, 'vapid.json')).toString()); } catch (ex) { }
1726
+ if ((vapidKeys == null) || (typeof vapidKeys.publicKey != 'string') || (typeof vapidKeys.privateKey != 'string')) {
1727
+ console.log("Generating web push VAPID keys...");
1728
+ vapidKeys = obj.webpush.generateVAPIDKeys();
1729
+ obj.fs.writeFileSync(obj.path.join(obj.datapath, 'vapid.json'), JSON.stringify(vapidKeys));
1730
+ }
1731
+ obj.webpush.vapidPublicKey = vapidKeys.publicKey;
1732
+ obj.webpush.setVapidDetails('mailto:' + config.settings.webpush.email, vapidKeys.publicKey, vapidKeys.privateKey);
1733
+ if (typeof config.settings.webpush.gcmapi == 'string') { webpush.setGCMAPIKey(config.settings.webpush.gcmapi); }
1734
+ }
1735
1746
- // Start periodic maintenance
1747
- obj.maintenanceTimer = setInterval(obj.maintenanceActions, 1000 * 60 * 60); // Run this every hour
1736
+ // Setup Firebase
1737
+ if ((config.firebase != null) && (typeof config.firebase.senderid == 'string') && (typeof config.firebase.serverkey == 'string')) {
1738
+ obj.firebase = require('./firebase').CreateFirebase(obj, config.firebase.senderid, config.firebase.serverkey);
1739
+ } else if ((typeof config.firebaserelay == 'object') && (typeof config.firebaserelay.url == 'string')) {
1740
+ // Setup the push messaging relay
1741
+ obj.firebase = require('./firebase').CreateFirebaseRelay(obj, config.firebaserelay.url, config.firebaserelay.key);
1742
+ } else if (obj.config.settings.publicpushnotifications === true) {
1743
+ // Setup the Firebase push messaging relay using https://meshcentral.com, this is the public push notification server.
1744
+ obj.firebase = require('./firebase').CreateFirebaseRelay(obj, 'https://meshcentral.com/firebaserelay.aspx');
1745
+ }
1746
1749
- // Dispatch an event that the server is now running
1750
- obj.DispatchEvent(['*'], obj, { etype: 'server', action: 'started', msg: 'Server started' });
1747
+ // Start periodic maintenance
1748
+ obj.maintenanceTimer = setInterval(obj.maintenanceActions, 1000 * 60 * 60); // Run this every hour
1749
1752
- // Plugin hook. Need to run something at server startup? This is the place.
1753
- if (obj.pluginHandler) { obj.pluginHandler.callHook('server_startup'); }
1754
-
1755
- // Setup the login cookie encryption key
1756
- if ((obj.config) && (obj.config.settings) && (typeof obj.config.settings.logincookieencryptionkey == 'string')) {
1757
- // We have a string, hash it and use that as a key
1758
- try { obj.loginCookieEncryptionKey = Buffer.from(obj.config.settings.logincookieencryptionkey, 'hex'); } catch (ex) { }
1759
- if ((obj.loginCookieEncryptionKey == null) || (obj.loginCookieEncryptionKey.length != 80)) { addServerWarning("Invalid \"LoginCookieEncryptionKey\" in config.json.", 20); obj.loginCookieEncryptionKey = null; }
1760
- }
1750
+ // Dispatch an event that the server is now running
1751
+ obj.DispatchEvent(['*'], obj, { etype: 'server', action: 'started', msg: 'Server started' });
1752
+
1753
+ // Plugin hook. Need to run something at server startup? This is the place.
1754
+ if (obj.pluginHandler) { obj.pluginHandler.callHook('server_startup'); }
1755
+
1756
+ // Setup the login cookie encryption key
1757
+ if ((obj.config) && (obj.config.settings) && (typeof obj.config.settings.logincookieencryptionkey == 'string')) {
1758
+ // We have a string, hash it and use that as a key
1759
+ try { obj.loginCookieEncryptionKey = Buffer.from(obj.config.settings.logincookieencryptionkey, 'hex'); } catch (ex) { }
1760
+ if ((obj.loginCookieEncryptionKey == null) || (obj.loginCookieEncryptionKey.length != 80)) { addServerWarning("Invalid \"LoginCookieEncryptionKey\" in config.json.", 20); obj.loginCookieEncryptionKey = null; }
1761
+ }
1762
1762
- // Login cookie encryption key not set, use one from the database
1763
- if (obj.loginCookieEncryptionKey == null) {
1764
- obj.db.Get('LoginCookieEncryptionKey', function (err, docs) {
1765
- if ((docs != null) && (docs.length > 0) && (docs[0].key != null) && (obj.args.logintokengen == null) && (docs[0].key.length >= 160)) {
1766
- obj.loginCookieEncryptionKey = Buffer.from(docs[0].key, 'hex');
1763
+ // Login cookie encryption key not set, use one from the database
1764
+ if (obj.loginCookieEncryptionKey == null) {
1765
+ obj.db.Get('LoginCookieEncryptionKey', function (err, docs) {
1766
+ if ((docs != null) && (docs.length > 0) && (docs[0].key != null) && (obj.args.logintokengen == null) && (docs[0].key.length >= 160)) {
1767
+ obj.loginCookieEncryptionKey = Buffer.from(docs[0].key, 'hex');
1768
+ } else {
1769
+ obj.loginCookieEncryptionKey = obj.generateCookieKey(); obj.db.Set({ _id: 'LoginCookieEncryptionKey', key: obj.loginCookieEncryptionKey.toString('hex'), time: Date.now() });
1770
+ }
1771
+ });
1772
+ }
1773
+
1774
+ // Load the invitation link encryption key from the database
1775
+ obj.db.Get('InvitationLinkEncryptionKey', function (err, docs) {
1776
+ if ((docs != null) && (docs.length > 0) && (docs[0].key != null) && (docs[0].key.length >= 160)) {
1777
+ obj.invitationLinkEncryptionKey = Buffer.from(docs[0].key, 'hex');
1778
} else {
1768
- obj.loginCookieEncryptionKey = obj.generateCookieKey(); obj.db.Set({ _id: 'LoginCookieEncryptionKey', key: obj.loginCookieEncryptionKey.toString('hex'), time: Date.now() });
1779
+ obj.invitationLinkEncryptionKey = obj.generateCookieKey(); obj.db.Set({ _id: 'InvitationLinkEncryptionKey', key: obj.invitationLinkEncryptionKey.toString('hex'), time: Date.now() });
1780
}
1781
});
1771
- }
1782
1773
- // Load the invitation link encryption key from the database
1774
- obj.db.Get('InvitationLinkEncryptionKey', function (err, docs) {
1775
- if ((docs != null) && (docs.length > 0) && (docs[0].key != null) && (docs[0].key.length >= 160)) {
1776
- obj.invitationLinkEncryptionKey = Buffer.from(docs[0].key, 'hex');
1777
- } else {
1778
- obj.invitationLinkEncryptionKey = obj.generateCookieKey(); obj.db.Set({ _id: 'InvitationLinkEncryptionKey', key: obj.invitationLinkEncryptionKey.toString('hex'), time: Date.now() });
1783
+ // Setup Intel AMT hello server
1784
+ 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')) {
1785
+ obj.amtProvisioningServer = require('./amtprovisioningserver').CreateAmtProvisioningServer(obj, config.settings.amtprovisioningserver);
1786
}
1780
- });
1781
-
1782
- // Setup Intel AMT hello server
1783
- 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')) {
1784
- obj.amtProvisioningServer = require('./amtprovisioningserver').CreateAmtProvisioningServer(obj, config.settings.amtprovisioningserver);
1785
- }
1787
1787
- // Start collecting server stats every 5 minutes
1788
- obj.trafficStats = obj.webserver.getTrafficStats();
1789
- setInterval(function () {
1790
- obj.serverStatsCounter++;
1791
- var hours = 720; // Start with all events lasting 30 days.
1792
- if (((obj.serverStatsCounter) % 2) == 1) { hours = 3; } // Half of the event get removed after 3 hours.
1793
- else if ((Math.floor(obj.serverStatsCounter / 2) % 2) == 1) { hours = 8; } // Another half of the event get removed after 8 hours.
1794
- else if ((Math.floor(obj.serverStatsCounter / 4) % 2) == 1) { hours = 24; } // Another half of the event get removed after 24 hours.
1795
- else if ((Math.floor(obj.serverStatsCounter / 8) % 2) == 1) { hours = 48; } // Another half of the event get removed after 48 hours.
1796
- else if ((Math.floor(obj.serverStatsCounter / 16) % 2) == 1) { hours = 72; } // Another half of the event get removed after 72 hours.
1797
- const expire = new Date();
1798
- expire.setTime(expire.getTime() + (60 * 60 * 1000 * hours));
1799
-
1800
- // Get traffic data
1801
- var trafficStats = obj.webserver.getTrafficDelta(obj.trafficStats);
1802
- obj.trafficStats = trafficStats.current;
1803
-
1804
- var data = {
1805
- time: new Date(),
1806
- expire: expire,
1807
- mem: process.memoryUsage(),
1808
- conn: {
1809
- ca: Object.keys(obj.webserver.wsagents).length,
1810
- cu: Object.keys(obj.webserver.wssessions).length,
1811
- us: Object.keys(obj.webserver.wssessions2).length,
1812
- rs: obj.webserver.relaySessionCount
1813
- },
1814
- traffic: trafficStats.delta
1815
- };
1816
- try { data.cpu = require('os').loadavg(); } catch (ex) { }
1817
- if (obj.mpsserver != null) {
1818
- data.conn.am = 0;
1819
- for (var i in obj.mpsserver.ciraConnections) { data.conn.am += obj.mpsserver.ciraConnections[i].length; }
1788
+ // Start collecting server stats every 5 minutes
1789
+ obj.trafficStats = obj.webserver.getTrafficStats();
1790
+ setInterval(function () {
1791
+ obj.serverStatsCounter++;
1792
+ var hours = 720; // Start with all events lasting 30 days.
1793
+ if (((obj.serverStatsCounter) % 2) == 1) { hours = 3; } // Half of the event get removed after 3 hours.
1794
+ else if ((Math.floor(obj.serverStatsCounter / 2) % 2) == 1) { hours = 8; } // Another half of the event get removed after 8 hours.
1795
+ else if ((Math.floor(obj.serverStatsCounter / 4) % 2) == 1) { hours = 24; } // Another half of the event get removed after 24 hours.
1796
+ else if ((Math.floor(obj.serverStatsCounter / 8) % 2) == 1) { hours = 48; } // Another half of the event get removed after 48 hours.
1797
+ else if ((Math.floor(obj.serverStatsCounter / 16) % 2) == 1) { hours = 72; } // Another half of the event get removed after 72 hours.
1798
+ const expire = new Date();
1799
+ expire.setTime(expire.getTime() + (60 * 60 * 1000 * hours));
1800
+
1801
+ // Get traffic data
1802
+ var trafficStats = obj.webserver.getTrafficDelta(obj.trafficStats);
1803
+ obj.trafficStats = trafficStats.current;
1804
+
1805
+ var data = {
1806
+ time: new Date(),
1807
+ expire: expire,
1808
+ mem: process.memoryUsage(),
1809
+ conn: {
1810
+ ca: Object.keys(obj.webserver.wsagents).length,
1811
+ cu: Object.keys(obj.webserver.wssessions).length,
1812
+ us: Object.keys(obj.webserver.wssessions2).length,
1813
+ rs: obj.webserver.relaySessionCount
1814
+ },
1815
+ traffic: trafficStats.delta
1816
+ };
1817
+ try { data.cpu = require('os').loadavg(); } catch (ex) { }
1818
+ if (obj.mpsserver != null) {
1819
+ data.conn.am = 0;
1820
+ for (var i in obj.mpsserver.ciraConnections) { data.conn.am += obj.mpsserver.ciraConnections[i].length; }
1821
+ }
1822
+ if (obj.firstStats === true) { delete obj.firstStats; data.first = true; }
1823
+ if (obj.multiServer != null) { data.s = obj.multiServer.serverid; }
1824
+ obj.db.SetServerStats(data); // Save the stats to the database
1825
+ obj.DispatchEvent(['*'], obj, { action: 'servertimelinestats', data: data }); // Event the server stats
1826
+ }, 300000);
1827
+
1828
+ obj.debug('main', "Server started");
1829
+ if (obj.args.nousers == true) { obj.updateServerState('nousers', '1'); }
1830
+ obj.updateServerState('state', "running");
1831
+
1832
+ // Setup auto-backup defaults
1833
+ if (obj.config.settings.autobackup == null) { obj.config.settings.autobackup = { backupintervalhours: 24, keeplastdaysbackup: 10 }; }
1834
+ else if (obj.config.settings.autobackup === false) { delete obj.config.settings.autobackup; }
1835
+
1836
+ // Check that autobackup path is not within the "meshcentral-data" folder.
1837
+ 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)))) {
1838
+ addServerWarning("Backup path can't be set within meshcentral-data folder, backup settings ignored.", 21);
1839
+ delete obj.config.settings.autobackup;
1840
}
1821
- if (obj.firstStats === true) { delete obj.firstStats; data.first = true; }
1822
- if (obj.multiServer != null) { data.s = obj.multiServer.serverid; }
1823
- obj.db.SetServerStats(data); // Save the stats to the database
1824
- obj.DispatchEvent(['*'], obj, { action: 'servertimelinestats', data: data }); // Event the server stats
1825
- }, 300000);
1826
-
1827
- obj.debug('main', "Server started");
1828
- if (obj.args.nousers == true) { obj.updateServerState('nousers', '1'); }
1829
- obj.updateServerState('state', "running");
1830
-
1831
- // Setup auto-backup defaults
1832
- if (obj.config.settings.autobackup == null) { obj.config.settings.autobackup = { backupintervalhours: 24, keeplastdaysbackup: 10 }; }
1833
- else if (obj.config.settings.autobackup === false) { delete obj.config.settings.autobackup; }
1834
-
1835
- // Check that autobackup path is not within the "meshcentral-data" folder.
1836
- 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)))) {
1837
- addServerWarning("Backup path can't be set within meshcentral-data folder, backup settings ignored.", 21);
1838
- delete obj.config.settings.autobackup;
1839
- }
1841
1841
- // Load Intel AMT passwords from the "amtactivation.log" file
1842
- obj.loadAmtActivationLogPasswords(function (amtPasswords) {
1843
- obj.amtPasswords = amtPasswords;
1844
- });
1842
+ // Load Intel AMT passwords from the "amtactivation.log" file
1843
+ obj.loadAmtActivationLogPasswords(function (amtPasswords) {
1844
+ obj.amtPasswords = amtPasswords;
1845
+ });
1846
1846
- // Setup users that can see all device groups
1847
- if (typeof obj.config.settings.managealldevicegroups == 'string') { obj.config.settings.managealldevicegroups = obj.config.settings.managealldevicegroups.split(','); }
1848
- else if (Array.isArray(obj.config.settings.managealldevicegroups) == false) { obj.config.settings.managealldevicegroups = []; }
1849
- for (i in obj.config.domains) {
1850
- if (Array.isArray(obj.config.domains[i].managealldevicegroups)) {
1851
- for (var j in obj.config.domains[i].managealldevicegroups) {
1852
- if (typeof obj.config.domains[i].managealldevicegroups[j] == 'string') {
1853
- const u = 'user/' + i + '/' + obj.config.domains[i].managealldevicegroups[j];
1854
- if (obj.config.settings.managealldevicegroups.indexOf(u) == -1) { obj.config.settings.managealldevicegroups.push(u); }
1847
+ // Setup users that can see all device groups
1848
+ if (typeof obj.config.settings.managealldevicegroups == 'string') { obj.config.settings.managealldevicegroups = obj.config.settings.managealldevicegroups.split(','); }
1849
+ else if (Array.isArray(obj.config.settings.managealldevicegroups) == false) { obj.config.settings.managealldevicegroups = []; }
1850
+ for (i in obj.config.domains) {
1851
+ if (Array.isArray(obj.config.domains[i].managealldevicegroups)) {
1852
+ for (var j in obj.config.domains[i].managealldevicegroups) {
1853
+ if (typeof obj.config.domains[i].managealldevicegroups[j] == 'string') {
1854
+ const u = 'user/' + i + '/' + obj.config.domains[i].managealldevicegroups[j];
1855
+ if (obj.config.settings.managealldevicegroups.indexOf(u) == -1) { obj.config.settings.managealldevicegroups.push(u); }
1856
+ }
1857
}
1858
}
1859
}
1858
- }
1859
- obj.config.settings.managealldevicegroups.sort();
1860
-
1861
- // Start watchdog timer if needed
1862
- // 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
1863
- // "watchDog": { "interval": 100, "timeout": 150 }
1864
- // This will check every 100ms, if the timer is more than 150ms late, it will warn.
1865
- 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)) {
1866
- obj.watchdogtime = Date.now();
1867
- obj.watchdogmax = 0;
1868
- obj.watchdogmaxtime = null;
1869
- obj.watchdogtable = [];
1870
- obj.watchdog = setInterval(function () {
1871
- const now = Date.now(), delta = now - obj.watchdogtime - config.settings.watchdog.interval;
1872
- if (delta > obj.watchdogmax) { obj.watchdogmax = delta; obj.watchdogmaxtime = new Date().toLocaleString(); }
1873
- if (delta > config.settings.watchdog.timeout) {
1874
- const msg = obj.common.format("Watchdog timer timeout, {0}ms.", delta);
1875
- obj.watchdogtable.push(new Date().toLocaleString() + ', ' + delta + 'ms');
1876
- while (obj.watchdogtable.length > 10) { obj.watchdogtable.shift(); }
1877
- obj.debug('main', msg);
1878
- try {
1879
- var errlogpath = null;
1880
- if (typeof obj.args.mesherrorlogpath == 'string') { errlogpath = obj.path.join(obj.args.mesherrorlogpath, 'mesherrors.txt'); } else { errlogpath = obj.getConfigFilePath('mesherrors.txt'); }
1881
- obj.fs.appendFileSync(errlogpath, new Date().toLocaleString() + ': ' + msg + '\r\n');
1882
- } catch (ex) { console.log('ERROR: Unable to write to mesherrors.txt.'); }
1883
- }
1884
- obj.watchdogtime = now;
1885
- }, config.settings.watchdog.interval);
1886
- obj.debug('main', "Started watchdog timer.");
1887
- }
1860
+ obj.config.settings.managealldevicegroups.sort();
1861
+
1862
+ // Start watchdog timer if needed
1863
+ // 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
1864
+ // "watchDog": { "interval": 100, "timeout": 150 }
1865
+ // This will check every 100ms, if the timer is more than 150ms late, it will warn.
1866
+ 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)) {
1867
+ obj.watchdogtime = Date.now();
1868
+ obj.watchdogmax = 0;
1869
+ obj.watchdogmaxtime = null;
1870
+ obj.watchdogtable = [];
1871
+ obj.watchdog = setInterval(function () {
1872
+ const now = Date.now(), delta = now - obj.watchdogtime - config.settings.watchdog.interval;
1873
+ if (delta > obj.watchdogmax) { obj.watchdogmax = delta; obj.watchdogmaxtime = new Date().toLocaleString(); }
1874
+ if (delta > config.settings.watchdog.timeout) {
1875
+ const msg = obj.common.format("Watchdog timer timeout, {0}ms.", delta);
1876
+ obj.watchdogtable.push(new Date().toLocaleString() + ', ' + delta + 'ms');
1877
+ while (obj.watchdogtable.length > 10) { obj.watchdogtable.shift(); }
1878
+ obj.debug('main', msg);
1879
+ try {
1880
+ var errlogpath = null;
1881
+ if (typeof obj.args.mesherrorlogpath == 'string') { errlogpath = obj.path.join(obj.args.mesherrorlogpath, 'mesherrors.txt'); } else { errlogpath = obj.getConfigFilePath('mesherrors.txt'); }
1882
+ obj.fs.appendFileSync(errlogpath, new Date().toLocaleString() + ': ' + msg + '\r\n');
1883
+ } catch (ex) { console.log('ERROR: Unable to write to mesherrors.txt.'); }
1884
+ }
1885
+ obj.watchdogtime = now;
1886
+ }, config.settings.watchdog.interval);
1887
+ obj.debug('main', "Started watchdog timer.");
1888
+ }
1889
1890
+ });
1891
});
1892
});
1893
};
@@ -2841,24 +2843,29 @@ function CreateMeshCentralServer(config, args) {
2843
10006: { id: 10006, localname: 'MeshCentralAssistant.exe', rname: 'MeshCentralAssistant.exe', desc: 'MeshCentral Assistant for Windows', update: false, amt: false, platform: 'win32' } // MeshCentral Assistant
2844
};
2845
2844
- // Update the list of available mesh agents
2845
- obj.updateMeshAgentsTable = function (domain, func) {
2846
+ // Sign windows agents
2847
+ obj.signMeshAgents = function (domain, func) {
2848
// Setup the domain is specified
2849
var objx = domain, suffix = '';
2850
if (domain.id == '') { objx = obj; } else { suffix = '-' + domain.id; objx.meshAgentBinaries = {}; }
2851
2852
// Check if a custom agent signing certificate is available
2851
- var agentSignCertInfo = require('./authenticode.js').loadCertificates([ obj.path.join(obj.datapath, 'agentsigningcert.pem') ]);
2853
+ var agentSignCertInfo = require('./authenticode.js').loadCertificates([obj.path.join(obj.datapath, 'agentsigningcert.pem')]);
2854
+ if (agentSignCertInfo == null) { func(); return; } // No code signing certificate, nothing to do.
2855
2856
// If not using a custom signing cert, get agent code signature certificate ready with the full cert chain
2857
if ((agentSignCertInfo == null) && (obj.certificates.codesign != null)) {
2858
agentSignCertInfo = {
2859
cert: obj.certificateOperations.forge.pki.certificateFromPem(obj.certificates.codesign.cert),
2860
key: obj.certificateOperations.forge.pki.privateKeyFromPem(obj.certificates.codesign.key),
2858
- extraCerts: [obj.certificateOperations.forge.pki.certificateFromPem(obj.certificates.root.cert) ]
2861
+ extraCerts: [obj.certificateOperations.forge.pki.certificateFromPem(obj.certificates.root.cert)]
2862
}
2863
}
2864
2865
+ // Setup the domain is specified
2866
+ var objx = domain, suffix = '';
2867
+ if (domain.id == '') { objx = obj; } else { suffix = '-' + domain.id; objx.meshAgentBinaries = {}; }
2868
+
2869
// Generate the agent signature description and URL
2870
var serverSignedAgentsPath, signDesc, signUrl;
2871
if (agentSignCertInfo != null) {
@@ -2877,12 +2884,17 @@ function CreateMeshCentralServer(config, args) {
2884
if (obj.config.settings.agentsignlock) { signUrl += '?ServerID=' + obj.certificateOperations.getPublicKeyHash(obj.certificates.agent.cert).toUpperCase(); }
2885
}
2886
2880
- // Load agent information file. This includes the data & time of the agent.
2881
- const agentInfo = [];
2882
- try { agentInfo = JSON.parse(obj.fs.readFileSync(obj.path.join(__dirname, 'agents', 'hashagents.json'), 'utf8')); } catch (ex) { }
2887
+ // Setup the time server
2888
+ var timeStampUrl = 'http://timestamp.comodoca.com/authenticode';
2889
+ if (args.agenttimestampserver === false) { timeStampUrl = null; }
2890
+ else if (typeof args.agenttimestampserver == 'string') { timeStampUrl = args.agenttimestampserver; }
2891
+
2892
+ // Setup the pending operations counter
2893
+ var pendingOperations = 1;
2894
2884
- var archcount = 0;
2895
for (var archid in obj.meshAgentsArchitectureNumbers) {
2896
+ if (obj.meshAgentsArchitectureNumbers[archid].codesign !== true) continue;
2897
+
2898
var agentpath;
2899
if (domain.id == '') {
2900
// Load all agents when processing the default domain
@@ -2895,45 +2907,82 @@ function CreateMeshCentralServer(config, args) {
2907
if (obj.fs.existsSync(agentpath)) { delete obj.meshAgentsArchitectureNumbers[archid].codesign; } else { continue; } // If the agent is not present in "meshcentral-data/agents" skip.
2908
}
2909
2898
- // Fetch agent binary information
2899
- var stats = null;
2900
- try { stats = obj.fs.statSync(agentpath); } catch (ex) { }
2901
- if ((stats == null)) continue; // If this agent does not exist, skip it.
2902
-
2903
- // Check if we need to sign this agent, if so, check if it's already been signed
2904
- if ((obj.meshAgentsArchitectureNumbers[archid].codesign === true) && (agentSignCertInfo != null)) {
2905
- // Open the original agent with authenticode
2906
- var signeedagentpath = obj.path.join(serverSignedAgentsPath, obj.meshAgentsArchitectureNumbers[archid].localname);
2907
- const originalAgent = require('./authenticode.js').createAuthenticodeHandler(agentpath);
2908
- if (originalAgent != null) {
2909
- // Check if the agent is already signed correctly
2910
- const destinationAgent = require('./authenticode.js').createAuthenticodeHandler(signeedagentpath);
2911
- var destinationAgentOk = (
2912
- (destinationAgent != null) &&
2913
- (destinationAgent.fileHashSigned != null) &&
2914
- (Buffer.compare(destinationAgent.fileHashSigned, destinationAgent.fileHashActual) == 0) &&
2915
- ((Buffer.compare(destinationAgent.fileHashSigned, originalAgent.getHash(destinationAgent.fileHashAlgo))) == 0) &&
2916
- (destinationAgent.signingAttribs.indexOf(signUrl) >= 0) &&
2917
- (destinationAgent.signingAttribs.indexOf(signDesc) >= 0)
2918
- );
2919
- if (destinationAgent != null) { destinationAgent.close(); }
2920
- if (destinationAgentOk == false) {
2921
- // If not signed correctly, sign it. First, create the server signed agent folder if needed
2922
- try { obj.fs.mkdirSync(serverSignedAgentsPath); } catch (ex) { }
2923
- if (originalAgent.sign(agentSignCertInfo, { out: signeedagentpath, desc: signDesc, url: signUrl }) == true) {
2910
+ // Open the original agent with authenticode
2911
+ var signeedagentpath = obj.path.join(serverSignedAgentsPath, obj.meshAgentsArchitectureNumbers[archid].localname);
2912
+ const originalAgent = require('./authenticode.js').createAuthenticodeHandler(agentpath);
2913
+ if (originalAgent != null) {
2914
+ // Check if the agent is already signed correctly
2915
+ const destinationAgent = require('./authenticode.js').createAuthenticodeHandler(signeedagentpath);
2916
+ var destinationAgentOk = (
2917
+ (destinationAgent != null) &&
2918
+ (destinationAgent.fileHashSigned != null) &&
2919
+ (Buffer.compare(destinationAgent.fileHashSigned, destinationAgent.fileHashActual) == 0) &&
2920
+ ((Buffer.compare(destinationAgent.fileHashSigned, originalAgent.getHash(destinationAgent.fileHashAlgo))) == 0) &&
2921
+ (destinationAgent.signingAttribs.indexOf(signUrl) >= 0) &&
2922
+ (destinationAgent.signingAttribs.indexOf(signDesc) >= 0)
2923
+ );
2924
+ if (destinationAgent != null) { destinationAgent.close(); }
2925
+ if (destinationAgentOk == false) {
2926
+ // If not signed correctly, sign it. First, create the server signed agent folder if needed
2927
+ try { obj.fs.mkdirSync(serverSignedAgentsPath); } catch (ex) { }
2928
+ const xagentSignedFunc = function agentSignedFunc(err, size) {
2929
+ if (err == null) {
2930
// Agent was signed succesfuly
2925
- agentpath = signeedagentpath;
2926
- console.log(obj.common.format('Code signed agent {0}.', obj.meshAgentsArchitectureNumbers[archid].localname));
2931
+ console.log(obj.common.format('Code signed agent {0}.', agentSignedFunc.objx.meshAgentsArchitectureNumbers[agentSignedFunc.archid].localname));
2932
} else {
2928
- console.log(obj.common.format('Failed to sign agent {0}.', obj.meshAgentsArchitectureNumbers[archid].localname));
2933
+ console.log(obj.common.format('Failed to sign agent {0}: ' + err, agentSignedFunc.objx.meshAgentsArchitectureNumbers[agentSignedFunc.archid].localname));
2934
}
2930
- } else {
2931
- // Signed agent is already ok, use it.
2932
- agentpath = signeedagentpath;
2935
+ if (--pendingOperations === 0) { agentSignedFunc.func(); }
2936
}
2937
+ pendingOperations++;
2938
+ xagentSignedFunc.func = func;
2939
+ xagentSignedFunc.objx = objx;
2940
+ xagentSignedFunc.archid = archid;
2941
+ xagentSignedFunc.signeedagentpath = signeedagentpath;
2942
+ originalAgent.sign(agentSignCertInfo, { out: signeedagentpath, desc: signDesc, url: signUrl, time: timeStampUrl }, xagentSignedFunc);
2943
+ } else {
2944
+ // Signed agent is already ok, use it.
2945
originalAgent.close();
2946
}
2947
}
2948
+ }
2949
+
2950
+ if (--pendingOperations === 0) { func(); }
2951
+ }
2952
+
2953
+ // Update the list of available mesh agents
2954
+ obj.updateMeshAgentsTable = function (domain, func) {
2955
+ // Check if a custom agent signing certificate is available
2956
+ var agentSignCertInfo = require('./authenticode.js').loadCertificates([obj.path.join(obj.datapath, 'agentsigningcert.pem')]);
2957
+
2958
+ // Setup the domain is specified
2959
+ var objx = domain, suffix = '';
2960
+ if (domain.id == '') { objx = obj; } else { suffix = '-' + domain.id; objx.meshAgentBinaries = {}; }
2961
+
2962
+ // Load agent information file. This includes the data & time of the agent.
2963
+ const agentInfo = [];
2964
+ try { agentInfo = JSON.parse(obj.fs.readFileSync(obj.path.join(__dirname, 'agents', 'hashagents.json'), 'utf8')); } catch (ex) { }
2965
+
2966
+ var archcount = 0;
2967
+ for (var archid in obj.meshAgentsArchitectureNumbers) {
2968
+ var agentpath;
2969
+ if (domain.id == '') {
2970
+ // Load all agents when processing the default domain
2971
+ agentpath = obj.path.join(__dirname, 'agents' + suffix, obj.meshAgentsArchitectureNumbers[archid].localname);
2972
+ const agentpath2 = obj.path.join(obj.datapath, 'signedagents' + suffix, obj.meshAgentsArchitectureNumbers[archid].localname);
2973
+ if (obj.fs.existsSync(agentpath2)) { agentpath = agentpath2; } // If the agent is present in "meshcentral-data/signedagents", use that one instead.
2974
+ const agentpath3 = obj.path.join(obj.datapath, 'agents' + suffix, obj.meshAgentsArchitectureNumbers[archid].localname);
2975
+ if (obj.fs.existsSync(agentpath3)) { agentpath = agentpath3; } // If the agent is present in "meshcentral-data/agents", use that one instead.
2976
+ } else {
2977
+ // When processing an extra domain, only load agents that are specific to that domain
2978
+ var agentpath = obj.path.join(obj.datapath, 'agents' + suffix, obj.meshAgentsArchitectureNumbers[archid].localname);
2979
+ if (obj.fs.existsSync(agentpath)) { delete obj.meshAgentsArchitectureNumbers[archid].codesign; } else { continue; } // If the agent is not present in "meshcentral-data/agents" skip.
2980
+ }
2981
+
2982
+ // Fetch agent binary information
2983
+ var stats = null;
2984
+ try { stats = obj.fs.statSync(agentpath); } catch (ex) { }
2985
+ if ((stats == null)) continue; // If this agent does not exist, skip it.
2986
2987
// Setup agent information
2988
archcount++;
sample-config-advanced.json
+1
@@ -38,6 +38,7 @@
38
"_agentCoreDump": true,
39
"_agentCoreDumpUsers": "user1,user2",
40
"_agentSignLock": true,
41
+ "_agentTimeStampServer": "http://timestamp.digicert.com",
42
"_ignoreAgentHashCheck": true,
43
"_exactPorts": true,
44
"_allowLoginToken": true,