diff --git a/certoperations.js b/certoperations.js index fa99e30c..4e827bd0 100644 --- a/certoperations.js +++ b/certoperations.js @@ -131,6 +131,22 @@ module.exports.CertificateOperations = function (parent) { // Log the Intel AMT activation operation in the domain log obj.logAmtActivation = function (domain, x) { if (x == null) return true; + + // Add the password to the Intel AMT list of UUID to passwords + if ((typeof x.amtUuid == 'string') && (typeof x.password == 'string')) { + if (parent.amtPasswords == null) { parent.amtPasswords = {}; } + if (parent.amtPasswords[x.amtUuid] == null) { + parent.amtPasswords[x.amtUuid] = [x.password]; // Add password to array + parent.amtPasswords = parent.common.sortObj(parent.amtPasswords); + } else { + if (parent.amtPasswords[x.amtUuid].indexOf(x.password) == -1) { + parent.amtPasswords[x.amtUuid].unshift(x.password); // Add password at the start of the array + while (parent.amtPasswords[x.amtUuid].length > 3) { parent.amtPasswords[x.amtUuid].pop(); } // Only keep the 3 last passwords for any given device + } + } + } + + // Append to the log file var logpath = null; if ((domain.amtacmactivation == null) || (domain.amtacmactivation.log == null) || (typeof domain.amtacmactivation.log != 'string')) { if (domain.id == '') { logpath = parent.path.join(obj.parent.datapath, 'amtactivation.log'); } else { logpath = parent.path.join(obj.parent.datapath, 'amtactivation-' + domain.id + '.log'); } diff --git a/common.js b/common.js index 4f840957..d9ae68f7 100644 --- a/common.js +++ b/common.js @@ -294,6 +294,8 @@ module.exports.meshServerRightsArrayToNumber = function (val) { return null; } +// Sort an object by key +module.exports.sortObj = function (obj) { return Object.keys(obj).sort().reduce(function (result, key) { result[key] = obj[key]; return result; }, {}); } // Validate an object to make sure it can be stored in MongoDB module.exports.validateObjectForMongo = function (obj, maxStrLen) { diff --git a/meshcentral.js b/meshcentral.js index 899741fd..c872efcd 100644 --- a/meshcentral.js +++ b/meshcentral.js @@ -1696,6 +1696,11 @@ function CreateMeshCentralServer(config, args) { 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; } + // 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 = []; } @@ -2680,6 +2685,34 @@ function CreateMeshCentralServer(config, args) { }); }; + // Load the list of Intel AMT UUID and passwords from "amtactivation.log" + obj.loadAmtActivationLogPasswords = function (func) { + var amtlogfilename = obj.path.join(obj.datapath, 'amtactivation.log'); + obj.fs.readFile(amtlogfilename, 'utf8', function (err, data) { + var amtPasswords = {}; // UUID --> [Passwords] + if ((err == null) && (data != null)) { + const lines = data.split('\r\n'); + for (var i in lines) { + var line = lines[i]; + if (line.startsWith('{')) { + var j = JSON.parse(line); + if ((typeof j.amtUuid == 'string') && (typeof j.password == 'string')) { + if (amtPasswords[j.amtUuid] == null) { + amtPasswords[j.amtUuid] = [j.password]; // Add password to array + } else { + if (amtPasswords[j.amtUuid].indexOf(j.password) == -1) { + amtPasswords[j.amtUuid].unshift(j.password); // Add password at the start of the array + while (amtPasswords[j.amtUuid].length > 3) { amtPasswords[j.amtUuid].pop(); } // Only keep the 3 last passwords for any given device + } + } + } + } + } + } + func(obj.common.sortObj(amtPasswords)); // Sort by UUID + }); + } + // Generate a cryptographic key used to encode and decode cookies obj.generateCookieKey = function () { return Buffer.from(obj.crypto.randomBytes(80), 'binary'); diff --git a/meshuser.js b/meshuser.js index ffc30ec9..dc405e1b 100644 --- a/meshuser.js +++ b/meshuser.js @@ -888,7 +888,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use switch (cmd) { case 'help': { - var fin = '', f = '', availcommands = 'help,maintenance,info,versions,resetserver,usersessions,closeusersessions,tasklimiter,setmaxtasks,cores,migrationagents,agentstats,agentissues,webstats,mpsstats,swarmstats,acceleratorsstats,updatecheck,serverupdate,nodeconfig,heapdump,relays,autobackup,backupconfig,dupagents,dispatchtable,badlogins,showpaths,le,lecheck,leevents,dbstats,dbcounters,sms,amtacm,certhashes,watchdog,amtmanager'; + var fin = '', f = '', availcommands = 'help,maintenance,info,versions,resetserver,usersessions,closeusersessions,tasklimiter,setmaxtasks,cores,migrationagents,agentstats,agentissues,webstats,mpsstats,swarmstats,acceleratorsstats,updatecheck,serverupdate,nodeconfig,heapdump,relays,autobackup,backupconfig,dupagents,dispatchtable,badlogins,showpaths,le,lecheck,leevents,dbstats,dbcounters,sms,amtacm,certhashes,watchdog,amtmanager,amtpasswords'; if (parent.parent.config.settings.heapdump === true) { availcommands += ',heapdump'; } availcommands = availcommands.split(',').sort(); while (availcommands.length > 0) { if (f.length > 80) { fin += (f + ',\r\n'); f = ''; } f += (((f != '') ? ', ' : ' ') + availcommands.shift()); } @@ -1152,6 +1152,14 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use console.log(cmdargs['_'][0]); break; } + case 'amtpasswords': { + if (parent.parent.amtPasswords == null) { + r = "No Intel AMT password table." + } else { + for (var i in parent.parent.amtPasswords) { r += (i + ' - ' + parent.parent.amtPasswords[i].join(', ') + '\r\n'); } + } + break; + } case 'updatecheck': { parent.parent.getServerTags(function (tags, error) { var r2 = '';